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.

Question 1 Part A

set.seed(123) #Sets seed
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)

B <- 5000 #Number of bootstrap samples
n <- length(soil) #Gets n which is used later
boot_ex <- numeric(B) #Sets empty vector to store bootstrap sample means

for(b in 1:B){
  boot_sample <- sample(soil, n, replace=TRUE) #Does bootstrap sampling
  boot_mu <- mean(log(boot_sample)) #Gets mu
  boot_sigma2 <- var(log(boot_sample)) #Gets sigma^2
  boot_ex[b] <- exp(boot_mu + boot_sigma2/2) #Gets E[X]
  
}

kde_soil <- density(boot_ex) #Makes KDE of bootstrap sample means

plot(kde_soil, main = "KDE from Bootstrap Sample Means", xlab="Sample Means", col="blue")

The bootstrap sampling distribution appears to follow a symmetric distribution centered somewhere between 4 and 5. It’s approximately a bell shaped distribution and the vast majority of the observations are are between 3 and 6.

b). Construct a 95% bootstrap percentile confidence interval for \(\mu_{LN} = \mathbb{E}[X]\).

Question 1 Part B

For the bootstrap percentile confidence interval we first need to sort the bootstrap \(\widehat{\mathbb{E}[X]}\) values (this will be done automatically in the quantile function in the code). Then we need to plug these sorted values into the formula:

\[ \left[\hat{\theta}_{B\cdot\alpha/2}^*, \hat{\theta}_{B\cdot(1-\alpha/2)}^* \right] \Rightarrow \left[\widehat{\mathbb{E}[X]}_{(5000\cdot 0.05/2)}^*, \widehat{\mathbb{E}[X]}_{(5000\cdot (1-0.05/2))}^* \right] \]

This formula can then be used to find the bootstrap percentile confidence interval in the code below:

ci_percentile <- function(boot_vals, alpha = 0.05){ #Creates function
  output_ci <- quantile(boot_vals, c(alpha/2, 1-alpha/2)) #Creates interval
  return(output_ci)
}
lowuppercentile <- ci_percentile(boot_ex) 
lowuppercentile #States interval 
    2.5%    97.5% 
3.110817 5.683647 

From this output we know that the lower bound of the bootstrap percentile confidence interval is 3.110817 and the upper bound is 5.683647.

library(boot)

boot_fn <- function(data, i) { #Used to create function used later
  x <- data[i]
  mu_hat <- mean(log(x))
  sigma2_hat <- var(log(x))
  exp(mu_hat + sigma2_hat / 2)
}

boot_obj <- boot(soil, boot_fn, R = 5000) #Creates boot object

boot.ci(boot_obj, type = "perc") #Uses boot.ci to get confidence interval
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates

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

Intervals : 
Level     Percentile     
95%   ( 3.140,  5.649 )  
Calculations and Intervals on Original Scale

Given that the interval provided by the ‘boot.ci’ function is (3.134, 5.676) which is similar to our function’s output of (3.110817, 5.683647) it seems that our function is accurate.

c). Construct a 95% bootstrap BCa confidence interval for \(\mu_{LN} = \mathbb{E}[X]\).

Question 1 Part C

In order to find the bootstrap BCa confidence interval we will first compute the bias correction using the \(\hat{z}_0\) formula shown in class. Then we will use the jackknife method to find \(\hat{a}\). Finally, we will compute the adjusted percentiles \(\alpha_1\) and \(\alpha_2\). We will then use the adjusted percentiles to find the confidence interval:

\[ \left[\hat{\theta}_{B\cdot\alpha_1}^*, \hat{\theta}_{B\cdot\alpha_2}^* \right] \Rightarrow \left[\widehat{\mathbb{E}[X]}_{(5000\cdot \alpha_1)}^*, \widehat{\mathbb{E}[X]}_{(5000\cdot\alpha_2}^* \right] \]

We can then plug these formulas into the code below to get the bootstrap BCa confidence interval:

ex_hat_fn <- function(x) { #Used later to get E[X]
  mu_hat <- mean(log(x))
  sigma2_hat <- var(log(x))
  exp(mu_hat + sigma2_hat / 2)
}

ci_bca <- function(data, boot_vals, ex_hat_fn, alpha = 0.05) {
  n <- length(data) #Gets n
  ex_hat <- ex_hat_fn(data) #Gets E[X] from sample
  
  z0 <- qnorm(mean(boot_vals < ex_hat)) #Gets bias correction factors
  
  jack <- sapply(1:n, function(i) ex_hat_fn(data[-i])) #Gets the jackknife estimates
  jack_mean <- mean(jack) #Gets mean
  
  num <- sum((jack_mean - jack)^3) #Gets acceleration factor
  den <- 6 * (sum((jack_mean - jack)^2))^(3/2)
  a <- num / den
  
  z_alpha <- qnorm(c(alpha/2, 1 - alpha/2)) #Gets normal cutoffs
  
  adj <- pnorm(z0 + (z0 + z_alpha) / (1 - a * (z0 + z_alpha))) #Uses formula from above
  
  output_ci2 <- quantile(boot_vals, adj) #Uses adjusted probabilities to get to get confidence interval
  
  return(output_ci2)
}

lowupbca <- ci_bca(soil, boot_ex, ex_hat_fn)
lowupbca #States confidence interval
4.196505%  98.7084% 
 3.244080  5.915138 

From this output we know that the lower bound of the bootstrap percentile confidence interval is 3.244080 and the upper bound is 5.915138.

boot.ci(boot_obj, type = "bca") #Uses boot.ci to get confidence interval
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates

CALL : 
boot.ci(boot.out = boot_obj, type = "bca")

Intervals : 
Level       BCa          
95%   ( 3.241,  5.848 )  
Calculations and Intervals on Original Scale

Given that the interval provided by the ‘boot.ci’ function is (3.248, 6.001) which is similar to our function’s output of (3.244080, 5.915138) it seems that our function is accurate.

d). Use the Central Limit Theorem to construct a 95% asymptotic confidence interval for \(\mu_{LN} = \mathbb{E}[X]\).

Question 1 Part D

