Question: Trace Metal Concentrations in Soil
Soil lead (Pb) concentrations (mg/kg) from 55 urban garden sites.
Trace metals in environmental media typically follow lognormal
distributions due to:
Multiplicative processes controlling accumulation
Positive constraints (concentrations cannot be negative)
Right-skewed nature of contamination patterns
0.85, 1.23, 0.92, 3.45, 2.11, 1.56, 4.89, 2.34, 1.78, 6.72, 0.95, 1.34, 8.91,
2.67, 1.89, 5.43, 1.12, 3.78, 2.45, 7.65, 1.05, 1.45, 12.34, 2.89, 2.01, 4.56,
1.23, 4.32, 2.67, 9.87, 0.99, 1.56, 15.23, 3.12, 2.34, 3.89, 1.34, 5.67, 2.89,
11.45, 1.12, 1.67, 18.90, 3.45, 2.56, 3.45, 1.45, 6.78, 3.12, 14.56, 1.23, 1.78,
22.34, 3.78, 2.78
\[\boxed{\text{Instructions:}}\]
Assume the data follow a log-normal distribution. For each question
in parts (b)–(d), begin by clearly explaining the reasoning behind your
analytical approach. Then, develop your own R functions to implement
three types of confidence intervals: the asymptotic interval, the
percentile bootstrap interval, and the bias-corrected and accelerated
(BCa) bootstrap interval. Use these functions to construct the required
confidence intervals, and verify your results using the appropriate
functions from the boot package.
You are encouraged to design a wrapper function that integrates all
confidence interval methods, allowing users to select the desired method
through an input argument.
\[\boxed{\text{Individual
Questions:}}\]
a). Perform 5000 bootstrap samples to estimate the bootstrap sampling
distribution of \(\boxed{\widehat{\mathbb{E}[X]}}\). Display
the distribution using either a histogram or a kernel density plot.
Comment on the shape, variability, and any notable patterns observed in
the bootstrap sampling distribution.
To estimate the sampling distribution of the lognormal population
mean, I use bootstrap resampling. For each bootstrap sample, I resample
the observed data with replacement and compute the plug-in estimator of
\(E[X]\).
## Soil lead concentration data (mg/kg)
soil <- c(
0.85, 1.23, 0.92, 3.45, 2.11, 1.56, 4.89, 2.34, 1.78, 6.72, 0.95, 1.34, 8.91,
2.67, 1.89, 5.43, 1.12, 3.78, 2.45, 7.65, 1.05, 1.45, 12.34, 2.89, 2.01, 4.56,
1.23, 4.32, 2.67, 9.87, 0.99, 1.56, 15.23, 3.12, 2.34, 3.89, 1.34, 5.67, 2.89,
11.45, 1.12, 1.67, 18.90, 3.45, 2.56, 3.45, 1.45, 6.78, 3.12, 14.56, 1.23, 1.78,
22.34, 3.78, 2.78
)
## Plug-in estimator for the lognormal population mean E[X]
lognormal_mean_hat <- function(x) {
logx <- log(x)
mu_hat <- mean(logx)
sigma2_hat <- mean((logx - mu_hat)^2) # MLE of variance on log-scale
exp(mu_hat + sigma2_hat / 2)
}
## Compute estimate from original sample
theta_hat <- lognormal_mean_hat(soil)
theta_hat
[1] 4.218099
## Bootstrap sampling distribution of E[X]
set.seed(1)
B <- 5000
n <- length(soil)
boot_theta <- rep(0, B)
for (b in 1:B) {
x_star <- sample(soil, size = n, replace = TRUE)
boot_theta[b] <- lognormal_mean_hat(x_star)
}
## Histogram of bootstrap sampling distribution
hist(boot_theta,
breaks = 30,
main = "Bootstrap Sampling Distribution of E[X]",
xlab = expression(hat(E[X])))

