DOI(https://zenodo.org/badge/latestdoi/185887587)

1 Abstract

Approximate statistical inference via determination of the asymptotic distribution of the statistics is a technique that epidemiologists and applied statisticians use routinely, we name it the classical delta-method, but there is a gap as it is not routinely taught and many applied researchers do not understand it neither its uses. The delta-method is a theorem which states that a smooth function of an asymptotically normal estimator is also asymptotically normally distributed. It can also be viewed as a technique for approximating the variance of a functional i.e., a nonlinear function of a random variable that can be approximated by averages. A fundamental problem in inferential statistics is to approximate the distribution of a statistic calculated from a functional derived from a transformation or the predictions from a regression model fitted parameters. Machine learning methods and causal inference problems applied to epidemiology requires to generate the point estimates from asymptotically linear parameters derived as functionals that are approximated by averages, but the standard error of these point estimates are not so easily calculated with analytical forms. Therefore, we need to approximate the distribution of the standard error for statistical inference using the functional delta-method based on the influence curve. The venue of new methods and techniques requires a constant update on valid statistical inference for applied epidemiologists and statisticians. In this tutorial we introduce the use of the classical and functional delta-method and its link to the Influence Curve in Epidemiology from a practical perspective. We provided a mostly applied overview of the classical and functional delta-method, the influence curve and the bootstrap including easy to understand R code and examples based on cancer epidemiology that may help to fill this gap.

Keywords: Statistical inference; Bootstrap; Delta-method; Epidemiology; Causal Inference; Tutorial.

2 Introduction

A fundamental problem in inferential statistics is to approximate the distribution of a statistic calculated from a probability sample of data. The statistic is usually a parameter estimate that characterizes the sampling variability of the estimate (Boos and Stefanski, 2013). Because the number and type of inference problems for which exact parametric distributions can be determined is limited the approximation of the distribution of the statistic is necessary. Approximate inference via determination of the asymptotic distribution of the statistics is a technique that epidemiologists and applied statisticians use routinely, we name it the delta-method. The delta-method is a theorem which states that a smooth function of an asymptotically normal estimator is also asymptotically normally distributed. It can also be viewed as a technique for approximating variance of a functional i.e., a nonlinear function of a random variable that can be approximated by averages (Armitage and Colton, 2005; Boos and Stefanski, 2013).

Often in addition to reporting parameters fit by a model, we need to report some marginal asymptotically linear transformation of these parameters. The transformation can generate the point estimates of our desired values, but the standard error (SE) of these point estimates are not so easily calculated with analytical forms. Therefore, we need to approximate the distribution of the SE for statistical inference using the delta-method (Boos and Stefanski, 2013) for large samples, or other computational methods such as the bootstrap (Efron and Tibshirani, 1993; Efron and Efron, 1982). For instance, in epidemiology we use routinely the delta-method to compute the SE of functionals as the risk difference (RD), the risk ratio (RR), and the odds ratio (OR) (Agresti, 2010).

More recently for causal inference we compute the average treatment effect (ATE) using G-computation, a generalization of the standardization, among other estimations techniques as the inverse probability of treatment weights (Rubin, 2007). The ATE is defined by an average which is a function of two random variables (i.e., the potential outcomes Y(1) and Y(0)) (Rubin, 2007; Gutman and Rubin, 2015). These two random variables are predicted from the coefficients of the parameters fitted in two different regression models (Greenland and Robins, 1986). The functional delta-method applied to an estimator implicitly defined by averages, also known as M-estimator, can be used to approximate the variance of the estimator (i.e., G-computation for the ATE) (Boos and Stefanski, 2013; Kennedy, 2016; Kennedy et al., 2017) in addition to the bootstrap (Efron and Tibshirani, 1993; Efron and Efron, 1982). Semi-parametric and Empirical Process theory is needed to estimate the SE of the ATE using the functional delta-method under some theoretical assumptions (i.e., the estimator used to derive the ATE must be pathwise differentiable and asymptotically regular and linear (Boos and Stefanski, 2013; Kennedy, 2016; Kennedy et al., 2017). We, applied statisticians and epidemiologists, should known how to determine when a large sample approximation to the distribution of a statistic is appropriate, how to derive the approximation, and how to use it for inference applications.

In this tutorial we introduce the use of the classical and functional delta-method and its link to the Influence Curve (IC) in Epidemiology from a practical perspective including boxes with code in R statistical software (R Foundation for Statistical Computing, Vienna, Austria) (R Core Team, 2020) to allow readers learning by doing. In section two we introduce some basic notation for the delta-method and derive the SE for the a sample mean of an independent variable and the ratio of two means of two independent variables. In section three we derive the SE for the classical epidemiological measures of association. In section four we introduce an empirical example to derive the SE for a single proportion, the conditional odds ratio and relative risk, and finally a marginal causal risk ratio estimated using the augmented inverse probability of treatment weights estimator. Then, in section five we contrast the functional delta-method with the bootstrap approach and finish the article in section five with some applied conclusions.

3 The delta-method

3.1 The classical delta-method

Essentially, the delta-method involves calculating the expansion up to the first order of a Taylor series approximation of a function (f) (Herberg and Bristol, 1962) to derive the empirical value and the SE of an estimator (See appendix for the delta-method theorem from Serfling, 1980, Ch.3). When a statistic can be approximate by an average, the approximating average is usually an average of some function (f) of the sample values and can be written in the form:

\[f(\hat\theta)-f(\theta)\;\approx\;f'(\theta)(\hat\theta\,-\,\theta)\,+\,\text{Op}\left(\frac{1}{\sqrt(n)}\right) .\]

Where \(f(\hat\theta))\) can be interpreted as the large sample stochastic limit of \((f(\theta))\) and \(f'(\theta)(\hat\theta\,-\,\theta)\) is a function called the Influence Curve (IC). The remainder \(\text{Op}(\frac{1}{\sqrt(n)})\) is negligibly small as the sample size increases as asymptotically converges to zero (Boos and Stefanski, 2013).

So the remainder converges to zero

\[\text{Op}\left(\frac{1}{\sqrt(n)}\right) \rightarrow 0 \;,\text{and}\]

the distribution of the \(\theta\) converges in probability to a normally distributed random variable with mean zero and finite variance when the sample size n goes to infinity.

\[\sqrt(n)\left(f(\hat\theta)-f(\theta)\right)\; \rightarrow N(0\,,var(\theta)).\]

Therefore, suppose that \((\hat\theta)\) is a sample mean and f is a smooth scalar valued function. Then, the mean of an estimator \(f(\hat\theta)\) can be approximate with the population mean \(f(\theta)\) plus the IC estimated as the first derivative of the estimator times the difference between the sample population mean minus the mean of the estimator approximated using the delta-method:

\[f(\hat\theta) \approx\;f(\theta)\,+\,f'(\theta)(\hat\theta\,-\,\theta)\;(1)\]

Then we have for the sample mean

\[f(\bar{Y}) \approx\; f(\mu)\,+\,f'(\mu)(\bar{Y}\,-\,\mu)\,=\, n^{-1} \sum\, (\mu)\,+\,f'(\mu)(\bar{Y_{i}}\,-\,\mu),\]

Now lets suppose that we want to consider a pair of independent identically distributed (iid) random sample means (i.e., Y1 and Y2) and we want to derive the SE for the ratio estimator \((f(\bar{Y})\,=\,\bar{Y}_{1}/\bar{Y}_{2})\) where \((\mu_{2}\neq\,0)\). In this case the IC for the ratio will be estimated as follows:

\[f'(\mu)\,=\, \frac{1}{\mu_{1}}\,-\,\frac{\mu_{1}}{\mu_{2}^{2}}.\]

Therefore the IC is given

\[IC = \frac{1}{\mu_{1}}{}(\bar{Y}_{i1}\,-\,\mu_{1})\,-\,\frac{\mu_{1}}{\mu_{2}^{2}}(\bar{Y}_{i2}\,-\,\mu_{2})\]

3.2 The functional delta-method

A function in mathematical statistics is defined by a rule, which associates a number with a function of one or several variables (i.e, the predictions of the linear combinations of the coefficients from regression models). In order to explore the properties of the functionals a generalization of the (ordinary or partial) derivative is required, named the functional derivative. It can be defined via the variation \(\delta f\) of the functional which results from variation of the function by \(\delta f\). Thus, it implies that the function must be differentiable and asymptotically linear (i.e, continuous).

When we have more than two iid random variables that map to a function, we also get the Taylor series approximation of the function using the first two terms of the expansion of a functional about the mean, but we need to compute a vector of partial derivatives along one direction of the functional. We can then take the variance of this approximation to estimate the variance of \(\boldsymbol\theta\) and thus the SE of a transformed functional parameter. The first two terms of the Taylor expansion are then an approximation for \(\boldsymbol{\hat\theta}\) as follows:

\[f(\boldsymbol{\hat\theta}) \approx\, f(\boldsymbol\theta) \,+\,\nabla(\boldsymbol\theta)^T\,(\boldsymbol{\hat\theta}\,-\,\boldsymbol\theta)\; (2).\]

\[\text{Var}(\boldsymbol{\hat\theta}) \approx\; \nabla(\boldsymbol\theta)\text{Cov}(\boldsymbol\theta) \nabla(\boldsymbol\theta)^{T}\; (3).\]

Where Cov(\(\boldsymbol\theta\)) is the variance-covariance matrix of \(\theta\) (Boos and Stefanski, 2013). The variance formula in (3) is also known as the “Huber Sandwich Estimator” that often is used to estimate the variance of the maximum likelihood estimation when the underlying model is misspecified. (Freedman, 2006) In summary, for an observed data \(\text{O}_i\), (i = 1, \(\ldots\), n) an asymptotically linear estimator of \(\hat\theta\) can be evaluated as follows:

\[\hat\theta\;=\;\theta\,+\,\frac{1}{\sqrt{n}}\sum_{i=1}^n (\text{IC}_{i})\,+\,\text{Op}(\frac{1}{\sqrt(n)})\,.\]

Where \(\theta\) is the plug-in estimator of a real value differentiable function (i.e., empirical sample mean) evaluated at \(\theta\) plus the IC represented as the sample mean of a fixed function plus a remainder term that must converge to 0 at a rate faster than \(\frac{1}{\sqrt{n}}\). (Vaart, 1998) Note that the IC measures the influence of the sample observations on the estimator. Plotting the IC provides a tool to discover outliers and tells us how robust is the estimator. Most importantly, the estimated IC provides an asymptotic variance estimate for the asymptotically linear estimator. Therefore, we can readily apply the (CLT) to compute type confidence intervals [CI]).(Laan and Rose, 2011)

In box 1 we compute the SE for a sample mean using the classical delta-method based on the IC and we compare the results with the delta-method implementation of the R package MSM (Kavroudakis et al., 2015).

Box 1. Delta-method for the sample mean and IC visualization in R

# M-estimation for the sample mean
# Data generation
set.seed(7777)
n <- 1000
x <- runif(n,0,1)
mx = mean(x)

# Functional delta-method: influence curve for the sample mean (first derivative=1(constant))
IC = 1 * (x - mx)

# M-estimation of the sample mean
Yhat <- x + IC # Pluging estimator
Yhat <- mean(Yhat); Yhat
[1] 0.508518
# Geometry of the IC
plot(x, IC)

# Standard Error: Influence Curve
varYhat.IC <- var(IC)/n;
seIC <- sqrt(varYhat.IC)

# Asymptotic linear inference 95% Confidence Intervals
Yhat_CI <- c(mean(Yhat) - 1.96*sqrt(varYhat.IC), mean(Yhat) + 1.96*sqrt(varYhat.IC)); 
mean(Yhat); Yhat_CI
[1] 0.508518
[1] 0.4905607 0.5264753
# Check with implemented delta-method in library MSM 
library(msm)

se = deltamethod(g= ~x1, mean= mx, cov= varYhat.IC)
print(se)
[1] 0.009161893
seIC
[1] 0.009161893
# Check 95%CI delta-method computed by hand with delta-method implemented in RcmdrMisc library
Yhat_CI <- c(mean(Yhat) - 1.96*sqrt(varYhat.IC), mean(Yhat) + 1.96*sqrt(varYhat.IC)); 
mean(Yhat); Yhat_CI
[1] 0.508518
[1] 0.4905607 0.5264753
library(RcmdrMisc)
Loading required package: car
Loading required package: carData
Loading required package: sandwich
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
DeltaMethod(lm(x ~ 1), "b0")

    Estimate        SE     2.5 % 97.5 %
b0 0.5085180 0.0091619 0.4905610 0.5265

4 Classical delta-method for common measures of association in epidemiology

We use the classical 2 by 2 epidemiological table, presenting outcome counts by the levels of a risk factor, to derive the SE for the risk differences (RD), risk ratio (RR), and odds ratio (OR) using the delta-method.

Risk Alive Dead
Exposed \(n_{11} = (p_1)\) \(n_{21} = (p_2)\)
Unexposed \(n_{12} = (1-p_1)\) \(n_{22} = (1-p_2)\)
N \(N_1\) \(N_2\)

4.1 Risk Difference

The risk difference (RD) is defined as follows (Rothman et al., 2008):

\[\widehat{RD} \,=\, \hat \theta_{1}\,-\,\hat \theta_{2} \,=\, \hat p_{1}\,-\,\hat p_{2}.\]

Assuming that the probability of the event () can be modelled using a Binomial distribution with range \(0\;\leq \text{p} \leq\;1\), expectation of p is E(\(\theta\)) = p, and the variance var(\(\theta\)) = p(1-p)/ n (Rothman et al., 2008).

Using the delta-method in (1) and substituting \((\hat\theta\,-\,\theta)\) for the variance of \(theta\) i.e., var(\(\theta\)) = p(1-p)/ n, we can derive the \(SE(\widehat{RD})\) for a single proportion computing the IC of the risk difference as follows:

\[SE(\widehat{RD}\,=f'(\theta)(var(\theta))\;=\; 1\,\times\,\sqrt{\frac{p(1-p)}{n}}\]

Therefore, to estimate the var(\(\widehat{RD}\)) for the risk differences we sum the variances var(\(\hat \theta_{1})\) + var\((\hat\theta_{2})\) as follows:

\[SE(\widehat{RD})\,=\, \sqrt{\frac{(1-\hat p_{1})}{n_{1}}}\,+\,\sqrt{\frac{(1-\hat p_{2})}{n_{2}}}\,=\,\sqrt{\frac{(1-\hat p_{1})}{n_{1}}\,+\,\frac{(1-\hat p_{2})}{n_{2}}}\]

4.2 Risk Ratio

Similarly to estimate the SE for risk ratio (RR) we have

\[\widehat{RR} \,=\, \frac{\hat \theta_{1}}{\hat \theta_{2}} \,=\, log\left(\frac{\hat p_{1}}{\hat p_{2}}\right)\,=\,log(\hat p_{1}) - log(\hat p_{2})\]

Note that the derivative of the log(p) is equal to 1/p.

Then, \[SE(log(\hat{\theta}))\,=f'(\theta)(var(\theta))\;=\;\frac{1}{p}\sqrt{\frac{p(1-p)}{n}}\,=\,\sqrt{\frac{(1-p)}{pn}},\; and\]

\[SE(log(\widehat{RR}))\,=\, \sqrt{\frac{(1-\hat p_{1})}{\hat p_{1}n_{1}}}\,+\,\sqrt{\frac{(1-\hat p_{2})}{\hat p_{2}n_{2}}}\,=\,\sqrt{\frac{(1-\hat p_{1})}{\hat p_{1}n_{1}}\,+\,\frac{(1-\hat p_{2})}{\hat p_{2}n_{2}}}\]

4.3 Odds Ratio

Similarly to estimate the SE for odds ratio (OR) we have

\[\widehat{OR} \,=\, \frac{\hat \theta_{1}}{\hat \theta_{2}} \,=\, log\left(\frac{\hat p_{1}/(1-\hat p_{1})}{\hat p_{2}/(1-\hat p_{2})}\right)\,=\,log\left(\frac{\text{n}_{11}\text{n}_{22}}{\text{n}_{12}\text{n}_{21}}\right)\,,\]

Note that the log of the odds \(\frac{p}{1-p}\) is equal to the log(p) - log(1-p) and therefore the derivative is \(\frac{1}{p(1-p)}\).

Then,

\[\text{SE}(log(\hat{\theta}))\,=\,f'(\theta)(var(\theta))\;=\;\frac{1}{p(1-p)}\sqrt{\frac{p(1-p)}{n}}\,=\,\sqrt{\frac{1}{n}}\;, and\]

\[\text{SE}(log(\widehat{OR}))\,=\, \sqrt{\frac{1}{n_{11}}\,+\,\frac{1}{n_{12}}\,+\,\frac{1}{n_{21}}\,+\,\frac{1}{n_{22}}}\]

Finally, after applying the delta-method and assuming the asymptotical linear properties for the estimators of the variance for the different measures of association, we can readily apply the and therefore to derive type Wald 95% CI (i.e., 1.96 \(\times\; \text{SE}\; (\hat\theta)\)) for the different epidemiological measures of association.

5 Empirical example

To illustrate the use of the delta-method we simulate data based on a cancer epidemiology example. We want to estimate the effect of the presence of comorbidities (binary indicator) on one-year cancer mortality in cancer patients controlling for the confounding effect of age in a cohort of 1,000 individuals in their middle age. We assume that it is an extremely lethal type of cancer (i.e., pancreatic cancer) thus we can expect high one-year mortality rate. Age in years was generated as a normal random variable with mean 65 years and standard deviation of 5 years. Comorbidities was generated as a binary indicator and as a function of age using a binomial model. Patients one-year mortality rate was generated as a function of the patients age and the presence of comorbidities using a binomial distribution. The data generation and models specifications are provide here below in the box 2.

Box 2. Data generation

# Data generation
library(dplyr)

Attaching package: ‘dplyr’

The following object is masked from ‘package:car’:

    recode

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
generateData <- function(n, seed){
    set.seed(seed)
    age <- rnorm(n, 65, 5)
    cmbd <- rbinom(n, size=1, prob = plogis(1 - 0.05 * age))
    Y <- rbinom(n, size=1, prob = plogis(1 - 0.02* age - 0.02 * cmbd))
    data.frame(Y, cmbd, age)
}

# Describing the data
data <- generateData(n = 1000, seed = 777) 
str(data)
'data.frame':   1000 obs. of  3 variables:
 $ Y   : int  0 1 1 0 0 1 0 0 1 1 ...
 $ cmbd: int  0 0 0 0 0 0 0 0 0 1 ...
 $ age : num  67.4 63 67.6 63 73.2 ...
summarize(
  data,
  Status = mean(Y), 
  Comorbidities = mean(cmbd),
  Age =  mean(age)) 

5.1 Delta-method for a singly proportion parameter

First, we would like to derive the SE for the single probability or risk of death using the delta-method. In box 3, we compute the risk or probability of death base on the empirical sample example and its variance. We defined the probability of death as the functional \(f(\theta)\) = \(\hat p\). Then the first derivative of f is equal to one. So the variance of the risk of death can be estimated using:

\[ \text{Variance}(\hat{\text{p}}) \,=\,1\,\times\,\left(\frac{p(1-p)}{n}\right)\,.\]

Box 3. Standard error for the single proportion parameter using the delta-method

# Risk of death
p_hat = mean(data$Y)
print(p_hat)
[1] 0.411
# Varianze for the risk of death
 n = nrow(data)
 var_p_hat = p_hat * (1 - p_hat) / n
 print(var_p_hat)
[1] 0.000242079
#This can be implemented in the following R code:
dev_p_hat = 1
se_risk = sqrt((dev_p_hat) * var_p_hat)
print(se_risk)
[1] 0.01555889
# To check that our results are consistent with the implementation of the
# delta-method function provide by the sms R package used for
# advanced Geographical Analysis.

library(msm)
se_risk_delta = deltamethod(g = ~ x1, 
                            mean = p_hat,         
                            cov  = var_p_hat)
print(se_risk_delta)
[1] 0.01555889
## Are the same se_risk and se_risk_delta?
if(se_risk == se_risk_delta) print("Yes")
[1] "Yes"

5.2 Delta method for the odds ratio derived from a regression model

We compute the SE for the odds ratio (OR) derived from a multivariate binomial regression model. Note that the OR transformation is a function of the regression coefficients from the model. First we estimate the conditional probability of the risk of death for those patients with comorbidities adjusting for age. The model summary is described here below in box 3.1. The probability of death for a cancer patient in our sample with comorbidities compared with a patient without comorbidities and in average with the same age is approximately 40% higher:

Box 3.1 OR estimation

m1 <- glm(Y ~ age + cmbd, data = data, family = binomial)
summary(m1)

Call:
glm(formula = Y ~ age + cmbd, family = binomial, data = data)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.2756  -1.0264  -0.9628   1.3141   1.5119  

Coefficients:
            Estimate Std. Error z value Pr(>|z|)  
(Intercept)  1.36593    0.85231   1.603   0.1090  
age         -0.02703    0.01307  -2.069   0.0386 *
cmbd         0.33029    0.22385   1.475   0.1401  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 1354.4  on 999  degrees of freedom
Residual deviance: 1347.4  on 997  degrees of freedom
AIC: 1353.4

Number of Fisher Scoring iterations: 4
b1 <- coef(m1)[3]
cat("One-year mortality risk for patients with comorbidities vs no comorbidities:") 
One-year mortality risk for patients with comorbidities vs no comorbidities:
exp(b1)
    cmbd 
1.391365 

We now can derive the SE for the OR using the equation (3) for the delta-method applied to the multivariate case. Note that the first derivative for the exponential function is equal to exponential and therefore the partial derivatives for age are all the same. Then, to get the matrix of the covariance of the parameter fitted in the model for age we use the command vcov in R (Box 3.2).

Box 3.2 Delta-method for the OR derived from a multivariate regression model

grad <- exp(b1)
vcov(m1)
            (Intercept)           age         cmbd
(Intercept)  0.72643498 -0.0111017571 -0.020775569
age         -0.01110176  0.0001707399  0.000249041
cmbd        -0.02077557  0.0002490410  0.050107817
# Applying formula 3
vb1 <- vcov(m1)[3,3]
se <- grad %*% vb1 %*% grad
se_or <- as.vector(sqrt(se)); se_or
[1] 0.311454
# Now, we have to check that our results are consistent with the
# implementation of the delta-method function provide by the sms
# R package 

se_or_delta <- deltamethod(~ exp(x1), b1, vb1); se_or_delta
[1] 0.311454
# Are the same se_or and se_or_delta?
ifelse(
  se_or == se_or_delta,
  print("Yes"), print("No")
)
[1] "Yes"
[1] "Yes"

5.3 Conditional risk ratio from a multivariate regression model

We computed the SE for the RR as the ratio of two probabilities derived from the predictions of a multivariate binomial regression model. First we fit the model with the binary indicator of one-year mortality as dependent variable and patients age and comorbidities as independent variables. Then, from the fitted model and using the function we derive the probability of death from pancreatic cancer among patients aged 45 years and with comorbidities versus patients aged 75 years old with no comorbidities. Finally, we compute the conditional RR as the ratio between both probabilities. The simulated risk of death in a population where cancer patients were aged 45 years with comorbidities is approximately 81.5% higher than the risk of one-year mortality among cancer patients aged 75 years and with no comorbidities (we assume that the pancreatic cancer is more aggressive among young adults with comorbidities).

Box 4.1. Standard error for the conditional risk ratio derived from a multivariate regression model

m2 <- glm(Y ~ age + cmbd, data = data, family = binomial)
p75 <- predict(m2, newdata = data.frame(age = 75, cmbd = 0), type="response")
p45 <- predict(m2, newdata = data.frame(age = 45, cmbd = 1), type="response")
rr <- p45 / p75;
cat("Conditional risk ratio: ", rr)
Conditional risk ratio:  1.814684

Note that the relative risk transformation is a function of the regression coefficients from the model. Thus, in order to compute the SE for the RR, we should define the conditional probability in terms of the regression coefficients. So, the one year probability of death, given patients age and comorbidities is computed as follows:

\[ \text{P(Y=1|\textbf{W})}\,=\,\frac{1}{1\,+\,\text{exp}(-\sum_{i=1}^{k} \beta(\textbf{w}))}\]

Where k is the number of parameters in the model \(\beta\,=\,(\beta_{0},\beta_{1},\beta_{2})\) and represents the vector of covariates represented for the \(\beta\) parameters (one for each covariate, i.e., \(\beta_{1}\; and\; \beta_{2}\, \text{for patients age and comorbidities, respectively})\), plus the intercept \(\beta_{0}\). Therefore, the probability of one-year mortality for cancer patients aged 45 years old with comorbidities is computed as follows:

\[\text{P(Y = 1|w1 = 45, w3 = 1)}\,=\,\frac{1}{1\,+\,\text{exp}(-\beta_{0}\,-\,\beta_{1}\times 45\,-\,\beta_{2}\times 1)},\]

and the probability of one-year mortality for cancer patients aged 75 years with no comorbidities

\[\text{P(Y = 1|W2 = 75, W4 = 0)}\,=\,\frac{1}{1\,+\,\text{exp}(-\beta_{0}\,-\,\beta_{1}\times 75\,-\,\beta_{2}\times 0)}.\]

Now we can compute the RR as a function of the two previous probabilities. Note that w1 = 75 years, w2 = 45 years, w3 = comorbidities and w4 = no comoribidities)

\[\text{f(w)}\,=\,\frac{\frac{1}{1\,+\,\text{exp}(-\beta_{0}\,-\,\beta_{1} w1\,-\,\beta_{2} w3)}}{\frac{1}{1\,+\,\text{exp}(-\beta_{0}\,-\,\beta_{1} w2\,-\,\beta_{2} w4)}},\]

which simplifies to

\[\text{f(w)}\,=\,\frac{1\,+\,\text{exp}(-\beta_{0}\,-\,\beta_{1} w2\,-\,\beta_{2} w4)}{1\,+\,\text{exp}(-\beta_{0}\,-\,\beta_{1} w1\,-\,\beta_{2} w3)}.\]

We now need to solve the partial derivatives for f(w) using the product and chain rules. (Wolfram, 1992) However, we can use the online open source available software Wolfram alpha to readily get the result of the partial derivatives.(Wolfram, 1992) Then, we apply formula (3) to derive the SE for the RR using the delta-method.

The partial derivatives for f(w) using the product and chain rules are given here below:

\[\frac{\text{df}}{\text{d}\beta_{0}}\,=\,\text{-exp}(-\beta_{0}\,-\,\beta_{1}w2\,-\,\beta_{2} w4))\times \text{p}\,+\,(1\,+\,\text{-exp}(-\beta_{0}\,-\,\beta_{1} w2\,-\,\beta_{2} w4))\times \text{p}(1\,-\,\text{p}),\]

then,

\[\frac{\text{df}}{\text{d}\beta_{1}}\,=\,\text{-exp}(-\beta_{0}\,-\,\beta_{1}w2\,-\,\beta_{2} w4))\times w2 \times \text{p}\,+\,(1\,+\,\text{exp}(-\beta_{0}\,-\,\beta_{1} w2\,-\,\beta_{2} w4))\times x1 \times \text{p}(1\,-\,\text{p}),\]

and,

\[\frac{\text{df}}{\text{d}\beta_{2}}\,=\,\text{-exp}(-\beta_{0}\,-\,\beta_{1}w2\,-\,\beta_{2} w4))\times w4 \times \text{p}\,+\,(1\,+\,\text{exp}(-\beta_{0}\,-\,\beta_{1} w3\,-\,\beta_{2} w4))\times w3 \times \text{p}(1\,-\,\text{p}).\]

where p is

\[\text{P(Y=1|w1,w2)}\,=\,\frac{1}{1\,+\text{exp}(-\beta_{0}\,-\,\beta_{1}w1\,-\,\beta_{2} w3)},\]

i.e., the probability of one-year mortality for cancer patients aged 45 years with comorbidities.

Box 4.2 Delta-method to derive the SE for the conditional RR

#The partial derivative are computed in R as follows:
x1 <- 45
x2 <- 75
x3 <- 1
x4 <- 0
b0 <- coef(m2)[1]
b1 <- coef(m2)[2]
b2 <- coef(m2)[3]
e1 <- exp(-b0 - 45 * b1 - 1 * b2)
e2 <- exp(-b0 - 75 * b1 - 0 * b2)
p1 <- 1 / (1 + e1)
p2 <- 1 / (1 + e2)
dfdb0 <- -e2 * p1 + (1 + e2) * p1 * (1 - p1)
dfdb1 <- -x2 * e2 * p1 + (1 + e2) * x1 * p1 * (1 - p1)
dfdb2 <- -x4 * e2 * p1 + (1 + e2) * x3 * p1 * (1 - p1)
grad <- c(dfdb0, dfdb1, dfdb2)
vG <- t(grad) %*% vcov(m2) %*% (grad)
se_rr <- c(sqrt(vG));se_rr
[1] 0.3653979
#Now, we check whether the results are consistent with the msm R package. 
#We obtain the same results for the SE of the RR computed before (0.3653979)
se_rr_delta <- deltamethod( ~(1 + exp(-x1 -75*x2 -0*x3)) / (1 + exp(-x1 -45*x2 -1*x3)), 
             c(b0, b1, b2), 
             vcov(m2)
             ); se_rr_delta
[1] 0.3653979
#Finally, we compute the type Wald 95% CI
lb <- rr - 1.96*sqrt(vG)
ub <- rr + 1.96*sqrt(vG)
cat("\n Conditional Risk Ratio (95%CI): ") ; cat(rr, "(", lb,",", ub,")")

 Conditional Risk Ratio (95%CI): 1.814684 ( 1.098504 , 2.530864 )

5.4 Statistical inference for the causal risk ratio derived from the AIPTW estimator

Let’s suppose that we want to emulate an impossible clinical trial where we would like to estimate the effect of cancer treatment on the population average one-year risk of death, standardized across all the levels of patients age, TNM cancer stage, comorbidities status, and gender as depicted in the Directed Acyclic Graph in Figure 1.

Figure 1: Directed Acyclic Graph

When estimating the marginal causal risk ratio (CRR) for a binary treatment (or exposure), methods that incorporate propensity scores, the G-computation, or a combination of both, namely double-robust methods, are preferred over naive regression approaches which are biased under misspecification of a parametric outcome model. (Laan and Rose, 2011)

Causal effects are often formulated regarding comparisons of potential outcomes, as formalised by Rubin. (Rubin, 2011) Let A denote a binary exposure, a vector of potential confounders, and Y a binary outcome. Given A, each individual has a pair of potential outcomes i.e., the outcome when exposed, denoted Y(1), and the outcome when unexposed Y(0). These quantities are referred to as potential outcomes, since they are hypothetical, given that it is only possible to observe a single realization of the outcome for an individual; we observe Y(1) only for those in the exposure group and Y(0) only for those in the unexposed group. (Rubin, 1974) Under causal untestable assumptions, namely conditional mean independence or exchangeability, positivity and consistency the potential outcomes can be identified from the observed data.(Greenland and Robins, 1986; Robins et al., 2000) Two common causal estimands are the average treatment effect (ATE), defined as the difference of the expectation of both potential outcomes i.e., \(E[Y_{1}-Y_{0}]\) and the causal risk ratio (CRR), estimated as the ratio of the expectation of the potential outcomes i.e., \(\frac{E[Y_{1}]}{E[Y_{0}]}\).

Classical epidemiological methods use regression adjustment to explain the main effect of a risk factor measure on a disease or outcome. Regression adjustment control for confounding but requires making the assumption that the effect measure is constant across levels of confounders included in the model. However, in non-randomized observational studies, the effect measure is not constant across groups given the different distribution of individual characteristics at baseline. Using the , a generalization of the , allows obtaining a unconfounded marginal estimation of the ATE using (Greenland and Robins, 1986):

\[ ATE\,=\,\sum_{w}\,\left(\sum_{y}\,P(Y=y\mid A=1,W=w)-\,\sum_{y}\,P(Y = y\mid A=0,W=w)\right)P(W=w). \]

where,
\[P(Y = y \mid A = a, W = w)\,=\,\frac{P(W = w, A = a, Y = y)}{\sum_{y}\,P(W = w, A = a, Y = y)}\]

is the conditional probability distribution of Y = y, given A = a, W = w.

The ATE and the CRR can be estimated non-parametrically using the G-formula. However, the curse of dimensionality in observational studies limits its estimation. Hence, the estimation of the ATE using the G-formula relies mostly on parametric modelling and maximum likelihood estimation. The correct model specification in parametric modelling is crucial to obtain unbiased estimates of the true ATE and CRR(Rubin, 2011). Alternatively, propensity score methods, introduced by Rosenbaum and Rubin (Rosenbaum and Rubin, 1983), are also commonly used for estimation of the ATE. The propensity score is a balancing score that can be used to create statistically equivalent exposure groups to estimate the ATE via matching, weighting, or stratification. (Rosenbaum and Rubin, 1983) However, very low or very high propensity scores can lead to very large weights, resulting in unstable estimates with high variance and values outside the constraints of the statistical model. (Lunceford and Davidian, 2004) Furthermore, when analyizing observational data with a large number of variables and potentially complex relationships among them, model misspecification during estimation is of particular concern. Hence, the correct model specification in parametric modelling is crucial to obtain unbiased estimates of the true ATE and CRR. (Laan and Rose, 2011) Therefore, doubly robust (DR) methods were developed combining both the g-computation with propensity score methods to reduce the risk of parametric modelling misspecification. DR methods, relies on semi-parametric theory (i.e., estimation equations) and the most commonly used estimator is the augmented inverse probability of treatment weights (AIPTW) which integrates two parametric models i.e., a model for the outcome and a model for the treatment.(Robins et al., 1994) DR procedures produce a consistent estimate of the parameter if either of the two models has been correctly specified.(Kang and Schafer, 2007)

AIPTW estimation is a double-robust two-step procedure with two equation (propensity score and mean outcome). To estimate the CRR using the AIPTW we use the ratio of the expectations of the potential outcomes. Note that to ease the derivation of the IC and thus the estimation of the SE for the CRR we use the log of the ratio as follows:

\[\text{log(CRR-AIPTW)}\,=\,log\left(\frac{EY1}{EY0}\right)\,=\,\text{log(EY1)}\,-\,\text{log(EY0)}.\]

In box 5.1 we generate the simulated data replicating the DAG from Figure 1. The simulated data in box 5.1 included the following variables:

  • Y: mortality binary indicator (1 death, 0 alive)

  • A: binary treatment (1 Chemotherapy, 0 Radiotherapy )

  • w1: Gender (1 male; 0 female)

  • w2: Age at diagnosis (binary with levels: 0 <65; 1 >=65)

  • w3: Cancer TNM classification (multinomial with levels: 1 to 4; 1: early stage no metastasis; 4: advanced stage with metastasis)

  • w4: Comorbidities count from 1 to 5)

Box 5.1 Data generation

options(digits=4)
generateData <- function(n){
  w1 <- rbinom(n, size=1, prob=0.5)
  w2 <- rbinom(n, size=1, prob=0.65)
  w3 <- round(runif(n, min=0, max=4), digits=3)
  w4 <- round(runif(n, min=0, max=5), digits=3)
  A  <- rbinom(n, size=1, prob= plogis(-0.4 + 0.2*w2 + 0.15*w3 + 0.2*w4 + 0.15*w2*w4))
  # counterfactual
Y.1 <- rbinom(n, size=1, prob= plogis(-1 + 1 -0.1*w1 + 0.3*w2 + 0.25*w3 + 0.2*w4 + 0.15*w2*w4))
Y.0 <- rbinom(n, size=1, prob= plogis(-1 + 0 -0.1*w1 + 0.3*w2 + 0.25*w3 + 0.2*w4 + 0.15*w2*w4))
  # Observed outcome
  Y <- Y.1*A + Y.0*(1 - A)
  # return data.frame
  data.frame(w1, w2, w3, w4, A, Y)
}
set.seed(7777)
n <- 10000
Obsdata <- generateData(n=n)
Obsdata <- as.data.frame(Obsdata)
Obsdata <-subset(Obsdata, select=c(w1,w2,w3,w4,A,Y))
Y  <- Obsdata$Y
A  <- Obsdata$A
w1 <- Obsdata$w1
w2 <- Obsdata$w2
w3 <- Obsdata$w3
w4 <- Obsdata$w4

In box 5.2 we show how to estimate the CRR using the AIPTW estimator.

Box 5.2 CRR estimation using the AIPTW estimator

# Step 1 estimation and prediction of the model for the outcome (G-computation)
gm <- glm(Y ~ A + w1 + w2 + w3 + w4, data = Obsdata, family = binomial(link=logit))
# Prediction for E(Y|A,W), and E(Y|A = 1, W) and, E(Y|A = 0, W)
QAW <- predict(gm, type = "response")
Q1W <- predict(gm, newdata=data.frame(A = 1, w1, w2, w3, w4), type = "response")
Q0W <- predict(gm, newdata=data.frame(A = 0, w1, w2, w3, w4), type = "response")
# Step 2 estimation and prediction of the propensity score (ps): E(A|W) or E(cmbd|age)
psm <- glm(A ~ w1 + w2 + w3 + w4, family = binomial, data = Obsdata)
gW = predict(psm, type = "response")
# AIPTW CRR
EY1 <- mean((Obsdata$Y) * (Obsdata$Y - Q1W) / gW + Q1W)
EY0 <- mean((1 - Obsdata$Y) * (Obsdata$Y - Q0W) / (1 - gW) + Q0W)
logCRR <- log(EY1) - log(EY0) 
CRR <- exp(logCRR);CRR
[1] 8.156

The marginal contrast of a population of patients where all of them were treated with chemotherapy versus other where patients were treated with radiotherapy after standardizing by the levels of patients age, TNM stage, comoribidities and gender for the one-year mortality risk is 8 times higher for patients treated with chemotherapy. However, we would like to get statistical inference for the estimate of the CRR. Often researchers use the bootstrap procedure to derive 95% CI but computing efficiency is low. However, we can use the functional delta-method to apply the Central Limit Theorem and derive 95% type Wald CI for the CRR.

In box 5.3 we show how to derive the functional delta-method based based on the efficient IC for the AIPTW estimator using equation (2) to estimate the SE of the CRR.(Laan and Rose, 2011). While many influence functions and corresponding estimators exist for a given target parameter, there always exists an IC that achieves the lower bound on asymptotic variance. The AIPTW is constructed by using the efficient IC, making it asymptotically efficient when all necessary models are correctly specified (i.e., the model for the outcome and the model for the treatment or exposure mechanism). To compute the efficient IC for the log(CRR) = log(\(\hat{E}\)[Y1]) - log(\(\hat{E}\)[Y0]) = \(\psi_{1}\) - \(\psi_{2}\), we first have to derive the following two partial derivatives a.k.a as the canonical gradient of the pathwise derivative of the target parameter:(Laan and Rose, 2011)

\[\frac{\partial log(\psi_{1})}{\partial \psi_{1}}\,=\,\frac{1}{\psi_{1}}\,=\,\frac{1}{\hat{E}[Y(1)]},\]

and,

\[ \frac{\partial log(\psi_{2})}{\partial \psi_{2}}\,=\,\frac{1}{\psi_{2}}\,=\,\frac{1}{\hat{E}[Y(0)]},\]

then, to compute \((\hat\theta\,-\,\theta)\) from equation (2) we define D1 and D0 as follows:

\[\text{D1}\,=\,\left(\left(\frac{I\left(A_{i}=1\right)}{g_n(1\mid W_{i})}\right)\left(Y_{i}-{Q}_{n}\left(A_{i},W_{i}\right)\right)\,+\,\text{Q}_{n}\left(1,\ W_{i}\right)\right)\,-\,\hat{E}[Y(1)]\; (6),\]

and

\[\text{D0}\,=\,\left(\left(\frac{I\left(A_{i}=0\right)}{g_n(0\mid W_{i})}\right)\left(Y_{i}-{Q}_{n}\left(A_{i},W_{i}\right)\right)\,+\,\text{Q}_{n}\left(0,\ W_{i}\right)\right)\,-\,\hat{E}[Y(0)]\; (7).\]

Where refers to a binary indicator variable for the treatment A, \(g_{n}\) is the propensity score for the treatment mechanism (A) and \(Q_{n}\) is the estimate of the conditional mean of outcome given treatment and confounders () i.e., \(E(Y|A,\textbf{W})\). The mean expected outcome under treatment and control (i.e., \(\hat{E}\)[Y(1)] and \(\hat{E}\)[Y(0)]: chemotherapy and radiotherapy in our example) are given by solving the estimating equations:

\[\hat{E}[Y(1)]\,=\,\frac{1}{n}\sum_{i=1}^{n}\left(\frac{I\left(A_{i}=1\right)}{g_n(1\mid W_{i})}\right)\left(Y_{i}-{Q}_{n}\left(A_{i},W_{i}\right)\right)+\frac{1}{n}\sum_{i=1}^{n}{Q}_{n}\left(1,\ W_{i}\right)\, (4),\]

and

\[\hat{E}[Y(0)]\,=\,\frac{1}{n}\sum_{i=1}^{n}\left(\frac{I\left(A_{i}=1\right)}{g_n(0\mid W_{i})}\right)\left(Y_{i}-{Q}_{n}\left(A_{i},W_{i}\right)\right)+\frac{1}{n}\sum_{i=1}^{n}{Q}_{n}\left(0,\ W_{i}\right)\,(5).\]

Finally, the efficient (\(\text{IC}_{i}\)) for the log(CRR) is given by:

\[\,=\,\frac{1}{\hat{E}[Y(1)]}D1\,+\,\frac{1}{\hat{E}[Y(0)]}D0.\; (8)\]

Box 5.3 Statistical inference for the CRR based on the IC

# Functional Delta Method for statisical inference
D1 <- (A) * (Y - Q1W) / gW + Q1W - EY1 
D0 <- (1 - A) * (Y - Q0W) / (1 - gW) + Q0W - EY0
# AIPTW CRR 95%CI
EIC <- ((1 / EY1) * D1) + ((1 / EY0) * D0)
varEIC <- var(EIC) / n
CI <- c(exp(logCRR - 1.96 * sqrt(varEIC)), exp(logCRR + 1.96 * sqrt(varEIC))); 
cat("\n CRR:", CRR)

 CRR: 8.156
cat("\n CRR 95%CI:", CI)

 CRR 95%CI: 7.109 9.359
# Summary IC
cat("\n Variance EIC:", varEIC)

 Variance EIC: 0.004921

Note: Exploring the distribution of the IC will allow to discover outliers and tells us how robust is the estimator as shown in the histogram for the distribution of the IC (Figure 2). Note that the mean of the variance of the EIC must be equal to zero. In general, when we have data sparsity and identifiability problems such as near-positivity violations (i.e., the positivity assumption states that within strata of W every patient had a nonzero probability of receiving either of the two treatment conditions (i.e.~0 P(A=1)1)), the Bootstrap is preferred for statistical inference. (Cai and Laan, 2019)

Figure 2. Influence curve distribution

6 The Bootstrap

Finally, we are going to use a more conservative approach for statistical inference (i.e., the bootstrap). Using the Bootstrap the original sample approximates the population from which it was drawn. So resamples from this sample approximate what we would get if we took many samples from the population. The bootstrap distribution of a statistic, based on many resamples, approximates the sampling distribution of the statistic, based on many samples and therefore it can only be applied under certain smoothness conditions. (Efron and Efron, 1982; Efron and Gong, 1983) For statistical inference, the standard deviation of the bootstrap distribution of that statistic is the SE of the statistic. For most statistics, bootstrap distributions approximate the spread, bias, and shape of the actual sampling distribution. The interval between 2.5 and 97.5 percentiles of the bootstrap distribution of a statistic is a 95% bootstrap percentile confidence interval for the corresponding parameter. (Efron and Efron, 1982; Efron and Gong, 1983)

In box 6, we use the R package which provides extensive facilities for bootstrapping and related resampling methods. You can bootstrap a single statistic (e.g.~a median), or a vector (e.g., regression weights). We are going to use the nonparametric bootstrapping based on 10.000 bootstrap sample estimates. (Canty, 2002)

Box 6. Bootstrap statistical inference for SE

library(boot)

Attaching package: ‘boot’

The following object is masked from ‘package:car’:

    logit

The following object is masked from ‘package:msm’:

    cav
aiptw.w = function(data,indices)
{
    dat=Obsdata[indices,]
    # CRR
    gm <- glm(Y ~ A + w1 + w2 + w3 + w4, data = dat, family = binomial(link=logit))
    # Prediction for E(Y|A,W), and E(Y|cmbd = 1, age) and, E(Y|cmbd = 0, age)
    Q1W <- predict(gm, newdata = data.frame(A = 1, w1, w2, w3, w4), type = "response")
    Q0W <- predict(gm, newdata = data.frame(A = 0, w1, w2, w3, w4), type = "response")
    # Step 2 estimation and prediction of the propensity score (ps): E(A|W) or E(cmbd|age)
    psm <- glm(A ~ w1 + w2 + w3 + w4, family = binomial, data = dat)
    gW = predict(psm, type = "response")
    # CRR
    EY1 <- mean((Y) * (Y - Q1W) / gW + Q1W)
    EY0 <- mean((1 - Y) * (Y - Q0W) / (1 - gW) + Q0W)
    CRR <- EY1 / EY0
}
# Can get original estimate, by plugging in indices 1:n
aiptw.w(data, indices =1:nrow(data))
# Draw 1000 bootstrap sample estimates 
boot.out = boot(data, aiptw.w, 10000)
# compute confidence intervals using percentile method
boot.ci(boot.out, type = "perc", conf = 0.95)
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 10000 bootstrap replicates

CALL : 
boot.ci(boot.out = boot.out, conf = 0.95, type = "perc")

Intervals : 
Level     Percentile     
95%   ( 6.224, 19.223 )  
Calculations and Intervals on Original Scale

Note that we got narrower confidence intervals using the delta-method compared to the Bootstrap procedure (i.e., the bootstrap estimate of the SE for the AIPTW estimator is more conservative). It has been shown that the coverage of the functional delta-method in finite samples decreases when there are identifiability problems such as violations of the positivity assumption for causal inference (Dorie et al., 2019). Basically, it is due to ignore the potentially very large contributions of the remainder term \(\text{Op}(\frac{1}{\sqrt(n)})\) that easily dominates the first order empirical mean of the IC term. It is why the functional delta-method provides more precise confidence intervals than other approaches such as the Bootstrap in finite samples when problems related with the course of dimensionality such as violations of positivity in the causal inference setting. (Dorie et al., 2019) However, when data adaptive (i.e., machine learning algorithms) are use to predict the potential outcomes there is not scientific evidence supporting the use of Bootstrap for statistical inference. (Laan and Rose, 2011)

7 Conclusion

The delta-method is widely used in classical epidemiological methods for statistical inference. For instance, it is used to derive the SE of an asymptotically linear estimator or function that can be approximated by averages (i.e., such as the conditional estimations from coefficients of the parameters fitted in regression models). In casual inference the functional delta-method and ICs are largely used because it ease the derivation of type Wald CIs for data-adaptive double-robust estimators.

Recently, the study of the behavior of the delta-method for data-adaptive double-robust estimators in finite samples where there are positivity violations revealed that the functional delta-method provides less conservative confidence intervals than the Bootstrap procedures. Simulation studies have shown that in such situations the SE coverage is poor. (Dorie et al., 2019). Therefore, more conservative and robust approaches such as the bootstrap procedure is still a valid and preferred method for statistical inference under violations and near violations of the positivity assumption. However, the use of cross-validation procedures for the estimation of the causal parameter has been shown to improve the performance of the functional delta-method under finite sample identifiability problems. (Levy, 2018; Laan and Rose, 2011) Furthermore, when data adaptive methods are used for causal inference estimation, the Bootstrap procedure for statistical inference is not supported. Nevertheless, recent studies have demonstrated the validity and better performance of the bootstrap procedure for cross-validated causal inference methods using data adaptive procedures such as the targeted maximum likelihood estimation. (Cai and Laan, 2019)

To conclude, there is an active research development of methods and tools for highly dimensional data analysis such as machine learning and causal inference. The new venue of methods requires a constant update on valid statistical inference for applied epidemiologists and statisticians. We provided a mostly applied overview of the delta-method, the functional delta-method, IC and the bootstrap that may help to fill this gap.

8 Funding

Miguel Angel Luque Fernandez is supported by the National Institute of Health, Carlos III, Miguel Servet I Investigator Award (CP17/00206), Madrid, Spain.

9 Authors contributions

The article arise from the motivation to disseminate the principles of modern epidemiology among clinicians and applied researchers. MALF developed the concept, designed the study, analysed the data, and wrote the tutorial All authors interpreted and reviewed the code and the data, drafted and revised the tutorial.

10 Session Info

devtools::session_info()
─ Session info ───────────────────────────────────────────────────────────
 setting  value
 version  R version 4.1.2 (2021-11-01)
 os       macOS Monterey 12.3.1
 system   x86_64, darwin17.0
 ui       RStudio
 language (EN)
 collate  en_US.UTF-8
 ctype    en_US.UTF-8
 tz       Europe/Madrid
 date     2022-04-18
 rstudio  2021.09.1+372 Ghost Orchid (desktop)
 pandoc   2.14.0.3 @ /Applications/RStudio.app/Contents/MacOS/pandoc/ (via rmarkdown)

─ Packages ───────────────────────────────────────────────────────────────
 package      * version date (UTC) lib source
 abind          1.4-5   2016-07-21 [2] CRAN (R 4.1.0)
 assertthat     0.2.1   2019-03-21 [2] CRAN (R 4.1.0)
 backports      1.4.0   2021-11-23 [2] CRAN (R 4.1.0)
 base64enc      0.1-3   2015-07-28 [2] CRAN (R 4.1.0)
 boot         * 1.3-28  2021-05-03 [2] CRAN (R 4.1.2)
 bslib          0.3.1   2021-10-06 [2] CRAN (R 4.1.0)
 cachem         1.0.6   2021-08-19 [2] CRAN (R 4.1.0)
 callr          3.7.0   2021-04-20 [2] CRAN (R 4.1.0)
 car          * 3.0-12  2021-11-06 [2] CRAN (R 4.1.0)
 carData      * 3.0-4   2020-05-22 [2] CRAN (R 4.1.0)
 cellranger     1.1.0   2016-07-27 [2] CRAN (R 4.1.0)
 checkmate      2.0.0   2020-02-06 [2] CRAN (R 4.1.0)
 class          7.3-19  2021-05-03 [2] CRAN (R 4.1.2)
 cli            3.1.0   2021-10-27 [2] CRAN (R 4.1.0)
 cluster        2.1.2   2021-04-17 [2] CRAN (R 4.1.2)
 colorspace     2.0-2   2021-06-24 [2] CRAN (R 4.1.0)
 crayon         1.4.2   2021-10-29 [2] CRAN (R 4.1.0)
 data.table     1.14.2  2021-09-27 [2] CRAN (R 4.1.0)
 DBI            1.1.2   2021-12-20 [2] CRAN (R 4.1.0)
 desc           1.4.0   2021-09-28 [2] CRAN (R 4.1.0)
 devtools       2.4.3   2021-11-30 [2] CRAN (R 4.1.0)
 digest         0.6.29  2021-12-01 [2] CRAN (R 4.1.0)
 dplyr        * 1.0.7   2021-06-18 [2] CRAN (R 4.1.0)
 e1071          1.7-9   2021-09-16 [2] CRAN (R 4.1.0)
 ellipsis       0.3.2   2021-04-29 [2] CRAN (R 4.1.0)
 evaluate       0.14    2019-05-28 [2] CRAN (R 4.1.0)
 expm           0.999-6 2021-01-13 [2] CRAN (R 4.1.0)
 fansi          0.5.0   2021-05-25 [2] CRAN (R 4.1.0)
 fastmap        1.1.0   2021-01-25 [2] CRAN (R 4.1.0)
 forcats        0.5.1   2021-01-27 [2] CRAN (R 4.1.0)
 foreign        0.8-81  2020-12-22 [2] CRAN (R 4.1.2)
 Formula        1.2-4   2020-10-16 [2] CRAN (R 4.1.0)
 fs             1.5.1   2021-11-30 [2] CRAN (R 4.1.0)
 generics       0.1.1   2021-10-25 [2] CRAN (R 4.1.0)
 ggplot2        3.3.5   2021-06-25 [2] CRAN (R 4.1.0)
 glue           1.5.1   2021-11-30 [2] CRAN (R 4.1.0)
 gridExtra      2.3     2017-09-09 [2] CRAN (R 4.1.0)
 gtable         0.3.0   2019-03-25 [2] CRAN (R 4.1.0)
 haven          2.4.3   2021-08-04 [2] CRAN (R 4.1.0)
 Hmisc          4.6-0   2021-10-07 [2] CRAN (R 4.1.0)
 hms            1.1.1   2021-09-26 [2] CRAN (R 4.1.0)
 htmlTable      2.3.0   2021-10-12 [2] CRAN (R 4.1.0)
 htmltools      0.5.2   2021-08-25 [2] CRAN (R 4.1.0)
 htmlwidgets    1.5.4   2021-09-08 [2] CRAN (R 4.1.0)
 jpeg           0.1-9   2021-07-24 [2] CRAN (R 4.1.0)
 jquerylib      0.1.4   2021-04-26 [2] CRAN (R 4.1.0)
 jsonlite       1.7.2   2020-12-09 [2] CRAN (R 4.1.0)
 knitr          1.36    2021-09-29 [2] CRAN (R 4.1.0)
 lattice        0.20-45 2021-09-22 [2] CRAN (R 4.1.2)
 latticeExtra   0.6-29  2019-12-19 [2] CRAN (R 4.1.0)
 lifecycle      1.0.1   2021-09-24 [2] CRAN (R 4.1.0)
 magrittr       2.0.1   2020-11-17 [2] CRAN (R 4.1.0)
 MASS           7.3-54  2021-05-03 [2] CRAN (R 4.1.2)
 Matrix         1.3-4   2021-06-01 [2] CRAN (R 4.1.2)
 memoise        2.0.1   2021-11-26 [2] CRAN (R 4.1.0)
 msm          * 1.6.9   2021-09-27 [2] CRAN (R 4.1.0)
 munsell        0.5.0   2018-06-12 [2] CRAN (R 4.1.0)
 mvtnorm        1.1-3   2021-10-08 [2] CRAN (R 4.1.0)
 nnet           7.3-16  2021-05-03 [2] CRAN (R 4.1.2)
 nortest        1.0-4   2015-07-30 [2] CRAN (R 4.1.0)
 pillar         1.6.4   2021-10-18 [2] CRAN (R 4.1.0)
 pkgbuild       1.3.1   2021-12-20 [2] CRAN (R 4.1.0)
 pkgconfig      2.0.3   2019-09-22 [2] CRAN (R 4.1.0)
 pkgload        1.2.4   2021-11-30 [2] CRAN (R 4.1.0)
 png            0.1-7   2013-12-03 [2] CRAN (R 4.1.0)
 prettyunits    1.1.1   2020-01-24 [2] CRAN (R 4.1.0)
 processx       3.5.2   2021-04-30 [2] CRAN (R 4.1.0)
 proxy          0.4-26  2021-06-07 [2] CRAN (R 4.1.0)
 ps             1.6.0   2021-02-28 [2] CRAN (R 4.1.0)
 purrr          0.3.4   2020-04-17 [2] CRAN (R 4.1.0)
 R6             2.5.1   2021-08-19 [2] CRAN (R 4.1.0)
 RcmdrMisc    * 2.7-1   2020-08-13 [2] CRAN (R 4.1.0)
 RColorBrewer   1.1-2   2014-12-07 [2] CRAN (R 4.1.0)
 Rcpp           1.0.7   2021-07-07 [2] CRAN (R 4.1.0)
 readxl         1.3.1   2019-03-13 [2] CRAN (R 4.1.0)
 remotes        2.4.2   2021-11-30 [2] CRAN (R 4.1.0)
 rlang          0.4.12  2021-10-18 [2] CRAN (R 4.1.0)
 rmarkdown      2.11    2021-09-14 [2] CRAN (R 4.1.0)
 rpart          4.1-15  2019-04-12 [2] CRAN (R 4.1.2)
 rprojroot      2.0.2   2020-11-15 [2] CRAN (R 4.1.0)
 rstudioapi     0.13    2020-11-12 [2] CRAN (R 4.1.0)
 sandwich     * 3.0-1   2021-05-18 [2] CRAN (R 4.1.0)
 sass           0.4.0   2021-05-12 [2] CRAN (R 4.1.0)
 scales         1.1.1   2020-05-11 [2] CRAN (R 4.1.0)
 sessioninfo    1.2.2   2021-12-06 [2] CRAN (R 4.1.0)
 stringi        1.7.6   2021-11-29 [2] CRAN (R 4.1.0)
 stringr        1.4.0   2019-02-10 [2] CRAN (R 4.1.0)
 survival       3.2-13  2021-08-24 [2] CRAN (R 4.1.2)
 testthat       3.1.1   2021-12-03 [2] CRAN (R 4.1.0)
 tibble         3.1.6   2021-11-07 [2] CRAN (R 4.1.0)
 tidyselect     1.1.1   2021-04-30 [2] CRAN (R 4.1.0)
 usethis      * 2.1.3   2021-10-27 [2] CRAN (R 4.1.0)
 utf8           1.2.2   2021-07-24 [2] CRAN (R 4.1.0)
 vctrs          0.3.8   2021-04-29 [2] CRAN (R 4.1.0)
 withr          2.4.3   2021-11-30 [2] CRAN (R 4.1.0)
 xfun           0.29    2021-12-14 [2] CRAN (R 4.1.0)
 yaml           2.2.1   2020-02-01 [2] CRAN (R 4.1.0)
 zoo            1.8-9   2021-03-09 [2] CRAN (R 4.1.0)

 [1] /Users/MALF/Library/R/x86_64/4.1/library
 [2] /Library/Frameworks/R.framework/Versions/4.1/Resources/library

──────────────────────────────────────────────────────────────────────────

11 Thank you

Thank you for reading the tutorial.

You can cite this repository as:
Luque-Fernandez MA, (2020) et al. Delta Method in Epidemiology: An Applied and Reproducible Tutorial. GitHub repository, http://migariane.github.io/DeltaMethodEpi.nb.html

DOI(https://zenodo.org/badge/latestdoi/185887587

If you have updates or changes that you would like to make, please send me a pull request. Alternatively, if you have any questions, please e-mail me.

Miguel Angel Luque Fernandez
E-mail: miguel-angel.luque at lshtm.ac.uk
Twitter @WATZILEI
Website: https://scholar.harvard.edu/malf/home
ORCID: https://orcid.org/0000-0001-6683-5164

12 References

Agresti A. (2010). Analysis of ordinal categorical data. 2nd ed. Wiley: Hoboken, N.J.
Armitage P, Colton T. (2005). Encyclopedia of biostatistics. 2nd ed. John Wiley: Chichester, West Sussex, England.
Boos DD, Stefanski LA. (2013). Essential statistical inference: Theory and methods. Springer.
Cai W, Laan M van der. (2019). Nonparametric bootstrap inference for the targeted highly adaptive LASSO estimator. https://arxiv.org/pdf/1905.10299.pdf.
Canty A. (2002). Resampling methods in r: The boot package. R News 2: 2–7.
Dorie V, Hill J, Shalit U, Scott M, Cervone D. (2019). Rejoinder: Response to discussions and a look ahead. Statistical Science 34: 94–99.
Efron B, Efron B. (1982). The jackknife, the bootstrap and other resampling plans. SIAM.
Efron B, Gong G. (1983). A leisurely look at the bootstrap, the jackknife, and cross-validation. The American Statistician 37: 36–48.
Efron B, Tibshirani R. (1993). An introduction to the bootstrap. Chapman & Hall: New York.
Freedman DA. (2006). On the so-called "huber sandwich estimator" and "robust standard errors". The American Statistician 60: 299–302.
Greenland S, Robins JM. (1986). Identifiability, exchangeability, and epidemiological confounding. International journal of epidemiology 15: 413–419.
Gutman R, Rubin DB. (2015). Estimation of causal effects of binary treatments in unconfounded studies. Stat Med 34: 3381–98.
Herberg T, Bristol JD. (1962). Elementary mathematical analysis. Heath: Boston.
Kang JDY, Schafer JL. (2007). Demystifying double robustness: A comparison of alternative strategies for estimating a population mean from incomplete data. Statistical Science 22: 523–539.
Kavroudakis D et al. (2015). Sms: An r package for the construction of microdata for geographical analysis. Journal of Statistical Software 68.
Kennedy EH. (2016). Semiparametric theory and empirical processes in causal inference. In: Statistical causal inferences and their applications in public health research. Springer, pp 141–167.
Kennedy EH, Ma Z, McHugh MD, Small DS. (2017). Non-parametric methods for doubly robust estimation of continuous treatment effects. Journal of the Royal Statistical Society: Series B (Statistical Methodology) 79: 1229–1245.
Laan M van der, Rose S. (2011). Targeted learning: Causal inference for observational and experimental data. Springer Series in Statistics.
Levy J. (2018). An easy implementation of CV-TMLE. https://arxiv.org/pdf/1811.04573.pdf.
Lunceford JK, Davidian M. (2004). Stratification and weighting via the propensity score in estimation of causal treatment effects: A comparative study. Statistics in Medicine 23: 2937–2960.
R Core Team. (2020). R: A language and environment for statistical computing. R Foundation for Statistical Computing: Vienna, Austria.
Robins JM, Hernan MA, Brumback B. (2000). Marginal structural models and causal inference in epidemiology. Epidemiology 550–560.
Robins JM, Rotnitzky A, Zhao LP. (1994). Estimation of regression coefficients when some regressors are not always observed. Journal of the American Statistical Association 89: 846–866.
Rosenbaum PR, Rubin DB. (1983). The central role of the propensity score in observational studies for causal effects. Biometrika 70: 41–55.
Rothman KJ, Greenland S, Lash TL. (2008). Modern epidemiology. 3rd ed., thoroughly rev. and updated. Wolters Kluwer Health/Lippincott Williams & Wilkins: Philadelphia.
Rubin DB. (2011). Causal inference using potential outcomes. Journal of the American Statistical Association.
Rubin DB. (1974). Estimating causal effects of treatments in randomized and nonrandomized studies. Journal of educational Psychology 66: 688.
Rubin DB. (2007). The design versus the analysis of observational studies for causal effects: Parallels with the design of randomized trials. Stat Med 26: 20–36.
Vaart AW van der. (1998). Asymptotic statistics. Cambridge University Press: Cambridge, UK.
Wolfram S. (1992). Mathematica reference guide. Addison-Wesley Pub. Co.: Reading, Mass.
LS0tCnRpdGxlOiAiRGVsdGEgTWV0aG9kIGluIEVwaWRlbWlvbG9neTogQW4gQXBwbGllZCBhbmQgUmVwcm9kdWNpYmxlIFR1dG9yaWFsLiIKYXV0aG9yOiAiTWlndWVsIEFuZ2VsIEx1cXVlIEZlcm5hbmRleiwgTUEsIE1QSCwgTVNjLCBQaC5EIgpkYXRlOiAiMjAvMTAvMjAyMCBcbiBodHRwczovL3NjaG9sYXIuaGFydmFyZC5lZHUvbWFsZi9ob21lIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgaGlnaGxpZ2h0OiBkZWZhdWx0CiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdGhlbWU6IGpvdXJuYWwKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6CiAgICAgIGNvbGxhcHNlZDogbm8KICAgICAgc21vb3RoX3Njcm9sbDogeWVzCiAgICAgIHRvY19kZXB0aDogMwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHBkZl9kb2N1bWVudDoKICAgICB0b2M6IHRydWUKICAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKZm9udC1mYW1pbHk6IFJpc3F1ZQpmb250LWltcG9ydDogaHR0cDovL2ZvbnRzLmdvb2dsZWFwaXMuY29tL2Nzcz9mYW1pbHk9UmlzcXVlCmNzbDogcmVmZXJlbmNlcy9pc21lLmNzbApiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMvYmlibGlvZ3JhcGh5LmJpYgotLS0KCjxhIGhyZWY9Imh0dHBzOi8vdHdpdHRlci5jb20vc2hhcmU/cmVmX3NyYz10d3NyYyU1RXRmdyIgY2xhc3M9InR3aXR0ZXItc2hhcmUtYnV0dG9uIiBkYXRhLXNob3ctY291bnQ9ImZhbHNlIj5Ud2VldDwvYT48c2NyaXB0IGFzeW5jIHNyYz0iaHR0cHM6Ly9wbGF0Zm9ybS50d2l0dGVyLmNvbS93aWRnZXRzLmpzIiBjaGFyc2V0PSJ1dGYtOCI+PC9zY3JpcHQ+CgohW0RPSV0oaHR0cHM6Ly96ZW5vZG8ub3JnL2JhZGdlLzE4NTg4NzU4Ny5zdmcpKGh0dHBzOi8vemVub2RvLm9yZy9iYWRnZS9sYXRlc3Rkb2kvMTg1ODg3NTg3KQoKYGBge3Igb3B0aW9ucywgZWNobz1GQUxTRSwgZXZhbD1GQUxTRX0Kb3B0aW9ucyhzY2lwZW49OTk5LCBkaWdpdHM9NSwgdGlueXRleC52ZXJib3NlID0gVFJVRSkKYGBgCgojIEFic3RyYWN0CgpBcHByb3hpbWF0ZSBzdGF0aXN0aWNhbCBpbmZlcmVuY2UgdmlhIGRldGVybWluYXRpb24gb2YgdGhlIGFzeW1wdG90aWMgZGlzdHJpYnV0aW9uIG9mIHRoZSBzdGF0aXN0aWNzIGlzIGEgdGVjaG5pcXVlIHRoYXQgZXBpZGVtaW9sb2dpc3RzIGFuZCBhcHBsaWVkIHN0YXRpc3RpY2lhbnMgdXNlIHJvdXRpbmVseSwgd2UgbmFtZSBpdCB0aGUgY2xhc3NpY2FsIGRlbHRhLW1ldGhvZCwgYnV0IHRoZXJlIGlzIGEgZ2FwIGFzIGl0IGlzIG5vdCByb3V0aW5lbHkgdGF1Z2h0IGFuZCBtYW55IGFwcGxpZWQgcmVzZWFyY2hlcnMgZG8gbm90IHVuZGVyc3RhbmQgaXQgbmVpdGhlciBpdHMgdXNlcy4gVGhlIGRlbHRhLW1ldGhvZCBpcyBhIHRoZW9yZW0gd2hpY2ggc3RhdGVzIHRoYXQgYSBzbW9vdGggZnVuY3Rpb24gb2YgYW4gYXN5bXB0b3RpY2FsbHkgbm9ybWFsIGVzdGltYXRvciBpcyBhbHNvIGFzeW1wdG90aWNhbGx5IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLiBJdCBjYW4gYWxzbyBiZSB2aWV3ZWQgYXMgYSB0ZWNobmlxdWUgZm9yIGFwcHJveGltYXRpbmcgdGhlIHZhcmlhbmNlIG9mIGEgZnVuY3Rpb25hbCBpLmUuLCBhIG5vbmxpbmVhciBmdW5jdGlvbiBvZiBhIHJhbmRvbSB2YXJpYWJsZSB0aGF0IGNhbiBiZSBhcHByb3hpbWF0ZWQgYnkgYXZlcmFnZXMuIEEgZnVuZGFtZW50YWwgcHJvYmxlbSBpbiBpbmZlcmVudGlhbCBzdGF0aXN0aWNzIGlzIHRvIGFwcHJveGltYXRlIHRoZSBkaXN0cmlidXRpb24gb2YgYSBzdGF0aXN0aWMgY2FsY3VsYXRlZCBmcm9tIGEgZnVuY3Rpb25hbCBkZXJpdmVkIGZyb20gYSB0cmFuc2Zvcm1hdGlvbiBvciB0aGUgcHJlZGljdGlvbnMgZnJvbSBhIHJlZ3Jlc3Npb24gbW9kZWwgZml0dGVkIHBhcmFtZXRlcnMuIE1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kcyBhbmQgY2F1c2FsIGluZmVyZW5jZSBwcm9ibGVtcyBhcHBsaWVkIHRvIGVwaWRlbWlvbG9neSByZXF1aXJlcyB0byBnZW5lcmF0ZSB0aGUgcG9pbnQgZXN0aW1hdGVzIGZyb20gYXN5bXB0b3RpY2FsbHkgbGluZWFyIHBhcmFtZXRlcnMgZGVyaXZlZCBhcyBmdW5jdGlvbmFscyB0aGF0IGFyZSBhcHByb3hpbWF0ZWQgYnkgYXZlcmFnZXMsIGJ1dCB0aGUgc3RhbmRhcmQgZXJyb3Igb2YgdGhlc2UgcG9pbnQgZXN0aW1hdGVzIGFyZSBub3Qgc28gZWFzaWx5IGNhbGN1bGF0ZWQgd2l0aCBhbmFseXRpY2FsIGZvcm1zLiBUaGVyZWZvcmUsIHdlIG5lZWQgdG8gYXBwcm94aW1hdGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc3RhbmRhcmQgZXJyb3IgZm9yIHN0YXRpc3RpY2FsIGluZmVyZW5jZSB1c2luZyB0aGUgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QgYmFzZWQgb24gdGhlIGluZmx1ZW5jZSBjdXJ2ZS4gVGhlIHZlbnVlIG9mIG5ldyBtZXRob2RzIGFuZCB0ZWNobmlxdWVzIHJlcXVpcmVzIGEgY29uc3RhbnQgdXBkYXRlIG9uIHZhbGlkIHN0YXRpc3RpY2FsIGluZmVyZW5jZSBmb3IgYXBwbGllZCBlcGlkZW1pb2xvZ2lzdHMgYW5kIHN0YXRpc3RpY2lhbnMuIEluIHRoaXMgdHV0b3JpYWwgd2UgaW50cm9kdWNlIHRoZSB1c2Ugb2YgdGhlIGNsYXNzaWNhbCBhbmQgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QgYW5kIGl0cyBsaW5rIHRvIHRoZSBJbmZsdWVuY2UgQ3VydmUgaW4gRXBpZGVtaW9sb2d5IGZyb20gYSBwcmFjdGljYWwgcGVyc3BlY3RpdmUuIFdlIHByb3ZpZGVkIGEgbW9zdGx5IGFwcGxpZWQgb3ZlcnZpZXcgb2YgdGhlIGNsYXNzaWNhbCBhbmQgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QsIHRoZSBpbmZsdWVuY2UgY3VydmUgYW5kIHRoZSBib290c3RyYXAgaW5jbHVkaW5nIGVhc3kgdG8gdW5kZXJzdGFuZCBSIGNvZGUgYW5kIGV4YW1wbGVzIGJhc2VkIG9uIGNhbmNlciBlcGlkZW1pb2xvZ3kgdGhhdCBtYXkgaGVscCB0byBmaWxsIHRoaXMgZ2FwLiAKCioqS2V5d29yZHMqKjogU3RhdGlzdGljYWwgaW5mZXJlbmNlOyBCb290c3RyYXA7IERlbHRhLW1ldGhvZDsgRXBpZGVtaW9sb2d5OyBDYXVzYWwgSW5mZXJlbmNlOyBUdXRvcmlhbC4KCiMgSW50cm9kdWN0aW9uCgpBIGZ1bmRhbWVudGFsIHByb2JsZW0gaW4gaW5mZXJlbnRpYWwgc3RhdGlzdGljcyBpcyB0byBhcHByb3hpbWF0ZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGEgc3RhdGlzdGljIGNhbGN1bGF0ZWQgZnJvbSBhIHByb2JhYmlsaXR5IHNhbXBsZSBvZiBkYXRhLiBUaGUgc3RhdGlzdGljIGlzIHVzdWFsbHkgYSBwYXJhbWV0ZXIgZXN0aW1hdGUgdGhhdCBjaGFyYWN0ZXJpemVzIHRoZSBzYW1wbGluZyB2YXJpYWJpbGl0eSBvZiB0aGUgZXN0aW1hdGUgW0BCb29zMjAxM10uIEJlY2F1c2UgdGhlIG51bWJlciBhbmQgdHlwZSBvZiBpbmZlcmVuY2UgcHJvYmxlbXMgZm9yIHdoaWNoIGV4YWN0IHBhcmFtZXRyaWMgZGlzdHJpYnV0aW9ucyBjYW4gYmUgZGV0ZXJtaW5lZCBpcyBsaW1pdGVkIHRoZSBhcHByb3hpbWF0aW9uIG9mIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHN0YXRpc3RpYyBpcyBuZWNlc3NhcnkuIEFwcHJveGltYXRlIGluZmVyZW5jZSB2aWEgZGV0ZXJtaW5hdGlvbiBvZiB0aGUgYXN5bXB0b3RpYyBkaXN0cmlidXRpb24gb2YgdGhlIHN0YXRpc3RpY3MgaXMgYSB0ZWNobmlxdWUgdGhhdCBlcGlkZW1pb2xvZ2lzdHMgYW5kIGFwcGxpZWQgc3RhdGlzdGljaWFucyB1c2Ugcm91dGluZWx5LCB3ZSBuYW1lIGl0IHRoZSBkZWx0YS1tZXRob2QuIFRoZSBkZWx0YS1tZXRob2QgaXMgYSB0aGVvcmVtIHdoaWNoIHN0YXRlcyB0aGF0IGEgc21vb3RoIGZ1bmN0aW9uIG9mIGFuIGFzeW1wdG90aWNhbGx5IG5vcm1hbCBlc3RpbWF0b3IgaXMgYWxzbyBhc3ltcHRvdGljYWxseSBub3JtYWxseSBkaXN0cmlidXRlZC4gSXQgY2FuIGFsc28gYmUgdmlld2VkIGFzIGEgdGVjaG5pcXVlIGZvciBhcHByb3hpbWF0aW5nIHZhcmlhbmNlIG9mIGEgZnVuY3Rpb25hbCBpLmUuLCBhIG5vbmxpbmVhciBmdW5jdGlvbiBvZiBhIHJhbmRvbSB2YXJpYWJsZSB0aGF0IGNhbiBiZSBhcHByb3hpbWF0ZWQgYnkgYXZlcmFnZXMgW0BBcm1pMjAwNTsgQEJvb3MyMDEzXS4gCgpPZnRlbiBpbiBhZGRpdGlvbiB0byByZXBvcnRpbmcgcGFyYW1ldGVycyBmaXQgYnkgYSBtb2RlbCwgd2UgbmVlZCB0byByZXBvcnQgc29tZSBtYXJnaW5hbCBhc3ltcHRvdGljYWxseSBsaW5lYXIgdHJhbnNmb3JtYXRpb24gb2YgdGhlc2UgcGFyYW1ldGVycy4gVGhlIHRyYW5zZm9ybWF0aW9uIGNhbiBnZW5lcmF0ZSB0aGUgcG9pbnQgZXN0aW1hdGVzIG9mIG91ciBkZXNpcmVkIHZhbHVlcywgYnV0IHRoZSBzdGFuZGFyZCBlcnJvciAoU0UpIG9mIHRoZXNlIHBvaW50IGVzdGltYXRlcyBhcmUgbm90IHNvIGVhc2lseSBjYWxjdWxhdGVkIHdpdGggYW5hbHl0aWNhbCBmb3Jtcy4gVGhlcmVmb3JlLCB3ZSBuZWVkIHRvIGFwcHJveGltYXRlIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIFNFIGZvciBzdGF0aXN0aWNhbCBpbmZlcmVuY2UgdXNpbmcgdGhlIGRlbHRhLW1ldGhvZCBbQEJvb3MyMDEzXSBmb3IgbGFyZ2Ugc2FtcGxlcywgb3Igb3RoZXIgY29tcHV0YXRpb25hbCBtZXRob2RzIHN1Y2ggYXMgdGhlIGJvb3RzdHJhcCBbQEVmcm9uMTk5MzsgQGVmcm9uMTk4Ml0uIEZvciBpbnN0YW5jZSwgaW4gZXBpZGVtaW9sb2d5IHdlIHVzZSByb3V0aW5lbHkgdGhlIGRlbHRhLW1ldGhvZCB0byBjb21wdXRlIHRoZSBTRSBvZiBmdW5jdGlvbmFscyBhcyB0aGUgcmlzayBkaWZmZXJlbmNlIChSRCksIHRoZSByaXNrIHJhdGlvIChSUiksIGFuZCB0aGUgb2RkcyByYXRpbyAoT1IpIFtAQWdyZXN0aTIwMTBdLgoKTW9yZSByZWNlbnRseSBmb3IgY2F1c2FsIGluZmVyZW5jZSB3ZSBjb21wdXRlIHRoZSBhdmVyYWdlIHRyZWF0bWVudCBlZmZlY3QgKEFURSkgdXNpbmcgRy1jb21wdXRhdGlvbiwgYSBnZW5lcmFsaXphdGlvbiBvZiB0aGUgc3RhbmRhcmRpemF0aW9uLCBhbW9uZyBvdGhlciBlc3RpbWF0aW9ucyB0ZWNobmlxdWVzIGFzIHRoZSBpbnZlcnNlIHByb2JhYmlsaXR5IG9mIHRyZWF0bWVudCB3ZWlnaHRzIFtAUnViaW4yMDA3XS4gVGhlIEFURSBpcyBkZWZpbmVkIGJ5IGFuIGF2ZXJhZ2Ugd2hpY2ggaXMgYSBmdW5jdGlvbiBvZiB0d28gcmFuZG9tIHZhcmlhYmxlcyAoaS5lLiwgdGhlIHBvdGVudGlhbCBvdXRjb21lcyBZKDEpIGFuZCBZKDApKSBbQFJ1YmluMjAwNzsgQEd1dG1hbjIwMTVdLiBUaGVzZSB0d28gcmFuZG9tIHZhcmlhYmxlcyBhcmUgcHJlZGljdGVkIGZyb20gdGhlIGNvZWZmaWNpZW50cyBvZiB0aGUgcGFyYW1ldGVycyBmaXR0ZWQgaW4gdHdvIGRpZmZlcmVudCByZWdyZXNzaW9uIG1vZGVscyBbQHJvYmluczE5ODZdLiBUaGUgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QgYXBwbGllZCB0byBhbiBlc3RpbWF0b3IgaW1wbGljaXRseSBkZWZpbmVkIGJ5IGF2ZXJhZ2VzLCBhbHNvIGtub3duIGFzIE0tZXN0aW1hdG9yLCBjYW4gYmUgdXNlZCB0byBhcHByb3hpbWF0ZSB0aGUgdmFyaWFuY2Ugb2YgdGhlIGVzdGltYXRvciAoaS5lLiwgRy1jb21wdXRhdGlvbiBmb3IgdGhlIEFURSkgW0BCb29zMjAxMzsgQGtlbm5lZHkyMDE2OyBAa2VubmVkeTIwMTddIGluIGFkZGl0aW9uIHRvIHRoZSBib290c3RyYXAgW0BFZnJvbjE5OTM7IEBlZnJvbjE5ODJdLiBTZW1pLXBhcmFtZXRyaWMgYW5kIEVtcGlyaWNhbCBQcm9jZXNzIHRoZW9yeSBpcyBuZWVkZWQgdG8gZXN0aW1hdGUgdGhlIFNFIG9mIHRoZSBBVEUgdXNpbmcgdGhlIGZ1bmN0aW9uYWwgZGVsdGEtbWV0aG9kIHVuZGVyIHNvbWUgdGhlb3JldGljYWwgYXNzdW1wdGlvbnMgKGkuZS4sIHRoZSBlc3RpbWF0b3IgdXNlZCB0byBkZXJpdmUgdGhlIEFURSBtdXN0IGJlIHBhdGh3aXNlIGRpZmZlcmVudGlhYmxlIGFuZCBhc3ltcHRvdGljYWxseSByZWd1bGFyIGFuZCBsaW5lYXIgW0BCb29zMjAxMzsgQGtlbm5lZHkyMDE2OyBAa2VubmVkeTIwMTddLiBXZSwgYXBwbGllZCBzdGF0aXN0aWNpYW5zIGFuZCBlcGlkZW1pb2xvZ2lzdHMsIHNob3VsZCBrbm93biBob3cgdG8gZGV0ZXJtaW5lIHdoZW4gYSBsYXJnZSBzYW1wbGUgYXBwcm94aW1hdGlvbiB0byB0aGUgZGlzdHJpYnV0aW9uIG9mIGEgc3RhdGlzdGljIGlzIGFwcHJvcHJpYXRlLCBob3cgdG8gZGVyaXZlIHRoZSBhcHByb3hpbWF0aW9uLCBhbmQgaG93IHRvIHVzZSBpdCBmb3IgaW5mZXJlbmNlIGFwcGxpY2F0aW9ucy4KCkluIHRoaXMgdHV0b3JpYWwgd2UgaW50cm9kdWNlIHRoZSB1c2Ugb2YgdGhlIGNsYXNzaWNhbCBhbmQgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QgYW5kIGl0cyBsaW5rIHRvIHRoZSBJbmZsdWVuY2UgQ3VydmUgKElDKSBpbiBFcGlkZW1pb2xvZ3kgZnJvbSBhIHByYWN0aWNhbCBwZXJzcGVjdGl2ZSBpbmNsdWRpbmcgYm94ZXMgd2l0aCBjb2RlIGluIFIgc3RhdGlzdGljYWwgc29mdHdhcmUgKFIgRm91bmRhdGlvbiBmb3IgU3RhdGlzdGljYWwgQ29tcHV0aW5nLCBWaWVubmEsIEF1c3RyaWEpIFtAUjIwMjBdIHRvIGFsbG93IHJlYWRlcnMgbGVhcm5pbmcgYnkgZG9pbmcuIEluIHNlY3Rpb24gdHdvIHdlIGludHJvZHVjZSBzb21lIGJhc2ljIG5vdGF0aW9uIGZvciB0aGUgZGVsdGEtbWV0aG9kIGFuZCBkZXJpdmUgdGhlIFNFIGZvciB0aGUgYSBzYW1wbGUgbWVhbiBvZiBhbiBpbmRlcGVuZGVudCB2YXJpYWJsZSBhbmQgdGhlIHJhdGlvIG9mIHR3byBtZWFucyBvZiB0d28gaW5kZXBlbmRlbnQgdmFyaWFibGVzLiBJbiBzZWN0aW9uIHRocmVlIHdlIGRlcml2ZSB0aGUgU0UgZm9yIHRoZSBjbGFzc2ljYWwgZXBpZGVtaW9sb2dpY2FsIG1lYXN1cmVzIG9mIGFzc29jaWF0aW9uLiBJbiBzZWN0aW9uIGZvdXIgd2UgaW50cm9kdWNlIGFuIGVtcGlyaWNhbCBleGFtcGxlIHRvIGRlcml2ZSB0aGUgU0UgZm9yIGEgc2luZ2xlIHByb3BvcnRpb24sIHRoZSBjb25kaXRpb25hbCBvZGRzIHJhdGlvIGFuZCByZWxhdGl2ZSByaXNrLCBhbmQgZmluYWxseSBhIG1hcmdpbmFsIGNhdXNhbCByaXNrIHJhdGlvIGVzdGltYXRlZCB1c2luZyB0aGUgYXVnbWVudGVkIGludmVyc2UgcHJvYmFiaWxpdHkgb2YgdHJlYXRtZW50IHdlaWdodHMgZXN0aW1hdG9yLiBUaGVuLCBpbiBzZWN0aW9uIGZpdmUgd2UgY29udHJhc3QgdGhlIGZ1bmN0aW9uYWwgZGVsdGEtbWV0aG9kIHdpdGggdGhlIGJvb3RzdHJhcCBhcHByb2FjaCBhbmQgZmluaXNoIHRoZSBhcnRpY2xlIGluIHNlY3Rpb24gZml2ZSB3aXRoIHNvbWUgYXBwbGllZCBjb25jbHVzaW9ucy4KCiMgVGhlIGRlbHRhLW1ldGhvZAoKIyMgVGhlIGNsYXNzaWNhbCBkZWx0YS1tZXRob2QKCkVzc2VudGlhbGx5LCB0aGUgZGVsdGEtbWV0aG9kIGludm9sdmVzIGNhbGN1bGF0aW5nIHRoZSBleHBhbnNpb24gdXAgdG8gdGhlIGZpcnN0IG9yZGVyIG9mIGEgVGF5bG9yIHNlcmllcyBhcHByb3hpbWF0aW9uIG9mIGEgZnVuY3Rpb24gKGYpIFtASGVyYmVyZzE5NjJdIHRvIGRlcml2ZSB0aGUgZW1waXJpY2FsIHZhbHVlIGFuZCB0aGUgU0Ugb2YgYW4gZXN0aW1hdG9yIChTZWUgYXBwZW5kaXggZm9yIHRoZSBkZWx0YS1tZXRob2QgdGhlb3JlbSBmcm9tIFNlcmZsaW5nLCAxOTgwLCBDaC4zKS4gV2hlbiBhIHN0YXRpc3RpYyBjYW4gYmUgYXBwcm94aW1hdGUgYnkgYW4gYXZlcmFnZSwgdGhlIGFwcHJveGltYXRpbmcgYXZlcmFnZSBpcyB1c3VhbGx5IGFuIGF2ZXJhZ2Ugb2Ygc29tZSBmdW5jdGlvbiAoZikgb2YgdGhlIHNhbXBsZSB2YWx1ZXMgYW5kIGNhbiBiZSB3cml0dGVuIGluIHRoZSBmb3JtOgoKClxbZihcaGF0XHRoZXRhKS1mKFx0aGV0YSlcO1xhcHByb3hcO2YnKFx0aGV0YSkoXGhhdFx0aGV0YVwsLVwsXHRoZXRhKVwsK1wsXHRleHR7T3B9XGxlZnQoXGZyYWN7MX17XHNxcnQobil9XHJpZ2h0KSAuXF0KCldoZXJlIFwoZihcaGF0XHRoZXRhKSlcKSBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgdGhlIGxhcmdlIHNhbXBsZSBzdG9jaGFzdGljIGxpbWl0IG9mIFwoKGYoXHRoZXRhKSlcKSBhbmQgXChmJyhcdGhldGEpKFxoYXRcdGhldGFcLC1cLFx0aGV0YSlcKSBpcyBhIGZ1bmN0aW9uIGNhbGxlZCB0aGUKSW5mbHVlbmNlIEN1cnZlIChJQykuIFRoZSByZW1haW5kZXIgXChcdGV4dHtPcH0oXGZyYWN7MX17XHNxcnQobil9KVwpIGlzCm5lZ2xpZ2libHkgc21hbGwgYXMgdGhlIHNhbXBsZSBzaXplIGluY3JlYXNlcyBhcyBhc3ltcHRvdGljYWxseSBjb252ZXJnZXMgdG8gemVybyBbQEJvb3MyMDEzXS4KClNvIHRoZSByZW1haW5kZXIgY29udmVyZ2VzIHRvIHplcm8KClxbXHRleHR7T3B9XGxlZnQoXGZyYWN7MX17XHNxcnQobil9XHJpZ2h0KSBccmlnaHRhcnJvdyAwIFw7LFx0ZXh0e2FuZH1cXQoKdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgXChcdGhldGFcKSBjb252ZXJnZXMgaW4gcHJvYmFiaWxpdHkgdG8gYSBub3JtYWxseSBkaXN0cmlidXRlZApyYW5kb20gdmFyaWFibGUgd2l0aCBtZWFuIHplcm8gYW5kIGZpbml0ZSB2YXJpYW5jZSB3aGVuIHRoZSBzYW1wbGUgc2l6ZSBuIGdvZXMgdG8gaW5maW5pdHkuCgpcW1xzcXJ0KG4pXGxlZnQoZihcaGF0XHRoZXRhKS1mKFx0aGV0YSlccmlnaHQpXDsgXHJpZ2h0YXJyb3cgTigwXCwsdmFyKFx0aGV0YSkpLlxdCgpUaGVyZWZvcmUsIHN1cHBvc2UgdGhhdCBcKChcaGF0XHRoZXRhKVwpIGlzIGEgc2FtcGxlIG1lYW4gYW5kIGYgaXMgYSBzbW9vdGggc2NhbGFyIHZhbHVlZCBmdW5jdGlvbi4gVGhlbiwgdGhlIG1lYW4gb2YgYW4gZXN0aW1hdG9yIFwoZihcaGF0XHRoZXRhKVwpIGNhbiBiZSBhcHByb3hpbWF0ZSB3aXRoIHRoZSBwb3B1bGF0aW9uIG1lYW4gXChmKFx0aGV0YSlcKSBwbHVzIHRoZSBJQyBlc3RpbWF0ZWQgYXMgdGhlIGZpcnN0IGRlcml2YXRpdmUgb2YgdGhlIGVzdGltYXRvciB0aW1lcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBzYW1wbGUgcG9wdWxhdGlvbiBtZWFuIG1pbnVzIHRoZSBtZWFuIG9mIHRoZSBlc3RpbWF0b3IgYXBwcm94aW1hdGVkIHVzaW5nIHRoZSBkZWx0YS1tZXRob2Q6CgpcW2YoXGhhdFx0aGV0YSkgXGFwcHJveFw7ZihcdGhldGEpXCwrXCxmJyhcdGhldGEpKFxoYXRcdGhldGFcLC1cLFx0aGV0YSlcOygxKVxdCgpUaGVuIHdlIGhhdmUgZm9yIHRoZSBzYW1wbGUgbWVhbgoKXFtmKFxiYXJ7WX0pIFxhcHByb3hcOyBmKFxtdSlcLCtcLGYnKFxtdSkoXGJhcntZfVwsLVwsXG11KVwsPVwsIG5eey0xfSBcc3VtXCwgKFxtdSlcLCtcLGYnKFxtdSkoXGJhcntZX3tpfX1cLC1cLFxtdSksXF0KCk5vdyBsZXRzIHN1cHBvc2UgdGhhdCB3ZSB3YW50IHRvIGNvbnNpZGVyIGEgcGFpciBvZiBpbmRlcGVuZGVudCBpZGVudGljYWxseSBkaXN0cmlidXRlZCAoaWlkKSByYW5kb20gc2FtcGxlIG1lYW5zIChpLmUuLCBZMSBhbmQgWTIpIGFuZCB3ZSB3YW50IHRvIGRlcml2ZSB0aGUgU0UgZm9yIHRoZSByYXRpbyBlc3RpbWF0b3IgXCgoZihcYmFye1l9KVwsPVwsXGJhcntZfV97MX0vXGJhcntZfV97Mn0pXCkgd2hlcmUgXCgoXG11X3syfVxuZXFcLDApXCkuIEluIHRoaXMgY2FzZSB0aGUgSUMgZm9yIHRoZSByYXRpbyB3aWxsIGJlIGVzdGltYXRlZCBhcyBmb2xsb3dzOgoKXFtmJyhcbXUpXCw9XCwgXGZyYWN7MX17XG11X3sxfX1cLC1cLFxmcmFje1xtdV97MX19e1xtdV97Mn1eezJ9fS5cXSAKClRoZXJlZm9yZSB0aGUgSUMgaXMgZ2l2ZW4KClxbSUMgPSBcZnJhY3sxfXtcbXVfezF9fXt9KFxiYXJ7WX1fe2kxfVwsLVwsXG11X3sxfSlcLC1cLFxmcmFje1xtdV97MX19e1xtdV97Mn1eezJ9fShcYmFye1l9X3tpMn1cLC1cLFxtdV97Mn0pXF0KCgojIyBUaGUgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QKCkEgZnVuY3Rpb24gaW4gbWF0aGVtYXRpY2FsIHN0YXRpc3RpY3MgaXMgZGVmaW5lZCBieSBhIHJ1bGUsIHdoaWNoIGFzc29jaWF0ZXMgYSBudW1iZXIgd2l0aCBhIGZ1bmN0aW9uIG9mIG9uZSBvciBzZXZlcmFsIHZhcmlhYmxlcyAoaS5lLCB0aGUgcHJlZGljdGlvbnMgb2YgdGhlIGxpbmVhciBjb21iaW5hdGlvbnMgb2YgdGhlIGNvZWZmaWNpZW50cyBmcm9tIHJlZ3Jlc3Npb24gbW9kZWxzKS4gSW4gb3JkZXIgdG8gZXhwbG9yZSB0aGUgcHJvcGVydGllcyBvZiB0aGUgZnVuY3Rpb25hbHMgYSBnZW5lcmFsaXphdGlvbiBvZiB0aGUgKG9yZGluYXJ5IG9yIHBhcnRpYWwpIGRlcml2YXRpdmUgaXMgcmVxdWlyZWQsIG5hbWVkIHRoZSBmdW5jdGlvbmFsIGRlcml2YXRpdmUuIEl0IGNhbiBiZSBkZWZpbmVkIHZpYSB0aGUgdmFyaWF0aW9uIFwoXGRlbHRhIGZcKSBvZiB0aGUgZnVuY3Rpb25hbCB3aGljaCByZXN1bHRzIGZyb20gdmFyaWF0aW9uIG9mIHRoZSBmdW5jdGlvbiBieSBcKFxkZWx0YSBmXCkuIFRodXMsIGl0IGltcGxpZXMgdGhhdCB0aGUgZnVuY3Rpb24gbXVzdCBiZSBkaWZmZXJlbnRpYWJsZSBhbmQgYXN5bXB0b3RpY2FsbHkgbGluZWFyIChpLmUsIGNvbnRpbnVvdXMpLiAKCldoZW4gd2UgaGF2ZSBtb3JlIHRoYW4gdHdvIGlpZCByYW5kb20gdmFyaWFibGVzIHRoYXQgbWFwIHRvIGEgZnVuY3Rpb24sIHdlIGFsc28gZ2V0IHRoZSBUYXlsb3Igc2VyaWVzIGFwcHJveGltYXRpb24gb2YgdGhlIGZ1bmN0aW9uIHVzaW5nIHRoZSBmaXJzdCB0d28gdGVybXMgb2YgdGhlIGV4cGFuc2lvbiBvZiBhIGZ1bmN0aW9uYWwgYWJvdXQgdGhlIG1lYW4sIGJ1dCB3ZSBuZWVkIHRvIGNvbXB1dGUgYSB2ZWN0b3Igb2YgcGFydGlhbCBkZXJpdmF0aXZlcyBhbG9uZyBvbmUgZGlyZWN0aW9uIG9mIHRoZSBmdW5jdGlvbmFsLiBXZSBjYW4gdGhlbiB0YWtlIHRoZSB2YXJpYW5jZSBvZiB0aGlzIGFwcHJveGltYXRpb24gdG8gZXN0aW1hdGUgdGhlIHZhcmlhbmNlIG9mIFwoXGJvbGRzeW1ib2xcdGhldGFcKSBhbmQgdGh1cyB0aGUgU0Ugb2YgYSB0cmFuc2Zvcm1lZCBmdW5jdGlvbmFsIHBhcmFtZXRlci4gVGhlIGZpcnN0IHR3byB0ZXJtcyBvZiB0aGUgVGF5bG9yIGV4cGFuc2lvbiBhcmUgdGhlbiBhbiBhcHByb3hpbWF0aW9uIGZvciBcKFxib2xkc3ltYm9se1xoYXRcdGhldGF9XCkgYXMgZm9sbG93czoKClxbZihcYm9sZHN5bWJvbHtcaGF0XHRoZXRhfSkgXGFwcHJveFwsIGYoXGJvbGRzeW1ib2xcdGhldGEpIFwsK1wsXG5hYmxhKFxib2xkc3ltYm9sXHRoZXRhKV5UXCwoXGJvbGRzeW1ib2x7XGhhdFx0aGV0YX1cLC1cLFxib2xkc3ltYm9sXHRoZXRhKVw7ICgyKS5cXQoKClxbXHRleHR7VmFyfShcYm9sZHN5bWJvbHtcaGF0XHRoZXRhfSkgXGFwcHJveFw7IFxuYWJsYShcYm9sZHN5bWJvbFx0aGV0YSlcdGV4dHtDb3Z9KFxib2xkc3ltYm9sXHRoZXRhKSBcbmFibGEoXGJvbGRzeW1ib2xcdGhldGEpXntUfVw7ICgzKS5cXQoKCldoZXJlIENvdihcKFxib2xkc3ltYm9sXHRoZXRhXCkpIGlzIHRoZSB2YXJpYW5jZS1jb3ZhcmlhbmNlIG1hdHJpeCBvZiBcKFx0aGV0YVwpIFtAQm9vczIwMTNdLiBUaGUgdmFyaWFuY2UgZm9ybXVsYSBpbiAoMykgaXMgYWxzbyBrbm93biBhcyB0aGUgIkh1YmVyIFNhbmR3aWNoIEVzdGltYXRvciIgdGhhdCBvZnRlbiBpcyB1c2VkIHRvIGVzdGltYXRlIHRoZSB2YXJpYW5jZSBvZiB0aGUgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRpb24gd2hlbiB0aGUgdW5kZXJseWluZyBtb2RlbCBpcyBtaXNzcGVjaWZpZWQuIFtARnJlZG1hbjIwMDZdIEluIHN1bW1hcnksIGZvciBhbiBvYnNlcnZlZCBkYXRhIFwoXHRleHR7T31faVwpLCAoaSA9IDEsICRcbGRvdHMkLCBuKSBhbiBhc3ltcHRvdGljYWxseSBsaW5lYXIgZXN0aW1hdG9yIG9mIFwoXGhhdFx0aGV0YVwpIGNhbiBiZSBldmFsdWF0ZWQgYXMgZm9sbG93czoKClxbXGhhdFx0aGV0YVw7PVw7XHRoZXRhXCwrXCxcZnJhY3sxfXtcc3FydHtufX1cc3VtX3tpPTF9Xm4gKFx0ZXh0e0lDfV97aX0pXCwrXCxcdGV4dHtPcH0oXGZyYWN7MX17XHNxcnQobil9KVwsLlxdCgpXaGVyZSBcKFx0aGV0YVwpIGlzIHRoZSBwbHVnLWluIGVzdGltYXRvciBvZiBhIHJlYWwgdmFsdWUgZGlmZmVyZW50aWFibGUgZnVuY3Rpb24gKGkuZS4sIGVtcGlyaWNhbCBzYW1wbGUgbWVhbikgZXZhbHVhdGVkIGF0IFwoXHRoZXRhXCkgcGx1cyB0aGUgSUMgcmVwcmVzZW50ZWQgYXMgdGhlIHNhbXBsZSBtZWFuIG9mIGEgZml4ZWQgZnVuY3Rpb24gcGx1cyBhIHJlbWFpbmRlciB0ZXJtIHRoYXQgbXVzdCBjb252ZXJnZSB0byAwIGF0IGEgcmF0ZSBmYXN0ZXIgdGhhbiBcKFxmcmFjezF9e1xzcXJ0e259fVwpLiBbQFZhYXJ0OThdIE5vdGUgdGhhdCB0aGUgSUMgbWVhc3VyZXMgdGhlIGluZmx1ZW5jZSBvZiB0aGUgc2FtcGxlIG9ic2VydmF0aW9ucyBvbiB0aGUgZXN0aW1hdG9yLiBQbG90dGluZyB0aGUgSUMgcHJvdmlkZXMgYSB0b29sIHRvIGRpc2NvdmVyIG91dGxpZXJzIGFuZCB0ZWxscyB1cyBob3cgcm9idXN0IGlzIHRoZSBlc3RpbWF0b3IuIE1vc3QgaW1wb3J0YW50bHksIHRoZSBlc3RpbWF0ZWQgSUMgcHJvdmlkZXMgYW4gYXN5bXB0b3RpYyB2YXJpYW5jZSBlc3RpbWF0ZSBmb3IgdGhlIGFzeW1wdG90aWNhbGx5IGxpbmVhciBlc3RpbWF0b3IuIFRoZXJlZm9yZSwgd2UgY2FuIHJlYWRpbHkgYXBwbHkgdGhlIFx0ZXh0YmZ7Q2VudHJhbCBMaW1pdCBUaGVvcmVtfSAoQ0xUKSB0byBjb21wdXRlIFxlbXBoe1dhbGR9IHR5cGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgW0NJXSkuW0B2YW4yMDExXQoKSW4gYm94IDEgd2UgY29tcHV0ZSB0aGUgU0UgZm9yIGEgc2FtcGxlIG1lYW4gdXNpbmcgdGhlIGNsYXNzaWNhbCBkZWx0YS1tZXRob2QgYmFzZWQgb24gdGhlIElDIGFuZCB3ZSBjb21wYXJlIHRoZSByZXN1bHRzIHdpdGggdGhlIGRlbHRhLW1ldGhvZCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgUiBwYWNrYWdlIE1TTSBbQGthdnJvdWRha2lzMjAxNV0uCgoqKkJveCAxLiBEZWx0YS1tZXRob2QgZm9yIHRoZSBzYW1wbGUgbWVhbiBhbmQgSUMgdmlzdWFsaXphdGlvbiBpbiBSKioKCmBgYHtyLCBtZXNzYWdlID0gRkFMU0V9CiMgTS1lc3RpbWF0aW9uIGZvciB0aGUgc2FtcGxlIG1lYW4KIyBEYXRhIGdlbmVyYXRpb24Kc2V0LnNlZWQoNzc3NykKbiA8LSAxMDAwCnggPC0gcnVuaWYobiwwLDEpCm14ID0gbWVhbih4KQoKIyBGdW5jdGlvbmFsIGRlbHRhLW1ldGhvZDogaW5mbHVlbmNlIGN1cnZlIGZvciB0aGUgc2FtcGxlIG1lYW4gKGZpcnN0IGRlcml2YXRpdmU9MShjb25zdGFudCkpCklDID0gMSAqICh4IC0gbXgpCgojIE0tZXN0aW1hdGlvbiBvZiB0aGUgc2FtcGxlIG1lYW4KWWhhdCA8LSB4ICsgSUMgIyBQbHVnaW5nIGVzdGltYXRvcgpZaGF0IDwtIG1lYW4oWWhhdCk7IFloYXQKCiMgR2VvbWV0cnkgb2YgdGhlIElDCnBsb3QoeCwgSUMpCgojIFN0YW5kYXJkIEVycm9yOiBJbmZsdWVuY2UgQ3VydmUKdmFyWWhhdC5JQyA8LSB2YXIoSUMpL247CnNlSUMgPC0gc3FydCh2YXJZaGF0LklDKQoKIyBBc3ltcHRvdGljIGxpbmVhciBpbmZlcmVuY2UgOTUlIENvbmZpZGVuY2UgSW50ZXJ2YWxzClloYXRfQ0kgPC0gYyhtZWFuKFloYXQpIC0gMS45NipzcXJ0KHZhclloYXQuSUMpLCBtZWFuKFloYXQpICsgMS45NipzcXJ0KHZhclloYXQuSUMpKTsgCm1lYW4oWWhhdCk7IFloYXRfQ0kKCiMgQ2hlY2sgd2l0aCBpbXBsZW1lbnRlZCBkZWx0YS1tZXRob2QgaW4gbGlicmFyeSBNU00gCmxpYnJhcnkobXNtKQpzZSA9IGRlbHRhbWV0aG9kKGc9IH54MSwgbWVhbj0gbXgsIGNvdj0gdmFyWWhhdC5JQykKcHJpbnQoc2UpCnNlSUMKCiMgQ2hlY2sgOTUlQ0kgZGVsdGEtbWV0aG9kIGNvbXB1dGVkIGJ5IGhhbmQgd2l0aCBkZWx0YS1tZXRob2QgaW1wbGVtZW50ZWQgaW4gUmNtZHJNaXNjIGxpYnJhcnkKWWhhdF9DSSA8LSBjKG1lYW4oWWhhdCkgLSAxLjk2KnNxcnQodmFyWWhhdC5JQyksIG1lYW4oWWhhdCkgKyAxLjk2KnNxcnQodmFyWWhhdC5JQykpOyAKbWVhbihZaGF0KTsgWWhhdF9DSQoKbGlicmFyeShSY21kck1pc2MpCkRlbHRhTWV0aG9kKGxtKHggfiAxKSwgImIwIikKYGBgCgojIENsYXNzaWNhbCBkZWx0YS1tZXRob2QgZm9yIGNvbW1vbiBtZWFzdXJlcyBvZiBhc3NvY2lhdGlvbiBpbiBlcGlkZW1pb2xvZ3kKCldlIHVzZSB0aGUgY2xhc3NpY2FsIDIgYnkgMiBlcGlkZW1pb2xvZ2ljYWwgdGFibGUsIHByZXNlbnRpbmcgb3V0Y29tZSBjb3VudHMgYnkgdGhlIGxldmVscyBvZiBhIHJpc2sgZmFjdG9yLCB0byBkZXJpdmUgdGhlIFNFIGZvciB0aGUgcmlzayBkaWZmZXJlbmNlcyAoUkQpLCByaXNrIHJhdGlvIChSUiksIGFuZCBvZGRzIHJhdGlvIChPUikgdXNpbmcgdGhlIGRlbHRhLW1ldGhvZC4KCnwgUmlzayAgICAgIHwgQWxpdmUgfCBEZWFkIHwKfC0tLS0tLS0tLS0tfC0tLS0tLS18LS0tLS0tfAp8IEV4cG9zZWQgICB8ICRuX3sxMX0gPSAocF8xKSQgICAgIHwgJG5fezIxfSA9IChwXzIpJCAgICB8CnwgVW5leHBvc2VkIHwgJG5fezEyfSA9ICgxLXBfMSkkICAgICB8ICRuX3syMn0gPSAoMS1wXzIpJCAgICB8CnwgTiAgICAgICAgIHwgJE5fMSQgICAgIHwgJE5fMiQgICAgfAoKIyMgUmlzayBEaWZmZXJlbmNlCgpUaGUgcmlzayBkaWZmZXJlbmNlIChSRCkgaXMgZGVmaW5lZCBhcyBmb2xsb3dzIFtAUm90aG1hbjIwMDhdOgoKXFtcd2lkZWhhdHtSRH0gXCw9XCwgXGhhdCBcdGhldGFfezF9XCwtXCxcaGF0IFx0aGV0YV97Mn0gXCw9XCwgXGhhdCBwX3sxfVwsLVwsXGhhdCBwX3syfS5cXQoKQXNzdW1pbmcgdGhhdCB0aGUgcHJvYmFiaWxpdHkgb2YgdGhlIGV2ZW50IChcdGV4dGJme3B9KSBjYW4gYmUgbW9kZWxsZWQKdXNpbmcgYSBCaW5vbWlhbCBkaXN0cmlidXRpb24gd2l0aCByYW5nZSBcKDBcO1xsZXEgXHRleHR7cH0gXGxlcVw7MVwpLApleHBlY3RhdGlvbiBvZiBwIGlzIEUoXChcdGhldGFcKSkgPSBwLCBhbmQgdGhlIHZhcmlhbmNlIHZhcihcKFx0aGV0YVwpKSA9IHAoMS1wKS8gbiBbQFJvdGhtYW4yMDA4XS4gCgpVc2luZyB0aGUgZGVsdGEtbWV0aG9kIGluICgxKSBhbmQgc3Vic3RpdHV0aW5nIFwoKFxoYXRcdGhldGFcLC1cLFx0aGV0YSlcKSBmb3IgdGhlIHZhcmlhbmNlIG9mIFwodGhldGFcKSBpLmUuLCB2YXIoXChcdGhldGFcKSkgPSBwKDEtcCkvIG4sICB3ZSBjYW4gZGVyaXZlIHRoZSAgXChTRShcd2lkZWhhdHtSRH0pXCkgZm9yIGEgc2luZ2xlIHByb3BvcnRpb24gY29tcHV0aW5nIHRoZSBJQyBvZiB0aGUgcmlzayBkaWZmZXJlbmNlIGFzIGZvbGxvd3M6CgpcW1NFKFx3aWRlaGF0e1JEfVwsPWYnKFx0aGV0YSkodmFyKFx0aGV0YSkpXDs9XDsgMVwsXHRpbWVzXCxcc3FydHtcZnJhY3twKDEtcCl9e259fVxdCgpUaGVyZWZvcmUsIHRvIGVzdGltYXRlIHRoZSB2YXIoXChcd2lkZWhhdHtSRH1cKSkgZm9yIHRoZSByaXNrIGRpZmZlcmVuY2VzIHdlIHN1bSB0aGUgdmFyaWFuY2VzIHZhcihcKFxoYXQgXHRoZXRhX3sxfSlcKSArIHZhclwoKFxoYXRcdGhldGFfezJ9KVwpIGFzIGZvbGxvd3M6CgoKXFtTRShcd2lkZWhhdHtSRH0pXCw9XCwgXHNxcnR7XGZyYWN7KDEtXGhhdCBwX3sxfSl9e25fezF9fX1cLCtcLFxzcXJ0e1xmcmFjeygxLVxoYXQgcF97Mn0pfXtuX3syfX19XCw9XCxcc3FydHtcZnJhY3soMS1caGF0IHBfezF9KX17bl97MX19XCwrXCxcZnJhY3soMS1caGF0IHBfezJ9KX17bl97Mn19fVxdCgojIyBSaXNrIFJhdGlvCgoKU2ltaWxhcmx5IHRvIGVzdGltYXRlIHRoZSBTRSBmb3IgcmlzayByYXRpbyAoUlIpIHdlIGhhdmUKClxbXHdpZGVoYXR7UlJ9IFwsPVwsIFxmcmFje1xoYXQgXHRoZXRhX3sxfX17XGhhdCBcdGhldGFfezJ9fSBcLD1cLCBsb2dcbGVmdChcZnJhY3tcaGF0IHBfezF9fXtcaGF0IHBfezJ9fVxyaWdodClcLD1cLGxvZyhcaGF0IHBfezF9KSAtIGxvZyhcaGF0IHBfezJ9KVxdCgpOb3RlIHRoYXQgdGhlIGRlcml2YXRpdmUgb2YgdGhlIGxvZyhwKSBpcyBlcXVhbCB0byAxL3AuCgpUaGVuLCAKXFtTRShsb2coXGhhdHtcdGhldGF9KSlcLD1mJyhcdGhldGEpKHZhcihcdGhldGEpKVw7PVw7XGZyYWN7MX17cH1cc3FydHtcZnJhY3twKDEtcCl9e259fVwsPVwsXHNxcnR7XGZyYWN7KDEtcCl9e3BufX0sXDsgYW5kXF0KClxbU0UobG9nKFx3aWRlaGF0e1JSfSkpXCw9XCwgXHNxcnR7XGZyYWN7KDEtXGhhdCBwX3sxfSl9e1xoYXQgcF97MX1uX3sxfX19XCwrXCxcc3FydHtcZnJhY3soMS1caGF0IHBfezJ9KX17XGhhdCBwX3syfW5fezJ9fX1cLD1cLFxzcXJ0e1xmcmFjeygxLVxoYXQgcF97MX0pfXtcaGF0IHBfezF9bl97MX19XCwrXCxcZnJhY3soMS1caGF0IHBfezJ9KX17XGhhdCBwX3syfW5fezJ9fX1cXQoKIyMgT2RkcyBSYXRpbwoKU2ltaWxhcmx5IHRvIGVzdGltYXRlIHRoZSBTRSBmb3Igb2RkcyByYXRpbyAoT1IpIHdlIGhhdmUKClxbXHdpZGVoYXR7T1J9IFwsPVwsIFxmcmFje1xoYXQgXHRoZXRhX3sxfX17XGhhdCBcdGhldGFfezJ9fSBcLD1cLCBsb2dcbGVmdChcZnJhY3tcaGF0IHBfezF9LygxLVxoYXQgcF97MX0pfXtcaGF0IHBfezJ9LygxLVxoYXQgcF97Mn0pfVxyaWdodClcLD1cLGxvZ1xsZWZ0KFxmcmFje1x0ZXh0e259X3sxMX1cdGV4dHtufV97MjJ9fXtcdGV4dHtufV97MTJ9XHRleHR7bn1fezIxfX1ccmlnaHQpXCwsXF0KCk5vdGUgdGhhdCB0aGUgbG9nIG9mIHRoZSBvZGRzIFwoXGZyYWN7cH17MS1wfVwpIGlzIGVxdWFsIHRvIHRoZSBsb2cocCkgLSBsb2coMS1wKSBhbmQgdGhlcmVmb3JlIHRoZSBkZXJpdmF0aXZlIGlzIFwoXGZyYWN7MX17cCgxLXApfVwpLgoKVGhlbiwKClxbXHRleHR7U0V9KGxvZyhcaGF0e1x0aGV0YX0pKVwsPVwsZicoXHRoZXRhKSh2YXIoXHRoZXRhKSlcOz1cO1xmcmFjezF9e3AoMS1wKX1cc3FydHtcZnJhY3twKDEtcCl9e259fVwsPVwsXHNxcnR7XGZyYWN7MX17bn19XDssIGFuZFxdCgoKXFtcdGV4dHtTRX0obG9nKFx3aWRlaGF0e09SfSkpXCw9XCwgXHNxcnR7XGZyYWN7MX17bl97MTF9fVwsK1wsXGZyYWN7MX17bl97MTJ9fVwsK1wsXGZyYWN7MX17bl97MjF9fVwsK1wsXGZyYWN7MX17bl97MjJ9fX1cXQoKRmluYWxseSwgYWZ0ZXIgYXBwbHlpbmcgdGhlIGRlbHRhLW1ldGhvZCBhbmQgYXNzdW1pbmcgdGhlIGFzeW1wdG90aWNhbCBsaW5lYXIgcHJvcGVydGllcyBmb3IgdGhlIGVzdGltYXRvcnMgb2YgdGhlIHZhcmlhbmNlIGZvciB0aGUgZGlmZmVyZW50IG1lYXN1cmVzIG9mIGFzc29jaWF0aW9uLCB3ZSBjYW4gcmVhZGlseSBhcHBseSB0aGUgXHRleHRiZntDTFR9IGFuZCB0aGVyZWZvcmUgdG8gZGVyaXZlIHR5cGUgV2FsZCA5NVwlIENJIChpLmUuLCAxLjk2IFwoIFx0aW1lc1w7IFx0ZXh0e1NFfVw7IChcaGF0XHRoZXRhKVwpKSBmb3IgdGhlIGRpZmZlcmVudCBlcGlkZW1pb2xvZ2ljYWwgbWVhc3VyZXMgb2YgYXNzb2NpYXRpb24uCgojIEVtcGlyaWNhbCBleGFtcGxlCgpUbyBpbGx1c3RyYXRlIHRoZSB1c2Ugb2YgdGhlIGRlbHRhLW1ldGhvZCB3ZSBzaW11bGF0ZSBkYXRhIGJhc2VkIG9uIGEgY2FuY2VyIGVwaWRlbWlvbG9neSBleGFtcGxlLiBXZSB3YW50IHRvIGVzdGltYXRlIHRoZSBlZmZlY3Qgb2YgdGhlIHByZXNlbmNlIG9mIGNvbW9yYmlkaXRpZXMgKGJpbmFyeSBpbmRpY2F0b3IpIG9uIG9uZS15ZWFyIGNhbmNlciBtb3J0YWxpdHkgaW4gY2FuY2VyIHBhdGllbnRzIGNvbnRyb2xsaW5nIGZvciB0aGUgY29uZm91bmRpbmcgZWZmZWN0IG9mIGFnZSBpbiBhIGNvaG9ydCBvZiAxLDAwMCBpbmRpdmlkdWFscyBpbiB0aGVpciBtaWRkbGUgYWdlLiBXZSBhc3N1bWUgdGhhdCBpdCBpcyBhbiBleHRyZW1lbHkgbGV0aGFsIHR5cGUgb2YgY2FuY2VyIChpLmUuLCBwYW5jcmVhdGljIGNhbmNlcikgdGh1cyB3ZSBjYW4gZXhwZWN0IGhpZ2ggb25lLXllYXIgbW9ydGFsaXR5IHJhdGUuIEFnZSBpbiB5ZWFycyB3YXMgZ2VuZXJhdGVkIGFzIGEgbm9ybWFsIHJhbmRvbSB2YXJpYWJsZSB3aXRoIG1lYW4gNjUgeWVhcnMgYW5kIHN0YW5kYXJkIGRldmlhdGlvbiBvZiA1IHllYXJzLiBDb21vcmJpZGl0aWVzIHdhcyBnZW5lcmF0ZWQgYXMgYSBiaW5hcnkgaW5kaWNhdG9yIGFuZCBhcyBhIGZ1bmN0aW9uIG9mIGFnZSB1c2luZyBhIGJpbm9taWFsIG1vZGVsLiBQYXRpZW50cyBvbmUteWVhciBtb3J0YWxpdHkgcmF0ZSB3YXMgZ2VuZXJhdGVkIGFzIGEgZnVuY3Rpb24gb2YgdGhlIHBhdGllbnRzIGFnZSBhbmQgdGhlIHByZXNlbmNlIG9mIGNvbW9yYmlkaXRpZXMgdXNpbmcgYSBiaW5vbWlhbCBkaXN0cmlidXRpb24uIFRoZSBkYXRhIGdlbmVyYXRpb24gYW5kIG1vZGVscyBzcGVjaWZpY2F0aW9ucyBhcmUgcHJvdmlkZSBoZXJlIGJlbG93IGluIHRoZSBib3ggMi4KCioqQm94IDIuIERhdGEgZ2VuZXJhdGlvbioqCgpgYGB7cn0KIyBEYXRhIGdlbmVyYXRpb24KbGlicmFyeShkcGx5cikKZ2VuZXJhdGVEYXRhIDwtIGZ1bmN0aW9uKG4sIHNlZWQpewogICAgc2V0LnNlZWQoc2VlZCkKICAgIGFnZSA8LSBybm9ybShuLCA2NSwgNSkKICAgIGNtYmQgPC0gcmJpbm9tKG4sIHNpemU9MSwgcHJvYiA9IHBsb2dpcygxIC0gMC4wNSAqIGFnZSkpCiAgICBZIDwtIHJiaW5vbShuLCBzaXplPTEsIHByb2IgPSBwbG9naXMoMSAtIDAuMDIqIGFnZSAtIDAuMDIgKiBjbWJkKSkKICAgIGRhdGEuZnJhbWUoWSwgY21iZCwgYWdlKQp9CgojIERlc2NyaWJpbmcgdGhlIGRhdGEKZGF0YSA8LSBnZW5lcmF0ZURhdGEobiA9IDEwMDAsIHNlZWQgPSA3NzcpIApzdHIoZGF0YSkKc3VtbWFyaXplKAogIGRhdGEsCiAgU3RhdHVzID0gbWVhbihZKSwgCiAgQ29tb3JiaWRpdGllcyA9IG1lYW4oY21iZCksCiAgQWdlID0gIG1lYW4oYWdlKSkgCmBgYAoKCiMjIERlbHRhLW1ldGhvZCBmb3IgYSBzaW5nbHkgcHJvcG9ydGlvbiBwYXJhbWV0ZXIKCkZpcnN0LCB3ZSB3b3VsZCBsaWtlIHRvIGRlcml2ZSB0aGUgU0UgZm9yIHRoZSBzaW5nbGUgcHJvYmFiaWxpdHkgb3IgcmlzawpvZiBkZWF0aCB1c2luZyB0aGUgZGVsdGEtbWV0aG9kLiBJbiBib3ggMywgd2UgY29tcHV0ZSB0aGUgcmlzayBvciBwcm9iYWJpbGl0eSBvZiBkZWF0aCBiYXNlIG9uIHRoZSBlbXBpcmljYWwgCnNhbXBsZSBleGFtcGxlIGFuZCBpdHMgdmFyaWFuY2UuIFdlIGRlZmluZWQgdGhlIHByb2JhYmlsaXR5IG9mIGRlYXRoIGFzIHRoZSBmdW5jdGlvbmFsIFwoZihcdGhldGEpXCkgPSBcKFxoYXQgcFwpLiBUaGVuIHRoZSBmaXJzdCBkZXJpdmF0aXZlIG9mIGYgaXMgZXF1YWwgdG8gb25lLiBTbyB0aGUgdmFyaWFuY2Ugb2YgdGhlIHJpc2sgb2YgZGVhdGggY2FuIGJlIGVzdGltYXRlZCB1c2luZzoKCgpcWyBcdGV4dHtWYXJpYW5jZX0oXGhhdHtcdGV4dHtwfX0pIFwsPVwsMVwsXHRpbWVzXCxcbGVmdChcZnJhY3twKDEtcCl9e259XHJpZ2h0KVwsLlxdCgoKKipCb3ggMy4gU3RhbmRhcmQgZXJyb3IgZm9yIHRoZSBzaW5nbGUgcHJvcG9ydGlvbiBwYXJhbWV0ZXIgdXNpbmcgdGhlIGRlbHRhLW1ldGhvZCoqCgpgYGB7cn0KIyBSaXNrIG9mIGRlYXRoCnBfaGF0ID0gbWVhbihkYXRhJFkpCnByaW50KHBfaGF0KQoKIyBWYXJpYW56ZSBmb3IgdGhlIHJpc2sgb2YgZGVhdGgKIG4gPSBucm93KGRhdGEpCiB2YXJfcF9oYXQgPSBwX2hhdCAqICgxIC0gcF9oYXQpIC8gbgogcHJpbnQodmFyX3BfaGF0KQoKI1RoaXMgY2FuIGJlIGltcGxlbWVudGVkIGluIHRoZSBmb2xsb3dpbmcgUiBjb2RlOgpkZXZfcF9oYXQgPSAxCnNlX3Jpc2sgPSBzcXJ0KChkZXZfcF9oYXQpICogdmFyX3BfaGF0KQpwcmludChzZV9yaXNrKQoKIyBUbyBjaGVjayB0aGF0IG91ciByZXN1bHRzIGFyZSBjb25zaXN0ZW50IHdpdGggdGhlIGltcGxlbWVudGF0aW9uIG9mIHRoZQojIGRlbHRhLW1ldGhvZCBmdW5jdGlvbiBwcm92aWRlIGJ5IHRoZSBzbXMgUiBwYWNrYWdlIHVzZWQgZm9yCiMgYWR2YW5jZWQgR2VvZ3JhcGhpY2FsIEFuYWx5c2lzLgoKbGlicmFyeShtc20pCnNlX3Jpc2tfZGVsdGEgPSBkZWx0YW1ldGhvZChnID0gfiB4MSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWFuID0gcF9oYXQsICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3YgID0gdmFyX3BfaGF0KQpwcmludChzZV9yaXNrX2RlbHRhKQoKIyMgQXJlIHRoZSBzYW1lIHNlX3Jpc2sgYW5kIHNlX3Jpc2tfZGVsdGE/CmlmKHNlX3Jpc2sgPT0gc2Vfcmlza19kZWx0YSkgcHJpbnQoIlllcyIpCmBgYCAKCiMjIERlbHRhIG1ldGhvZCBmb3IgdGhlIG9kZHMgcmF0aW8gZGVyaXZlZCBmcm9tIGEgcmVncmVzc2lvbiBtb2RlbAoKV2UgY29tcHV0ZSB0aGUgU0UgZm9yIHRoZSBvZGRzIHJhdGlvIChPUikgZGVyaXZlZCBmcm9tIGEgbXVsdGl2YXJpYXRlCmJpbm9taWFsIHJlZ3Jlc3Npb24gbW9kZWwuIE5vdGUgdGhhdCB0aGUgT1IgdHJhbnNmb3JtYXRpb24gaXMgYQpmdW5jdGlvbiBvZiB0aGUgcmVncmVzc2lvbiBjb2VmZmljaWVudHMgZnJvbSB0aGUgbW9kZWwuIEZpcnN0CndlIGVzdGltYXRlIHRoZSBjb25kaXRpb25hbCBwcm9iYWJpbGl0eSBvZiB0aGUgcmlzayBvZiBkZWF0aCBmb3IgdGhvc2UKcGF0aWVudHMgd2l0aCBjb21vcmJpZGl0aWVzIGFkanVzdGluZyBmb3IgYWdlLiBUaGUgbW9kZWwgc3VtbWFyeSBpcwpkZXNjcmliZWQgaGVyZSBiZWxvdyBpbiBib3ggMy4xLiBUaGUgcHJvYmFiaWxpdHkgb2YgZGVhdGggZm9yIGEgY2FuY2VyIHBhdGllbnQgaW4Kb3VyIHNhbXBsZSB3aXRoIGNvbW9yYmlkaXRpZXMgY29tcGFyZWQgd2l0aCBhIHBhdGllbnQgd2l0aG91dApjb21vcmJpZGl0aWVzIGFuZCBpbiBhdmVyYWdlIHdpdGggdGhlIHNhbWUgYWdlIGlzIGFwcHJveGltYXRlbHkgNDBcJQpoaWdoZXI6CgoqKkJveCAzLjEgT1IgZXN0aW1hdGlvbioqCgpgYGB7cn0KbTEgPC0gZ2xtKFkgfiBhZ2UgKyBjbWJkLCBkYXRhID0gZGF0YSwgZmFtaWx5ID0gYmlub21pYWwpCnN1bW1hcnkobTEpCgpiMSA8LSBjb2VmKG0xKVszXQpjYXQoIk9uZS15ZWFyIG1vcnRhbGl0eSByaXNrIGZvciBwYXRpZW50cyB3aXRoIGNvbW9yYmlkaXRpZXMgdnMgbm8gY29tb3JiaWRpdGllczoiKSAKZXhwKGIxKQpgYGAKCldlIG5vdyBjYW4gZGVyaXZlIHRoZSBTRSBmb3IgdGhlIE9SIHVzaW5nIHRoZSBlcXVhdGlvbiAoMykgZm9yIHRoZSBkZWx0YS1tZXRob2QgYXBwbGllZCB0byB0aGUgbXVsdGl2YXJpYXRlIGNhc2UuIE5vdGUgdGhhdCB0aGUgZmlyc3QgZGVyaXZhdGl2ZSBmb3IgdGhlIGV4cG9uZW50aWFsIGZ1bmN0aW9uIGlzIGVxdWFsIHRvIGV4cG9uZW50aWFsIGFuZCB0aGVyZWZvcmUgdGhlIHBhcnRpYWwgZGVyaXZhdGl2ZXMgZm9yIGFnZSBhcmUgYWxsIHRoZSBzYW1lLiBUaGVuLCB0byBnZXQgdGhlIG1hdHJpeCBvZiB0aGUgY292YXJpYW5jZSBvZiB0aGUgcGFyYW1ldGVyIGZpdHRlZCBpbiB0aGUgbW9kZWwgZm9yIGFnZSB3ZSB1c2UgdGhlIGNvbW1hbmQgdmNvdiBpbiBSIChCb3ggMy4yKS4KCioqQm94IDMuMiBEZWx0YS1tZXRob2QgZm9yIHRoZSBPUiBkZXJpdmVkIGZyb20gYSBtdWx0aXZhcmlhdGUgcmVncmVzc2lvbiBtb2RlbCoqCgpgYGB7cn0KZ3JhZCA8LSBleHAoYjEpCnZjb3YobTEpCgojIEFwcGx5aW5nIGZvcm11bGEgMwp2YjEgPC0gdmNvdihtMSlbMywzXQpzZSA8LSBncmFkICUqJSB2YjEgJSolIGdyYWQKc2Vfb3IgPC0gYXMudmVjdG9yKHNxcnQoc2UpKTsgc2Vfb3IKCiMgTm93LCB3ZSBoYXZlIHRvIGNoZWNrIHRoYXQgb3VyIHJlc3VsdHMgYXJlIGNvbnNpc3RlbnQgd2l0aCB0aGUKIyBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgZGVsdGEtbWV0aG9kIGZ1bmN0aW9uIHByb3ZpZGUgYnkgdGhlIHNtcwojIFIgcGFja2FnZSAKCnNlX29yX2RlbHRhIDwtIGRlbHRhbWV0aG9kKH4gZXhwKHgxKSwgYjEsIHZiMSk7IHNlX29yX2RlbHRhCgojIEFyZSB0aGUgc2FtZSBzZV9vciBhbmQgc2Vfb3JfZGVsdGE/CmlmZWxzZSgKICBzZV9vciA9PSBzZV9vcl9kZWx0YSwKICBwcmludCgiWWVzIiksIHByaW50KCJObyIpCikKYGBgCgojIyBDb25kaXRpb25hbCByaXNrIHJhdGlvIGZyb20gYSBtdWx0aXZhcmlhdGUgcmVncmVzc2lvbiBtb2RlbAoKV2UgY29tcHV0ZWQgdGhlIFNFIGZvciB0aGUgUlIgYXMgdGhlIHJhdGlvIG9mIHR3byBwcm9iYWJpbGl0aWVzIGRlcml2ZWQgZnJvbSB0aGUgcHJlZGljdGlvbnMgb2YgYSBtdWx0aXZhcmlhdGUgYmlub21pYWwgcmVncmVzc2lvbiBtb2RlbC4gRmlyc3Qgd2UgZml0IHRoZSBtb2RlbCB3aXRoIHRoZSBiaW5hcnkgaW5kaWNhdG9yIG9mIG9uZS15ZWFyIG1vcnRhbGl0eSBhcyBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHBhdGllbnRzIGFnZSBhbmQgY29tb3JiaWRpdGllcyBhcyBpbmRlcGVuZGVudCB2YXJpYWJsZXMuIFRoZW4sIGZyb20gdGhlIGZpdHRlZCBtb2RlbCBhbmQgdXNpbmcgdGhlIFx0ZXh0YmZ7cHJlZGljdH0gZnVuY3Rpb24gd2UgZGVyaXZlIHRoZSBwcm9iYWJpbGl0eSBvZiBkZWF0aCBmcm9tIHBhbmNyZWF0aWMgY2FuY2VyIGFtb25nIHBhdGllbnRzIGFnZWQgNDUgeWVhcnMgYW5kIHdpdGggY29tb3JiaWRpdGllcyB2ZXJzdXMgcGF0aWVudHMgYWdlZCA3NSB5ZWFycyBvbGQgd2l0aCBubyBjb21vcmJpZGl0aWVzLiBGaW5hbGx5LCB3ZSBjb21wdXRlIHRoZSBjb25kaXRpb25hbCBSUiBhcyB0aGUgcmF0aW8gYmV0d2VlbiBib3RoIHByb2JhYmlsaXRpZXMuIFRoZSBzaW11bGF0ZWQgcmlzayBvZiBkZWF0aCBpbiBhIHBvcHVsYXRpb24gd2hlcmUgY2FuY2VyIHBhdGllbnRzIHdlcmUgYWdlZCA0NSB5ZWFycyB3aXRoIGNvbW9yYmlkaXRpZXMgaXMgYXBwcm94aW1hdGVseSA4MS41XCUgaGlnaGVyIHRoYW4gdGhlIHJpc2sgb2Ygb25lLXllYXIgbW9ydGFsaXR5IGFtb25nIGNhbmNlciBwYXRpZW50cyBhZ2VkIDc1IHllYXJzIGFuZCB3aXRoIG5vIGNvbW9yYmlkaXRpZXMgKHdlIGFzc3VtZSB0aGF0IHRoZSBwYW5jcmVhdGljIGNhbmNlciBpcyBtb3JlIGFnZ3Jlc3NpdmUgYW1vbmcgeW91bmcgYWR1bHRzIHdpdGggY29tb3JiaWRpdGllcykuCgoKKipCb3ggNC4xLiBTdGFuZGFyZCBlcnJvciBmb3IgdGhlIGNvbmRpdGlvbmFsIHJpc2sgcmF0aW8gZGVyaXZlZCBmcm9tIGEgbXVsdGl2YXJpYXRlIHJlZ3Jlc3Npb24gbW9kZWwqKgoKYGBge3J9Cm0yIDwtIGdsbShZIH4gYWdlICsgY21iZCwgZGF0YSA9IGRhdGEsIGZhbWlseSA9IGJpbm9taWFsKQpwNzUgPC0gcHJlZGljdChtMiwgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoYWdlID0gNzUsIGNtYmQgPSAwKSwgdHlwZT0icmVzcG9uc2UiKQpwNDUgPC0gcHJlZGljdChtMiwgbmV3ZGF0YSA9IGRhdGEuZnJhbWUoYWdlID0gNDUsIGNtYmQgPSAxKSwgdHlwZT0icmVzcG9uc2UiKQpyciA8LSBwNDUgLyBwNzU7CmNhdCgiQ29uZGl0aW9uYWwgcmlzayByYXRpbzogIiwgcnIpCmBgYAoKTm90ZSB0aGF0IHRoZSByZWxhdGl2ZSByaXNrIHRyYW5zZm9ybWF0aW9uIGlzIGEgZnVuY3Rpb24gb2YgdGhlIHJlZ3Jlc3Npb24gY29lZmZpY2llbnRzIGZyb20gdGhlIG1vZGVsLiBUaHVzLCBpbiBvcmRlciB0byBjb21wdXRlIHRoZSBTRSBmb3IgdGhlIFJSLCB3ZSBzaG91bGQgZGVmaW5lIHRoZSBjb25kaXRpb25hbCBwcm9iYWJpbGl0eSBpbiB0ZXJtcyBvZiB0aGUgcmVncmVzc2lvbiBjb2VmZmljaWVudHMuIFNvLCB0aGUgb25lIHllYXIgcHJvYmFiaWxpdHkgb2YgZGVhdGgsIGdpdmVuIHBhdGllbnRzIGFnZSBhbmQgY29tb3JiaWRpdGllcyBpcyBjb21wdXRlZCBhcyBmb2xsb3dzOgoKXFsgXHRleHR7UChZPTF8XHRleHRiZntXfSl9XCw9XCxcZnJhY3sxfXsxXCwrXCxcdGV4dHtleHB9KC1cc3VtX3tpPTF9XntrfSBcYmV0YShcdGV4dGJme3d9KSl9XF0KCldoZXJlIGsgaXMgdGhlIG51bWJlciBvZiBwYXJhbWV0ZXJzIGluIHRoZSBtb2RlbCBcKFxiZXRhXCw9XCwoXGJldGFfezB9LFxiZXRhX3sxfSxcYmV0YV97Mn0pXCkgYW5kIFx0ZXh0YmZ7V30gcmVwcmVzZW50cyB0aGUgdmVjdG9yIG9mIGNvdmFyaWF0ZXMgcmVwcmVzZW50ZWQgZm9yIHRoZSBcKFxiZXRhXCkgcGFyYW1ldGVycyAob25lIGZvciBlYWNoIGNvdmFyaWF0ZSwgaS5lLiwgXChcYmV0YV97MX1cOyBhbmRcOyBcYmV0YV97Mn1cLCBcdGV4dHtmb3IgcGF0aWVudHMgYWdlIGFuZCBjb21vcmJpZGl0aWVzLCByZXNwZWN0aXZlbHl9KVwpLCBwbHVzIHRoZSBpbnRlcmNlcHQgXChcYmV0YV97MH1cKS4gVGhlcmVmb3JlLCB0aGUgcHJvYmFiaWxpdHkgb2Ygb25lLXllYXIgbW9ydGFsaXR5IGZvciBjYW5jZXIgcGF0aWVudHMgYWdlZCA0NSB5ZWFycyBvbGQgd2l0aCBjb21vcmJpZGl0aWVzIGlzIGNvbXB1dGVkIGFzIGZvbGxvd3M6IAoKClxbXHRleHR7UChZID0gMXx3MSA9IDQ1LCB3MyA9IDEpfVwsPVwsXGZyYWN7MX17MVwsK1wsXHRleHR7ZXhwfSgtXGJldGFfezB9XCwtXCxcYmV0YV97MX1cdGltZXMgNDVcLC1cLFxiZXRhX3syfVx0aW1lcyAxKX0sXF0KCgphbmQgdGhlIHByb2JhYmlsaXR5IG9mIG9uZS15ZWFyIG1vcnRhbGl0eSBmb3IgY2FuY2VyIHBhdGllbnRzIGFnZWQgNzUgeWVhcnMgd2l0aCBubyBjb21vcmJpZGl0aWVzCgoKXFtcdGV4dHtQKFkgPSAxfFcyID0gNzUsIFc0ID0gMCl9XCw9XCxcZnJhY3sxfXsxXCwrXCxcdGV4dHtleHB9KC1cYmV0YV97MH1cLC1cLFxiZXRhX3sxfVx0aW1lcyA3NVwsLVwsXGJldGFfezJ9XHRpbWVzIDApfS5cXQoKClxub2luZGVudCBOb3cgd2UgY2FuIGNvbXB1dGUgdGhlIFJSIGFzIGEgZnVuY3Rpb24gb2YgdGhlIHR3byBwcmV2aW91cyBwcm9iYWJpbGl0aWVzLiBOb3RlIHRoYXQgdzEgPSA3NSB5ZWFycywgdzIgPSA0NSB5ZWFycywgdzMgPSBjb21vcmJpZGl0aWVzIGFuZCB3NCA9IG5vIGNvbW9yaWJpZGl0aWVzKQoKXFtcdGV4dHtmKHcpfVwsPVwsXGZyYWN7XGZyYWN7MX17MVwsK1wsXHRleHR7ZXhwfSgtXGJldGFfezB9XCwtXCxcYmV0YV97MX0gdzFcLC1cLFxiZXRhX3syfSB3Myl9fXtcZnJhY3sxfXsxXCwrXCxcdGV4dHtleHB9KC1cYmV0YV97MH1cLC1cLFxiZXRhX3sxfSB3MlwsLVwsXGJldGFfezJ9IHc0KX19LFxdCgoKd2hpY2ggc2ltcGxpZmllcyB0bwoKXFtcdGV4dHtmKHcpfVwsPVwsXGZyYWN7MVwsK1wsXHRleHR7ZXhwfSgtXGJldGFfezB9XCwtXCxcYmV0YV97MX0gdzJcLC1cLFxiZXRhX3syfSB3NCl9ezFcLCtcLFx0ZXh0e2V4cH0oLVxiZXRhX3swfVwsLVwsXGJldGFfezF9IHcxXCwtXCxcYmV0YV97Mn0gdzMpfS5cXQoKCldlIG5vdyBuZWVkIHRvIHNvbHZlIHRoZSBwYXJ0aWFsIGRlcml2YXRpdmVzIGZvciBmKHcpIHVzaW5nIHRoZSBwcm9kdWN0IGFuZCBjaGFpbiBydWxlcy4gW0BXb2xmcmFtOTJdIEhvd2V2ZXIsIHdlIGNhbiB1c2UgdGhlIG9ubGluZSBvcGVuIHNvdXJjZSBhdmFpbGFibGUgc29mdHdhcmUgV29sZnJhbSBhbHBoYSBcdXJse2h0dHBzOi8vd3d3LndvbGZyYW1hbHBoYS5jb20vfSB0byByZWFkaWx5IGdldCB0aGUgcmVzdWx0IG9mIHRoZSBwYXJ0aWFsIGRlcml2YXRpdmVzLltAV29sZnJhbTkyXSBUaGVuLCB3ZSBhcHBseSBmb3JtdWxhICgzKSB0byBkZXJpdmUgdGhlIFNFIGZvciB0aGUgUlIgdXNpbmcgdGhlIGRlbHRhLW1ldGhvZC4gCgpUaGUgcGFydGlhbCBkZXJpdmF0aXZlcyBmb3IgZih3KSB1c2luZyB0aGUgcHJvZHVjdCBhbmQgY2hhaW4gcnVsZXMgYXJlIGdpdmVuIGhlcmUgYmVsb3c6CgpcW1xmcmFje1x0ZXh0e2RmfX17XHRleHR7ZH1cYmV0YV97MH19XCw9XCxcdGV4dHstZXhwfSgtXGJldGFfezB9XCwtXCxcYmV0YV97MX13MlwsLVwsXGJldGFfezJ9IHc0KSlcdGltZXMgXHRleHR7cH1cLCtcLCgxXCwrXCxcdGV4dHstZXhwfSgtXGJldGFfezB9XCwtXCxcYmV0YV97MX0gdzJcLC1cLFxiZXRhX3syfSB3NCkpXHRpbWVzIFx0ZXh0e3B9KDFcLC1cLFx0ZXh0e3B9KSxcXQoKdGhlbiwKClxbXGZyYWN7XHRleHR7ZGZ9fXtcdGV4dHtkfVxiZXRhX3sxfX1cLD1cLFx0ZXh0ey1leHB9KC1cYmV0YV97MH1cLC1cLFxiZXRhX3sxfXcyXCwtXCxcYmV0YV97Mn0gdzQpKVx0aW1lcyB3MiBcdGltZXMgXHRleHR7cH1cLCtcLCgxXCwrXCxcdGV4dHtleHB9KC1cYmV0YV97MH1cLC1cLFxiZXRhX3sxfSB3MlwsLVwsXGJldGFfezJ9IHc0KSlcdGltZXMgeDEgXHRpbWVzIFx0ZXh0e3B9KDFcLC1cLFx0ZXh0e3B9KSxcXQoKYW5kLCAKClxbXGZyYWN7XHRleHR7ZGZ9fXtcdGV4dHtkfVxiZXRhX3syfX1cLD1cLFx0ZXh0ey1leHB9KC1cYmV0YV97MH1cLC1cLFxiZXRhX3sxfXcyXCwtXCxcYmV0YV97Mn0gdzQpKVx0aW1lcyB3NCBcdGltZXMgXHRleHR7cH1cLCtcLCgxXCwrXCxcdGV4dHtleHB9KC1cYmV0YV97MH1cLC1cLFxiZXRhX3sxfSB3M1wsLVwsXGJldGFfezJ9IHc0KSlcdGltZXMgdzMgXHRpbWVzIFx0ZXh0e3B9KDFcLC1cLFx0ZXh0e3B9KS5cXQoKCndoZXJlIHAgaXMgCgpcW1x0ZXh0e1AoWT0xfHcxLHcyKX1cLD1cLFxmcmFjezF9ezFcLCtcdGV4dHtleHB9KC1cYmV0YV97MH1cLC1cLFxiZXRhX3sxfXcxXCwtXCxcYmV0YV97Mn0gdzMpfSxcXQoKCmkuZS4sIHRoZSBwcm9iYWJpbGl0eSBvZiBvbmUteWVhciBtb3J0YWxpdHkgZm9yIGNhbmNlciBwYXRpZW50cyBhZ2VkIDQ1IHllYXJzIHdpdGggY29tb3JiaWRpdGllcy4gCgoKKipCb3ggNC4yIERlbHRhLW1ldGhvZCB0byBkZXJpdmUgdGhlIFNFIGZvciB0aGUgY29uZGl0aW9uYWwgUlIqKgoKYGBge3J9CiNUaGUgcGFydGlhbCBkZXJpdmF0aXZlIGFyZSBjb21wdXRlZCBpbiBSIGFzIGZvbGxvd3M6CngxIDwtIDQ1CngyIDwtIDc1CngzIDwtIDEKeDQgPC0gMApiMCA8LSBjb2VmKG0yKVsxXQpiMSA8LSBjb2VmKG0yKVsyXQpiMiA8LSBjb2VmKG0yKVszXQplMSA8LSBleHAoLWIwIC0gNDUgKiBiMSAtIDEgKiBiMikKZTIgPC0gZXhwKC1iMCAtIDc1ICogYjEgLSAwICogYjIpCnAxIDwtIDEgLyAoMSArIGUxKQpwMiA8LSAxIC8gKDEgKyBlMikKZGZkYjAgPC0gLWUyICogcDEgKyAoMSArIGUyKSAqIHAxICogKDEgLSBwMSkKZGZkYjEgPC0gLXgyICogZTIgKiBwMSArICgxICsgZTIpICogeDEgKiBwMSAqICgxIC0gcDEpCmRmZGIyIDwtIC14NCAqIGUyICogcDEgKyAoMSArIGUyKSAqIHgzICogcDEgKiAoMSAtIHAxKQpncmFkIDwtIGMoZGZkYjAsIGRmZGIxLCBkZmRiMikKdkcgPC0gdChncmFkKSAlKiUgdmNvdihtMikgJSolIChncmFkKQpzZV9yciA8LSBjKHNxcnQodkcpKTtzZV9ycgoKI05vdywgd2UgY2hlY2sgd2hldGhlciB0aGUgcmVzdWx0cyBhcmUgY29uc2lzdGVudCB3aXRoIHRoZSBtc20gUiBwYWNrYWdlLiAKI1dlIG9idGFpbiB0aGUgc2FtZSByZXN1bHRzIGZvciB0aGUgU0Ugb2YgdGhlIFJSIGNvbXB1dGVkIGJlZm9yZSAoMC4zNjUzOTc5KQpzZV9ycl9kZWx0YSA8LSBkZWx0YW1ldGhvZCggfigxICsgZXhwKC14MSAtNzUqeDIgLTAqeDMpKSAvICgxICsgZXhwKC14MSAtNDUqeDIgLTEqeDMpKSwgCiAgICAgICAgICAgICBjKGIwLCBiMSwgYjIpLCAKICAgICAgICAgICAgIHZjb3YobTIpCiAgICAgICAgICAgICApOyBzZV9ycl9kZWx0YQoKI0ZpbmFsbHksIHdlIGNvbXB1dGUgdGhlIHR5cGUgV2FsZCA5NSUgQ0kKbGIgPC0gcnIgLSAxLjk2KnNxcnQodkcpCnViIDwtIHJyICsgMS45NipzcXJ0KHZHKQpjYXQoIlxuIENvbmRpdGlvbmFsIFJpc2sgUmF0aW8gKDk1JUNJKTogIikgOyBjYXQocnIsICIoIiwgbGIsIiwiLCB1YiwiKSIpCmBgYAoKIyMgU3RhdGlzdGljYWwgaW5mZXJlbmNlIGZvciB0aGUgY2F1c2FsIHJpc2sgcmF0aW8gZGVyaXZlZCBmcm9tIHRoZSBBSVBUVyBlc3RpbWF0b3IKCkxldCdzIHN1cHBvc2UgdGhhdCB3ZSB3YW50IHRvIGVtdWxhdGUgYW4gaW1wb3NzaWJsZSBjbGluaWNhbCB0cmlhbCB3aGVyZSB3ZSB3b3VsZCBsaWtlIHRvIGVzdGltYXRlIHRoZSBlZmZlY3Qgb2YgY2FuY2VyIHRyZWF0bWVudCBvbiB0aGUgIHBvcHVsYXRpb24gYXZlcmFnZSBvbmUteWVhciByaXNrIG9mIGRlYXRoLCBzdGFuZGFyZGl6ZWQgYWNyb3NzIGFsbCB0aGUgbGV2ZWxzIG9mIHBhdGllbnRzIGFnZSwgVE5NIGNhbmNlciBzdGFnZSwgY29tb3JiaWRpdGllcyBzdGF0dXMsIGFuZCBnZW5kZXIgYXMgZGVwaWN0ZWQgaW4gdGhlIERpcmVjdGVkIEFjeWNsaWMgR3JhcGggaW4gRmlndXJlIDEuIAoKKipGaWd1cmUgMTogRGlyZWN0ZWQgQWN5Y2xpYyBHcmFwaCoqCiFbXShpbWFnZXMvZjEucG5nKQoKV2hlbiBlc3RpbWF0aW5nIHRoZSBtYXJnaW5hbCBjYXVzYWwgcmlzayByYXRpbyAoQ1JSKSBmb3IgYSBiaW5hcnkgdHJlYXRtZW50IChvciBleHBvc3VyZSksIG1ldGhvZHMgdGhhdCBpbmNvcnBvcmF0ZSBwcm9wZW5zaXR5IHNjb3JlcywgdGhlIEctY29tcHV0YXRpb24sIG9yIGEgY29tYmluYXRpb24gb2YgYm90aCwgbmFtZWx5IGRvdWJsZS1yb2J1c3QgbWV0aG9kcywgYXJlIHByZWZlcnJlZCBvdmVyIG5haXZlIHJlZ3Jlc3Npb24gYXBwcm9hY2hlcyB3aGljaCBhcmUgYmlhc2VkIHVuZGVyIG1pc3NwZWNpZmljYXRpb24gb2YgYSBwYXJhbWV0cmljIG91dGNvbWUgbW9kZWwuIFtAdmFuMjAxMV0KCgpDYXVzYWwgZWZmZWN0cyBhcmUgb2Z0ZW4gZm9ybXVsYXRlZCByZWdhcmRpbmcgY29tcGFyaXNvbnMgb2YgcG90ZW50aWFsIG91dGNvbWVzLCBhcyBmb3JtYWxpc2VkIGJ5IFJ1YmluLiBbQHJ1YmluMjAxMV0gTGV0IEEgZGVub3RlIGEgYmluYXJ5IGV4cG9zdXJlLCBcdGV4dGJme1d9IGEgdmVjdG9yIG9mIHBvdGVudGlhbCBjb25mb3VuZGVycywgYW5kIFkgYSBiaW5hcnkgb3V0Y29tZS4gR2l2ZW4gQSwgZWFjaCBpbmRpdmlkdWFsIGhhcyBhIHBhaXIgb2YgcG90ZW50aWFsIG91dGNvbWVzIGkuZS4sIHRoZSBvdXRjb21lIHdoZW4gZXhwb3NlZCwgZGVub3RlZCBZKDEpLCBhbmQgdGhlIG91dGNvbWUgd2hlbiB1bmV4cG9zZWQgWSgwKS4gVGhlc2UgcXVhbnRpdGllcyBhcmUgcmVmZXJyZWQgdG8gYXMgcG90ZW50aWFsIG91dGNvbWVzLCBzaW5jZSB0aGV5IGFyZSBoeXBvdGhldGljYWwsIGdpdmVuIHRoYXQgaXQgaXMgb25seSBwb3NzaWJsZSB0byBvYnNlcnZlIGEgc2luZ2xlIHJlYWxpemF0aW9uIG9mIHRoZSBvdXRjb21lIGZvciBhbiBpbmRpdmlkdWFsOyB3ZSBvYnNlcnZlIFkoMSkgb25seSBmb3IgdGhvc2UgaW4gdGhlIGV4cG9zdXJlIGdyb3VwIGFuZCBZKDApIG9ubHkgZm9yIHRob3NlIGluIHRoZSB1bmV4cG9zZWQgZ3JvdXAuIFtAcnViaW4xOTc0XSBVbmRlciBjYXVzYWwgdW50ZXN0YWJsZSBhc3N1bXB0aW9ucywgbmFtZWx5IGNvbmRpdGlvbmFsIG1lYW4gaW5kZXBlbmRlbmNlIG9yIGV4Y2hhbmdlYWJpbGl0eSwgcG9zaXRpdml0eSBhbmQgY29uc2lzdGVuY3kgIHRoZSBwb3RlbnRpYWwgb3V0Y29tZXMgY2FuIGJlIGlkZW50aWZpZWQgZnJvbSB0aGUgb2JzZXJ2ZWQgZGF0YS5bQHJvYmluczE5ODY7IEByb2JpbnMyMDAwXSBUd28gY29tbW9uIGNhdXNhbCBlc3RpbWFuZHMgYXJlIHRoZSBhdmVyYWdlIHRyZWF0bWVudCBlZmZlY3QgKEFURSksIGRlZmluZWQgYXMgdGhlIGRpZmZlcmVuY2Ugb2YgdGhlIGV4cGVjdGF0aW9uIG9mIGJvdGggcG90ZW50aWFsIG91dGNvbWVzIGkuZS4sIFwoRVtZX3sxfS1ZX3swfV1cKSBhbmQgdGhlIGNhdXNhbCByaXNrIHJhdGlvIChDUlIpLCBlc3RpbWF0ZWQgYXMgdGhlIHJhdGlvIG9mIHRoZSBleHBlY3RhdGlvbiBvZiB0aGUgcG90ZW50aWFsIG91dGNvbWVzIGkuZS4sIFwoXGZyYWN7RVtZX3sxfV19e0VbWV97MH1dfVwpLiAgIAoKCkNsYXNzaWNhbCBlcGlkZW1pb2xvZ2ljYWwgbWV0aG9kcyB1c2UgcmVncmVzc2lvbiBhZGp1c3RtZW50IHRvIGV4cGxhaW4gdGhlIG1haW4gZWZmZWN0IG9mIGEgcmlzayBmYWN0b3IgbWVhc3VyZSBvbiBhIGRpc2Vhc2Ugb3Igb3V0Y29tZS4gUmVncmVzc2lvbiBhZGp1c3RtZW50IGNvbnRyb2wgZm9yIGNvbmZvdW5kaW5nIGJ1dCByZXF1aXJlcyBtYWtpbmcgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgZWZmZWN0IG1lYXN1cmUgaXMgY29uc3RhbnQgYWNyb3NzIGxldmVscyBvZiBjb25mb3VuZGVycyBpbmNsdWRlZCBpbiB0aGUgbW9kZWwuIEhvd2V2ZXIsIGluIG5vbi1yYW5kb21pemVkIG9ic2VydmF0aW9uYWwgc3R1ZGllcywgdGhlIGVmZmVjdCBtZWFzdXJlIGlzIG5vdCBjb25zdGFudCBhY3Jvc3MgZ3JvdXBzIGdpdmVuIHRoZSBkaWZmZXJlbnQgZGlzdHJpYnV0aW9uIG9mIGluZGl2aWR1YWwgY2hhcmFjdGVyaXN0aWNzIGF0IGJhc2VsaW5lLiBVc2luZyB0aGUgXHRleHRiZntHLWZvcm11bGF9LCBhIGdlbmVyYWxpemF0aW9uIG9mIHRoZSBcdGV4dGJme3N0YW5kYXJkaXNhdGlvbn0sIGFsbG93cyBvYnRhaW5pbmcgYSB1bmNvbmZvdW5kZWQgbWFyZ2luYWwgZXN0aW1hdGlvbiBvZiB0aGUgQVRFIHVzaW5nIApbQHJvYmluczE5ODZdOgoKXFsgQVRFXCw9XCxcc3VtX3t3fVwsXGxlZnQoXHN1bV97eX1cLFAoWT15XG1pZCBBPTEsVz13KS1cLFxzdW1fe3l9XCxQKFkgPSB5XG1pZCBBPTAsVz13KVxyaWdodClQKFc9dykuIFxdCgp3aGVyZSwgICAKJCRQKFkgPSB5IFxtaWQgQSA9IGEsIFcgPSB3KVwsPVwsXGZyYWN7UChXID0gdywgQSA9IGEsIFkgPSB5KX17XHN1bV97eX1cLFAoVyA9IHcsIEEgPSBhLCBZID0geSl9JCQgCgppcyB0aGUgY29uZGl0aW9uYWwgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uIG9mIFkgPSB5LCBnaXZlbiBBID0gYSwgVyA9IHcuIAoKVGhlIEFURSBhbmQgdGhlIENSUiBjYW4gYmUgZXN0aW1hdGVkIG5vbi1wYXJhbWV0cmljYWxseSB1c2luZyB0aGUgRy1mb3JtdWxhLiBIb3dldmVyLCB0aGUgY3Vyc2Ugb2YgZGltZW5zaW9uYWxpdHkgaW4gb2JzZXJ2YXRpb25hbCBzdHVkaWVzIGxpbWl0cyBpdHMgZXN0aW1hdGlvbi4gSGVuY2UsIHRoZSBlc3RpbWF0aW9uIG9mIHRoZSBBVEUgdXNpbmcgdGhlIEctZm9ybXVsYSByZWxpZXMgbW9zdGx5IG9uIHBhcmFtZXRyaWMgbW9kZWxsaW5nIGFuZCBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGlvbi4gVGhlIGNvcnJlY3QgbW9kZWwgc3BlY2lmaWNhdGlvbiBpbiBwYXJhbWV0cmljIG1vZGVsbGluZyBpcyBjcnVjaWFsIHRvIG9idGFpbiB1bmJpYXNlZCBlc3RpbWF0ZXMgb2YgdGhlIHRydWUgQVRFIGFuZCBDUlJbQHJ1YmluMjAxMV0uIEFsdGVybmF0aXZlbHksIHByb3BlbnNpdHkgc2NvcmUgbWV0aG9kcywgaW50cm9kdWNlZCBieSBSb3NlbmJhdW0gYW5kIFJ1YmluIFtAcm9zZW5iYXVtMTk4M10sIGFyZSBhbHNvIGNvbW1vbmx5IHVzZWQgZm9yIGVzdGltYXRpb24gb2YgdGhlIEFURS4gVGhlIHByb3BlbnNpdHkgc2NvcmUgaXMgYSBiYWxhbmNpbmcgc2NvcmUgdGhhdCBjYW4gYmUgdXNlZCB0byBjcmVhdGUgc3RhdGlzdGljYWxseSBlcXVpdmFsZW50IGV4cG9zdXJlIGdyb3VwcyB0byBlc3RpbWF0ZSB0aGUgQVRFIHZpYSBtYXRjaGluZywgd2VpZ2h0aW5nLCBvciBzdHJhdGlmaWNhdGlvbi4gW0Byb3NlbmJhdW0xOTgzXSBIb3dldmVyLCB2ZXJ5IGxvdyBvciB2ZXJ5IGhpZ2ggcHJvcGVuc2l0eSBzY29yZXMgY2FuIGxlYWQgdG8gdmVyeSBsYXJnZSB3ZWlnaHRzLCByZXN1bHRpbmcgaW4gdW5zdGFibGUgZXN0aW1hdGVzIHdpdGggaGlnaCB2YXJpYW5jZSBhbmQgdmFsdWVzIG91dHNpZGUgdGhlIGNvbnN0cmFpbnRzIG9mIHRoZSBzdGF0aXN0aWNhbCBtb2RlbC4gW0BsdW5jZWZvcmQyMDA0XSBGdXJ0aGVybW9yZSwgd2hlbiBhbmFseWl6aW5nIG9ic2VydmF0aW9uYWwgZGF0YSB3aXRoIGEgbGFyZ2UgbnVtYmVyIG9mIHZhcmlhYmxlcyBhbmQgcG90ZW50aWFsbHkgY29tcGxleCByZWxhdGlvbnNoaXBzIGFtb25nIHRoZW0sIG1vZGVsIG1pc3NwZWNpZmljYXRpb24gZHVyaW5nIGVzdGltYXRpb24gaXMgb2YgcGFydGljdWxhciBjb25jZXJuLiBIZW5jZSwgdGhlIGNvcnJlY3QgbW9kZWwgc3BlY2lmaWNhdGlvbiBpbiBwYXJhbWV0cmljIG1vZGVsbGluZyBpcyBjcnVjaWFsIHRvIG9idGFpbiB1bmJpYXNlZCBlc3RpbWF0ZXMgb2YgdGhlIHRydWUgQVRFIGFuZCBDUlIuIFtAdmFuMjAxMV0gVGhlcmVmb3JlLCBkb3VibHkgcm9idXN0IChEUikgbWV0aG9kcyB3ZXJlIGRldmVsb3BlZCBjb21iaW5pbmcgYm90aCB0aGUgZy1jb21wdXRhdGlvbiB3aXRoIHByb3BlbnNpdHkgc2NvcmUgbWV0aG9kcyB0byByZWR1Y2UgdGhlIHJpc2sgb2YgcGFyYW1ldHJpYyBtb2RlbGxpbmcgbWlzc3BlY2lmaWNhdGlvbi4gRFIgbWV0aG9kcywgcmVsaWVzIG9uIHNlbWktcGFyYW1ldHJpYyB0aGVvcnkgKGkuZS4sIGVzdGltYXRpb24gZXF1YXRpb25zKSBhbmQgdGhlIG1vc3QgY29tbW9ubHkgdXNlZCBlc3RpbWF0b3IgaXMgdGhlIGF1Z21lbnRlZCBpbnZlcnNlIHByb2JhYmlsaXR5IG9mIHRyZWF0bWVudCB3ZWlnaHRzIChBSVBUVykgd2hpY2ggaW50ZWdyYXRlcyB0d28gcGFyYW1ldHJpYyBtb2RlbHMgaS5lLiwgYSBtb2RlbCBmb3IgdGhlIG91dGNvbWUgYW5kIGEgbW9kZWwgZm9yIHRoZSB0cmVhdG1lbnQuW0Byb2JpbnMxOTk0XSBEUiBwcm9jZWR1cmVzIHByb2R1Y2UgYSBjb25zaXN0ZW50IGVzdGltYXRlIG9mIHRoZSBwYXJhbWV0ZXIgaWYgZWl0aGVyIG9mIHRoZSB0d28gbW9kZWxzIGhhcyBiZWVuIGNvcnJlY3RseSBzcGVjaWZpZWQuW0BzY2hhZmVyMjAwN10gCgpBSVBUVyBlc3RpbWF0aW9uIGlzIGEgZG91YmxlLXJvYnVzdCB0d28tc3RlcCBwcm9jZWR1cmUgd2l0aCB0d28gZXF1YXRpb24gKHByb3BlbnNpdHkgc2NvcmUgYW5kIG1lYW4gb3V0Y29tZSkuIFRvIGVzdGltYXRlIHRoZSBDUlIgdXNpbmcgdGhlIEFJUFRXIHdlIHVzZSB0aGUgcmF0aW8gb2YgdGhlIGV4cGVjdGF0aW9ucyBvZiB0aGUgcG90ZW50aWFsIG91dGNvbWVzLiBOb3RlIHRoYXQgdG8gZWFzZSB0aGUgZGVyaXZhdGlvbiBvZiB0aGUgSUMgYW5kIHRodXMgdGhlIGVzdGltYXRpb24gb2YgdGhlIFNFIGZvciB0aGUgQ1JSIHdlIHVzZSB0aGUgbG9nIG9mIHRoZSByYXRpbyBhcyBmb2xsb3dzOiAKClxbXHRleHR7bG9nKENSUi1BSVBUVyl9XCw9XCxsb2dcbGVmdChcZnJhY3tFWTF9e0VZMH1ccmlnaHQpXCw9XCxcdGV4dHtsb2coRVkxKX1cLC1cLFx0ZXh0e2xvZyhFWTApfS5cXQoKSW4gYm94IDUuMSB3ZSBnZW5lcmF0ZSB0aGUgc2ltdWxhdGVkIGRhdGEgcmVwbGljYXRpbmcgdGhlIERBRyBmcm9tIEZpZ3VyZSAxLiBUaGUgc2ltdWxhdGVkIGRhdGEgaW4gYm94IDUuMSBpbmNsdWRlZCB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczoKCi0gWTogbW9ydGFsaXR5IGJpbmFyeSBpbmRpY2F0b3IgKDEgZGVhdGgsIDAgYWxpdmUpIAoKLSBBOiBiaW5hcnkgdHJlYXRtZW50ICgxIENoZW1vdGhlcmFweSwgMCBSYWRpb3RoZXJhcHkgKSAgICAKCi0gdzE6IEdlbmRlciAoMSBtYWxlOyAwIGZlbWFsZSkgIAoKLSB3MjogQWdlIGF0IGRpYWdub3NpcyAoYmluYXJ5IHdpdGggbGV2ZWxzOiAwIDw2NTsgMSA+PTY1KSAgCgotIHczOiBDYW5jZXIgVE5NIGNsYXNzaWZpY2F0aW9uIChtdWx0aW5vbWlhbCB3aXRoIGxldmVsczogMSB0byA0OyAxOiBlYXJseSBzdGFnZSBubyBtZXRhc3Rhc2lzOyA0OiBhZHZhbmNlZCBzdGFnZSB3aXRoIG1ldGFzdGFzaXMpICAKCi0gdzQ6IENvbW9yYmlkaXRpZXMgY291bnQgZnJvbSAxIHRvIDUpCgoKKipCb3ggNS4xIERhdGEgZ2VuZXJhdGlvbioqCgpgYGB7cn0Kb3B0aW9ucyhkaWdpdHM9NCkKZ2VuZXJhdGVEYXRhIDwtIGZ1bmN0aW9uKG4pewogIHcxIDwtIHJiaW5vbShuLCBzaXplPTEsIHByb2I9MC41KQogIHcyIDwtIHJiaW5vbShuLCBzaXplPTEsIHByb2I9MC42NSkKICB3MyA8LSByb3VuZChydW5pZihuLCBtaW49MCwgbWF4PTQpLCBkaWdpdHM9MykKICB3NCA8LSByb3VuZChydW5pZihuLCBtaW49MCwgbWF4PTUpLCBkaWdpdHM9MykKICBBICA8LSByYmlub20obiwgc2l6ZT0xLCBwcm9iPSBwbG9naXMoLTAuNCArIDAuMip3MiArIDAuMTUqdzMgKyAwLjIqdzQgKyAwLjE1KncyKnc0KSkKICAjIGNvdW50ZXJmYWN0dWFsClkuMSA8LSByYmlub20obiwgc2l6ZT0xLCBwcm9iPSBwbG9naXMoLTEgKyAxIC0wLjEqdzEgKyAwLjMqdzIgKyAwLjI1KnczICsgMC4yKnc0ICsgMC4xNSp3Mip3NCkpClkuMCA8LSByYmlub20obiwgc2l6ZT0xLCBwcm9iPSBwbG9naXMoLTEgKyAwIC0wLjEqdzEgKyAwLjMqdzIgKyAwLjI1KnczICsgMC4yKnc0ICsgMC4xNSp3Mip3NCkpCiAgIyBPYnNlcnZlZCBvdXRjb21lCiAgWSA8LSBZLjEqQSArIFkuMCooMSAtIEEpCiAgIyByZXR1cm4gZGF0YS5mcmFtZQogIGRhdGEuZnJhbWUodzEsIHcyLCB3MywgdzQsIEEsIFkpCn0Kc2V0LnNlZWQoNzc3NykKbiA8LSAxMDAwMApPYnNkYXRhIDwtIGdlbmVyYXRlRGF0YShuPW4pCk9ic2RhdGEgPC0gYXMuZGF0YS5mcmFtZShPYnNkYXRhKQpPYnNkYXRhIDwtc3Vic2V0KE9ic2RhdGEsIHNlbGVjdD1jKHcxLHcyLHczLHc0LEEsWSkpClkgIDwtIE9ic2RhdGEkWQpBICA8LSBPYnNkYXRhJEEKdzEgPC0gT2JzZGF0YSR3MQp3MiA8LSBPYnNkYXRhJHcyCnczIDwtIE9ic2RhdGEkdzMKdzQgPC0gT2JzZGF0YSR3NApgYGAKCkluIGJveCA1LjIgd2Ugc2hvdyBob3cgdG8gZXN0aW1hdGUgdGhlIENSUiB1c2luZyB0aGUgQUlQVFcgZXN0aW1hdG9yLiAKCioqQm94IDUuMiBDUlIgZXN0aW1hdGlvbiB1c2luZyB0aGUgQUlQVFcgZXN0aW1hdG9yKioKCmBgYHtyfQojIFN0ZXAgMSBlc3RpbWF0aW9uIGFuZCBwcmVkaWN0aW9uIG9mIHRoZSBtb2RlbCBmb3IgdGhlIG91dGNvbWUgKEctY29tcHV0YXRpb24pCmdtIDwtIGdsbShZIH4gQSArIHcxICsgdzIgKyB3MyArIHc0LCBkYXRhID0gT2JzZGF0YSwgZmFtaWx5ID0gYmlub21pYWwobGluaz1sb2dpdCkpCiMgUHJlZGljdGlvbiBmb3IgRShZfEEsVyksIGFuZCBFKFl8QSA9IDEsIFcpIGFuZCwgRShZfEEgPSAwLCBXKQpRQVcgPC0gcHJlZGljdChnbSwgdHlwZSA9ICJyZXNwb25zZSIpClExVyA8LSBwcmVkaWN0KGdtLCBuZXdkYXRhPWRhdGEuZnJhbWUoQSA9IDEsIHcxLCB3MiwgdzMsIHc0KSwgdHlwZSA9ICJyZXNwb25zZSIpClEwVyA8LSBwcmVkaWN0KGdtLCBuZXdkYXRhPWRhdGEuZnJhbWUoQSA9IDAsIHcxLCB3MiwgdzMsIHc0KSwgdHlwZSA9ICJyZXNwb25zZSIpCiMgU3RlcCAyIGVzdGltYXRpb24gYW5kIHByZWRpY3Rpb24gb2YgdGhlIHByb3BlbnNpdHkgc2NvcmUgKHBzKTogRShBfFcpIG9yIEUoY21iZHxhZ2UpCnBzbSA8LSBnbG0oQSB+IHcxICsgdzIgKyB3MyArIHc0LCBmYW1pbHkgPSBiaW5vbWlhbCwgZGF0YSA9IE9ic2RhdGEpCmdXID0gcHJlZGljdChwc20sIHR5cGUgPSAicmVzcG9uc2UiKQojIEFJUFRXIENSUgpFWTEgPC0gbWVhbigoT2JzZGF0YSRZKSAqIChPYnNkYXRhJFkgLSBRMVcpIC8gZ1cgKyBRMVcpCkVZMCA8LSBtZWFuKCgxIC0gT2JzZGF0YSRZKSAqIChPYnNkYXRhJFkgLSBRMFcpIC8gKDEgLSBnVykgKyBRMFcpCmxvZ0NSUiA8LSBsb2coRVkxKSAtIGxvZyhFWTApIApDUlIgPC0gZXhwKGxvZ0NSUik7Q1JSCmBgYAoKVGhlIG1hcmdpbmFsIGNvbnRyYXN0IG9mIGEgcG9wdWxhdGlvbiBvZiBwYXRpZW50cyB3aGVyZSBhbGwgb2YgdGhlbSB3ZXJlIHRyZWF0ZWQgd2l0aCBjaGVtb3RoZXJhcHkgdmVyc3VzIG90aGVyIHdoZXJlIHBhdGllbnRzIHdlcmUgdHJlYXRlZCB3aXRoIHJhZGlvdGhlcmFweSBhZnRlciBzdGFuZGFyZGl6aW5nIGJ5IHRoZSBsZXZlbHMgb2YgcGF0aWVudHMgYWdlLCBUTk0gc3RhZ2UsIGNvbW9yaWJpZGl0aWVzIGFuZCBnZW5kZXIgZm9yIHRoZSBvbmUteWVhciBtb3J0YWxpdHkgcmlzayBpcyA4IHRpbWVzIGhpZ2hlciBmb3IgcGF0aWVudHMgdHJlYXRlZCB3aXRoIGNoZW1vdGhlcmFweS4gSG93ZXZlciwgd2Ugd291bGQgbGlrZSB0byBnZXQgc3RhdGlzdGljYWwgaW5mZXJlbmNlIGZvciB0aGUgZXN0aW1hdGUgb2YgdGhlIENSUi4gT2Z0ZW4gcmVzZWFyY2hlcnMgdXNlIHRoZSBib290c3RyYXAgcHJvY2VkdXJlIHRvIGRlcml2ZSA5NVwlIENJIGJ1dCBjb21wdXRpbmcgZWZmaWNpZW5jeSBpcyBsb3cuIEhvd2V2ZXIsIHdlIGNhbiB1c2UgdGhlIGZ1bmN0aW9uYWwgZGVsdGEtbWV0aG9kIHRvIGFwcGx5IHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gYW5kIGRlcml2ZSA5NVwlIHR5cGUgV2FsZCBDSSBmb3IgdGhlIENSUi4KClxub2luZGVudCBJbiBib3ggNS4zIHdlIHNob3cgaG93IHRvIGRlcml2ZSB0aGUgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QgYmFzZWQgYmFzZWQgb24gdGhlIGVmZmljaWVudCBJQyBmb3IgdGhlIEFJUFRXIGVzdGltYXRvciB1c2luZyBlcXVhdGlvbiAoMikgdG8gZXN0aW1hdGUgdGhlIFNFIG9mIHRoZSBDUlIuW0B2YW4yMDExXS4gV2hpbGUgbWFueSBpbmZsdWVuY2UgZnVuY3Rpb25zIGFuZCBjb3JyZXNwb25kaW5nIGVzdGltYXRvcnMgZXhpc3QgZm9yIGEgZ2l2ZW4gdGFyZ2V0IHBhcmFtZXRlciwgdGhlcmUgYWx3YXlzIGV4aXN0cyBhbiBcdGV4dGJme2VmZmljaWVudH0gSUMgdGhhdCBhY2hpZXZlcyB0aGUgbG93ZXIgYm91bmQgb24gYXN5bXB0b3RpYyB2YXJpYW5jZS4gVGhlIEFJUFRXIGlzIGNvbnN0cnVjdGVkIGJ5IHVzaW5nIHRoZSBlZmZpY2llbnQgSUMsIG1ha2luZyBpdCBhc3ltcHRvdGljYWxseSBlZmZpY2llbnQgd2hlbiBhbGwgbmVjZXNzYXJ5IG1vZGVscyBhcmUgY29ycmVjdGx5IHNwZWNpZmllZCAoaS5lLiwgdGhlIG1vZGVsIGZvciB0aGUgb3V0Y29tZSBhbmQgdGhlIG1vZGVsIGZvciB0aGUgdHJlYXRtZW50IG9yIGV4cG9zdXJlIG1lY2hhbmlzbSkuIFRvIGNvbXB1dGUgdGhlIGVmZmljaWVudCBJQyBmb3IgdGhlIGxvZyhDUlIpID0gbG9nKFwoXGhhdHtFfVwpW1kxXSkgLSBsb2coXChcaGF0e0V9XClbWTBdKSA9IFwoXHBzaV97MX1cKSAtIFwoXHBzaV97Mn1cKSwgd2UgZmlyc3QgaGF2ZSB0byBkZXJpdmUgdGhlIGZvbGxvd2luZyB0d28gcGFydGlhbCBkZXJpdmF0aXZlcyBhLmsuYSBhcyB0aGUgY2Fub25pY2FsIGdyYWRpZW50IG9mIHRoZSBwYXRod2lzZSBkZXJpdmF0aXZlIG9mIHRoZSB0YXJnZXQgcGFyYW1ldGVyOltAdmFuMjAxMV0KClxbXGZyYWN7XHBhcnRpYWwgbG9nKFxwc2lfezF9KX17XHBhcnRpYWwgXHBzaV97MX19XCw9XCxcZnJhY3sxfXtccHNpX3sxfX1cLD1cLFxmcmFjezF9e1xoYXR7RX1bWSgxKV19LFxdIAoKYW5kLAoKXFsgXGZyYWN7XHBhcnRpYWwgbG9nKFxwc2lfezJ9KX17XHBhcnRpYWwgXHBzaV97Mn19XCw9XCxcZnJhY3sxfXtccHNpX3syfX1cLD1cLFxmcmFjezF9e1xoYXR7RX1bWSgwKV19LFxdIAoKCnRoZW4sIHRvIGNvbXB1dGUgXCgoXGhhdFx0aGV0YVwsLVwsXHRoZXRhKVwpIGZyb20gZXF1YXRpb24gKDIpIHdlIGRlZmluZSBEMSBhbmQgRDAgYXMgZm9sbG93czogIAoKClxbXHRleHR7RDF9XCw9XCxcbGVmdChcbGVmdChcZnJhY3tJXGxlZnQoQV97aX09MVxyaWdodCl9e2dfbigxXG1pZCBXX3tpfSl9XHJpZ2h0KVxsZWZ0KFlfe2l9LXtRfV97bn1cbGVmdChBX3tpfSxXX3tpfVxyaWdodClccmlnaHQpXCwrXCxcdGV4dHtRfV97bn1cbGVmdCgxLFwgV197aX1ccmlnaHQpXHJpZ2h0KVwsLVwsXGhhdHtFfVtZKDEpXVw7ICg2KSxcXQoKYW5kCgpcW1x0ZXh0e0QwfVwsPVwsXGxlZnQoXGxlZnQoXGZyYWN7SVxsZWZ0KEFfe2l9PTBccmlnaHQpfXtnX24oMFxtaWQgV197aX0pfVxyaWdodClcbGVmdChZX3tpfS17UX1fe259XGxlZnQoQV97aX0sV197aX1ccmlnaHQpXHJpZ2h0KVwsK1wsXHRleHR7UX1fe259XGxlZnQoMCxcIFdfe2l9XHJpZ2h0KVxyaWdodClcLC1cLFxoYXR7RX1bWSgwKV1cOyAoNykuXF0KCgpXaGVyZSBcdGV4dGJme0l9IHJlZmVycyB0byBhIGJpbmFyeSBpbmRpY2F0b3IgdmFyaWFibGUgZm9yIHRoZSB0cmVhdG1lbnQgQSwgXChnX3tufVwpIGlzIHRoZSBwcm9wZW5zaXR5IHNjb3JlIGZvciB0aGUgdHJlYXRtZW50IG1lY2hhbmlzbSAoQSkgYW5kIFwoUV97bn1cKSBpcyB0aGUgZXN0aW1hdGUgb2YgdGhlIGNvbmRpdGlvbmFsIG1lYW4gb2Ygb3V0Y29tZSBnaXZlbiB0cmVhdG1lbnQgYW5kIGNvbmZvdW5kZXJzIChcdGV4dGJme1d9KSBpLmUuLCBcKEUoWXxBLFx0ZXh0YmZ7V30pXCkuIFRoZSBtZWFuIGV4cGVjdGVkIG91dGNvbWUgdW5kZXIgdHJlYXRtZW50IGFuZCBjb250cm9sIChpLmUuLCBcKFxoYXR7RX1cKVtZKDEpXSBhbmQgXChcaGF0e0V9XClbWSgwKV06IGNoZW1vdGhlcmFweSBhbmQgcmFkaW90aGVyYXB5IGluIG91ciBleGFtcGxlKSBhcmUgZ2l2ZW4gYnkgc29sdmluZyB0aGUgZXN0aW1hdGluZyBlcXVhdGlvbnM6IAoKClxbXGhhdHtFfVtZKDEpXVwsPVwsXGZyYWN7MX17bn1cc3VtX3tpPTF9XntufVxsZWZ0KFxmcmFje0lcbGVmdChBX3tpfT0xXHJpZ2h0KX17Z19uKDFcbWlkIFdfe2l9KX1ccmlnaHQpXGxlZnQoWV97aX0te1F9X3tufVxsZWZ0KEFfe2l9LFdfe2l9XHJpZ2h0KVxyaWdodCkrXGZyYWN7MX17bn1cc3VtX3tpPTF9XntufXtRfV97bn1cbGVmdCgxLFwgV197aX1ccmlnaHQpXCwgKDQpLFxdCgphbmQKClxbXGhhdHtFfVtZKDApXVwsPVwsXGZyYWN7MX17bn1cc3VtX3tpPTF9XntufVxsZWZ0KFxmcmFje0lcbGVmdChBX3tpfT0xXHJpZ2h0KX17Z19uKDBcbWlkIFdfe2l9KX1ccmlnaHQpXGxlZnQoWV97aX0te1F9X3tufVxsZWZ0KEFfe2l9LFdfe2l9XHJpZ2h0KVxyaWdodCkrXGZyYWN7MX17bn1cc3VtX3tpPTF9XntufXtRfV97bn1cbGVmdCgwLFwgV197aX1ccmlnaHQpXCwoNSkuXF0KCkZpbmFsbHksIHRoZSBlZmZpY2llbnQgKFwoXHRleHR7SUN9X3tpfVwpKSBmb3IgdGhlIGxvZyhDUlIpIGlzIGdpdmVuIGJ5OgoKXFtcLD1cLFxmcmFjezF9e1xoYXR7RX1bWSgxKV19RDFcLCtcLFxmcmFjezF9e1xoYXR7RX1bWSgwKV19RDAuXDsgKDgpXF0KCioqQm94IDUuMyBTdGF0aXN0aWNhbCBpbmZlcmVuY2UgZm9yIHRoZSBDUlIgYmFzZWQgb24gdGhlIElDKioKCmBgYHtyfQojIEZ1bmN0aW9uYWwgRGVsdGEgTWV0aG9kIGZvciBzdGF0aXNpY2FsIGluZmVyZW5jZQpEMSA8LSAoQSkgKiAoWSAtIFExVykgLyBnVyArIFExVyAtIEVZMSAKRDAgPC0gKDEgLSBBKSAqIChZIC0gUTBXKSAvICgxIC0gZ1cpICsgUTBXIC0gRVkwCiMgQUlQVFcgQ1JSIDk1JUNJCkVJQyA8LSAoKDEgLyBFWTEpICogRDEpICsgKCgxIC8gRVkwKSAqIEQwKQp2YXJFSUMgPC0gdmFyKEVJQykgLyBuCkNJIDwtIGMoZXhwKGxvZ0NSUiAtIDEuOTYgKiBzcXJ0KHZhckVJQykpLCBleHAobG9nQ1JSICsgMS45NiAqIHNxcnQodmFyRUlDKSkpOyAKY2F0KCJcbiBDUlI6IiwgQ1JSKQpjYXQoIlxuIENSUiA5NSVDSToiLCBDSSkKIyBTdW1tYXJ5IElDCmNhdCgiXG4gVmFyaWFuY2UgRUlDOiIsIHZhckVJQykKYGBgCgpOb3RlOiBFeHBsb3JpbmcgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgSUMgd2lsbCBhbGxvdyB0byBkaXNjb3ZlciBvdXRsaWVycyBhbmQgdGVsbHMgdXMgaG93IHJvYnVzdCBpcyB0aGUgZXN0aW1hdG9yIGFzIHNob3duIGluIHRoZSBoaXN0b2dyYW0gZm9yIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIElDIChGaWd1cmUgMikuIE5vdGUgdGhhdCB0aGUgbWVhbiBvZiB0aGUgdmFyaWFuY2Ugb2YgdGhlIEVJQyBtdXN0IGJlIGVxdWFsIHRvIHplcm8uIEluIGdlbmVyYWwsIHdoZW4gd2UgaGF2ZSBkYXRhIHNwYXJzaXR5IGFuZCBpZGVudGlmaWFiaWxpdHkgcHJvYmxlbXMgc3VjaCBhcyBuZWFyLXBvc2l0aXZpdHkgdmlvbGF0aW9ucyAoaS5lLiwgdGhlIHBvc2l0aXZpdHkgYXNzdW1wdGlvbiBzdGF0ZXMgdGhhdCB3aXRoaW4gc3RyYXRhIG9mIFcgZXZlcnkgcGF0aWVudCBoYWQgYSBub256ZXJvIHByb2JhYmlsaXR5IG9mIHJlY2VpdmluZyBlaXRoZXIgb2YgdGhlIHR3byB0cmVhdG1lbnQgY29uZGl0aW9ucyAoaS5lLn4wIFx0ZXh0bGVzcyBQKEE9MVx0ZXh0YmFyIFx0ZXh0YmZ7V30pXHRleHRsZXNzMSkpLCB0aGUgQm9vdHN0cmFwIGlzIHByZWZlcnJlZCBmb3Igc3RhdGlzdGljYWwgaW5mZXJlbmNlLiBbQENhaTIwMTldCgoqKkZpZ3VyZSAyLiBJbmZsdWVuY2UgY3VydmUgZGlzdHJpYnV0aW9uKioKIVtdKGltYWdlcy9mMi5wbmcpCgojIFRoZSBCb290c3RyYXAKCkZpbmFsbHksIHdlIGFyZSBnb2luZyB0byB1c2UgYSBtb3JlIGNvbnNlcnZhdGl2ZSBhcHByb2FjaCBmb3IKc3RhdGlzdGljYWwgaW5mZXJlbmNlIChpLmUuLCB0aGUgYm9vdHN0cmFwKS4gVXNpbmcgdGhlIEJvb3RzdHJhcCB0aGUKb3JpZ2luYWwgc2FtcGxlIGFwcHJveGltYXRlcyB0aGUgcG9wdWxhdGlvbiBmcm9tIHdoaWNoIGl0IHdhcyBkcmF3bi4gU28gcmVzYW1wbGVzIGZyb20gdGhpcyBzYW1wbGUgYXBwcm94aW1hdGUgd2hhdCB3ZSB3b3VsZCBnZXQgaWYgd2UgdG9vayBtYW55IHNhbXBsZXMgZnJvbSB0aGUgcG9wdWxhdGlvbi4gVGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gb2YgYSBzdGF0aXN0aWMsIGJhc2VkIG9uIG1hbnkgcmVzYW1wbGVzLCBhcHByb3hpbWF0ZXMgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc3RhdGlzdGljLCBiYXNlZCBvbiBtYW55IHNhbXBsZXMgYW5kIHRoZXJlZm9yZSBpdCBjYW4gb25seSBiZSBhcHBsaWVkIHVuZGVyIGNlcnRhaW4gc21vb3RobmVzcyBjb25kaXRpb25zLiBbQGVmcm9uMTk4MjsgQGVmcm9uMTk4M10gRm9yIHN0YXRpc3RpY2FsIGluZmVyZW5jZSwgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBvZiB0aGF0IHN0YXRpc3RpYyBpcyB0aGUgU0Ugb2YgdGhlIHN0YXRpc3RpYy4gRm9yIG1vc3Qgc3RhdGlzdGljcywgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbnMgYXBwcm94aW1hdGUgdGhlIHNwcmVhZCwgYmlhcywgYW5kIHNoYXBlIG9mIHRoZSBhY3R1YWwgc2FtcGxpbmcgZGlzdHJpYnV0aW9uLiBUaGUgaW50ZXJ2YWwgYmV0d2VlbiAyLjUgYW5kIDk3LjUgcGVyY2VudGlsZXMgb2YgdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24gb2YgYSBzdGF0aXN0aWMgaXMgYSA5NVwlIGJvb3RzdHJhcCBwZXJjZW50aWxlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoZSBjb3JyZXNwb25kaW5nIHBhcmFtZXRlci4gW0BlZnJvbjE5ODI7IEBlZnJvbjE5ODNdCgpJbiBib3ggNiwgd2UgdXNlIHRoZSBcdGV4dGJme2Jvb3R9IFIgcGFja2FnZSB3aGljaCBwcm92aWRlcyBleHRlbnNpdmUgZmFjaWxpdGllcyBmb3IgYm9vdHN0cmFwcGluZyBhbmQgcmVsYXRlZCByZXNhbXBsaW5nIG1ldGhvZHMuIFlvdSBjYW4gYm9vdHN0cmFwIGEgc2luZ2xlIHN0YXRpc3RpYyAoZS5nLn5hIG1lZGlhbiksIG9yIGEgdmVjdG9yIChlLmcuLCByZWdyZXNzaW9uIHdlaWdodHMpLiBXZSBhcmUgZ29pbmcgdG8gdXNlIHRoZSBub25wYXJhbWV0cmljIGJvb3RzdHJhcHBpbmcgYmFzZWQgb24gMTAuMDAwIGJvb3RzdHJhcCBzYW1wbGUgZXN0aW1hdGVzLgpbQGJvb3N0cmFwMjAwM10KCioqQm94IDYuIEJvb3RzdHJhcCBzdGF0aXN0aWNhbCBpbmZlcmVuY2UgZm9yIFNFKioKCmBgYHtyfQpsaWJyYXJ5KGJvb3QpCmFpcHR3LncgPSBmdW5jdGlvbihkYXRhLGluZGljZXMpCnsKICAgIGRhdD1PYnNkYXRhW2luZGljZXMsXQogICAgIyBDUlIKICAgIGdtIDwtIGdsbShZIH4gQSArIHcxICsgdzIgKyB3MyArIHc0LCBkYXRhID0gZGF0LCBmYW1pbHkgPSBiaW5vbWlhbChsaW5rPWxvZ2l0KSkKICAgICMgUHJlZGljdGlvbiBmb3IgRShZfEEsVyksIGFuZCBFKFl8Y21iZCA9IDEsIGFnZSkgYW5kLCBFKFl8Y21iZCA9IDAsIGFnZSkKICAgIFExVyA8LSBwcmVkaWN0KGdtLCBuZXdkYXRhID0gZGF0YS5mcmFtZShBID0gMSwgdzEsIHcyLCB3MywgdzQpLCB0eXBlID0gInJlc3BvbnNlIikKICAgIFEwVyA8LSBwcmVkaWN0KGdtLCBuZXdkYXRhID0gZGF0YS5mcmFtZShBID0gMCwgdzEsIHcyLCB3MywgdzQpLCB0eXBlID0gInJlc3BvbnNlIikKICAgICMgU3RlcCAyIGVzdGltYXRpb24gYW5kIHByZWRpY3Rpb24gb2YgdGhlIHByb3BlbnNpdHkgc2NvcmUgKHBzKTogRShBfFcpIG9yIEUoY21iZHxhZ2UpCiAgICBwc20gPC0gZ2xtKEEgfiB3MSArIHcyICsgdzMgKyB3NCwgZmFtaWx5ID0gYmlub21pYWwsIGRhdGEgPSBkYXQpCiAgICBnVyA9IHByZWRpY3QocHNtLCB0eXBlID0gInJlc3BvbnNlIikKICAgICMgQ1JSCiAgICBFWTEgPC0gbWVhbigoWSkgKiAoWSAtIFExVykgLyBnVyArIFExVykKICAgIEVZMCA8LSBtZWFuKCgxIC0gWSkgKiAoWSAtIFEwVykgLyAoMSAtIGdXKSArIFEwVykKICAgIENSUiA8LSBFWTEgLyBFWTAKfQojIENhbiBnZXQgb3JpZ2luYWwgZXN0aW1hdGUsIGJ5IHBsdWdnaW5nIGluIGluZGljZXMgMTpuCmFpcHR3LncoZGF0YSwgaW5kaWNlcyA9MTpucm93KGRhdGEpKQojIERyYXcgMTAwMCBib290c3RyYXAgc2FtcGxlIGVzdGltYXRlcyAKYm9vdC5vdXQgPSBib290KGRhdGEsIGFpcHR3LncsIDEwMDAwKQojIGNvbXB1dGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgdXNpbmcgcGVyY2VudGlsZSBtZXRob2QKYm9vdC5jaShib290Lm91dCwgdHlwZSA9ICJwZXJjIiwgY29uZiA9IDAuOTUpCmBgYAoKTm90ZSB0aGF0IHdlIGdvdCBuYXJyb3dlciBjb25maWRlbmNlIGludGVydmFscyB1c2luZyB0aGUgZGVsdGEtbWV0aG9kIGNvbXBhcmVkIHRvIHRoZSBCb290c3RyYXAgcHJvY2VkdXJlIChpLmUuLCB0aGUgYm9vdHN0cmFwIGVzdGltYXRlIG9mIHRoZSBTRSBmb3IgdGhlIEFJUFRXIGVzdGltYXRvciBpcyBtb3JlIGNvbnNlcnZhdGl2ZSkuIEl0IGhhcyBiZWVuIHNob3duIHRoYXQgdGhlIGNvdmVyYWdlIG9mIHRoZSBmdW5jdGlvbmFsIGRlbHRhLW1ldGhvZCBpbiBmaW5pdGUgc2FtcGxlcyBkZWNyZWFzZXMgd2hlbiB0aGVyZSBhcmUgaWRlbnRpZmlhYmlsaXR5IHByb2JsZW1zIHN1Y2ggYXMgdmlvbGF0aW9ucyBvZiB0aGUgcG9zaXRpdml0eSBhc3N1bXB0aW9uIGZvciBjYXVzYWwgaW5mZXJlbmNlIFtARG9yaWVfMjAxOV0uIEJhc2ljYWxseSwgaXQgaXMgZHVlIHRvIGlnbm9yZSB0aGUgcG90ZW50aWFsbHkgdmVyeSBsYXJnZSBjb250cmlidXRpb25zIG9mIHRoZSByZW1haW5kZXIgdGVybSBcKFx0ZXh0e09wfShcZnJhY3sxfXtcc3FydChuKX0pXCkgdGhhdCBlYXNpbHkgZG9taW5hdGVzIHRoZSBmaXJzdCBvcmRlciBlbXBpcmljYWwgbWVhbiBvZiB0aGUgSUMgdGVybS4gSXQgaXMgd2h5IHRoZSBmdW5jdGlvbmFsIGRlbHRhLW1ldGhvZCBwcm92aWRlcyBtb3JlIHByZWNpc2UgY29uZmlkZW5jZSBpbnRlcnZhbHMgdGhhbiBvdGhlciBhcHByb2FjaGVzIHN1Y2ggYXMgdGhlIEJvb3RzdHJhcCBpbiBmaW5pdGUgc2FtcGxlcyB3aGVuIHByb2JsZW1zIHJlbGF0ZWQgd2l0aCB0aGUgY291cnNlIG9mIGRpbWVuc2lvbmFsaXR5IHN1Y2ggYXMgdmlvbGF0aW9ucyBvZiBwb3NpdGl2aXR5IGluIHRoZSBjYXVzYWwgaW5mZXJlbmNlIHNldHRpbmcuIFtARG9yaWVfMjAxOV0gSG93ZXZlciwgd2hlbiBkYXRhIGFkYXB0aXZlIChpLmUuLCBtYWNoaW5lIGxlYXJuaW5nIGFsZ29yaXRobXMpIGFyZSB1c2UgdG8gcHJlZGljdCB0aGUgcG90ZW50aWFsIG91dGNvbWVzIHRoZXJlIGlzIG5vdCBzY2llbnRpZmljIGV2aWRlbmNlIHN1cHBvcnRpbmcgdGhlIHVzZSBvZiBCb290c3RyYXAgZm9yIHN0YXRpc3RpY2FsIGluZmVyZW5jZS4gW0B2YW4yMDExXSAKCgojIENvbmNsdXNpb24KCgpUaGUgZGVsdGEtbWV0aG9kIGlzIHdpZGVseSB1c2VkIGluIGNsYXNzaWNhbCBlcGlkZW1pb2xvZ2ljYWwgbWV0aG9kcyBmb3Igc3RhdGlzdGljYWwgaW5mZXJlbmNlLiBGb3IgaW5zdGFuY2UsIGl0IGlzIHVzZWQgdG8gZGVyaXZlIHRoZSBTRSBvZiBhbiBhc3ltcHRvdGljYWxseSBsaW5lYXIgZXN0aW1hdG9yIG9yIGZ1bmN0aW9uIHRoYXQgY2FuIGJlIGFwcHJveGltYXRlZCBieSBhdmVyYWdlcyAoaS5lLiwgc3VjaCBhcyB0aGUgY29uZGl0aW9uYWwgZXN0aW1hdGlvbnMgZnJvbSBjb2VmZmljaWVudHMgb2YgdGhlIHBhcmFtZXRlcnMgZml0dGVkIGluIHJlZ3Jlc3Npb24gbW9kZWxzKS4gSW4gY2FzdWFsIGluZmVyZW5jZSB0aGUgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QgYW5kIElDcyBhcmUgbGFyZ2VseSB1c2VkIGJlY2F1c2UgaXQgZWFzZSB0aGUgZGVyaXZhdGlvbiBvZiB0eXBlIFdhbGQgQ0lzIGZvciBkYXRhLWFkYXB0aXZlIGRvdWJsZS1yb2J1c3QgZXN0aW1hdG9ycy4KClJlY2VudGx5LCB0aGUgc3R1ZHkgb2YgdGhlIGJlaGF2aW9yIG9mIHRoZSBkZWx0YS1tZXRob2QgZm9yIGRhdGEtYWRhcHRpdmUgZG91YmxlLXJvYnVzdCBlc3RpbWF0b3JzIGluIGZpbml0ZSBzYW1wbGVzIHdoZXJlIHRoZXJlIGFyZSBwb3NpdGl2aXR5IHZpb2xhdGlvbnMgcmV2ZWFsZWQgdGhhdCB0aGUgZnVuY3Rpb25hbCBkZWx0YS1tZXRob2QgcHJvdmlkZXMgbGVzcyBjb25zZXJ2YXRpdmUgY29uZmlkZW5jZSBpbnRlcnZhbHMgdGhhbiB0aGUgQm9vdHN0cmFwIHByb2NlZHVyZXMuIFNpbXVsYXRpb24gc3R1ZGllcyBoYXZlIHNob3duIHRoYXQgaW4gc3VjaCBzaXR1YXRpb25zIHRoZSBTRSBjb3ZlcmFnZSBpcyBwb29yLiBbQERvcmllXzIwMTldLiBUaGVyZWZvcmUsIG1vcmUgY29uc2VydmF0aXZlIGFuZCByb2J1c3QgYXBwcm9hY2hlcyBzdWNoIGFzIHRoZSBib290c3RyYXAgcHJvY2VkdXJlIGlzIHN0aWxsIGEgdmFsaWQgYW5kIHByZWZlcnJlZCBtZXRob2QgZm9yIHN0YXRpc3RpY2FsIGluZmVyZW5jZSB1bmRlciB2aW9sYXRpb25zIGFuZCBuZWFyIHZpb2xhdGlvbnMgb2YgdGhlIHBvc2l0aXZpdHkgYXNzdW1wdGlvbi4gSG93ZXZlciwgdGhlIHVzZSBvZiBjcm9zcy12YWxpZGF0aW9uIHByb2NlZHVyZXMgZm9yIHRoZSBlc3RpbWF0aW9uIG9mIHRoZSBjYXVzYWwgcGFyYW1ldGVyIGhhcyBiZWVuIHNob3duIHRvIGltcHJvdmUgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBmdW5jdGlvbmFsIGRlbHRhLW1ldGhvZCB1bmRlciBmaW5pdGUgc2FtcGxlIGlkZW50aWZpYWJpbGl0eSBwcm9ibGVtcy4gW0BMZXZ5MjAxODsgQHZhbjIwMTFdIEZ1cnRoZXJtb3JlLCB3aGVuIGRhdGEgYWRhcHRpdmUgIG1ldGhvZHMgYXJlIHVzZWQgZm9yIGNhdXNhbCBpbmZlcmVuY2UgZXN0aW1hdGlvbiwgdGhlIEJvb3RzdHJhcCBwcm9jZWR1cmUgZm9yIHN0YXRpc3RpY2FsIGluZmVyZW5jZSBpcyBub3Qgc3VwcG9ydGVkLiBOZXZlcnRoZWxlc3MsIHJlY2VudCBzdHVkaWVzIGhhdmUgZGVtb25zdHJhdGVkIHRoZSB2YWxpZGl0eSBhbmQgYmV0dGVyIHBlcmZvcm1hbmNlIG9mIHRoZSBib290c3RyYXAgcHJvY2VkdXJlIGZvciBjcm9zcy12YWxpZGF0ZWQgY2F1c2FsIGluZmVyZW5jZSBtZXRob2RzIHVzaW5nIGRhdGEgYWRhcHRpdmUgcHJvY2VkdXJlcyBzdWNoIGFzIHRoZSB0YXJnZXRlZCBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGlvbi4gW0BDYWkyMDE5XSAKICAgClRvIGNvbmNsdWRlLCB0aGVyZSBpcyBhbiBhY3RpdmUgcmVzZWFyY2ggZGV2ZWxvcG1lbnQgb2YgbWV0aG9kcyBhbmQgdG9vbHMgZm9yIGhpZ2hseSBkaW1lbnNpb25hbCBkYXRhIGFuYWx5c2lzIHN1Y2ggYXMgbWFjaGluZSBsZWFybmluZyBhbmQgY2F1c2FsIGluZmVyZW5jZS4gVGhlIG5ldyB2ZW51ZSBvZiBtZXRob2RzIHJlcXVpcmVzIGEgY29uc3RhbnQgdXBkYXRlIG9uIHZhbGlkIHN0YXRpc3RpY2FsIGluZmVyZW5jZSBmb3IgYXBwbGllZCBlcGlkZW1pb2xvZ2lzdHMgYW5kIHN0YXRpc3RpY2lhbnMuIFdlIHByb3ZpZGVkIGEgbW9zdGx5IGFwcGxpZWQgb3ZlcnZpZXcgb2YgdGhlIGRlbHRhLW1ldGhvZCwgdGhlIGZ1bmN0aW9uYWwgZGVsdGEtbWV0aG9kLCBJQyBhbmQgdGhlIGJvb3RzdHJhcCB0aGF0IG1heSBoZWxwIHRvIGZpbGwgdGhpcyBnYXAuCgojIEZ1bmRpbmcKTWlndWVsIEFuZ2VsIEx1cXVlIEZlcm5hbmRleiBpcyBzdXBwb3J0ZWQgYnkgdGhlIE5hdGlvbmFsIEluc3RpdHV0ZSBvZiBIZWFsdGgsIENhcmxvcyBJSUksIE1pZ3VlbCBTZXJ2ZXQgSSBJbnZlc3RpZ2F0b3IgQXdhcmQgKENQMTcvMDAyMDYpLCBNYWRyaWQsIFNwYWluLiAKCiMgQXV0aG9ycyBjb250cmlidXRpb25zClRoZSBhcnRpY2xlIGFyaXNlIGZyb20gdGhlIG1vdGl2YXRpb24gdG8gZGlzc2VtaW5hdGUgdGhlIHByaW5jaXBsZXMgb2YgbW9kZXJuIGVwaWRlbWlvbG9neSBhbW9uZyBjbGluaWNpYW5zIGFuZCBhcHBsaWVkIHJlc2VhcmNoZXJzLiBNQUxGIGRldmVsb3BlZCB0aGUgY29uY2VwdCwgZGVzaWduZWQgdGhlIHN0dWR5LCBhbmFseXNlZCB0aGUgZGF0YSwgYW5kIHdyb3RlIHRoZSB0dXRvcmlhbCBBbGwgYXV0aG9ycyBpbnRlcnByZXRlZCBhbmQgcmV2aWV3ZWQgdGhlIGNvZGUgYW5kIHRoZSBkYXRhLCBkcmFmdGVkIGFuZCByZXZpc2VkIHRoZSB0dXRvcmlhbC4KCgojIFNlc3Npb24gSW5mbyAKYGBge3Igc2Vzc2lvbi1pbmZvfQpkZXZ0b29sczo6c2Vzc2lvbl9pbmZvKCkKYGBgCgojIFRoYW5rIHlvdSAgClRoYW5rIHlvdSBmb3IgcmVhZGluZyB0aGUgdHV0b3JpYWwuICAKCllvdSBjYW4gY2l0ZSB0aGlzIHJlcG9zaXRvcnkgYXM6ICAgICAgICAKTHVxdWUtRmVybmFuZGV6IE1BLCAoMjAyMCkgZXQgYWwuIERlbHRhIE1ldGhvZCBpbiBFcGlkZW1pb2xvZ3k6IEFuIEFwcGxpZWQgYW5kIFJlcHJvZHVjaWJsZSBUdXRvcmlhbC4gR2l0SHViIHJlcG9zaXRvcnksIGh0dHA6Ly9taWdhcmlhbmUuZ2l0aHViLmlvL0RlbHRhTWV0aG9kRXBpLm5iLmh0bWwgIAoKIVtET0ldKGh0dHBzOi8vemVub2RvLm9yZy9iYWRnZS8xODU4ODc1ODcuc3ZnKShodHRwczovL3plbm9kby5vcmcvYmFkZ2UvbGF0ZXN0ZG9pLzE4NTg4NzU4NwoKSWYgeW91IGhhdmUgdXBkYXRlcyBvciBjaGFuZ2VzIHRoYXQgeW91IHdvdWxkIGxpa2UgdG8gbWFrZSwgcGxlYXNlIHNlbmQgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL21pZ2FyaWFuZS9EZWx0YU1ldGhvZFR1dG9yaWFsIiB0YXJnZXQ9Il9ibGFuayI+bWU8L2E+IGEgcHVsbCByZXF1ZXN0LiBBbHRlcm5hdGl2ZWx5LCBpZiB5b3UgaGF2ZSBhbnkgcXVlc3Rpb25zLCBwbGVhc2UgZS1tYWlsIG1lLiAgCgoqKk1pZ3VlbCBBbmdlbCBMdXF1ZSBGZXJuYW5kZXoqKiAgICAgCioqRS1tYWlsOioqICptaWd1ZWwtYW5nZWwubHVxdWUgYXQgbHNodG0uYWMudWsqICAKKipUd2l0dGVyKiogYEBXQVRaSUxFSWAgIAoqKldlYnNpdGU6KiogaHR0cHM6Ly9zY2hvbGFyLmhhcnZhcmQuZWR1L21hbGYvaG9tZSAgICAKKipPUkNJRDoqKiBodHRwczovL29yY2lkLm9yZy8wMDAwLTAwMDEtNjY4My01MTY0IAoKIyBSZWZlcmVuY2VzIAoK