Now that we have the bootstrap \(\widehat{\mathbb{E}[X]}\) values we can all we need to do is calculate \(\widehat{\mathbb{E}[X]}\) for our original sample, find the standard deviation of the bootstrap \(\widehat{\mathbb{E}[X]}\)’s. We know that:

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

We also know that the confidence interval can be found using:

\[ \widehat{\mathbb{E}[X]} \pm z_{\alpha/2} \cdot \hat{se}_{boot} \]

Where:

\[ \hat{se}_{boot}=\sqrt{\frac{1}{5000-1}\sum_{b=1}^{5000}(\widehat{\mathbb{E}[X]}_b^*-\overline{\mathbb{E}[X]}^*)^2} \]

We can plug these formulas into our code in order to find the confidence interval

ci_asymptotic <- function(data, boot_vals, alpha = 0.05) {
  ex_hat <- mean(boot_vals) #Gets E[X]
  se <- sd(boot_vals) #Gets standard deviation
  z <- qnorm(1 - alpha/2) #Gets z-value
  
  output3 <- c(lower = ex_hat - z * se, upper = ex_hat + z * se)  #Calculates confidence interval
  return(output3)
}

lowupasymptotic <- ci_asymptotic(soil, boot_ex) 
lowupasymptotic #States confidence interval
   lower    upper 
2.985746 5.532843 

From this output we know that the lower bound of the bootstrap percentile confidence interval is 2.985746 and the upper bound is 5.532843.

boot.ci(boot_obj, type = "norm") #Uses boot.ci to get confidence interval
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates

CALL : 
boot.ci(boot.out = boot_obj, type = "norm")

Intervals : 
Level      Normal        
95%   ( 2.980,  5.487 )  
Calculations and Intervals on Original Scale

Given that the interval provided by the ‘boot.ci’ function is (2.955, 5.531) which is similar to our function’s output of (2.985746, 5.532843 ) it seems that our function is accurate.

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.

Question 1 Part F

The asymptotic confidence interval has the smallest confidence interval with a width of 2.547097, compared to the bootstrap percentile confidence interval width of 2.57283 and the bootstrap BCa confidence interval width of 2.671058. The percentile method is simple and range-preserving, the BCa method correct bias/skew, and the asymptotic normal approximation is fast but assumes normality. Considering the KDE from the bootstrap sample means which is symmetric and appears normally distributed with a bell-shaped curve, the asymptotic confidence interval seems to be appropriate in this case. So, provided that all of the confidence intervals are valid (in that we can be at least 95% confident the true value of the expected value is between the upper and lower limits) I would recommend the asymptotic confidence interval given that it has the smallest interval and it seems appropriate in this setting.

LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgODogQm9vdHN0cmFwIE1ldGhvZHMgYW5kIEFwcGxpY2F0aW9ucyINCmF1dGhvcjogIkdyYWNlIExpcHBlcnQiDQpkYXRlOiAiIER1ZTogMy8zMS8yMDI2ICINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICBoaWdobGlnaHQ6IG1vbm9jaHJvbWUNCiAgICB0aGVtZTogc3BhY2VsYWINCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQogIHBkZl9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBmaWdfd2lkdGg6IDMNCiAgICBmaWdfaGVpZ2h0OiAzDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQojVE9DOjpiZWZvcmUgew0KICBjb250ZW50OiAiVGFibGUgb2YgQ29udGVudHMiOw0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAxLjJlbTsNCiAgZGlzcGxheTogYmxvY2s7DQogIGNvbG9yOiBuYXZ5Ow0KICBtYXJnaW4tYm90dG9tOiAxMHB4Ow0KfQ0KDQoNCmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8NCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCg0KaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8NCiAgZm9udC1zaXplOiAyMnB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KfQ0KDQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE1cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovDQouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7DQogIGNvbnRlbnQ6ICIuIjsNCg0KYm9keSB7YmFja2dyb3VuZC1jb2xvcjogI2ZmZmZmZjsNCiAgICAgIGNvbG9yOiAjMDAwMDAwOw0KICAgICAgZm9udC1mYW1pbHk6IEFyaWFsLCBzYW5zLXNlcmlmOw0KICAgICAgZm9udC1zaXplOiAxcmVtOw0KICAgICAgbGluZS1oZWlnaHQ6IDEuNjsNCiAgICAgIH0NCg0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCg0KcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KfQ0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoInBhbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJwYW5kZXIiKQ0KICAgbGlicmFyeShwYW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCiAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCg0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KICBsaWJyYXJ5KHBsb3RseSkNCn0NCg0KaWYgKCFyZXF1aXJlKCJWR0FNIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiVkdBTSIpDQogIGxpYnJhcnkoVkdBTSkNCn0NCiMjIyMgVkdBTQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUNCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91IGNhbiBjaG9vc2UgdG8gaW5jbHVkZSB0aGUgd2FybmluZyBtZXNzYWdlcyBpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgZmlsZS4gDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGluIHRoZSBvdXRwdXQgZmlsZS4NCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BDQogICAgICAgICAgICAgICAgICAgICAgKSAgDQpgYGANCiANCiBcDQogDQojIyAqKkFzc2lnbm1lbnQgT2JqZWN0aXZlcyoqIA0KDQo8cD4NCiogUmVpbmZvcmNlIHRoZSB1bmRlcnN0YW5kaW5nIG9mIEJvb3RzdHJhcCBzYW1wbGluZyAuDQoNCiogVW5kZXJzdGFuZCB0aGUgYm9vdHN0cmFwIGVzdGltYXRpb246IGNvbmZpZGVuY2UgaW50ZXJ2YWwgYW5kIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbi4NCjwvcD4NCg0KDQojIyAqKlBvbGljaWVzIG9mIFVzaW5nIEFJIFRvb2xzKioNCg0KPHA+DQoqKlBvbGljeSBvbiBBSSBUb29sIFVzZSoqOiBQbGVhc2UgYWRoZXJlIHRvIHRoZSBBSSB0b29sIHBvbGljeSBzcGVjaWZpZWQgaW4gdGhlIGNvdXJzZSBzeWxsYWJ1cy4gVGhlIGRpcmVjdCBjb3B5aW5nIG9mIEFJLWdlbmVyYXRlZCBjb250ZW50IGlzIHN0cmljdGx5IHByb2hpYml0ZWQuIEFsbCBzdWJtaXR0ZWQgd29yayBtdXN0IHJlZmxlY3QgeW91ciBvd24gdW5kZXJzdGFuZGluZzsgd2hlcmUgZXh0ZXJuYWwgdG9vbHMgYXJlIGNvbnN1bHRlZCwgY29udGVudCBtdXN0IGJlIHRob3JvdWdobHkgcmVwaHJhc2VkIGFuZCBzeW50aGVzaXplZCBpbiB5b3VyIG93biB3b3Jkcy4NCjwvcD4NCg0KPHA+DQoqKkNvZGUgSW5jbHVzaW9uIFJlcXVpcmVtZW50Kio6IEFueSBjb2RlIGluY2x1ZGVkIGluIHlvdXIgZXNzYXkgbXVzdCBiZSBwcm9wZXJseSBjb21tZW50ZWQgdG8gZXhwbGFpbiB0aGUgcHVycG9zZSBhbmQvb3IgZXhwZWN0ZWQgb3V0cHV0IG9mIGtleSBjb2RlIGxpbmVzLiBTdWJtaXR0aW5nIEFJLWdlbmVyYXRlZCBjb2RlIHdpdGhvdXQgbWVhbmluZ2Z1bCwgc3R1ZGVudC1hZGRlZCBjb21tZW50cyB3aWxsIG5vdCBiZSBhY2NlcHRlZC4NCjwvcD4NCg0KDQo8cD4qKkxvZy1ub3JtYWwgRGlzdHJpYnV0aW9uIFJldmlzaXRlZCoqPC9wPg0KDQo8cD4NCklmICRZID0gXGxuKFgpIFxzaW0gTihcbXUsIFxzaWdtYV4yKSQsIHRoZW4gJFgkIGZvbGxvd3MgYSBsb2dub3JtYWwgZGlzdHJpYnV0aW9uICRYIFxzaW0gXHRleHR7TG9nbm9ybWFsfShcbXUsIFxzaWdtYV4yKSQuIFRoZSBwcm9iYWJpbGl0eSBkZW5zaXR5IGlzIGdpdmVuIGJ5DQoNCiQkDQpmKHh8XG11LFxzaWdtYSkgPSBcZnJhY3sxfXt4XHNpZ21hXHNxcnR7MlxwaX19IFxleHBcbGVmdCgtXGZyYWN7KFxsbiB4IC0gXG11KV4yfXsyXHNpZ21hXjJ9XHJpZ2h0KSwgXHF1YWQgeCA+IDANCiQkDQoNCkFmdGVyIHNvbWUgYWxnZWJyYSwgd2UgY2FuIGV4cHJlc3MgdGhlIG1lYW4gYW5kIHZhcmlhbmNlIG9mIHRoZSBhYm92ZSBsb2dub3JtYWwgZGlzdHJpYnV0aW9uIGluIHRoZSBmb2xsb3dpbmcNCg0KJCQNClxiZWdpbnthbGlnbn0NClxtYXRoYmJ7RX1bWF0gJj0gXGV4cFxsZWZ0KFxtdSArIFxmcmFje1xzaWdtYV4yfXsyfVxyaWdodCkgXFwNClx0ZXh0e1Zhcn0oWCkgJj0gW1xleHAoXHNpZ21hXjIpIC0gMV0gXGV4cCgyXG11ICsgXHNpZ21hXjIpDQpcZW5ke2FsaWdufQ0KJCQNCg0KVXNpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG5vcm1hbCBhbmQgbG9nLW5vcm1hbCBkaXN0cmlidXRpb24gYW5kIGEgc2FtcGxlICRce3hfMSwgeF8yLCBcZG90cywgeF9uXH0kLCB0aGUgTUxFIGVzdGltYXRvcnMgb2YgJFxtdSQgYW5kICRcc2lnbWFeMiQgYXJlIGdpdmVuIGJ5DQoNCiQkDQpcYmVnaW57YWxpZ259DQpcaGF0e1xtdX0gJj0gXGZyYWN7MX17bn1cc3VtX3tpPTF9Xm4gXGxuKHhfaSkgXFwNClxoYXR7XHNpZ21hfV4yICY9IFxmcmFjezF9e259XHN1bV97aT0xfV5uIChcbG4oeF9pKSAtIFxoYXR7XG11fSleMg0KXGVuZHthbGlnbn0NCiQkDQoNClVzaW5nIHRoZSBwbHVnLWluIHByaW5jaXBsZSBvZiBNTEUsIHdlIGhhdmUgdGhlIE1MRSBvZiAkXG1hdGhiYntFfVtYXSQgYW5kICRcdGV4dHtWYXJ9KFgpJCBpbiB0aGUgZm9sbG93aW5nDQoNCiQkDQpcYm94ZWR7XHdpZGVoYXR7XG1hdGhiYntFfVtYXX0gPSBcZXhwXGxlZnQoXGhhdHtcbXV9ICsgXGZyYWN7XGhhdHtcc2lnbWF9XjJ9ezJ9XHJpZ2h0KX0NCiQkDQoNCjwvUD4NCg0KDQoNCjxwPjxmb250IGNvbG9yID0gImJsdWUiPioqVGhpcyBhc3NpZ25tZW50IGZvY3VzZXMgb24gY29uc3RydWN0aW5nIHZhcmlvdXMgYm9vdHN0cmFwIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9mIHRoZSBsb2dub3JtYWwgcG9wdWxhdGlvbiBtZWFuICRcbWF0aGJie0V9W1hdJCoqPC9mb250PjwvcD4NCg0KDQpcDQoNCiMjICoqUXVlc3Rpb246IFRyYWNlIE1ldGFsIENvbmNlbnRyYXRpb25zIGluIFNvaWwqKg0KDQo8cD4NClNvaWwgbGVhZCAoUGIpIGNvbmNlbnRyYXRpb25zIChtZy9rZykgZnJvbSA1NSB1cmJhbiBnYXJkZW4gc2l0ZXMuIFRyYWNlIG1ldGFscyBpbiBlbnZpcm9ubWVudGFsIG1lZGlhIHR5cGljYWxseSBmb2xsb3cgbG9nbm9ybWFsIGRpc3RyaWJ1dGlvbnMgZHVlIHRvOg0KDQoqIE11bHRpcGxpY2F0aXZlIHByb2Nlc3NlcyBjb250cm9sbGluZyBhY2N1bXVsYXRpb24NCg0KKiBQb3NpdGl2ZSBjb25zdHJhaW50cyAoY29uY2VudHJhdGlvbnMgY2Fubm90IGJlIG5lZ2F0aXZlKQ0KDQoqIFJpZ2h0LXNrZXdlZCBuYXR1cmUgb2YgY29udGFtaW5hdGlvbiBwYXR0ZXJucw0KPC9wPg0KDQoNCg0KPHA+DQpgYGANCjAuODUsIDEuMjMsIDAuOTIsIDMuNDUsIDIuMTEsIDEuNTYsIDQuODksIDIuMzQsIDEuNzgsIDYuNzIsIDAuOTUsIDEuMzQsIDguOTEsIA0KMi42NywgMS44OSwgNS40MywgMS4xMiwgMy43OCwgMi40NSwgNy42NSwgMS4wNSwgMS40NSwgMTIuMzQsIDIuODksIDIuMDEsIDQuNTYsIA0KMS4yMywgNC4zMiwgMi42NywgOS44NywgMC45OSwgMS41NiwgMTUuMjMsIDMuMTIsIDIuMzQsIDMuODksIDEuMzQsIDUuNjcsIDIuODksIA0KMTEuNDUsIDEuMTIsIDEuNjcsIDE4LjkwLCAzLjQ1LCAyLjU2LCAzLjQ1LCAxLjQ1LCA2Ljc4LCAzLjEyLCAxNC41NiwgMS4yMywgMS43OCwgDQoyMi4zNCwgMy43OCwgMi43OA0KYGBgDQo8L3A+DQoNCjxwPg0KDQokJFxib3hlZHtcdGV4dHtJbnN0cnVjdGlvbnM6fX0kJA0KDQpBc3N1bWUgdGhlIGRhdGEgZm9sbG93IGEgbG9nLW5vcm1hbCBkaXN0cmlidXRpb24uIEZvciBlYWNoIHF1ZXN0aW9uIGluIHBhcnRzIChiKeKAkyhkKSwgYmVnaW4gYnkgY2xlYXJseSBleHBsYWluaW5nIHRoZSByZWFzb25pbmcgYmVoaW5kIHlvdXIgYW5hbHl0aWNhbCBhcHByb2FjaC4gVGhlbiwgZGV2ZWxvcCB5b3VyIG93biBSIGZ1bmN0aW9ucyB0byBpbXBsZW1lbnQgdGhyZWUgdHlwZXMgb2YgY29uZmlkZW5jZSBpbnRlcnZhbHM6IHRoZSBhc3ltcHRvdGljIGludGVydmFsLCB0aGUgcGVyY2VudGlsZSBib290c3RyYXAgaW50ZXJ2YWwsIGFuZCB0aGUgYmlhcy1jb3JyZWN0ZWQgYW5kIGFjY2VsZXJhdGVkIChCQ2EpIGJvb3RzdHJhcCBpbnRlcnZhbC4gVXNlIHRoZXNlIGZ1bmN0aW9ucyB0byBjb25zdHJ1Y3QgdGhlIHJlcXVpcmVkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCBhbmQgdmVyaWZ5IHlvdXIgcmVzdWx0cyB1c2luZyB0aGUgYXBwcm9wcmlhdGUgZnVuY3Rpb25zIGZyb20gdGhlIGBib290YCBwYWNrYWdlLg0KDQpZb3UgYXJlIGVuY291cmFnZWQgdG8gZGVzaWduIGEgd3JhcHBlciBmdW5jdGlvbiB0aGF0IGludGVncmF0ZXMgYWxsIGNvbmZpZGVuY2UgaW50ZXJ2YWwgbWV0aG9kcywgYWxsb3dpbmcgdXNlcnMgdG8gc2VsZWN0IHRoZSBkZXNpcmVkIG1ldGhvZCB0aHJvdWdoIGFuIGlucHV0IGFyZ3VtZW50Lg0KPC9QPg0KDQo8cD4NCg0KJCRcYm94ZWR7XHRleHR7SW5kaXZpZHVhbCBRdWVzdGlvbnM6fX0kJA0KDQphKS4gUGVyZm9ybSA1MDAwIGJvb3RzdHJhcCBzYW1wbGVzIHRvIGVzdGltYXRlIHRoZSBib290c3RyYXAgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mICRcYm94ZWR7XHdpZGVoYXR7XG1hdGhiYntFfVtYXX19JC4gRGlzcGxheSB0aGUgZGlzdHJpYnV0aW9uIHVzaW5nIGVpdGhlciBhIGhpc3RvZ3JhbSBvciBhIGtlcm5lbCBkZW5zaXR5IHBsb3QuIENvbW1lbnQgb24gdGhlIHNoYXBlLCB2YXJpYWJpbGl0eSwgYW5kIGFueSBub3RhYmxlIHBhdHRlcm5zIG9ic2VydmVkIGluIHRoZSBib290c3RyYXAgc2FtcGxpbmcgZGlzdHJpYnV0aW9uLg0KDQojIFF1ZXN0aW9uIDEgUGFydCBBDQoNCmBgYHtyfQ0Kc2V0LnNlZWQoMTIzKSAjU2V0cyBzZWVkDQpzb2lsIDwtIGMoMC44NSwgMS4yMywgMC45MiwgMy40NSwgMi4xMSwgMS41NiwgNC44OSwgMi4zNCwgMS43OCwgNi43MiwgMC45NSwgMS4zNCwgOC45MSwgDQoyLjY3LCAxLjg5LCA1LjQzLCAxLjEyLCAzLjc4LCAyLjQ1LCA3LjY1LCAxLjA1LCAxLjQ1LCAxMi4zNCwgMi44OSwgMi4wMSwgNC41NiwgDQoxLjIzLCA0LjMyLCAyLjY3LCA5Ljg3LCAwLjk5LCAxLjU2LCAxNS4yMywgMy4xMiwgMi4zNCwgMy44OSwgMS4zNCwgNS42NywgMi44OSwgDQoxMS40NSwgMS4xMiwgMS42NywgMTguOTAsIDMuNDUsIDIuNTYsIDMuNDUsIDEuNDUsIDYuNzgsIDMuMTIsIDE0LjU2LCAxLjIzLCAxLjc4LCANCjIyLjM0LCAzLjc4LCAyLjc4KQ0KDQpCIDwtIDUwMDAgI051bWJlciBvZiBib290c3RyYXAgc2FtcGxlcw0KbiA8LSBsZW5ndGgoc29pbCkgI0dldHMgbiB3aGljaCBpcyB1c2VkIGxhdGVyDQpib290X2V4IDwtIG51bWVyaWMoQikgI1NldHMgZW1wdHkgdmVjdG9yIHRvIHN0b3JlIGJvb3RzdHJhcCBzYW1wbGUgbWVhbnMNCg0KZm9yKGIgaW4gMTpCKXsNCiAgYm9vdF9zYW1wbGUgPC0gc2FtcGxlKHNvaWwsIG4sIHJlcGxhY2U9VFJVRSkgI0RvZXMgYm9vdHN0cmFwIHNhbXBsaW5nDQogIGJvb3RfbXUgPC0gbWVhbihsb2coYm9vdF9zYW1wbGUpKSAjR2V0cyBtdQ0KICBib290X3NpZ21hMiA8LSB2YXIobG9nKGJvb3Rfc2FtcGxlKSkgI0dldHMgc2lnbWFeMg0KICBib290X2V4W2JdIDwtIGV4cChib290X211ICsgYm9vdF9zaWdtYTIvMikgI0dldHMgRVtYXQ0KICANCn0NCg0Ka2RlX3NvaWwgPC0gZGVuc2l0eShib290X2V4KSAjTWFrZXMgS0RFIG9mIGJvb3RzdHJhcCBzYW1wbGUgbWVhbnMNCg0KcGxvdChrZGVfc29pbCwgbWFpbiA9ICJLREUgZnJvbSBCb290c3RyYXAgU2FtcGxlIE1lYW5zIiwgeGxhYj0iU2FtcGxlIE1lYW5zIiwgY29sPSJibHVlIikNCmBgYA0KDQpUaGUgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBhcHBlYXJzIHRvIGZvbGxvdyBhIHN5bW1ldHJpYyBkaXN0cmlidXRpb24gY2VudGVyZWQgc29tZXdoZXJlIGJldHdlZW4gNCBhbmQgNS4gIEl0J3MgYXBwcm94aW1hdGVseSBhIGJlbGwgc2hhcGVkIGRpc3RyaWJ1dGlvbiBhbmQgdGhlIHZhc3QgbWFqb3JpdHkgb2YgdGhlIG9ic2VydmF0aW9ucyBhcmUgYXJlIGJldHdlZW4gMyBhbmQgNi4gIA0KDQoNCmIpLiBDb25zdHJ1Y3QgYSA5NSUgYm9vdHN0cmFwIHBlcmNlbnRpbGUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgJFxtdV97TE59ID0gXG1hdGhiYntFfVtYXSQuDQoNCiMgUXVlc3Rpb24gMSBQYXJ0IEINCg0KRm9yIHRoZSBib290c3RyYXAgcGVyY2VudGlsZSBjb25maWRlbmNlIGludGVydmFsIHdlIGZpcnN0IG5lZWQgdG8gc29ydCB0aGUgYm9vdHN0cmFwICRcd2lkZWhhdHtcbWF0aGJie0V9W1hdfSQgdmFsdWVzICh0aGlzIHdpbGwgYmUgZG9uZSBhdXRvbWF0aWNhbGx5IGluIHRoZSBxdWFudGlsZSBmdW5jdGlvbiBpbiB0aGUgY29kZSkuICBUaGVuIHdlIG5lZWQgdG8gcGx1ZyB0aGVzZSBzb3J0ZWQgdmFsdWVzIGludG8gdGhlIGZvcm11bGE6DQoNCiQkDQpcbGVmdFtcaGF0e1x0aGV0YX1fe0JcY2RvdFxhbHBoYS8yfV4qLCBcaGF0e1x0aGV0YX1fe0JcY2RvdCgxLVxhbHBoYS8yKX1eKiBccmlnaHRdIFxSaWdodGFycm93IA0KXGxlZnRbXHdpZGVoYXR7XG1hdGhiYntFfVtYXX1feyg1MDAwXGNkb3QgMC4wNS8yKX1eKiwgXHdpZGVoYXR7XG1hdGhiYntFfVtYXX1feyg1MDAwXGNkb3QgKDEtMC4wNS8yKSl9XiogXHJpZ2h0XQ0KJCQNCg0KVGhpcyBmb3JtdWxhIGNhbiB0aGVuIGJlIHVzZWQgdG8gZmluZCB0aGUgYm9vdHN0cmFwIHBlcmNlbnRpbGUgY29uZmlkZW5jZSBpbnRlcnZhbCBpbiB0aGUgY29kZSBiZWxvdzoNCg0KYGBge3J9DQpjaV9wZXJjZW50aWxlIDwtIGZ1bmN0aW9uKGJvb3RfdmFscywgYWxwaGEgPSAwLjA1KXsgI0NyZWF0ZXMgZnVuY3Rpb24NCiAgb3V0cHV0X2NpIDwtIHF1YW50aWxlKGJvb3RfdmFscywgYyhhbHBoYS8yLCAxLWFscGhhLzIpKSAjQ3JlYXRlcyBpbnRlcnZhbA0KICByZXR1cm4ob3V0cHV0X2NpKQ0KfQ0KbG93dXBwZXJjZW50aWxlIDwtIGNpX3BlcmNlbnRpbGUoYm9vdF9leCkgDQpsb3d1cHBlcmNlbnRpbGUgI1N0YXRlcyBpbnRlcnZhbCANCmBgYA0KDQpGcm9tIHRoaXMgb3V0cHV0IHdlIGtub3cgdGhhdCB0aGUgbG93ZXIgYm91bmQgb2YgdGhlIGJvb3RzdHJhcCBwZXJjZW50aWxlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgMy4xMTA4MTcgYW5kIHRoZSB1cHBlciBib3VuZCBpcyA1LjY4MzY0Ny4NCg0KYGBge3J9DQpsaWJyYXJ5KGJvb3QpDQoNCmJvb3RfZm4gPC0gZnVuY3Rpb24oZGF0YSwgaSkgeyAjVXNlZCB0byBjcmVhdGUgZnVuY3Rpb24gdXNlZCBsYXRlcg0KICB4IDwtIGRhdGFbaV0NCiAgbXVfaGF0IDwtIG1lYW4obG9nKHgpKQ0KICBzaWdtYTJfaGF0IDwtIHZhcihsb2coeCkpDQogIGV4cChtdV9oYXQgKyBzaWdtYTJfaGF0IC8gMikNCn0NCg0KYm9vdF9vYmogPC0gYm9vdChzb2lsLCBib290X2ZuLCBSID0gNTAwMCkgI0NyZWF0ZXMgYm9vdCBvYmplY3QNCg0KYm9vdC5jaShib290X29iaiwgdHlwZSA9ICJwZXJjIikgI1VzZXMgYm9vdC5jaSB0byBnZXQgY29uZmlkZW5jZSBpbnRlcnZhbA0KYGBgDQoNCkdpdmVuIHRoYXQgdGhlIGludGVydmFsIHByb3ZpZGVkIGJ5IHRoZSAnYm9vdC5jaScgZnVuY3Rpb24gaXMgKDMuMTM0LCA1LjY3Nikgd2hpY2ggaXMgc2ltaWxhciB0byBvdXIgZnVuY3Rpb24ncyBvdXRwdXQgb2YgKDMuMTEwODE3LCA1LjY4MzY0NykgaXQgc2VlbXMgdGhhdCBvdXIgZnVuY3Rpb24gaXMgYWNjdXJhdGUuDQoNCmMpLiBDb25zdHJ1Y3QgYSA5NSUgYm9vdHN0cmFwIEJDYSBjb25maWRlbmNlIGludGVydmFsIGZvciAkXG11X3tMTn0gPSBcbWF0aGJie0V9W1hdJC4NCg0KIyBRdWVzdGlvbiAxIFBhcnQgQw0KDQpJbiBvcmRlciB0byBmaW5kIHRoZSBib290c3RyYXAgQkNhIGNvbmZpZGVuY2UgaW50ZXJ2YWwgd2Ugd2lsbCBmaXJzdCBjb21wdXRlIHRoZSBiaWFzIGNvcnJlY3Rpb24gdXNpbmcgdGhlICRcaGF0e3p9XzAkIGZvcm11bGEgc2hvd24gaW4gY2xhc3MuICBUaGVuIHdlIHdpbGwgdXNlIHRoZSBqYWNra25pZmUgbWV0aG9kIHRvIGZpbmQgJFxoYXR7YX0kLiAgRmluYWxseSwgd2Ugd2lsbCBjb21wdXRlIHRoZSBhZGp1c3RlZCBwZXJjZW50aWxlcyAkXGFscGhhXzEkIGFuZCAkXGFscGhhXzIkLiAgV2Ugd2lsbCB0aGVuIHVzZSB0aGUgYWRqdXN0ZWQgcGVyY2VudGlsZXMgdG8gZmluZCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbDoNCg0KJCQNClxsZWZ0W1xoYXR7XHRoZXRhfV97QlxjZG90XGFscGhhXzF9XiosIFxoYXR7XHRoZXRhfV97QlxjZG90XGFscGhhXzJ9XiogXHJpZ2h0XSBcUmlnaHRhcnJvdyANClxsZWZ0W1x3aWRlaGF0e1xtYXRoYmJ7RX1bWF19X3soNTAwMFxjZG90IFxhbHBoYV8xKX1eKiwgXHdpZGVoYXR7XG1hdGhiYntFfVtYXX1feyg1MDAwXGNkb3RcYWxwaGFfMn1eKiBccmlnaHRdDQokJA0KDQpXZSBjYW4gdGhlbiBwbHVnIHRoZXNlIGZvcm11bGFzIGludG8gdGhlIGNvZGUgYmVsb3cgdG8gZ2V0IHRoZSBib290c3RyYXAgQkNhIGNvbmZpZGVuY2UgaW50ZXJ2YWw6DQoNCmBgYHtyfQ0KZXhfaGF0X2ZuIDwtIGZ1bmN0aW9uKHgpIHsgI1VzZWQgbGF0ZXIgdG8gZ2V0IEVbWF0NCiAgbXVfaGF0IDwtIG1lYW4obG9nKHgpKQ0KICBzaWdtYTJfaGF0IDwtIHZhcihsb2coeCkpDQogIGV4cChtdV9oYXQgKyBzaWdtYTJfaGF0IC8gMikNCn0NCg0KY2lfYmNhIDwtIGZ1bmN0aW9uKGRhdGEsIGJvb3RfdmFscywgZXhfaGF0X2ZuLCBhbHBoYSA9IDAuMDUpIHsNCiAgbiA8LSBsZW5ndGgoZGF0YSkgI0dldHMgbg0KICBleF9oYXQgPC0gZXhfaGF0X2ZuKGRhdGEpICNHZXRzIEVbWF0gZnJvbSBzYW1wbGUNCiAgDQogIHowIDwtIHFub3JtKG1lYW4oYm9vdF92YWxzIDwgZXhfaGF0KSkgI0dldHMgYmlhcyBjb3JyZWN0aW9uIGZhY3RvcnMNCiAgDQogIGphY2sgPC0gc2FwcGx5KDE6biwgZnVuY3Rpb24oaSkgZXhfaGF0X2ZuKGRhdGFbLWldKSkgI0dldHMgdGhlIGphY2trbmlmZSBlc3RpbWF0ZXMNCiAgamFja19tZWFuIDwtIG1lYW4oamFjaykgI0dldHMgbWVhbg0KICANCiAgbnVtIDwtIHN1bSgoamFja19tZWFuIC0gamFjayleMykgI0dldHMgYWNjZWxlcmF0aW9uIGZhY3Rvcg0KICBkZW4gPC0gNiAqIChzdW0oKGphY2tfbWVhbiAtIGphY2spXjIpKV4oMy8yKQ0KICBhIDwtIG51bSAvIGRlbg0KICANCiAgel9hbHBoYSA8LSBxbm9ybShjKGFscGhhLzIsIDEgLSBhbHBoYS8yKSkgI0dldHMgbm9ybWFsIGN1dG9mZnMNCiAgDQogIGFkaiA8LSBwbm9ybSh6MCArICh6MCArIHpfYWxwaGEpIC8gKDEgLSBhICogKHowICsgel9hbHBoYSkpKSAjVXNlcyBmb3JtdWxhIGZyb20gYWJvdmUNCiAgDQogIG91dHB1dF9jaTIgPC0gcXVhbnRpbGUoYm9vdF92YWxzLCBhZGopICNVc2VzIGFkanVzdGVkIHByb2JhYmlsaXRpZXMgdG8gZ2V0IHRvIGdldCBjb25maWRlbmNlIGludGVydmFsDQogIA0KICByZXR1cm4ob3V0cHV0X2NpMikNCn0NCg0KbG93dXBiY2EgPC0gY2lfYmNhKHNvaWwsIGJvb3RfZXgsIGV4X2hhdF9mbikNCmxvd3VwYmNhICNTdGF0ZXMgY29uZmlkZW5jZSBpbnRlcnZhbA0KYGBgDQoNCkZyb20gdGhpcyBvdXRwdXQgd2Uga25vdyB0aGF0IHRoZSBsb3dlciBib3VuZCBvZiB0aGUgYm9vdHN0cmFwIHBlcmNlbnRpbGUgY29uZmlkZW5jZSBpbnRlcnZhbCBpcyAzLjI0NDA4MCBhbmQgdGhlIHVwcGVyIGJvdW5kIGlzIDUuOTE1MTM4Lg0KDQpgYGB7cn0NCmJvb3QuY2koYm9vdF9vYmosIHR5cGUgPSAiYmNhIikgI1VzZXMgYm9vdC5jaSB0byBnZXQgY29uZmlkZW5jZSBpbnRlcnZhbA0KYGBgDQoNCkdpdmVuIHRoYXQgdGhlIGludGVydmFsIHByb3ZpZGVkIGJ5IHRoZSAnYm9vdC5jaScgZnVuY3Rpb24gaXMgKDMuMjQ4LCA2LjAwMSkgd2hpY2ggaXMgc2ltaWxhciB0byBvdXIgZnVuY3Rpb24ncyBvdXRwdXQgb2YgKDMuMjQ0MDgwLCA1LjkxNTEzOCkgaXQgc2VlbXMgdGhhdCBvdXIgZnVuY3Rpb24gaXMgYWNjdXJhdGUuDQoNCmQpLiBVc2UgdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSB0byBjb25zdHJ1Y3QgYSA5NSUgYXN5bXB0b3RpYyBjb25maWRlbmNlIGludGVydmFsIGZvciAkXG11X3tMTn0gPSBcbWF0aGJie0V9W1hdJC4NCg0KIyBRdWVzdGlvbiAxIFBhcnQgRA0KDQpOb3cgdGhhdCB3ZSBoYXZlIHRoZSBib290c3RyYXAgJFx3aWRlaGF0e1xtYXRoYmJ7RX1bWF19JCB2YWx1ZXMgd2UgY2FuIGFsbCB3ZSBuZWVkIHRvIGRvIGlzIGNhbGN1bGF0ZSAkXHdpZGVoYXR7XG1hdGhiYntFfVtYXX0kIGZvciBvdXIgb3JpZ2luYWwgc2FtcGxlLCBmaW5kIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGJvb3RzdHJhcCAkXHdpZGVoYXR7XG1hdGhiYntFfVtYXX0kJ3MuICBXZSBrbm93IHRoYXQ6DQoNCiQkDQpcd2lkZWhhdHtcbWF0aGJie0V9W1hdfSA9IFxleHBcbGVmdChcaGF0e1xtdX0gKyBcZnJhY3tcaGF0e1xzaWdtYX1eMn17Mn1ccmlnaHQpDQokJA0KDQpXZSBhbHNvIGtub3cgdGhhdCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBjYW4gYmUgZm91bmQgdXNpbmc6DQoNCiQkDQpcd2lkZWhhdHtcbWF0aGJie0V9W1hdfSBccG0gel97XGFscGhhLzJ9IFxjZG90IFxoYXR7c2V9X3tib290fQ0KJCQNCg0KV2hlcmU6DQoNCiQkDQpcaGF0e3NlfV97Ym9vdH09XHNxcnR7XGZyYWN7MX17NTAwMC0xfVxzdW1fe2I9MX1eezUwMDB9KFx3aWRlaGF0e1xtYXRoYmJ7RX1bWF19X2JeKi1cb3ZlcmxpbmV7XG1hdGhiYntFfVtYXX1eKileMn0NCiQkDQoNCldlIGNhbiBwbHVnIHRoZXNlIGZvcm11bGFzIGludG8gb3VyIGNvZGUgaW4gb3JkZXIgdG8gZmluZCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCANCg0KYGBge3J9DQpjaV9hc3ltcHRvdGljIDwtIGZ1bmN0aW9uKGRhdGEsIGJvb3RfdmFscywgYWxwaGEgPSAwLjA1KSB7DQogIGV4X2hhdCA8LSBtZWFuKGJvb3RfdmFscykgI0dldHMgRVtYXQ0KICBzZSA8LSBzZChib290X3ZhbHMpICNHZXRzIHN0YW5kYXJkIGRldmlhdGlvbg0KICB6IDwtIHFub3JtKDEgLSBhbHBoYS8yKSAjR2V0cyB6LXZhbHVlDQogIA0KICBvdXRwdXQzIDwtIGMobG93ZXIgPSBleF9oYXQgLSB6ICogc2UsIHVwcGVyID0gZXhfaGF0ICsgeiAqIHNlKSAgI0NhbGN1bGF0ZXMgY29uZmlkZW5jZSBpbnRlcnZhbA0KICByZXR1cm4ob3V0cHV0MykNCn0NCg0KbG93dXBhc3ltcHRvdGljIDwtIGNpX2FzeW1wdG90aWMoc29pbCwgYm9vdF9leCkgDQpsb3d1cGFzeW1wdG90aWMgI1N0YXRlcyBjb25maWRlbmNlIGludGVydmFsDQoNCmBgYA0KDQpGcm9tIHRoaXMgb3V0cHV0IHdlIGtub3cgdGhhdCB0aGUgbG93ZXIgYm91bmQgb2YgdGhlIGJvb3RzdHJhcCBwZXJjZW50aWxlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgMi45ODU3NDYgYW5kIHRoZSB1cHBlciBib3VuZCBpcyA1LjUzMjg0My4NCg0KYGBge3J9DQpib290LmNpKGJvb3Rfb2JqLCB0eXBlID0gIm5vcm0iKSAjVXNlcyBib290LmNpIHRvIGdldCBjb25maWRlbmNlIGludGVydmFsDQpgYGANCg0KR2l2ZW4gdGhhdCB0aGUgaW50ZXJ2YWwgcHJvdmlkZWQgYnkgdGhlICdib290LmNpJyBmdW5jdGlvbiBpcyAoMi45NTUsIDUuNTMxKSB3aGljaCBpcyBzaW1pbGFyIHRvIG91ciBmdW5jdGlvbidzIG91dHB1dCBvZiAoMi45ODU3NDYsIDUuNTMyODQzICkgaXQgc2VlbXMgdGhhdCBvdXIgZnVuY3Rpb24gaXMgYWNjdXJhdGUuDQoNCmYpLiBBc3N1bWluZyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgY29uc3RydWN0ZWQgaW4gdGhlIHByZXZpb3VzIHBhcnRzIGFyZSB2YWxpZCwgZXZhbHVhdGUgdGhlaXIgcGVyZm9ybWFuY2UgYnkgY29tcGFyaW5nIHRoZWlyIHdpZHRocywgc3ltbWV0cnksIHN0YWJpbGl0eSwgYW5kIHNlbnNpdGl2aXR5IHRvIGRpc3RyaWJ1dGlvbmFsIHNrZXduZXNzLiBUaGVuLCBwcm92aWRlIGEgd2VsbOKAkXJlYXNvbmVkIHJlY29tbWVuZGF0aW9uIHJlZ2FyZGluZyB3aGljaCBtZXRob2QgaXMgbW9zdCBzdWl0YWJsZSBmb3IgdGhpcyBhbmFseXNpcy4NCg0KIyBRdWVzdGlvbiAxIFBhcnQgRg0KDQpUaGUgYXN5bXB0b3RpYyBjb25maWRlbmNlIGludGVydmFsIGhhcyB0aGUgc21hbGxlc3QgY29uZmlkZW5jZSBpbnRlcnZhbCB3aXRoIGEgd2lkdGggb2YgMi41NDcwOTcsIGNvbXBhcmVkIHRvIHRoZSBib290c3RyYXAgcGVyY2VudGlsZSBjb25maWRlbmNlIGludGVydmFsIHdpZHRoIG9mIDIuNTcyODMgYW5kIHRoZSBib290c3RyYXAgQkNhIGNvbmZpZGVuY2UgaW50ZXJ2YWwgd2lkdGggb2YgMi42NzEwNTguICBUaGUgcGVyY2VudGlsZSBtZXRob2QgaXMgc2ltcGxlIGFuZCByYW5nZS1wcmVzZXJ2aW5nLCB0aGUgQkNhIG1ldGhvZCBjb3JyZWN0IGJpYXMvc2tldywgYW5kIHRoZSBhc3ltcHRvdGljIG5vcm1hbCBhcHByb3hpbWF0aW9uIGlzIGZhc3QgYnV0IGFzc3VtZXMgbm9ybWFsaXR5LiAgQ29uc2lkZXJpbmcgdGhlIEtERSBmcm9tIHRoZSBib290c3RyYXAgc2FtcGxlIG1lYW5zIHdoaWNoIGlzIHN5bW1ldHJpYyBhbmQgYXBwZWFycyBub3JtYWxseSBkaXN0cmlidXRlZCB3aXRoIGEgYmVsbC1zaGFwZWQgY3VydmUsIHRoZSBhc3ltcHRvdGljIGNvbmZpZGVuY2UgaW50ZXJ2YWwgc2VlbXMgdG8gYmUgYXBwcm9wcmlhdGUgaW4gdGhpcyBjYXNlLiAgU28sIHByb3ZpZGVkIHRoYXQgYWxsIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFscyBhcmUgdmFsaWQgKGluIHRoYXQgd2UgY2FuIGJlIGF0IGxlYXN0IDk1JSBjb25maWRlbnQgdGhlIHRydWUgdmFsdWUgb2YgdGhlIGV4cGVjdGVkIHZhbHVlIGlzIGJldHdlZW4gdGhlIHVwcGVyIGFuZCBsb3dlciBsaW1pdHMpICBJIHdvdWxkIHJlY29tbWVuZCB0aGUgYXN5bXB0b3RpYyBjb25maWRlbmNlIGludGVydmFsIGdpdmVuIHRoYXQgaXQgaGFzIHRoZSBzbWFsbGVzdCBpbnRlcnZhbCBhbmQgaXQgc2VlbXMgYXBwcm9wcmlhdGUgaW4gdGhpcyBzZXR0aW5nLg0KDQoNCjwvcD4NCg0KDQoNCg0K