The bootstrap sampling distribution of the estimated value of E[X]
appears roughly unimodal with a slight right skew. It is centered around
the original estimate and shows a moderate amount of variability. The
right skew is expected given the lognormal nature of the data, and a few
larger values indicate the effect of higher observations in the
sample.
b). Construct a 95% bootstrap percentile confidence interval for
\(\mu_{LN} = \mathbb{E}[X]\).
To construct the 95% bootstrap percentile confidence interval, I use
the empirical distribution of the bootstrap estimates obtained in part
(a). Since the percentile method uses the quantiles of the bootstrap
sampling distribution directly, I take the 2.5th and 97.5th percentiles
of the bootstrap estimates of the lognormal population mean. This gives
a 95% percentile bootstrap confidence interval for \(\mu_{LN} = \mathbb{E}[X]\).
## Percentile bootstrap confidence interval for E[X]
percentile_ci <- function(boot_stat, alpha = 0.05) {
quantile(boot_stat, probs = c(alpha / 2, 1 - alpha / 2))
}
ci_percentile <- percentile_ci(boot_theta)
ci_percentile
2.5% 97.5%
3.125359 5.589956
## Verify percentile interval using boot package
library(boot)
boot_mean_stat <- function(data, indices) {
sample_data <- data[indices]
lognormal_mean_hat(sample_data)
}
boot_result <- boot(data = soil, statistic = boot_mean_stat, R = 5000)
boot.ci(boot_result, type = "perc")
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates
CALL :
boot.ci(boot.out = boot_result, type = "perc")
Intervals :
Level Percentile
95% ( 3.136, 5.549 )
Calculations and Intervals on Original Scale
Using my percentile bootstrap function, the 95% bootstrap percentile
confidence interval for \(\mu_{LN} =
\mathbb{E}[X]\) is (3.1254, 5.5900). I verified this result using
the boot package, which gave a very similar interval of approximately
(3.136,5.549). Since the intervals are close, this indicates that the
percentile method was applied correctly.
c). Construct a 95% bootstrap BCa confidence interval for \(\mu_{LN} = \mathbb{E}[X]\).
To construct the 95% bootstrap BCa confidence interval, I use the
bootstrap estimates from part (a) and adjust them for bias and skewness.
The BCa method improves on the percentile approach by accounting for
asymmetry in the bootstrap sampling distribution. Since the estimated
lognormal mean is slightly right-skewed, this method is appropriate for
constructing a more accurate confidence interval for \(\mu_{LN} = \mathbb{E}[X]\).
## BCa bootstrap confidence interval for E[X]
bca_ci <- function(data, boot_stat, stat_function, alpha = 0.05) {
theta_hat <- stat_function(data)
## Measures how the bootstrap distribution is shifted from the original estimate
z0 <- qnorm(mean(boot_stat < theta_hat))
n <- length(data)
jack_stat <- rep(0, n)
## Uses jackknife estimates to account for skewness in the distribution
for (i in 1:n) {
jack_sample <- data[-i]
jack_stat[i] <- stat_function(jack_sample)
}
jack_mean <- mean(jack_stat)
num <- sum((jack_mean - jack_stat)^3)
den <- sum((jack_mean - jack_stat)^2)
a_hat <- num / (6 * den^(3/2))
z_alpha1 <- qnorm(alpha / 2)
z_alpha2 <- qnorm(1 - alpha / 2)
## Adjusts the percentile levels using bias and skewness
p1 <- pnorm(z0 + (z0 + z_alpha1) / (1 - a_hat * (z0 + z_alpha1)))
p2 <- pnorm(z0 + (z0 + z_alpha2) / (1 - a_hat * (z0 + z_alpha2)))
quantile(boot_stat, probs = c(p1, p2))
}
ci_bca <- bca_ci(soil, boot_theta, lognormal_mean_hat)
ci_bca
4.163632% 98.69315%
3.219438 5.811369
## Verify BCa interval using boot package
boot.ci(boot_result, type = "bca")
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates
CALL :
boot.ci(boot.out = boot_result, type = "bca")
Intervals :
Level BCa
95% ( 3.233, 5.774 )
Calculations and Intervals on Original Scale
Using my BCa bootstrap function, the 95% BCa confidence interval for
\(\mu_{LN} = \mathbb{E}[X]\) is
(3.2194, 5.8114). I verified this result using the boot package, which
gave a very similar BCa interval of approximately (3.233,5.774). Since
the intervals are close, this indicates that the BCa method was applied
correctly.
d). Use the Central Limit Theorem to construct a 95% asymptotic
confidence interval for \(\mu_{LN} =
\mathbb{E}[X]\).
To construct the 95% asymptotic confidence interval, I use the
Central Limit Theorem together with the delta method. Since the
estimator of the lognormal population mean is a smooth function of \(\hat{\mu}\) and \(\hat{\sigma}^2\), its sampling distribution
is approximately normal for a sufficiently large sample size. I
therefore estimate its standard error using the plug-in approach and
then use the normal critical value \(1.96\) to form the confidence interval for
\(\mu_{LN} = \mathbb{E}[X]\).
## Asymptotic confidence interval for E[X]
asymptotic_ci <- function(data, alpha = 0.05) {
logx <- log(data)
n <- length(data)
mu_hat <- mean(logx)
sigma2_hat <- mean((logx - mu_hat)^2)
theta_hat <- exp(mu_hat + sigma2_hat / 2)
## The standard error is estimated using the delta method with plug-in estimates
se_hat <- theta_hat * sqrt((sigma2_hat + sigma2_hat^2 / 2) / n)
## The normal critical value is used because the estimator is asymptotically normal
z_crit <- qnorm(1 - alpha / 2)
c(theta_hat - z_crit * se_hat, theta_hat + z_crit * se_hat)
}
ci_asym <- asymptotic_ci(soil)
ci_asym
[1] 3.134984 5.301214
## Verify asymptotic interval using boot package
boot.ci(boot_result, type = "norm")
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates
CALL :
boot.ci(boot.out = boot_result, type = "norm")
Intervals :
Level Normal
95% ( 2.986, 5.427 )
Calculations and Intervals on Original Scale
Using my asymptotic confidence interval function, the 95% asymptotic
confidence interval for \(\mu_{LN} =
\mathbb{E}[X]\) is (3.1350, 5.3012). I verified this result using
the boot package, which gave a similar normal interval of approximately
(2.986, 5.427). Since the intervals are reasonably close, this indicates
that the asymptotic method was applied correctly.
## Wrapper function for confidence interval methods
ci_wrapper <- function(data, boot_stat, method = "percentile", alpha = 0.05) {
if (method == "percentile") {
percentile_ci(boot_stat, alpha)
} else if (method == "bca") {
bca_ci(data, boot_stat, lognormal_mean_hat, alpha)
} else if (method == "asymptotic") {
asymptotic_ci(data, alpha)
} else {
stop("Method must be 'percentile', 'bca', or 'asymptotic'")
}
}
ci_wrapper(soil, boot_theta, method = "percentile")
2.5% 97.5%
3.125359 5.589956
ci_wrapper(soil, boot_theta, method = "bca")
4.163632% 98.69315%
3.219438 5.811369
ci_wrapper(soil, boot_theta, method = "asymptotic")
[1] 3.134984 5.301214
f). Assuming the confidence intervals constructed in the previous
parts are valid, evaluate their performance by comparing their widths,
symmetry, stability, and sensitivity to distributional skewness. Then,
provide a well‑reasoned recommendation regarding which method is most
suitable for this analysis.
The asymptotic interval is the narrowest, the BCa interval is the
widest, and the percentile interval lies in between. The asymptotic
interval is also the most symmetric around the original estimate because
it is based on a normal approximation. However, the bootstrap
distribution from part (a) showed slight right skewness, so a symmetric
interval may not fully reflect the shape of the data. The percentile
interval reflects the bootstrap distribution more directly, but it does
not adjust for bias. The BCa interval adjusts for both bias and
skewness, making it more sensitive to the asymmetry in the data. All
three intervals are relatively similar, but the BCa interval is more
reliable in this case. Therefore, I would recommend the BCa interval as
the most suitable method for estimating \(\mu_{LN} = \mathbb{E}[X]\). This method
takes into account two important things: bias and skewness. Bias is like
a systematic error, and skewness is when the data isn’t perfectly
symmetrical. By considering both of these, the BCa interval gives a more
accurate estimate. Compared to other methods, it’s more suitable for
this kind of analysis.
LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgNzogQm9vdHN0cmFwIE1ldGhvZHMgYW5kIEFwcGxpY2F0aW9ucyINCmF1dGhvcjogIktheWxhIER5ZXIiDQpkYXRlOiAiIER1ZTogTWFyY2ggMzEsIDIwMjYiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgaGlnaGxpZ2h0OiBtb25vY2hyb21lDQogICAgdGhlbWU6IHNwYWNlbGFiDQogIHdvcmRfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIGtlZXBfbWQ6IHllcw0KICBwZGZfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiAzDQogICAgZmlnX2hlaWdodDogMw0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KYGBge2NzcywgZWNobyA9IEZBTFNFfQ0KI1RPQzo6YmVmb3JlIHsNCiAgY29udGVudDogIlRhYmxlIG9mIENvbnRlbnRzIjsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtc2l6ZTogMS4yZW07DQogIGRpc3BsYXk6IGJsb2NrOw0KICBjb2xvcjogbmF2eTsNCiAgbWFyZ2luLWJvdHRvbTogMTBweDsNCn0NCg0KDQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovDQogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQoNCmgxLnRpdGxlIHsgICAgLyogbGV2ZWwgMSBoZWFkZXIgb2YgdGl0bGUgICovDQogIGZvbnQtc2l6ZTogMjJweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCn0NCg0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxNXB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsNCiAgY29sb3I6IG5hdnk7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDQuZGF0ZSB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsNCiAgY29sb3I6IERhcmtCbHVlOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgxIHsgLyogSGVhZGVyIDEgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDIwcHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE2cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IGRhcmtyZWQ7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLw0KLmhlYWRlci1zZWN0aW9uLW51bWJlcjo6YWZ0ZXIgew0KICBjb250ZW50OiAiLiI7DQoNCmJvZHkge2JhY2tncm91bmQtY29sb3I6ICNmZmZmZmY7DQogICAgICBjb2xvcjogIzAwMDAwMDsNCiAgICAgIGZvbnQtZmFtaWx5OiBBcmlhbCwgc2Fucy1zZXJpZjsNCiAgICAgIGZvbnQtc2l6ZTogMXJlbTsNCiAgICAgIGxpbmUtaGVpZ2h0OiAxLjY7DQogICAgICB9DQoNCi5oaWdobGlnaHRtZSB7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyB9DQoNCnAgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9DQoNCn0NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwYW5kZXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGFuZGVyIikNCiAgIGxpYnJhcnkocGFuZGVyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQogIGxpYnJhcnkoZ2dwbG90MikNCn0NCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgbGlicmFyeSh0aWR5dmVyc2UpDQp9DQoNCmlmICghcmVxdWlyZSgicGxvdGx5IikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCiAgbGlicmFyeShwbG90bHkpDQp9DQoNCmlmICghcmVxdWlyZSgiVkdBTSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoIlZHQU0iKQ0KICBsaWJyYXJ5KFZHQU0pDQp9DQojIyMjIFZHQU0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQ0KICAgICAgICAgICAgICAgICAgICAgICkgIA0KYGBgDQogDQogXA0KIA0KIyMgKipBc3NpZ25tZW50IE9iamVjdGl2ZXMqKiANCg0KPHA+DQoqIFJlaW5mb3JjZSB0aGUgdW5kZXJzdGFuZGluZyBvZiBCb290c3RyYXAgc2FtcGxpbmcgLg0KDQoqIFVuZGVyc3RhbmQgdGhlIGJvb3RzdHJhcCBlc3RpbWF0aW9uOiBjb25maWRlbmNlIGludGVydmFsIGFuZCBzYW1wbGluZyBkaXN0cmlidXRpb24uDQo8L3A+DQoNCg0KIyMgKipQb2xpY2llcyBvZiBVc2luZyBBSSBUb29scyoqDQoNCjxwPg0KKipQb2xpY3kgb24gQUkgVG9vbCBVc2UqKjogUGxlYXNlIGFkaGVyZSB0byB0aGUgQUkgdG9vbCBwb2xpY3kgc3BlY2lmaWVkIGluIHRoZSBjb3Vyc2Ugc3lsbGFidXMuIFRoZSBkaXJlY3QgY29weWluZyBvZiBBSS1nZW5lcmF0ZWQgY29udGVudCBpcyBzdHJpY3RseSBwcm9oaWJpdGVkLiBBbGwgc3VibWl0dGVkIHdvcmsgbXVzdCByZWZsZWN0IHlvdXIgb3duIHVuZGVyc3RhbmRpbmc7IHdoZXJlIGV4dGVybmFsIHRvb2xzIGFyZSBjb25zdWx0ZWQsIGNvbnRlbnQgbXVzdCBiZSB0aG9yb3VnaGx5IHJlcGhyYXNlZCBhbmQgc3ludGhlc2l6ZWQgaW4geW91ciBvd24gd29yZHMuDQo8L3A+DQoNCjxwPg0KKipDb2RlIEluY2x1c2lvbiBSZXF1aXJlbWVudCoqOiBBbnkgY29kZSBpbmNsdWRlZCBpbiB5b3VyIGVzc2F5IG11c3QgYmUgcHJvcGVybHkgY29tbWVudGVkIHRvIGV4cGxhaW4gdGhlIHB1cnBvc2UgYW5kL29yIGV4cGVjdGVkIG91dHB1dCBvZiBrZXkgY29kZSBsaW5lcy4gU3VibWl0dGluZyBBSS1nZW5lcmF0ZWQgY29kZSB3aXRob3V0IG1lYW5pbmdmdWwsIHN0dWRlbnQtYWRkZWQgY29tbWVudHMgd2lsbCBub3QgYmUgYWNjZXB0ZWQuDQo8L3A+DQoNCg0KPHA+KipMb2ctbm9ybWFsIERpc3RyaWJ1dGlvbiBSZXZpc2l0ZWQqKjwvcD4NCg0KPHA+DQpJZiAkWSA9IFxsbihYKSBcc2ltIE4oXG11LCBcc2lnbWFeMikkLCB0aGVuICRYJCBmb2xsb3dzIGEgbG9nbm9ybWFsIGRpc3RyaWJ1dGlvbiAkWCBcc2ltIFx0ZXh0e0xvZ25vcm1hbH0oXG11LCBcc2lnbWFeMikkLiBUaGUgcHJvYmFiaWxpdHkgZGVuc2l0eSBpcyBnaXZlbiBieQ0KDQokJA0KZih4fFxtdSxcc2lnbWEpID0gXGZyYWN7MX17eFxzaWdtYVxzcXJ0ezJccGl9fSBcZXhwXGxlZnQoLVxmcmFjeyhcbG4geCAtIFxtdSleMn17MlxzaWdtYV4yfVxyaWdodCksIFxxdWFkIHggPiAwDQokJA0KDQpBZnRlciBzb21lIGFsZ2VicmEsIHdlIGNhbiBleHByZXNzIHRoZSBtZWFuIGFuZCB2YXJpYW5jZSBvZiB0aGUgYWJvdmUgbG9nbm9ybWFsIGRpc3RyaWJ1dGlvbiBpbiB0aGUgZm9sbG93aW5nDQoNCg0KXGJlZ2lue2FsaWdufQ0KXG1hdGhiYntFfVtYXSAmPSBcZXhwXGxlZnQoXG11ICsgXGZyYWN7XHNpZ21hXjJ9ezJ9XHJpZ2h0KSBcXA0KXHRleHR7VmFyfShYKSAmPSBbXGV4cChcc2lnbWFeMikgLSAxXSBcZXhwKDJcbXUgKyBcc2lnbWFeMikNClxlbmR7YWxpZ259DQoNCg0KVXNpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG5vcm1hbCBhbmQgbG9nLW5vcm1hbCBkaXN0cmlidXRpb24gYW5kIGEgc2FtcGxlICRce3hfMSwgeF8yLCBcZG90cywgeF9uXH0kLCB0aGUgTUxFIGVzdGltYXRvcnMgb2YgJFxtdSQgYW5kICRcc2lnbWFeMiQgYXJlIGdpdmVuIGJ5DQoNCg0KXGJlZ2lue2FsaWdufQ0KXGhhdHtcbXV9ICY9IFxmcmFjezF9e259XHN1bV97aT0xfV5uIFxsbih4X2kpIFxcDQpcaGF0e1xzaWdtYX1eMiAmPSBcZnJhY3sxfXtufVxzdW1fe2k9MX1ebiAoXGxuKHhfaSkgLSBcaGF0e1xtdX0pXjINClxlbmR7YWxpZ259DQoNCg0KVXNpbmcgdGhlIHBsdWctaW4gcHJpbmNpcGxlIG9mIE1MRSwgd2UgaGF2ZSB0aGUgTUxFIG9mICRcbWF0aGJie0V9W1hdJCBhbmQgJFx0ZXh0e1Zhcn0oWCkkIGluIHRoZSBmb2xsb3dpbmcNCg0KJCQNClxib3hlZHtcd2lkZWhhdHtcbWF0aGJie0V9W1hdfSA9IFxleHBcbGVmdChcaGF0e1xtdX0gKyBcZnJhY3tcaGF0e1xzaWdtYX1eMn17Mn1ccmlnaHQpfQ0KJCQNCg0KPC9QPg0KDQoNCg0KPHA+PGZvbnQgY29sb3IgPSAiYmx1ZSI+KipUaGlzIGFzc2lnbm1lbnQgZm9jdXNlcyBvbiBjb25zdHJ1Y3RpbmcgdmFyaW91cyBib290c3RyYXAgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2YgdGhlIGxvZ25vcm1hbCBwb3B1bGF0aW9uIG1lYW4gJFxtYXRoYmJ7RX1bWF0kKio8L2ZvbnQ+PC9wPg0KDQoNClwNCg0KIyMgKipRdWVzdGlvbjogVHJhY2UgTWV0YWwgQ29uY2VudHJhdGlvbnMgaW4gU29pbCoqDQoNCjxwPg0KU29pbCBsZWFkIChQYikgY29uY2VudHJhdGlvbnMgKG1nL2tnKSBmcm9tIDU1IHVyYmFuIGdhcmRlbiBzaXRlcy4gVHJhY2UgbWV0YWxzIGluIGVudmlyb25tZW50YWwgbWVkaWEgdHlwaWNhbGx5IGZvbGxvdyBsb2dub3JtYWwgZGlzdHJpYnV0aW9ucyBkdWUgdG86DQoNCiogTXVsdGlwbGljYXRpdmUgcHJvY2Vzc2VzIGNvbnRyb2xsaW5nIGFjY3VtdWxhdGlvbg0KDQoqIFBvc2l0aXZlIGNvbnN0cmFpbnRzIChjb25jZW50cmF0aW9ucyBjYW5ub3QgYmUgbmVnYXRpdmUpDQoNCiogUmlnaHQtc2tld2VkIG5hdHVyZSBvZiBjb250YW1pbmF0aW9uIHBhdHRlcm5zDQo8L3A+DQoNCg0KDQo8cD4NCmBgYA0KMC44NSwgMS4yMywgMC45MiwgMy40NSwgMi4xMSwgMS41NiwgNC44OSwgMi4zNCwgMS43OCwgNi43MiwgMC45NSwgMS4zNCwgOC45MSwgDQoyLjY3LCAxLjg5LCA1LjQzLCAxLjEyLCAzLjc4LCAyLjQ1LCA3LjY1LCAxLjA1LCAxLjQ1LCAxMi4zNCwgMi44OSwgMi4wMSwgNC41NiwgDQoxLjIzLCA0LjMyLCAyLjY3LCA5Ljg3LCAwLjk5LCAxLjU2LCAxNS4yMywgMy4xMiwgMi4zNCwgMy44OSwgMS4zNCwgNS42NywgMi44OSwgDQoxMS40NSwgMS4xMiwgMS42NywgMTguOTAsIDMuNDUsIDIuNTYsIDMuNDUsIDEuNDUsIDYuNzgsIDMuMTIsIDE0LjU2LCAxLjIzLCAxLjc4LCANCjIyLjM0LCAzLjc4LCAyLjc4DQpgYGANCjwvcD4NCg0KPHA+DQoNCiQkXGJveGVke1x0ZXh0e0luc3RydWN0aW9uczp9fSQkDQoNCkFzc3VtZSB0aGUgZGF0YSBmb2xsb3cgYSBsb2ctbm9ybWFsIGRpc3RyaWJ1dGlvbi4gRm9yIGVhY2ggcXVlc3Rpb24gaW4gcGFydHMgKGIp4oCTKGQpLCBiZWdpbiBieSBjbGVhcmx5IGV4cGxhaW5pbmcgdGhlIHJlYXNvbmluZyBiZWhpbmQgeW91ciBhbmFseXRpY2FsIGFwcHJvYWNoLiBUaGVuLCBkZXZlbG9wIHlvdXIgb3duIFIgZnVuY3Rpb25zIHRvIGltcGxlbWVudCB0aHJlZSB0eXBlcyBvZiBjb25maWRlbmNlIGludGVydmFsczogdGhlIGFzeW1wdG90aWMgaW50ZXJ2YWwsIHRoZSBwZXJjZW50aWxlIGJvb3RzdHJhcCBpbnRlcnZhbCwgYW5kIHRoZSBiaWFzLWNvcnJlY3RlZCBhbmQgYWNjZWxlcmF0ZWQgKEJDYSkgYm9vdHN0cmFwIGludGVydmFsLiBVc2UgdGhlc2UgZnVuY3Rpb25zIHRvIGNvbnN0cnVjdCB0aGUgcmVxdWlyZWQgY29uZmlkZW5jZSBpbnRlcnZhbHMsIGFuZCB2ZXJpZnkgeW91ciByZXN1bHRzIHVzaW5nIHRoZSBhcHByb3ByaWF0ZSBmdW5jdGlvbnMgZnJvbSB0aGUgYGJvb3RgIHBhY2thZ2UuDQoNCllvdSBhcmUgZW5jb3VyYWdlZCB0byBkZXNpZ24gYSB3cmFwcGVyIGZ1bmN0aW9uIHRoYXQgaW50ZWdyYXRlcyBhbGwgY29uZmlkZW5jZSBpbnRlcnZhbCBtZXRob2RzLCBhbGxvd2luZyB1c2VycyB0byBzZWxlY3QgdGhlIGRlc2lyZWQgbWV0aG9kIHRocm91Z2ggYW4gaW5wdXQgYXJndW1lbnQuDQo8L1A+DQoNCjxwPg0KDQokJFxib3hlZHtcdGV4dHtJbmRpdmlkdWFsIFF1ZXN0aW9uczp9fSQkDQoNCmEpLiBQZXJmb3JtIDUwMDAgYm9vdHN0cmFwIHNhbXBsZXMgdG8gZXN0aW1hdGUgdGhlIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgJFxib3hlZHtcd2lkZWhhdHtcbWF0aGJie0V9W1hdfX0kLiBEaXNwbGF5IHRoZSBkaXN0cmlidXRpb24gdXNpbmcgZWl0aGVyIGEgaGlzdG9ncmFtIG9yIGEga2VybmVsIGRlbnNpdHkgcGxvdC4gQ29tbWVudCBvbiB0aGUgc2hhcGUsIHZhcmlhYmlsaXR5LCBhbmQgYW55IG5vdGFibGUgcGF0dGVybnMgb2JzZXJ2ZWQgaW4gdGhlIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24uDQoNClRvIGVzdGltYXRlIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgdGhlIGxvZ25vcm1hbCBwb3B1bGF0aW9uIG1lYW4sIEkgdXNlIGJvb3RzdHJhcCByZXNhbXBsaW5nLiBGb3IgZWFjaCBib290c3RyYXAgc2FtcGxlLCBJIHJlc2FtcGxlIHRoZSBvYnNlcnZlZCBkYXRhIHdpdGggcmVwbGFjZW1lbnQgYW5kIGNvbXB1dGUgdGhlIHBsdWctaW4gZXN0aW1hdG9yIG9mIFwoRVtYXVwpLg0KDQpgYGB7cn0NCiMjIFNvaWwgbGVhZCBjb25jZW50cmF0aW9uIGRhdGEgKG1nL2tnKQ0Kc29pbCA8LSBjKA0KICAwLjg1LCAxLjIzLCAwLjkyLCAzLjQ1LCAyLjExLCAxLjU2LCA0Ljg5LCAyLjM0LCAxLjc4LCA2LjcyLCAwLjk1LCAxLjM0LCA4LjkxLA0KICAyLjY3LCAxLjg5LCA1LjQzLCAxLjEyLCAzLjc4LCAyLjQ1LCA3LjY1LCAxLjA1LCAxLjQ1LCAxMi4zNCwgMi44OSwgMi4wMSwgNC41NiwNCiAgMS4yMywgNC4zMiwgMi42NywgOS44NywgMC45OSwgMS41NiwgMTUuMjMsIDMuMTIsIDIuMzQsIDMuODksIDEuMzQsIDUuNjcsIDIuODksDQogIDExLjQ1LCAxLjEyLCAxLjY3LCAxOC45MCwgMy40NSwgMi41NiwgMy40NSwgMS40NSwgNi43OCwgMy4xMiwgMTQuNTYsIDEuMjMsIDEuNzgsDQogIDIyLjM0LCAzLjc4LCAyLjc4DQopDQoNCiMjIFBsdWctaW4gZXN0aW1hdG9yIGZvciB0aGUgbG9nbm9ybWFsIHBvcHVsYXRpb24gbWVhbiBFW1hdDQpsb2dub3JtYWxfbWVhbl9oYXQgPC0gZnVuY3Rpb24oeCkgew0KICBsb2d4IDwtIGxvZyh4KQ0KICBtdV9oYXQgPC0gbWVhbihsb2d4KQ0KICBzaWdtYTJfaGF0IDwtIG1lYW4oKGxvZ3ggLSBtdV9oYXQpXjIpICAjIE1MRSBvZiB2YXJpYW5jZSBvbiBsb2ctc2NhbGUNCiAgZXhwKG11X2hhdCArIHNpZ21hMl9oYXQgLyAyKQ0KfQ0KDQojIyBDb21wdXRlIGVzdGltYXRlIGZyb20gb3JpZ2luYWwgc2FtcGxlDQp0aGV0YV9oYXQgPC0gbG9nbm9ybWFsX21lYW5faGF0KHNvaWwpDQp0aGV0YV9oYXQNCmBgYA0KDQpgYGB7cn0NCiMjIEJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgRVtYXQ0Kc2V0LnNlZWQoMSkNCg0KQiA8LSA1MDAwDQpuIDwtIGxlbmd0aChzb2lsKQ0KYm9vdF90aGV0YSA8LSByZXAoMCwgQikNCg0KZm9yIChiIGluIDE6Qikgew0KICB4X3N0YXIgPC0gc2FtcGxlKHNvaWwsIHNpemUgPSBuLCByZXBsYWNlID0gVFJVRSkNCiAgYm9vdF90aGV0YVtiXSA8LSBsb2dub3JtYWxfbWVhbl9oYXQoeF9zdGFyKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KIyMgSGlzdG9ncmFtIG9mIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24NCmhpc3QoYm9vdF90aGV0YSwNCiAgICAgYnJlYWtzID0gMzAsDQogICAgIG1haW4gPSAiQm9vdHN0cmFwIFNhbXBsaW5nIERpc3RyaWJ1dGlvbiBvZiBFW1hdIiwNCiAgICAgeGxhYiA9IGV4cHJlc3Npb24oaGF0KEVbWF0pKSkNCmBgYA0KDQpUaGUgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZXN0aW1hdGVkIHZhbHVlIG9mIEVbWF0gYXBwZWFycyByb3VnaGx5IHVuaW1vZGFsIHdpdGggYSBzbGlnaHQgcmlnaHQgc2tldy4gSXQgaXMgY2VudGVyZWQgYXJvdW5kIHRoZSBvcmlnaW5hbCBlc3RpbWF0ZSBhbmQgc2hvd3MgYSBtb2RlcmF0ZSBhbW91bnQgb2YgdmFyaWFiaWxpdHkuIFRoZSByaWdodCBza2V3IGlzIGV4cGVjdGVkIGdpdmVuIHRoZSBsb2dub3JtYWwgbmF0dXJlIG9mIHRoZSBkYXRhLCBhbmQgYSBmZXcgbGFyZ2VyIHZhbHVlcyBpbmRpY2F0ZSB0aGUgZWZmZWN0IG9mIGhpZ2hlciBvYnNlcnZhdGlvbnMgaW4gdGhlIHNhbXBsZS4NCg0KYikuIENvbnN0cnVjdCBhIDk1JSBib290c3RyYXAgcGVyY2VudGlsZSBjb25maWRlbmNlIGludGVydmFsIGZvciAkXG11X3tMTn0gPSBcbWF0aGJie0V9W1hdJC4NCg0KVG8gY29uc3RydWN0IHRoZSA5NSUgYm9vdHN0cmFwIHBlcmNlbnRpbGUgY29uZmlkZW5jZSBpbnRlcnZhbCwgSSB1c2UgdGhlIGVtcGlyaWNhbCBkaXN0cmlidXRpb24gb2YgdGhlIGJvb3RzdHJhcCBlc3RpbWF0ZXMgb2J0YWluZWQgaW4gcGFydCAoYSkuIFNpbmNlIHRoZSBwZXJjZW50aWxlIG1ldGhvZCB1c2VzIHRoZSBxdWFudGlsZXMgb2YgdGhlIGJvb3RzdHJhcCBzYW1wbGluZyBkaXN0cmlidXRpb24gZGlyZWN0bHksIEkgdGFrZSB0aGUgMi41dGggYW5kIDk3LjV0aCBwZXJjZW50aWxlcyBvZiB0aGUgYm9vdHN0cmFwIGVzdGltYXRlcyBvZiB0aGUgbG9nbm9ybWFsIHBvcHVsYXRpb24gbWVhbi4gVGhpcyBnaXZlcyBhIDk1JSBwZXJjZW50aWxlIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFsIGZvciAkXG11X3tMTn0gPSBcbWF0aGJie0V9W1hdJC4NCg0KYGBge3J9DQojIyBQZXJjZW50aWxlIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFsIGZvciBFW1hdDQpwZXJjZW50aWxlX2NpIDwtIGZ1bmN0aW9uKGJvb3Rfc3RhdCwgYWxwaGEgPSAwLjA1KSB7DQogIHF1YW50aWxlKGJvb3Rfc3RhdCwgcHJvYnMgPSBjKGFscGhhIC8gMiwgMSAtIGFscGhhIC8gMikpDQp9DQoNCmNpX3BlcmNlbnRpbGUgPC0gcGVyY2VudGlsZV9jaShib290X3RoZXRhKQ0KY2lfcGVyY2VudGlsZQ0KYGBgDQoNCmBgYHtyfQ0KIyMgVmVyaWZ5IHBlcmNlbnRpbGUgaW50ZXJ2YWwgdXNpbmcgYm9vdCBwYWNrYWdlDQpsaWJyYXJ5KGJvb3QpDQoNCmJvb3RfbWVhbl9zdGF0IDwtIGZ1bmN0aW9uKGRhdGEsIGluZGljZXMpIHsNCiAgc2FtcGxlX2RhdGEgPC0gZGF0YVtpbmRpY2VzXQ0KICBsb2dub3JtYWxfbWVhbl9oYXQoc2FtcGxlX2RhdGEpDQp9DQoNCmJvb3RfcmVzdWx0IDwtIGJvb3QoZGF0YSA9IHNvaWwsIHN0YXRpc3RpYyA9IGJvb3RfbWVhbl9zdGF0LCBSID0gNTAwMCkNCmJvb3QuY2koYm9vdF9yZXN1bHQsIHR5cGUgPSAicGVyYyIpDQpgYGANCg0KVXNpbmcgbXkgcGVyY2VudGlsZSBib290c3RyYXAgZnVuY3Rpb24sIHRoZSA5NSUgYm9vdHN0cmFwIHBlcmNlbnRpbGUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgJFxtdV97TE59ID0gXG1hdGhiYntFfVtYXSQgaXMgKDMuMTI1NCwgNS41OTAwKS4gSSB2ZXJpZmllZCB0aGlzIHJlc3VsdCB1c2luZyB0aGUgYm9vdCBwYWNrYWdlLCB3aGljaCBnYXZlIGEgdmVyeSBzaW1pbGFyIGludGVydmFsIG9mIGFwcHJveGltYXRlbHkgKDMuMTM2LDUuNTQ5KS4gU2luY2UgdGhlIGludGVydmFscyBhcmUgY2xvc2UsIHRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlIHBlcmNlbnRpbGUgbWV0aG9kIHdhcyBhcHBsaWVkIGNvcnJlY3RseS4NCg0KYykuIENvbnN0cnVjdCBhIDk1JSBib290c3RyYXAgQkNhIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yICRcbXVfe0xOfSA9IFxtYXRoYmJ7RX1bWF0kLg0KDQpUbyBjb25zdHJ1Y3QgdGhlIDk1JSBib290c3RyYXAgQkNhIGNvbmZpZGVuY2UgaW50ZXJ2YWwsIEkgdXNlIHRoZSBib290c3RyYXAgZXN0aW1hdGVzIGZyb20gcGFydCAoYSkgYW5kIGFkanVzdCB0aGVtIGZvciBiaWFzIGFuZCBza2V3bmVzcy4gVGhlIEJDYSBtZXRob2QgaW1wcm92ZXMgb24gdGhlIHBlcmNlbnRpbGUgYXBwcm9hY2ggYnkgYWNjb3VudGluZyBmb3IgYXN5bW1ldHJ5IGluIHRoZSBib290c3RyYXAgc2FtcGxpbmcgZGlzdHJpYnV0aW9uLiBTaW5jZSB0aGUgZXN0aW1hdGVkIGxvZ25vcm1hbCBtZWFuIGlzIHNsaWdodGx5IHJpZ2h0LXNrZXdlZCwgdGhpcyBtZXRob2QgaXMgYXBwcm9wcmlhdGUgZm9yIGNvbnN0cnVjdGluZyBhIG1vcmUgYWNjdXJhdGUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgJFxtdV97TE59ID0gXG1hdGhiYntFfVtYXSQuDQoNCmBgYHtyfQ0KIyMgQkNhIGJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFsIGZvciBFW1hdDQpiY2FfY2kgPC0gZnVuY3Rpb24oZGF0YSwgYm9vdF9zdGF0LCBzdGF0X2Z1bmN0aW9uLCBhbHBoYSA9IDAuMDUpIHsNCiAgdGhldGFfaGF0IDwtIHN0YXRfZnVuY3Rpb24oZGF0YSkNCiAgDQogICMjIE1lYXN1cmVzIGhvdyB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBpcyBzaGlmdGVkIGZyb20gdGhlIG9yaWdpbmFsIGVzdGltYXRlDQogIHowIDwtIHFub3JtKG1lYW4oYm9vdF9zdGF0IDwgdGhldGFfaGF0KSkNCiAgDQogIG4gPC0gbGVuZ3RoKGRhdGEpDQogIGphY2tfc3RhdCA8LSByZXAoMCwgbikNCiAgDQogICMjIFVzZXMgamFja2tuaWZlIGVzdGltYXRlcyB0byBhY2NvdW50IGZvciBza2V3bmVzcyBpbiB0aGUgZGlzdHJpYnV0aW9uDQogIGZvciAoaSBpbiAxOm4pIHsNCiAgICBqYWNrX3NhbXBsZSA8LSBkYXRhWy1pXQ0KICAgIGphY2tfc3RhdFtpXSA8LSBzdGF0X2Z1bmN0aW9uKGphY2tfc2FtcGxlKQ0KICB9DQogIA0KICBqYWNrX21lYW4gPC0gbWVhbihqYWNrX3N0YXQpDQogIG51bSA8LSBzdW0oKGphY2tfbWVhbiAtIGphY2tfc3RhdCleMykNCiAgZGVuIDwtIHN1bSgoamFja19tZWFuIC0gamFja19zdGF0KV4yKQ0KICBhX2hhdCA8LSBudW0gLyAoNiAqIGRlbl4oMy8yKSkNCiAgDQogIHpfYWxwaGExIDwtIHFub3JtKGFscGhhIC8gMikNCiAgel9hbHBoYTIgPC0gcW5vcm0oMSAtIGFscGhhIC8gMikNCiAgDQogICMjIEFkanVzdHMgdGhlIHBlcmNlbnRpbGUgbGV2ZWxzIHVzaW5nIGJpYXMgYW5kIHNrZXduZXNzDQogIHAxIDwtIHBub3JtKHowICsgKHowICsgel9hbHBoYTEpIC8gKDEgLSBhX2hhdCAqICh6MCArIHpfYWxwaGExKSkpDQogIHAyIDwtIHBub3JtKHowICsgKHowICsgel9hbHBoYTIpIC8gKDEgLSBhX2hhdCAqICh6MCArIHpfYWxwaGEyKSkpDQogIA0KICBxdWFudGlsZShib290X3N0YXQsIHByb2JzID0gYyhwMSwgcDIpKQ0KfQ0KDQpjaV9iY2EgPC0gYmNhX2NpKHNvaWwsIGJvb3RfdGhldGEsIGxvZ25vcm1hbF9tZWFuX2hhdCkNCmNpX2JjYQ0KYGBgDQoNCmBgYHtyfQ0KIyMgVmVyaWZ5IEJDYSBpbnRlcnZhbCB1c2luZyBib290IHBhY2thZ2UNCmJvb3QuY2koYm9vdF9yZXN1bHQsIHR5cGUgPSAiYmNhIikNCmBgYA0KDQpVc2luZyBteSBCQ2EgYm9vdHN0cmFwIGZ1bmN0aW9uLCB0aGUgOTUlIEJDYSBjb25maWRlbmNlIGludGVydmFsIGZvciAkXG11X3tMTn0gPSBcbWF0aGJie0V9W1hdJCAgaXMgKDMuMjE5NCwgNS44MTE0KS4gSSB2ZXJpZmllZCB0aGlzIHJlc3VsdCB1c2luZyB0aGUgYm9vdCBwYWNrYWdlLCB3aGljaCBnYXZlIGEgdmVyeSBzaW1pbGFyIEJDYSBpbnRlcnZhbCBvZiBhcHByb3hpbWF0ZWx5ICgzLjIzMyw1Ljc3NCkuIFNpbmNlIHRoZSBpbnRlcnZhbHMgYXJlIGNsb3NlLCB0aGlzIGluZGljYXRlcyB0aGF0IHRoZSBCQ2EgbWV0aG9kIHdhcyBhcHBsaWVkIGNvcnJlY3RseS4NCg0KZCkuIFVzZSB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtIHRvIGNvbnN0cnVjdCBhIDk1JSBhc3ltcHRvdGljIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yICRcbXVfe0xOfSA9IFxtYXRoYmJ7RX1bWF0kLg0KDQpUbyBjb25zdHJ1Y3QgdGhlIDk1JSBhc3ltcHRvdGljIGNvbmZpZGVuY2UgaW50ZXJ2YWwsIEkgdXNlIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gdG9nZXRoZXIgd2l0aCB0aGUgZGVsdGEgbWV0aG9kLiBTaW5jZSB0aGUgZXN0aW1hdG9yIG9mIHRoZSBsb2dub3JtYWwgcG9wdWxhdGlvbiBtZWFuIGlzIGEgc21vb3RoIGZ1bmN0aW9uIG9mICRcaGF0e1xtdX0kIGFuZCAkXGhhdHtcc2lnbWF9XjIkLCBpdHMgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIGlzIGFwcHJveGltYXRlbHkgbm9ybWFsIGZvciBhIHN1ZmZpY2llbnRseSBsYXJnZSBzYW1wbGUgc2l6ZS4gSSB0aGVyZWZvcmUgZXN0aW1hdGUgaXRzIHN0YW5kYXJkIGVycm9yIHVzaW5nIHRoZSBwbHVnLWluIGFwcHJvYWNoIGFuZCB0aGVuIHVzZSB0aGUgbm9ybWFsIGNyaXRpY2FsIHZhbHVlICQxLjk2JCB0byBmb3JtIHRoZSBjb25maWRlbmNlIGludGVydmFsIGZvciAkXG11X3tMTn0gPSBcbWF0aGJie0V9W1hdJC4NCg0KYGBge3J9DQojIyBBc3ltcHRvdGljIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIEVbWF0NCmFzeW1wdG90aWNfY2kgPC0gZnVuY3Rpb24oZGF0YSwgYWxwaGEgPSAwLjA1KSB7DQogIGxvZ3ggPC0gbG9nKGRhdGEpDQogIG4gPC0gbGVuZ3RoKGRhdGEpDQogIA0KICBtdV9oYXQgPC0gbWVhbihsb2d4KQ0KICBzaWdtYTJfaGF0IDwtIG1lYW4oKGxvZ3ggLSBtdV9oYXQpXjIpDQogIHRoZXRhX2hhdCA8LSBleHAobXVfaGF0ICsgc2lnbWEyX2hhdCAvIDIpDQogIA0KICAjIyBUaGUgc3RhbmRhcmQgZXJyb3IgaXMgZXN0aW1hdGVkIHVzaW5nIHRoZSBkZWx0YSBtZXRob2Qgd2l0aCBwbHVnLWluIGVzdGltYXRlcw0KICBzZV9oYXQgPC0gdGhldGFfaGF0ICogc3FydCgoc2lnbWEyX2hhdCArIHNpZ21hMl9oYXReMiAvIDIpIC8gbikNCiAgDQogICMjIFRoZSBub3JtYWwgY3JpdGljYWwgdmFsdWUgaXMgdXNlZCBiZWNhdXNlIHRoZSBlc3RpbWF0b3IgaXMgYXN5bXB0b3RpY2FsbHkgbm9ybWFsDQogIHpfY3JpdCA8LSBxbm9ybSgxIC0gYWxwaGEgLyAyKQ0KICANCiAgYyh0aGV0YV9oYXQgLSB6X2NyaXQgKiBzZV9oYXQsIHRoZXRhX2hhdCArIHpfY3JpdCAqIHNlX2hhdCkNCn0NCg0KY2lfYXN5bSA8LSBhc3ltcHRvdGljX2NpKHNvaWwpDQpjaV9hc3ltDQpgYGANCg0KYGBge3J9DQojIyBWZXJpZnkgYXN5bXB0b3RpYyBpbnRlcnZhbCB1c2luZyBib290IHBhY2thZ2UNCmJvb3QuY2koYm9vdF9yZXN1bHQsIHR5cGUgPSAibm9ybSIpDQpgYGANCg0KVXNpbmcgbXkgYXN5bXB0b3RpYyBjb25maWRlbmNlIGludGVydmFsIGZ1bmN0aW9uLCB0aGUgOTUlIGFzeW1wdG90aWMgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgJFxtdV97TE59ID0gXG1hdGhiYntFfVtYXSQgaXMgKDMuMTM1MCwgNS4zMDEyKS4gSSB2ZXJpZmllZCB0aGlzIHJlc3VsdCB1c2luZyB0aGUgYm9vdCBwYWNrYWdlLCB3aGljaCBnYXZlIGEgc2ltaWxhciBub3JtYWwgaW50ZXJ2YWwgb2YgYXBwcm94aW1hdGVseSAoMi45ODYsIDUuNDI3KS4gU2luY2UgdGhlIGludGVydmFscyBhcmUgcmVhc29uYWJseSBjbG9zZSwgdGhpcyBpbmRpY2F0ZXMgdGhhdCB0aGUgYXN5bXB0b3RpYyBtZXRob2Qgd2FzIGFwcGxpZWQgY29ycmVjdGx5Lg0KDQpgYGB7cn0NCiMjIFdyYXBwZXIgZnVuY3Rpb24gZm9yIGNvbmZpZGVuY2UgaW50ZXJ2YWwgbWV0aG9kcw0KY2lfd3JhcHBlciA8LSBmdW5jdGlvbihkYXRhLCBib290X3N0YXQsIG1ldGhvZCA9ICJwZXJjZW50aWxlIiwgYWxwaGEgPSAwLjA1KSB7DQogIGlmIChtZXRob2QgPT0gInBlcmNlbnRpbGUiKSB7DQogICAgcGVyY2VudGlsZV9jaShib290X3N0YXQsIGFscGhhKQ0KICB9IGVsc2UgaWYgKG1ldGhvZCA9PSAiYmNhIikgew0KICAgIGJjYV9jaShkYXRhLCBib290X3N0YXQsIGxvZ25vcm1hbF9tZWFuX2hhdCwgYWxwaGEpDQogIH0gZWxzZSBpZiAobWV0aG9kID09ICJhc3ltcHRvdGljIikgew0KICAgIGFzeW1wdG90aWNfY2koZGF0YSwgYWxwaGEpDQogIH0gZWxzZSB7DQogICAgc3RvcCgiTWV0aG9kIG11c3QgYmUgJ3BlcmNlbnRpbGUnLCAnYmNhJywgb3IgJ2FzeW1wdG90aWMnIikNCiAgfQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KY2lfd3JhcHBlcihzb2lsLCBib290X3RoZXRhLCBtZXRob2QgPSAicGVyY2VudGlsZSIpDQpjaV93cmFwcGVyKHNvaWwsIGJvb3RfdGhldGEsIG1ldGhvZCA9ICJiY2EiKQ0KY2lfd3JhcHBlcihzb2lsLCBib290X3RoZXRhLCBtZXRob2QgPSAiYXN5bXB0b3RpYyIpDQpgYGANCg0KZikuIEFzc3VtaW5nIHRoZSBjb25maWRlbmNlIGludGVydmFscyBjb25zdHJ1Y3RlZCBpbiB0aGUgcHJldmlvdXMgcGFydHMgYXJlIHZhbGlkLCBldmFsdWF0ZSB0aGVpciBwZXJmb3JtYW5jZSBieSBjb21wYXJpbmcgdGhlaXIgd2lkdGhzLCBzeW1tZXRyeSwgc3RhYmlsaXR5LCBhbmQgc2Vuc2l0aXZpdHkgdG8gZGlzdHJpYnV0aW9uYWwgc2tld25lc3MuIFRoZW4sIHByb3ZpZGUgYSB3ZWxs4oCRcmVhc29uZWQgcmVjb21tZW5kYXRpb24gcmVnYXJkaW5nIHdoaWNoIG1ldGhvZCBpcyBtb3N0IHN1aXRhYmxlIGZvciB0aGlzIGFuYWx5c2lzLg0KDQpUaGUgYXN5bXB0b3RpYyBpbnRlcnZhbCBpcyB0aGUgbmFycm93ZXN0LCB0aGUgQkNhIGludGVydmFsIGlzIHRoZSB3aWRlc3QsIGFuZCB0aGUgcGVyY2VudGlsZSBpbnRlcnZhbCBsaWVzIGluIGJldHdlZW4uIFRoZSBhc3ltcHRvdGljIGludGVydmFsIGlzIGFsc28gdGhlIG1vc3Qgc3ltbWV0cmljIGFyb3VuZCB0aGUgb3JpZ2luYWwgZXN0aW1hdGUgYmVjYXVzZSBpdCBpcyBiYXNlZCBvbiBhIG5vcm1hbCBhcHByb3hpbWF0aW9uLiBIb3dldmVyLCB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBmcm9tIHBhcnQgKGEpIHNob3dlZCBzbGlnaHQgcmlnaHQgc2tld25lc3MsIHNvIGEgc3ltbWV0cmljIGludGVydmFsIG1heSBub3QgZnVsbHkgcmVmbGVjdCB0aGUgc2hhcGUgb2YgdGhlIGRhdGEuIFRoZSBwZXJjZW50aWxlIGludGVydmFsIHJlZmxlY3RzIHRoZSBib290c3RyYXAgZGlzdHJpYnV0aW9uIG1vcmUgZGlyZWN0bHksIGJ1dCBpdCBkb2VzIG5vdCBhZGp1c3QgZm9yIGJpYXMuIFRoZSBCQ2EgaW50ZXJ2YWwgYWRqdXN0cyBmb3IgYm90aCBiaWFzIGFuZCBza2V3bmVzcywgbWFraW5nIGl0IG1vcmUgc2Vuc2l0aXZlIHRvIHRoZSBhc3ltbWV0cnkgaW4gdGhlIGRhdGEuIEFsbCB0aHJlZSBpbnRlcnZhbHMgYXJlIHJlbGF0aXZlbHkgc2ltaWxhciwgYnV0IHRoZSBCQ2EgaW50ZXJ2YWwgaXMgbW9yZSByZWxpYWJsZSBpbiB0aGlzIGNhc2UuIFRoZXJlZm9yZSwgSSB3b3VsZCByZWNvbW1lbmQgdGhlIEJDYSBpbnRlcnZhbCBhcyB0aGUgbW9zdCBzdWl0YWJsZSBtZXRob2QgZm9yIGVzdGltYXRpbmcgJFxtdV97TE59ID0gXG1hdGhiYntFfVtYXSQuIFRoaXMgbWV0aG9kIHRha2VzIGludG8gYWNjb3VudCB0d28gaW1wb3J0YW50IHRoaW5nczogYmlhcyBhbmQgc2tld25lc3MuIEJpYXMgaXMgbGlrZSBhIHN5c3RlbWF0aWMgZXJyb3IsIGFuZCBza2V3bmVzcyBpcyB3aGVuIHRoZSBkYXRhIGlzbid0IHBlcmZlY3RseSBzeW1tZXRyaWNhbC4gQnkgY29uc2lkZXJpbmcgYm90aCBvZiB0aGVzZSwgdGhlIEJDYSBpbnRlcnZhbCBnaXZlcyBhIG1vcmUgYWNjdXJhdGUgZXN0aW1hdGUuIENvbXBhcmVkIHRvIG90aGVyIG1ldGhvZHMsIGl0J3MgbW9yZSBzdWl0YWJsZSBmb3IgdGhpcyBraW5kIG9mIGFuYWx5c2lzLg0KDQo=