Assignment Objectives

  • Reinforce the understanding of Bootstrap sampling .

  • Understand the bootstrap estimation: confidence interval and sampling distribution.

Policies of Using AI Tools

Policy on AI Tool Use: Please adhere to the AI tool policy specified in the course syllabus. The direct copying of AI-generated content is strictly prohibited. All submitted work must reflect your own understanding; where external tools are consulted, content must be thoroughly rephrased and synthesized in your own words.

Code Inclusion Requirement: Any code included in your essay must be properly commented to explain the purpose and/or expected output of key code lines. Submitting AI-generated code without meaningful, student-added comments will not be accepted.

Log-normal Distribution Revisited

If \(Y = \ln(X) \sim N(\mu, \sigma^2)\), then \(X\) follows a lognormal distribution \(X \sim \text{Lognormal}(\mu, \sigma^2)\). The probability density is given by

\[ f(x|\mu,\sigma) = \frac{1}{x\sigma\sqrt{2\pi}} \exp\left(-\frac{(\ln x - \mu)^2}{2\sigma^2}\right), \quad x > 0 \]

After some algebra, we can express the mean and variance of the above lognormal distribution in the following

\[\begin{align} \mathbb{E}[X] &= \exp\left(\mu + \frac{\sigma^2}{2}\right) \\ \text{Var}(X) &= [\exp(\sigma^2) - 1] \exp(2\mu + \sigma^2) \end{align}\]

Using the relationship between normal and log-normal distribution and a sample \(\{x_1, x_2, \dots, x_n\}\), the MLE estimators of \(\mu\) and \(\sigma^2\) are given by

\[\begin{align} \hat{\mu} &= \frac{1}{n}\sum_{i=1}^n \ln(x_i) \\ \hat{\sigma}^2 &= \frac{1}{n}\sum_{i=1}^n (\ln(x_i) - \hat{\mu})^2 \end{align}\]

Using the plug-in principle of MLE, we have the MLE of \(\mathbb{E}[X]\) and \(\text{Var}(X)\) in the following

\[ \boxed{\widehat{\mathbb{E}[X]} = \exp\left(\hat{\mu} + \frac{\hat{\sigma}^2}{2}\right)} \]

This assignment focuses on constructing various bootstrap confidence intervals of the lognormal population mean \(\mathbb{E}[X]\)


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=