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.

#ANSWERS PROMPT A 
set.seed(123)
#soil is a log function
soilraw = sort(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))

n =length(soilraw)

#Estimate boot strap sampling distribution (MLE)

B =5000
boot_means <- numeric(B) #empty vector

for(b in 1:B){
  boot_sample = sample(soilraw, n, replace=TRUE) # bootstraps from original sample
  
  #Log transform for MLEs for log transformed resample
  
  
  log_sample=log(boot_sample)
  log_mean_perc = mean(log_sample)
  log_var_perc = sum((log_sample-log_mean_perc)^2)/n #calculate variance 

  
  boot_means[b] = exp(log_mean_perc + (log_var_perc/2)) #calculate all bootstrapped mean  Question A
  
  
  
}

#Calculate the MLE mean of the bootstrap distribution
boot_mle_per_means= mean(boot_means)


cat("Question A: ", "The average bootstrap sampling distribution mean of the soil metal concentration is ", boot_mle_per_means)  
Question A:  The average bootstrap sampling distribution mean of the soil metal concentration is  4.224807
#histogram
hist(boot_means,
     main = "Bootstrap Distribution of MLE Mean ",
     prob = TRUE)

** Viewing Characteristics of MLE Mean Bootstrap Distribution** The distribution of the bootstrapped MLE mean appears to have some skew although the skew does not appear extreme. This is expected as the distribution is a log of a normal distribution, most likely adding some right skew a previously normal distribution to better suit the model. There is moderate low variance through the histogram. Overall this is a unimodal model, with the greatest density between 3.5 and 4.5. The histogram suggests the variance of MLE bootstrapped mean values tend to be in similar ranges.

For each question in parts (b)–(d), begin by clearly explaining the reasoning behind your analytical approach.

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

Performing a Bootstrap Percentile 95%CI

Performing a bootstrap confidence interval for a percentile interval ranging all values in the distribution into quantiles between 0 and 1 while relying on the empirical distribution. The percentile bootstrap CI are constructed by quantiles around the parameter based on the alpha value, for example values between 2.5% and 97.5% from the distribution of bootstrap estimates. A percentile bootstrap works best when the bootstrap distribution is roughly symmetric and an estimator that has little bias. In this example the distribution and values is the normal log of the original distribution. The transformation still maintains the same 95% area even after being back transformed to calculate the more accurate confidence intervals to the distribution.

** Pseudo-Algorithm**

function percentile_ci(data, statistic, B=5000, alpha=0.05)

theta_hat, boot_dis = bootstrap(data, statistic B)
sort_boot = sort(log(boot_dist))
lower_idx = floor(B* alpha/2)
upper_idx = ceiling(B* (1-alpha/2))
lower = sorted_boot[lower_idx]
upper = sorted_boot[upper_idx]
return(lower, upper)
##Bootstrapping confidence intervals by hnad


#boot_result_per = boot(soil, boot_mle_per_means, R=5000)



for(b in 1:B){
  boot_sample = sample(soilraw, n, replace=TRUE) # bootstraps from original sample
  
  #Log transform for MLEs for log transformed resample
  
  
  log_sample=log(boot_sample)
  log_mean_perc = mean(log_sample)
  log_var_perc = sum((log_sample-log_mean_perc)^2)/n #calculate variance 

  
  boot_means[b] = exp(log_mean_perc + (log_var_perc/2)) #calculate all bootstrapped mean  Question A
  
  
  
}

#Calculate the MLE mean of the bootstrap distribution
boot_mle_per_means= mean(boot_means)




# Calculating the quanitles for Percentile CI
alpha = 0.05

ci_perc <- quantile(boot_means, probs=c(alpha/2, 1-alpha/2))
cat(" The bootstrapped confidence intervals for percentiles are: [ ", ci_perc, "] ", "\n")
 The bootstrapped confidence intervals for percentiles are: [  3.106209 5.63198 ]  
#Define statistic function
l_mean_stat <- function(data, indices) {
  sample_data <- data[indices]
  l_samp = log(sample_data)
  mean_sam = mean(l_samp)
  v = sum((l_samp - mean_sam)^2) / length(l_samp)
  
   return(exp(mean_sam + v/2))
}
#Verify with boot() and boot.ci() command

#perform bootstrap
  boot_result = boot(data = soilraw, statistic = l_mean_stat, R = 5000)
perc_boot_comm=  boot.ci(boot_result, type = "perc")

cat("Question B: The percentile bootstrap derived from the boot library command is: " )
Question B: The percentile bootstrap derived from the boot library command is: 
perc_boot_comm
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates

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

Intervals : 
Level     Percentile     
95%   ( 3.124,  5.624 )  
Calculations and Intervals on Original Scale
cat("The bootstrapped MLE Parameter is: ", boot_mle_per_means )
The bootstrapped MLE Parameter is:  4.243194

The hand calculated bootstrapped Percentile 95%CI at 3.1062094, 5.63198 is comparable to the boot() library bootstrap percentile 95% CI at ( 3.124, 5.624 ). The manual calculation of the percentile 95%CI has slightly smaller interval, which can suggest more accuracy, although both have highly similar widths. Further testing would be needed to determine if these differences are statistically significant.

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

We use the Bias Correlated and Accelerated (BCa) Confidence interval to avoid skewness and bias from the sampling distribution to being implemented into the confidence interval: * We perform this using a Jackknife * The Jackknife based BCa is the default method for bootstrapped CI

  • We correct bias correction by measuring the parameter bias by comparing the bootstrap estimate to the original estimate
  • Acceleration (a): measures how the standard error changes with the parameter value (estimate via jackknife)

It generally provides more accurate coverage than the simple percentile method, especially for skewed distributions or biased estimators, and resampling. The BCa is generally the most robust CI type due to its accounts for bias.

Algorithm

Create For-loop from rawsoil (dataset) with replacement for the bootstrap sample
Calculate mean and variance or parameter of interest to assist CI calculations 
Apply log normal to boostraps to apply log normal distribution 
Calculate bootstrapped mean and variance
Administer Bias-Correction with determined alpha levels
Jackknife the bootstrapped sample
Define alpha leves for the BCa CI's adjusted limits at the 95% Confidence level
Compare with boot and boot.ci() commands
##Bootstrapping confidence intervals by hnad


#boot_result_per = boot(soil, boot_mle_per_means, R=5000)



for(b in 1:B){
  boot_sample = sample(soilraw, n, replace=TRUE) # bootstraps from original sample
  
  #Log transform for MLEs for log transformed resample
  
  
  log_sample=log(boot_sample)
  log_mean_perc = mean(log_sample)
  log_var_perc = sum((log_sample-log_mean_perc)^2)/n #calculate variance 

  
  boot_means[b] = exp(log_mean_perc + (log_var_perc/2)) #calculate all bootstrapped mean  Question A
  
  
  
}

#Calculate the MLE mean of the bootstrap distribution
boot_mle_per_means= mean(boot_means)


##Emplicating the Jackknife Apporach (non boot.ci())

#Bias Correction
orig_log = log(soilraw)
theta_hat = exp(mean(orig_log) + (sum((orig_log - mean(orig_log))^2)/n)/2)
prop_less =sum(boot_means < theta_hat)/B
z0 = qnorm(prop_less)

# Acceleration (jackknife)
n = length(soilraw)

jack_mles = numeric(n)
    for( i in 1:n ){
        jack_sample = soilraw[-i] #all obs minus 1 
      l_j <- log(jack_sample) #log the collected sameple to meet normallog distubution
  # Calculate MLE for this jackknife set
  jack_mles[i] <- exp(mean(l_j) + (sum((l_j - mean(l_j))^2)/length(l_j))/2)
}

#adjustment
mean_jack = mean(jack_mles) #Jackknife Parameter
a_hat =sum((mean_jack - jack_mles)^3) / (6 * (sum((mean_jack - jack_mles)^2))^1.5)

#calculate percentiles of interest
alpha =0.05

z_alpha = qnorm(alpha/2) #defining alphas used for ci calculation
z_1alpha = qnorm(1 - alpha/2) #defining upper end of alpha used for ci calulation

#BCa CI with adjusted limits
alpha1 = pnorm(z0 + (z0 + z_alpha)/(1 - a_hat*(z0 + z_alpha)))
    alpha2 = pnorm(z0 + (z0 + z_1alpha)/(1 - a_hat*(z0 + z_1alpha)))



bca_manual <- quantile(boot_means, probs = c(alpha1, alpha2))

cat("Manual BCa Confidence Interval: [", bca_manual[1], ",", bca_manual[2], "]\n")
Manual BCa Confidence Interval: [ 3.24331 , 5.831848 ]
cat("The jackknife parameter is ", mean_jack)
The jackknife parameter is  4.218495
#Define statistic function
l_mean_stat <- function(data, indices) {
  sample_data <- data[indices]
  l_samp = log(sample_data)
  mean_sam = mean(l_samp)
  v = sum((l_samp - mean_sam)^2) / length(l_samp)
  
   return(exp(mean_sam + v/2))
}
#Verify with boot() and boot.ci() command

set.seed(123)
#perform bootstrap
  boot_result = boot(data = soilraw, statistic = l_mean_stat, R = 5000)


cat("Question B: The Bias- Correction and Acceleration (BCa)  bootstrap derived from the boot library command is: \n" )
Question B: The Bias- Correction and Acceleration (BCa)  bootstrap derived from the boot library command is: 
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.228,  5.795 )  
Calculations and Intervals on Original Scale
cat("The bootstrapped MLE Parameter is: ", boot_mle_per_means,  "\n")
The bootstrapped MLE Parameter is:  4.238161 

The hand calculated BCa 95%CI at (3.2433097, 5.8318478) is comparable and highly similar to the boot() library bootstrap BCa 95% CI at ( 3.212, 5.807 ).

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

Approaching an Asymptotic Confidence Interval The asymptotic confidence interval is a non-bootstrap confidence interval approach. It uses a pivotal quantities to Pivotal quantities based confidence intervals do not depend on the parameter for its construction. We use exact distributions whose normal, t and \(\chi^2\) distributions are independent of unknown parameters \(\mu\) and \(\sigma\) in the distribution.

Identify and calculate componets of the pivotal quanity
Calculate the standard error, variance and mean parameters.
Identify the alpha level for 95% confidence (0.05)
Calculate the critical value (z- critical)
Use z critical values to compute the intervals based on the mean parameter
Calculate confidence intervals
# Asymptotic Confidence Intervals (CLT-Based) ---

#Asymptotic Confidence intervals
soilraw = sort(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))

soil = log(soilraw)

n =length(soil)

##Finding mu hat and parameters for asymptotic 
mu_asym_hat = mean(soil)
sig_sq_hat_asym = sum((soil - mean(soil))^2)/n # Maximum Likelihood Estimate (MLE) for variance

#Point estimate (Lognormal mean)
theta_hat = exp(mu_asym_hat + (sig_sq_hat_asym/2))

# STANDARD ERROR 
# We find the SE for the log-mean, to account for uncertainty in both mu and sigma squared
# to measure the accuracy of a sample mean and to calculate CIs
wobble_mu = sig_sq_hat_asym / n
wobble_sig2 = (sig_sq_hat_asym^2) / (2 * n)

se_asym = sqrt(wobble_mu + wobble_sig2)

# the asymptotic parameter - mean
x_bar_asym = mu_asym_hat + (sig_sq_hat_asym / 2)

#Get the critical value (z score)

z_crit_asym= qnorm(0.975)

# Calculate the upper and lower asym ci (Still in LOG-SCALE)
asy_ci.low = x_bar_asym - (z_crit_asym * se_asym)
asy_ci.up  = x_bar_asym + (z_crit_asym * se_asym)
asy_ci = c(asy_ci.low, asy_ci.up)


# Transformation the log to the original non-log units
final_asy_ci <- exp(asy_ci)

cat("Point Estimate (MLE Mean):", theta_hat, "\n")
Point Estimate (MLE Mean): 4.218099 
cat("95% Asymptotic CI (Original Scale): [", final_asy_ci[1], ",", final_asy_ci[2], "]\n")
95% Asymptotic CI (Original Scale): [ 3.262868 , 5.452982 ]
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.

boot.ci(boot_result, type=c("perc", "bca"))
BOOTSTRAP CONFIDENCE INTERVAL CALCULATIONS
Based on 5000 bootstrap replicates

CALL : 
boot.ci(boot.out = boot_result, type = c("perc", "bca"))

Intervals : 
Level     Percentile            BCa          
95%   ( 3.103,  5.606 )   ( 3.228,  5.795 )  
Calculations and Intervals on Original Scale
#Comparing the asymptotic distribution
cat("95% Asymptotic CI: ",
    "[", final_asy_ci[1], ",", final_asy_ci[2], "]\n \n")
95% Asymptotic CI:  [ 3.262868 , 5.452982 ]
 
##FIXA asymptotic CI
cat("The bootstrapped MLE Parameter is: ", boot_mle_per_means, "\n" )
The bootstrapped MLE Parameter is:  4.238161 
cat("The jackknife parameter is ", mean_jack)
The jackknife parameter is  4.218495
#Testing width of the intervals
per= 5.587 - 3.106
per
[1] 2.481
Bc = 5.807 - 3.212
Bc
[1] 2.595
Asy = 5.452982 - 3.262868
Asy
[1] 2.190114
per > Bc
[1] FALSE
Asy > Bc
[1] FALSE
Asy > per
[1] FALSE
#Test symmetry from parameter


#how far BCa intervals from mean

5.831848 - boot_mle_per_means #1.593687
[1] 1.593687
boot_mle_per_means- 3.243310 #0.9948512
[1] 0.9948512
#how far perc intervals from mean
boot_mle_per_means -  3.124 #1.114161
[1] 1.114161
5.624 - boot_mle_per_means # 1.385839
[1] 1.385839
#How far asym intervals are from mean

x_bar_asym
[1] 1.439385
asy_ci
[1] 1.182606 1.696163
x_bar_asym - asy_ci
[1]  0.2567781 -0.2567781
# 0.2567781 -0.2567781

Considering the intervals of the percentile bootstrap 95% CI, BCa bootstrap 95% CI and the asymptotic 95%CI, we consider the width of the confidence interval, and the test’s ability to overcome bias to reach the greatest level of accuracy.

We know this is a skewed distribution, the percentile bootstrap CI has some strength in a skewed distribution, but is best suited for roughly symmetric distribution. The skew in this lognormal distribution does not have extreme skew, which is also shown in the percentile CI’s (2.481) similar performance as all 3 confidence interval tests, especially to the width of the BCa CI (2.595).

The percentile’s very slight inability to best follow a skewed distribution confidence interval with bias ends from the mean parameters may slightly artificially closer some of the true variation among the parameter captured during a bootstrap. The percentile interval’s distances from their mean are r boot_mle_per_means - 3.124 and 1.3858388.

As we know the BCa can capture skewness in its confidence intervals, any increases in width, most likely capture the true skewness in the distribution rather than any artificial closeness or widening unlike the percentile ci.

Although smaller confidence intervals, like the one observed in the percentile are typically more precises, variation that allows for possible omition and re-introduction of outliers during the repetitive jackknife test, can overall help lead to more true representations of the distribution as including bias is a strong contender when assessing the realistic use of a dataset. The BCa is the strongest CI test assessed in the model that can handel both skewness and bias, making it the more preferred test despite its larger CI at (3.212, 5.807) and distance from its mean at 2.595`.

Assessing Asymptotic CI Performance

An asymptotic CI uses exact distributions, that assume a shape, in this case a normal distribution. The soil mineral dataset does not follow a normal distribution. The asymptotic inability to follow a skewed distribution leaves force lack of symmetry in capturing the confidence interval ends from the mean parameters. The percentile interval’s distances look as symmetrically although due to the skew of the distribution this is an artificial narrowing of the distance between the mean parameter and confidence interval ends. The distances from the mean parameter for the asymptotic distribution are roughly equal when considered in the distance at the absolute value r x_bar_asym - asy_ci. The skewness of the true distribution is not reflected in the asymptotic distribution, making it the least useful CI test measured in this assessment. Not only is the distance from the mean parameter artificially narrow, so is the width of the confidence interval at 2.190114 with a confidence interval of 1.1826065, 1.6961626.

LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgODogQm9vdHN0cmFwIE1ldGhvZHMgYW5kIEFwcGxpY2F0aW9ucyINCmF1dGhvcjogIiBFemFuYSBSaXZlcnMgIg0KZGF0ZTogIiAwMy0zMS0yNjogIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIGhpZ2hsaWdodDogbW9ub2Nocm9tZQ0KICAgIHRoZW1lOiBzcGFjZWxhYg0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCiNUT0M6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICJUYWJsZSBvZiBDb250ZW50cyI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuMmVtOw0KICBkaXNwbGF5OiBibG9jazsNCiAgY29sb3I6IG5hdnk7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCg0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLw0KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLw0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTVweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KDQpib2R5IHtiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOw0KICAgICAgY29sb3I6ICMwMDAwMDA7DQogICAgICBmb250LWZhbWlseTogQXJpYWwsIHNhbnMtc2VyaWY7DQogICAgICBmb250LXNpemU6IDFyZW07DQogICAgICBsaW5lLWhlaWdodDogMS42Ow0KICAgICAgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KDQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogIGxpYnJhcnkocGxvdGx5KQ0KfQ0KDQppZiAoIXJlcXVpcmUoIlZHQU0iKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJWR0FNIikNCiAgbGlicmFyeShWR0FNKQ0KfQ0KDQppZiAoIXJlcXVpcmUoImJvb3QiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJib290IikNCiAgbGlicmFyeShib290KQ0KfQ0KIyMjIyBWR0FNDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgICMgaW5jbHVkZSBjb2RlIGNodW5rIGluIHRoZSBvdXRwdXQgZmlsZQ0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICAjIHNvbWV0aW1lcywgeW91IGNvZGUgbWF5IHByb2R1Y2Ugd2FybmluZyBtZXNzYWdlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZSB3YXJuaW5nIG1lc3NhZ2VzIGluDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhlIG91dHB1dCBmaWxlLiANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwgICAgIyB5b3UgY2FuIGFsc28gZGVjaWRlIHdoZXRoZXIgdG8gaW5jbHVkZSB0aGUgb3V0cHV0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gdGhlIG91dHB1dCBmaWxlLg0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkENCiAgICAgICAgICAgICAgICAgICAgICApICANCmBgYA0KIA0KIFwNCiANCiMjICoqQXNzaWdubWVudCBPYmplY3RpdmVzKiogDQoNCjxwPg0KKiBSZWluZm9yY2UgdGhlIHVuZGVyc3RhbmRpbmcgb2YgQm9vdHN0cmFwIHNhbXBsaW5nIC4NCg0KKiBVbmRlcnN0YW5kIHRoZSBib290c3RyYXAgZXN0aW1hdGlvbjogY29uZmlkZW5jZSBpbnRlcnZhbCBhbmQgc2FtcGxpbmcgZGlzdHJpYnV0aW9uLg0KPC9wPg0KDQoNCiMjICoqUG9saWNpZXMgb2YgVXNpbmcgQUkgVG9vbHMqKg0KDQo8cD4NCioqUG9saWN5IG9uIEFJIFRvb2wgVXNlKio6IFBsZWFzZSBhZGhlcmUgdG8gdGhlIEFJIHRvb2wgcG9saWN5IHNwZWNpZmllZCBpbiB0aGUgY291cnNlIHN5bGxhYnVzLiBUaGUgZGlyZWN0IGNvcHlpbmcgb2YgQUktZ2VuZXJhdGVkIGNvbnRlbnQgaXMgc3RyaWN0bHkgcHJvaGliaXRlZC4gQWxsIHN1Ym1pdHRlZCB3b3JrIG11c3QgcmVmbGVjdCB5b3VyIG93biB1bmRlcnN0YW5kaW5nOyB3aGVyZSBleHRlcm5hbCB0b29scyBhcmUgY29uc3VsdGVkLCBjb250ZW50IG11c3QgYmUgdGhvcm91Z2hseSByZXBocmFzZWQgYW5kIHN5bnRoZXNpemVkIGluIHlvdXIgb3duIHdvcmRzLg0KPC9wPg0KDQo8cD4NCioqQ29kZSBJbmNsdXNpb24gUmVxdWlyZW1lbnQqKjogQW55IGNvZGUgaW5jbHVkZWQgaW4geW91ciBlc3NheSBtdXN0IGJlIHByb3Blcmx5IGNvbW1lbnRlZCB0byBleHBsYWluIHRoZSBwdXJwb3NlIGFuZC9vciBleHBlY3RlZCBvdXRwdXQgb2Yga2V5IGNvZGUgbGluZXMuIFN1Ym1pdHRpbmcgQUktZ2VuZXJhdGVkIGNvZGUgd2l0aG91dCBtZWFuaW5nZnVsLCBzdHVkZW50LWFkZGVkIGNvbW1lbnRzIHdpbGwgbm90IGJlIGFjY2VwdGVkLg0KPC9wPg0KDQoNCjxwPioqTG9nLW5vcm1hbCBEaXN0cmlidXRpb24gUmV2aXNpdGVkKio8L3A+DQoNCjxwPg0KSWYgJFkgPSBcbG4oWCkgXHNpbSBOKFxtdSwgXHNpZ21hXjIpJCwgdGhlbiAkWCQgZm9sbG93cyBhIGxvZ25vcm1hbCBkaXN0cmlidXRpb24gJFggXHNpbSBcdGV4dHtMb2dub3JtYWx9KFxtdSwgXHNpZ21hXjIpJC4gVGhlIHByb2JhYmlsaXR5IGRlbnNpdHkgaXMgZ2l2ZW4gYnkNCg0KJCQNCmYoeHxcbXUsXHNpZ21hKSA9IFxmcmFjezF9e3hcc2lnbWFcc3FydHsyXHBpfX0gXGV4cFxsZWZ0KC1cZnJhY3soXGxuIHggLSBcbXUpXjJ9ezJcc2lnbWFeMn1ccmlnaHQpLCBccXVhZCB4ID4gMA0KJCQNCg0KQWZ0ZXIgc29tZSBhbGdlYnJhLCB3ZSBjYW4gZXhwcmVzcyB0aGUgbWVhbiBhbmQgdmFyaWFuY2Ugb2YgdGhlIGFib3ZlIGxvZ25vcm1hbCBkaXN0cmlidXRpb24gaW4gdGhlIGZvbGxvd2luZw0KDQoNClxiZWdpbnthbGlnbn0NClxtYXRoYmJ7RX1bWF0gJj0gXGV4cFxsZWZ0KFxtdSArIFxmcmFje1xzaWdtYV4yfXsyfVxyaWdodCkgXFwNClx0ZXh0e1Zhcn0oWCkgJj0gW1xleHAoXHNpZ21hXjIpIC0gMV0gXGV4cCgyXG11ICsgXHNpZ21hXjIpDQpcZW5ke2FsaWdufQ0KDQoNClVzaW5nIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBub3JtYWwgYW5kIGxvZy1ub3JtYWwgZGlzdHJpYnV0aW9uIGFuZCBhIHNhbXBsZSAkXHt4XzEsIHhfMiwgXGRvdHMsIHhfblx9JCwgdGhlIE1MRSBlc3RpbWF0b3JzIG9mICRcbXUkIGFuZCAkXHNpZ21hXjIkIGFyZSBnaXZlbiBieQ0KDQoNClxiZWdpbnthbGlnbn0NClxoYXR7XG11fSAmPSBcZnJhY3sxfXtufVxzdW1fe2k9MX1ebiBcbG4oeF9pKSBcXA0KXGhhdHtcc2lnbWF9XjIgJj0gXGZyYWN7MX17bn1cc3VtX3tpPTF9Xm4gKFxsbih4X2kpIC0gXGhhdHtcbXV9KV4yDQpcZW5ke2FsaWdufQ0KDQoNClVzaW5nIHRoZSBwbHVnLWluIHByaW5jaXBsZSBvZiBNTEUsIHdlIGhhdmUgdGhlIE1MRSBvZiAkXG1hdGhiYntFfVtYXSQgYW5kICRcdGV4dHtWYXJ9KFgpJCBpbiB0aGUgZm9sbG93aW5nDQoNCiQkDQpcYm94ZWR7XHdpZGVoYXR7XG1hdGhiYntFfVtYXX0gPSBcZXhwXGxlZnQoXGhhdHtcbXV9ICsgXGZyYWN7XGhhdHtcc2lnbWF9XjJ9ezJ9XHJpZ2h0KX0NCiQkDQoNCjwvUD4NCg0KDQoNCjxwPjxmb250IGNvbG9yID0gImJsdWUiPioqVGhpcyBhc3NpZ25tZW50IGZvY3VzZXMgb24gY29uc3RydWN0aW5nIHZhcmlvdXMgYm9vdHN0cmFwIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9mIHRoZSBsb2dub3JtYWwgcG9wdWxhdGlvbiBtZWFuICRcbWF0aGJie0V9W1hdJCoqPC9mb250PjwvcD4NCg0KDQpcDQoNCiMjICoqUXVlc3Rpb246IFRyYWNlIE1ldGFsIENvbmNlbnRyYXRpb25zIGluIFNvaWwqKg0KDQo8cD4NClNvaWwgbGVhZCAoUGIpIGNvbmNlbnRyYXRpb25zIChtZy9rZykgZnJvbSA1NSB1cmJhbiBnYXJkZW4gc2l0ZXMuIFRyYWNlIG1ldGFscyBpbiBlbnZpcm9ubWVudGFsIG1lZGlhIHR5cGljYWxseSBmb2xsb3cgbG9nbm9ybWFsIGRpc3RyaWJ1dGlvbnMgZHVlIHRvOg0KDQoqIE11bHRpcGxpY2F0aXZlIHByb2Nlc3NlcyBjb250cm9sbGluZyBhY2N1bXVsYXRpb24NCg0KKiBQb3NpdGl2ZSBjb25zdHJhaW50cyAoY29uY2VudHJhdGlvbnMgY2Fubm90IGJlIG5lZ2F0aXZlKQ0KDQoqIFJpZ2h0LXNrZXdlZCBuYXR1cmUgb2YgY29udGFtaW5hdGlvbiBwYXR0ZXJucw0KPC9wPg0KDQoNCg0KPHA+DQpgYGANCjAuODUsIDEuMjMsIDAuOTIsIDMuNDUsIDIuMTEsIDEuNTYsIDQuODksIDIuMzQsIDEuNzgsIDYuNzIsIDAuOTUsIDEuMzQsIDguOTEsIA0KMi42NywgMS44OSwgNS40MywgMS4xMiwgMy43OCwgMi40NSwgNy42NSwgMS4wNSwgMS40NSwgMTIuMzQsIDIuODksIDIuMDEsIDQuNTYsIA0KMS4yMywgNC4zMiwgMi42NywgOS44NywgMC45OSwgMS41NiwgMTUuMjMsIDMuMTIsIDIuMzQsIDMuODksIDEuMzQsIDUuNjcsIDIuODksIA0KMTEuNDUsIDEuMTIsIDEuNjcsIDE4LjkwLCAzLjQ1LCAyLjU2LCAzLjQ1LCAxLjQ1LCA2Ljc4LCAzLjEyLCAxNC41NiwgMS4yMywgMS43OCwgDQoyMi4zNCwgMy43OCwgMi43OA0KYGBgDQo8L3A+DQoNCjxwPg0KDQokJFxib3hlZHtcdGV4dHtJbnN0cnVjdGlvbnM6fX0kJA0KDQpBc3N1bWUgdGhlIGRhdGEgZm9sbG93IGEgbG9nLW5vcm1hbCBkaXN0cmlidXRpb24uIEZvciBlYWNoIHF1ZXN0aW9uIGluIHBhcnRzIChiKeKAkyhkKSwgYmVnaW4gYnkgY2xlYXJseSBleHBsYWluaW5nIHRoZSByZWFzb25pbmcgYmVoaW5kIHlvdXIgYW5hbHl0aWNhbCBhcHByb2FjaC4gVGhlbiwgZGV2ZWxvcCB5b3VyIG93biBSIGZ1bmN0aW9ucyB0byBpbXBsZW1lbnQgKip0aHJlZSB0eXBlcyBvZiBjb25maWRlbmNlIGludGVydmFsczoqKg0KICAqIHRoZSBhc3ltcHRvdGljIGludGVydmFsLCANCiAgKiB0aGUgcGVyY2VudGlsZSBib290c3RyYXAgaW50ZXJ2YWwsIGFuZCANCiAgKiB0aGUgYmlhcy1jb3JyZWN0ZWQgYW5kIGFjY2VsZXJhdGVkIChCQ2EpIGJvb3RzdHJhcCBpbnRlcnZhbC4gDQogIA0KVXNlIHRoZXNlIGZ1bmN0aW9ucyB0byBjb25zdHJ1Y3QgdGhlIHJlcXVpcmVkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCBhbmQgKip2ZXJpZnkgeW91ciByZXN1bHRzIHVzaW5nIHRoZSBhcHByb3ByaWF0ZSBmdW5jdGlvbnMgZnJvbSB0aGUqKiBgYm9vdGAgcGFja2FnZS4NCg0KWW91IGFyZSBlbmNvdXJhZ2VkIHRvIGRlc2lnbiBhIHdyYXBwZXIgZnVuY3Rpb24gdGhhdCBpbnRlZ3JhdGVzIGFsbCBjb25maWRlbmNlIGludGVydmFsIG1ldGhvZHMsIGFsbG93aW5nIHVzZXJzIHRvIHNlbGVjdCB0aGUgZGVzaXJlZCBtZXRob2QgdGhyb3VnaCBhbiBpbnB1dCBhcmd1bWVudC4NCjwvUD4NCg0KPHA+DQoNCiQkXGJveGVke1x0ZXh0e0luZGl2aWR1YWwgUXVlc3Rpb25zOn19JCQNCg0KYSkuIFBlcmZvcm0gNTAwMCBib290c3RyYXAgc2FtcGxlcyB0byBlc3RpbWF0ZSB0aGUgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiAkXGJveGVke1x3aWRlaGF0e1xtYXRoYmJ7RX1bWF19fSQuIERpc3BsYXkgdGhlIGRpc3RyaWJ1dGlvbiB1c2luZyBlaXRoZXIgYSBoaXN0b2dyYW0gb3IgYSBrZXJuZWwgZGVuc2l0eSBwbG90LiBDb21tZW50IG9uIHRoZSAqKnNoYXBlKiosICoqdmFyaWFiaWxpdHkqKiwgYW5kIGFueSAqKm5vdGFibGUgcGF0dGVybnMgb2JzZXJ2ZWQqKiBpbiB0aGUgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbi4NCg0KYGBge3J9DQoNCg0KI0FOU1dFUlMgUFJPTVBUIEEgDQpzZXQuc2VlZCgxMjMpDQojc29pbCBpcyBhIGxvZyBmdW5jdGlvbg0Kc29pbHJhdyA9IHNvcnQoYygwLjg1LCAxLjIzLCAwLjkyLCAzLjQ1LCAyLjExLCAxLjU2LCA0Ljg5LCAyLjM0LCAxLjc4LCA2LjcyLCAwLjk1LCAxLjM0LCA4LjkxLCAyLjY3LCAxLjg5LCA1LjQzLCAxLjEyLCAzLjc4LCAyLjQ1LCA3LjY1LCAxLjA1LCAxLjQ1LCAxMi4zNCwgMi44OSwgMi4wMSwgNC41NiwgMS4yMywgNC4zMiwgMi42NywgOS44NywgMC45OSwgMS41NiwgMTUuMjMsIDMuMTIsIDIuMzQsIDMuODksIDEuMzQsIDUuNjcsIDIuODksIDExLjQ1LCAxLjEyLCAxLjY3LCAxOC45MCwgMy40NSwgMi41NiwgMy40NSwgMS40NSwgNi43OCwgMy4xMiwgMTQuNTYsIDEuMjMsIDEuNzgsIDIyLjM0LCAzLjc4LCAyLjc4KSkNCg0KbiA9bGVuZ3RoKHNvaWxyYXcpDQoNCiNFc3RpbWF0ZSBib290IHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiAoTUxFKQ0KDQpCID01MDAwDQpib290X21lYW5zIDwtIG51bWVyaWMoQikgI2VtcHR5IHZlY3Rvcg0KDQpmb3IoYiBpbiAxOkIpew0KICBib290X3NhbXBsZSA9IHNhbXBsZShzb2lscmF3LCBuLCByZXBsYWNlPVRSVUUpICMgYm9vdHN0cmFwcyBmcm9tIG9yaWdpbmFsIHNhbXBsZQ0KICANCiAgI0xvZyB0cmFuc2Zvcm0gZm9yIE1MRXMgZm9yIGxvZyB0cmFuc2Zvcm1lZCByZXNhbXBsZQ0KICANCiAgDQogIGxvZ19zYW1wbGU9bG9nKGJvb3Rfc2FtcGxlKQ0KICBsb2dfbWVhbl9wZXJjID0gbWVhbihsb2dfc2FtcGxlKQ0KICBsb2dfdmFyX3BlcmMgPSBzdW0oKGxvZ19zYW1wbGUtbG9nX21lYW5fcGVyYyleMikvbiAjY2FsY3VsYXRlIHZhcmlhbmNlIA0KDQogIA0KICBib290X21lYW5zW2JdID0gZXhwKGxvZ19tZWFuX3BlcmMgKyAobG9nX3Zhcl9wZXJjLzIpKSAjY2FsY3VsYXRlIGFsbCBib290c3RyYXBwZWQgbWVhbiAgUXVlc3Rpb24gQQ0KICANCiAgDQogIA0KfQ0KDQojQ2FsY3VsYXRlIHRoZSBNTEUgbWVhbiBvZiB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbg0KYm9vdF9tbGVfcGVyX21lYW5zPSBtZWFuKGJvb3RfbWVhbnMpDQoNCg0KY2F0KCJRdWVzdGlvbiBBOiAiLCAiVGhlIGF2ZXJhZ2UgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBtZWFuIG9mIHRoZSBzb2lsIG1ldGFsIGNvbmNlbnRyYXRpb24gaXMgIiwgYm9vdF9tbGVfcGVyX21lYW5zKSAgDQogIA0KI2hpc3RvZ3JhbQ0KaGlzdChib290X21lYW5zLA0KICAgICBtYWluID0gIkJvb3RzdHJhcCBEaXN0cmlidXRpb24gb2YgTUxFIE1lYW4gIiwNCiAgICAgcHJvYiA9IFRSVUUpDQoNCmBgYA0KDQoNCioqIFZpZXdpbmcgQ2hhcmFjdGVyaXN0aWNzIG9mIE1MRSBNZWFuIEJvb3RzdHJhcCBEaXN0cmlidXRpb24qKg0KVGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgYm9vdHN0cmFwcGVkIE1MRSBtZWFuIGFwcGVhcnMgdG8gaGF2ZSBzb21lIHNrZXcgYWx0aG91Z2ggdGhlIHNrZXcgZG9lcyBub3QgYXBwZWFyIGV4dHJlbWUuIFRoaXMgaXMgZXhwZWN0ZWQgYXMgdGhlIGRpc3RyaWJ1dGlvbiBpcyBhIGxvZyBvZiBhIG5vcm1hbCBkaXN0cmlidXRpb24sIG1vc3QgbGlrZWx5IGFkZGluZyBzb21lIHJpZ2h0IHNrZXcgYSBwcmV2aW91c2x5IG5vcm1hbCBkaXN0cmlidXRpb24gdG8gYmV0dGVyIHN1aXQgdGhlIG1vZGVsLiBUaGVyZSBpcyBtb2RlcmF0ZSBsb3cgIHZhcmlhbmNlIHRocm91Z2ggdGhlIGhpc3RvZ3JhbS4gT3ZlcmFsbCB0aGlzIGlzIGEgdW5pbW9kYWwgbW9kZWwsIHdpdGggdGhlIGdyZWF0ZXN0IGRlbnNpdHkgYmV0d2VlbiAzLjUgYW5kIDQuNS4gVGhlIGhpc3RvZ3JhbSBzdWdnZXN0cyB0aGUgdmFyaWFuY2Ugb2YgTUxFIGJvb3RzdHJhcHBlZCBtZWFuIHZhbHVlcyB0ZW5kIHRvIGJlIGluIHNpbWlsYXIgcmFuZ2VzLiANCg0KDQpGb3IgZWFjaCBxdWVzdGlvbiBpbiBwYXJ0cyAoYinigJMoZCksIGJlZ2luIGJ5IGNsZWFybHkgZXhwbGFpbmluZyB0aGUgcmVhc29uaW5nIGJlaGluZCB5b3VyIGFuYWx5dGljYWwgYXBwcm9hY2guDQoNCmIpLiBDb25zdHJ1Y3QgYSA5NSUgYm9vdHN0cmFwIHBlcmNlbnRpbGUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgJFxtdV97TE59ID0gXG1hdGhiYntFfVtYXSQuDQoNCioqUGVyZm9ybWluZyBhIEJvb3RzdHJhcCBQZXJjZW50aWxlIDk1JUNJICoqDQoNClBlcmZvcm1pbmcgYSBib290c3RyYXAgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgYSBwZXJjZW50aWxlIGludGVydmFsIHJhbmdpbmcgYWxsIHZhbHVlcyBpbiB0aGUgZGlzdHJpYnV0aW9uIGludG8gcXVhbnRpbGVzIGJldHdlZW4gMCBhbmQgMSB3aGlsZSByZWx5aW5nIG9uIHRoZSBlbXBpcmljYWwgZGlzdHJpYnV0aW9uLiBUaGUgcGVyY2VudGlsZSBib290c3RyYXAgQ0kgYXJlIGNvbnN0cnVjdGVkIGJ5IHF1YW50aWxlcyBhcm91bmQgdGhlIHBhcmFtZXRlciBiYXNlZCBvbiB0aGUgYWxwaGEgdmFsdWUsIGZvciBleGFtcGxlIHZhbHVlcyBiZXR3ZWVuIDIuNSUgYW5kIDk3LjUlIGZyb20gdGhlIGRpc3RyaWJ1dGlvbiBvZiBib290c3RyYXAgZXN0aW1hdGVzLiBBIHBlcmNlbnRpbGUgYm9vdHN0cmFwIHdvcmtzIGJlc3Qgd2hlbiB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBpcyAqKnJvdWdobHkgc3ltbWV0cmljKiogYW5kIGFuICoqZXN0aW1hdG9yIHRoYXQgaGFzIGxpdHRsZSBiaWFzKiouIEluIHRoaXMgZXhhbXBsZSB0aGUgZGlzdHJpYnV0aW9uIGFuZCB2YWx1ZXMgaXMgdGhlIG5vcm1hbCBsb2cgb2YgdGhlIG9yaWdpbmFsICBkaXN0cmlidXRpb24uIFRoZSB0cmFuc2Zvcm1hdGlvbiBzdGlsbCBtYWludGFpbnMgdGhlIHNhbWUgOTUlIGFyZWEgZXZlbiBhZnRlciBiZWluZyBiYWNrIHRyYW5zZm9ybWVkIHRvIGNhbGN1bGF0ZSB0aGUgbW9yZSBhY2N1cmF0ZSBjb25maWRlbmNlIGludGVydmFscyB0byB0aGUgZGlzdHJpYnV0aW9uLg0KDQoNCioqIFBzZXVkby1BbGdvcml0aG0qKg0KYGBgDQpmdW5jdGlvbiBwZXJjZW50aWxlX2NpKGRhdGEsIHN0YXRpc3RpYywgQj01MDAwLCBhbHBoYT0wLjA1KQ0KDQp0aGV0YV9oYXQsIGJvb3RfZGlzID0gYm9vdHN0cmFwKGRhdGEsIHN0YXRpc3RpYyBCKQ0Kc29ydF9ib290ID0gc29ydChsb2coYm9vdF9kaXN0KSkNCmxvd2VyX2lkeCA9IGZsb29yKEIqIGFscGhhLzIpDQp1cHBlcl9pZHggPSBjZWlsaW5nKEIqICgxLWFscGhhLzIpKQ0KbG93ZXIgPSBzb3J0ZWRfYm9vdFtsb3dlcl9pZHhdDQp1cHBlciA9IHNvcnRlZF9ib290W3VwcGVyX2lkeF0NCnJldHVybihsb3dlciwgdXBwZXIpDQpgYGANCg0KYGBge3IgUEVSQ30NCg0KDQojI0Jvb3RzdHJhcHBpbmcgY29uZmlkZW5jZSBpbnRlcnZhbHMgYnkgaG5hZA0KDQoNCiNib290X3Jlc3VsdF9wZXIgPSBib290KHNvaWwsIGJvb3RfbWxlX3Blcl9tZWFucywgUj01MDAwKQ0KDQoNCg0KZm9yKGIgaW4gMTpCKXsNCiAgYm9vdF9zYW1wbGUgPSBzYW1wbGUoc29pbHJhdywgbiwgcmVwbGFjZT1UUlVFKSAjIGJvb3RzdHJhcHMgZnJvbSBvcmlnaW5hbCBzYW1wbGUNCiAgDQogICNMb2cgdHJhbnNmb3JtIGZvciBNTEVzIGZvciBsb2cgdHJhbnNmb3JtZWQgcmVzYW1wbGUNCiAgDQogIA0KICBsb2dfc2FtcGxlPWxvZyhib290X3NhbXBsZSkNCiAgbG9nX21lYW5fcGVyYyA9IG1lYW4obG9nX3NhbXBsZSkNCiAgbG9nX3Zhcl9wZXJjID0gc3VtKChsb2dfc2FtcGxlLWxvZ19tZWFuX3BlcmMpXjIpL24gI2NhbGN1bGF0ZSB2YXJpYW5jZSANCg0KICANCiAgYm9vdF9tZWFuc1tiXSA9IGV4cChsb2dfbWVhbl9wZXJjICsgKGxvZ192YXJfcGVyYy8yKSkgI2NhbGN1bGF0ZSBhbGwgYm9vdHN0cmFwcGVkIG1lYW4gIFF1ZXN0aW9uIEENCiAgDQogIA0KICANCn0NCg0KI0NhbGN1bGF0ZSB0aGUgTUxFIG1lYW4gb2YgdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24NCmJvb3RfbWxlX3Blcl9tZWFucz0gbWVhbihib290X21lYW5zKQ0KDQoNCg0KDQojIENhbGN1bGF0aW5nIHRoZSBxdWFuaXRsZXMgZm9yIFBlcmNlbnRpbGUgQ0kNCmFscGhhID0gMC4wNQ0KDQpjaV9wZXJjIDwtIHF1YW50aWxlKGJvb3RfbWVhbnMsIHByb2JzPWMoYWxwaGEvMiwgMS1hbHBoYS8yKSkNCmNhdCgiIFRoZSBib290c3RyYXBwZWQgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIHBlcmNlbnRpbGVzIGFyZTogWyAiLCBjaV9wZXJjLCAiXSAiLCAiXG4iKQ0KDQoNCg0KDQojRGVmaW5lIHN0YXRpc3RpYyBmdW5jdGlvbg0KbF9tZWFuX3N0YXQgPC0gZnVuY3Rpb24oZGF0YSwgaW5kaWNlcykgew0KICBzYW1wbGVfZGF0YSA8LSBkYXRhW2luZGljZXNdDQogIGxfc2FtcCA9IGxvZyhzYW1wbGVfZGF0YSkNCiAgbWVhbl9zYW0gPSBtZWFuKGxfc2FtcCkNCiAgdiA9IHN1bSgobF9zYW1wIC0gbWVhbl9zYW0pXjIpIC8gbGVuZ3RoKGxfc2FtcCkNCiAgDQogICByZXR1cm4oZXhwKG1lYW5fc2FtICsgdi8yKSkNCn0NCiNWZXJpZnkgd2l0aCBib290KCkgYW5kIGJvb3QuY2koKSBjb21tYW5kDQoNCiNwZXJmb3JtIGJvb3RzdHJhcA0KICBib290X3Jlc3VsdCA9IGJvb3QoZGF0YSA9IHNvaWxyYXcsIHN0YXRpc3RpYyA9IGxfbWVhbl9zdGF0LCBSID0gNTAwMCkNCnBlcmNfYm9vdF9jb21tPSAgYm9vdC5jaShib290X3Jlc3VsdCwgdHlwZSA9ICJwZXJjIikNCg0KY2F0KCJRdWVzdGlvbiBCOiBUaGUgcGVyY2VudGlsZSBib290c3RyYXAgZGVyaXZlZCBmcm9tIHRoZSBib290IGxpYnJhcnkgY29tbWFuZCBpczogIiApDQpwZXJjX2Jvb3RfY29tbQ0KDQpjYXQoIlRoZSBib290c3RyYXBwZWQgTUxFIFBhcmFtZXRlciBpczogIiwgYm9vdF9tbGVfcGVyX21lYW5zICkNCg0KYGBgDQpUaGUgaGFuZCBjYWxjdWxhdGVkIGJvb3RzdHJhcHBlZCBQZXJjZW50aWxlIDk1JUNJIGF0IGByIGNpX3BlcmNgIGlzIGNvbXBhcmFibGUgdG8gdGhlIGJvb3QoKSBsaWJyYXJ5IGJvb3RzdHJhcCBwZXJjZW50aWxlIDk1JSBDSSBhdCAoIDMuMTI0LCAgNS42MjQgKS4gVGhlIG1hbnVhbCBjYWxjdWxhdGlvbiBvZiB0aGUgcGVyY2VudGlsZSA5NSVDSSBoYXMgc2xpZ2h0bHkgc21hbGxlciBpbnRlcnZhbCwgd2hpY2ggY2FuIHN1Z2dlc3QgbW9yZSBhY2N1cmFjeSwgYWx0aG91Z2ggYm90aCBoYXZlIGhpZ2hseSBzaW1pbGFyIHdpZHRocy4gRnVydGhlciB0ZXN0aW5nIHdvdWxkIGJlIG5lZWRlZCB0byBkZXRlcm1pbmUgaWYgdGhlc2UgZGlmZmVyZW5jZXMgYXJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQuDQoNCg0KYykuIENvbnN0cnVjdCBhIDk1JSBib290c3RyYXAgQkNhIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yICRcbXVfe0xOfSA9IFxtYXRoYmJ7RX1bWF0kLg0KDQoNCldlIHVzZSB0aGUgKipCaWFzIENvcnJlbGF0ZWQgYW5kIEFjY2VsZXJhdGVkKiogKEJDYSkgQ29uZmlkZW5jZSBpbnRlcnZhbCB0byBhdm9pZCBza2V3bmVzcyBhbmQgYmlhcyBmcm9tIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gdG8gYmVpbmcgaW1wbGVtZW50ZWQgaW50byB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbDoNCiAgICAqIFdlIHBlcmZvcm0gdGhpcyB1c2luZyBhIEphY2trbmlmZSANCiAgICAqIFRoZSBKYWNra25pZmUgYmFzZWQgKkJDYSogaXMgdGhlIGRlZmF1bHQgbWV0aG9kIGZvciBib290c3RyYXBwZWQgQ0kNCg0KLSBXZSBjb3JyZWN0ICoqYmlhcyBjb3JyZWN0aW9uKiogYnkgbWVhc3VyaW5nIHRoZSAqKnBhcmFtZXRlciBiaWFzKiogYnkgY29tcGFyaW5nIHRoZSBib290c3RyYXAgZXN0aW1hdGUgdG8gdGhlIG9yaWdpbmFsIGVzdGltYXRlDQotIEFjY2VsZXJhdGlvbiAoYSk6IG1lYXN1cmVzICoqaG93KiogdGhlICoqc3RhbmRhcmQgZXJyb3IgY2hhbmdlcyoqIHdpdGggdGhlICoqcGFyYW1ldGVyIHZhbHVlKiogKGVzdGltYXRlIHZpYSBqYWNra25pZmUpDQoNCkl0IGdlbmVyYWxseSBwcm92aWRlcyBtb3JlIGFjY3VyYXRlIGNvdmVyYWdlIHRoYW4gdGhlIHNpbXBsZSBwZXJjZW50aWxlIG1ldGhvZCwgZXNwZWNpYWxseSBmb3Igc2tld2VkIGRpc3RyaWJ1dGlvbnMgb3IgYmlhc2VkIGVzdGltYXRvcnMsIGFuZCByZXNhbXBsaW5nLiBUaGUgQkNhIGlzIGdlbmVyYWxseSB0aGUgbW9zdCByb2J1c3QgQ0kgdHlwZSBkdWUgdG8gaXRzIGFjY291bnRzIGZvciBiaWFzLg0KDQoqKkFsZ29yaXRobSoqDQpgYGANCkNyZWF0ZSBGb3ItbG9vcCBmcm9tIHJhd3NvaWwgKGRhdGFzZXQpIHdpdGggcmVwbGFjZW1lbnQgZm9yIHRoZSBib290c3RyYXAgc2FtcGxlDQpDYWxjdWxhdGUgbWVhbiBhbmQgdmFyaWFuY2Ugb3IgcGFyYW1ldGVyIG9mIGludGVyZXN0IHRvIGFzc2lzdCBDSSBjYWxjdWxhdGlvbnMgDQpBcHBseSBsb2cgbm9ybWFsIHRvIGJvb3N0cmFwcyB0byBhcHBseSBsb2cgbm9ybWFsIGRpc3RyaWJ1dGlvbiANCkNhbGN1bGF0ZSBib290c3RyYXBwZWQgbWVhbiBhbmQgdmFyaWFuY2UNCkFkbWluaXN0ZXIgQmlhcy1Db3JyZWN0aW9uIHdpdGggZGV0ZXJtaW5lZCBhbHBoYSBsZXZlbHMNCkphY2trbmlmZSB0aGUgYm9vdHN0cmFwcGVkIHNhbXBsZQ0KRGVmaW5lIGFscGhhIGxldmVzIGZvciB0aGUgQkNhIENJJ3MgYWRqdXN0ZWQgbGltaXRzIGF0IHRoZSA5NSUgQ29uZmlkZW5jZSBsZXZlbA0KQ29tcGFyZSB3aXRoIGJvb3QgYW5kIGJvb3QuY2koKSBjb21tYW5kcw0KYGBgDQoNCmBgYHtyIEJDYX0NCg0KDQojI0Jvb3RzdHJhcHBpbmcgY29uZmlkZW5jZSBpbnRlcnZhbHMgYnkgaG5hZA0KDQoNCiNib290X3Jlc3VsdF9wZXIgPSBib290KHNvaWwsIGJvb3RfbWxlX3Blcl9tZWFucywgUj01MDAwKQ0KDQoNCg0KZm9yKGIgaW4gMTpCKXsNCiAgYm9vdF9zYW1wbGUgPSBzYW1wbGUoc29pbHJhdywgbiwgcmVwbGFjZT1UUlVFKSAjIGJvb3RzdHJhcHMgZnJvbSBvcmlnaW5hbCBzYW1wbGUNCiAgDQogICNMb2cgdHJhbnNmb3JtIGZvciBNTEVzIGZvciBsb2cgdHJhbnNmb3JtZWQgcmVzYW1wbGUNCiAgDQogIA0KICBsb2dfc2FtcGxlPWxvZyhib290X3NhbXBsZSkNCiAgbG9nX21lYW5fcGVyYyA9IG1lYW4obG9nX3NhbXBsZSkNCiAgbG9nX3Zhcl9wZXJjID0gc3VtKChsb2dfc2FtcGxlLWxvZ19tZWFuX3BlcmMpXjIpL24gI2NhbGN1bGF0ZSB2YXJpYW5jZSANCg0KICANCiAgYm9vdF9tZWFuc1tiXSA9IGV4cChsb2dfbWVhbl9wZXJjICsgKGxvZ192YXJfcGVyYy8yKSkgI2NhbGN1bGF0ZSBhbGwgYm9vdHN0cmFwcGVkIG1lYW4gIFF1ZXN0aW9uIEENCiAgDQogIA0KICANCn0NCg0KI0NhbGN1bGF0ZSB0aGUgTUxFIG1lYW4gb2YgdGhlIGJvb3RzdHJhcCBkaXN0cmlidXRpb24NCmJvb3RfbWxlX3Blcl9tZWFucz0gbWVhbihib290X21lYW5zKQ0KDQoNCiMjRW1wbGljYXRpbmcgdGhlIEphY2trbmlmZSBBcHBvcmFjaCAobm9uIGJvb3QuY2koKSkNCg0KI0JpYXMgQ29ycmVjdGlvbg0Kb3JpZ19sb2cgPSBsb2coc29pbHJhdykNCnRoZXRhX2hhdCA9IGV4cChtZWFuKG9yaWdfbG9nKSArIChzdW0oKG9yaWdfbG9nIC0gbWVhbihvcmlnX2xvZykpXjIpL24pLzIpDQpwcm9wX2xlc3MgPXN1bShib290X21lYW5zIDwgdGhldGFfaGF0KS9CDQp6MCA9IHFub3JtKHByb3BfbGVzcykNCg0KIyBBY2NlbGVyYXRpb24gKGphY2trbmlmZSkNCm4gPSBsZW5ndGgoc29pbHJhdykNCg0KamFja19tbGVzID0gbnVtZXJpYyhuKQ0KICAgIGZvciggaSBpbiAxOm4gKXsNCiAgICAgICAgamFja19zYW1wbGUgPSBzb2lscmF3Wy1pXSAjYWxsIG9icyBtaW51cyAxIA0KICAgICAgbF9qIDwtIGxvZyhqYWNrX3NhbXBsZSkgI2xvZyB0aGUgY29sbGVjdGVkIHNhbWVwbGUgdG8gbWVldCBub3JtYWxsb2cgZGlzdHVidXRpb24NCiAgIyBDYWxjdWxhdGUgTUxFIGZvciB0aGlzIGphY2trbmlmZSBzZXQNCiAgamFja19tbGVzW2ldIDwtIGV4cChtZWFuKGxfaikgKyAoc3VtKChsX2ogLSBtZWFuKGxfaikpXjIpL2xlbmd0aChsX2opKS8yKQ0KfQ0KDQojYWRqdXN0bWVudA0KbWVhbl9qYWNrID0gbWVhbihqYWNrX21sZXMpICNKYWNra25pZmUgUGFyYW1ldGVyDQphX2hhdCA9c3VtKChtZWFuX2phY2sgLSBqYWNrX21sZXMpXjMpIC8gKDYgKiAoc3VtKChtZWFuX2phY2sgLSBqYWNrX21sZXMpXjIpKV4xLjUpDQoNCiNjYWxjdWxhdGUgcGVyY2VudGlsZXMgb2YgaW50ZXJlc3QNCmFscGhhID0wLjA1DQoNCnpfYWxwaGEgPSBxbm9ybShhbHBoYS8yKSAjZGVmaW5pbmcgYWxwaGFzIHVzZWQgZm9yIGNpIGNhbGN1bGF0aW9uDQp6XzFhbHBoYSA9IHFub3JtKDEgLSBhbHBoYS8yKSAjZGVmaW5pbmcgdXBwZXIgZW5kIG9mIGFscGhhIHVzZWQgZm9yIGNpIGNhbHVsYXRpb24NCg0KI0JDYSBDSSB3aXRoIGFkanVzdGVkIGxpbWl0cw0KYWxwaGExID0gcG5vcm0oejAgKyAoejAgKyB6X2FscGhhKS8oMSAtIGFfaGF0Kih6MCArIHpfYWxwaGEpKSkNCiAgICBhbHBoYTIgPSBwbm9ybSh6MCArICh6MCArIHpfMWFscGhhKS8oMSAtIGFfaGF0Kih6MCArIHpfMWFscGhhKSkpDQoNCg0KDQpiY2FfbWFudWFsIDwtIHF1YW50aWxlKGJvb3RfbWVhbnMsIHByb2JzID0gYyhhbHBoYTEsIGFscGhhMikpDQoNCmNhdCgiTWFudWFsIEJDYSBDb25maWRlbmNlIEludGVydmFsOiBbIiwgYmNhX21hbnVhbFsxXSwgIiwiLCBiY2FfbWFudWFsWzJdLCAiXVxuIikNCmNhdCgiVGhlIGphY2trbmlmZSBwYXJhbWV0ZXIgaXMgIiwgbWVhbl9qYWNrKQ0KDQojRGVmaW5lIHN0YXRpc3RpYyBmdW5jdGlvbg0KbF9tZWFuX3N0YXQgPC0gZnVuY3Rpb24oZGF0YSwgaW5kaWNlcykgew0KICBzYW1wbGVfZGF0YSA8LSBkYXRhW2luZGljZXNdDQogIGxfc2FtcCA9IGxvZyhzYW1wbGVfZGF0YSkNCiAgbWVhbl9zYW0gPSBtZWFuKGxfc2FtcCkNCiAgdiA9IHN1bSgobF9zYW1wIC0gbWVhbl9zYW0pXjIpIC8gbGVuZ3RoKGxfc2FtcCkNCiAgDQogICByZXR1cm4oZXhwKG1lYW5fc2FtICsgdi8yKSkNCn0NCiNWZXJpZnkgd2l0aCBib290KCkgYW5kIGJvb3QuY2koKSBjb21tYW5kDQoNCnNldC5zZWVkKDEyMykNCiNwZXJmb3JtIGJvb3RzdHJhcA0KICBib290X3Jlc3VsdCA9IGJvb3QoZGF0YSA9IHNvaWxyYXcsIHN0YXRpc3RpYyA9IGxfbWVhbl9zdGF0LCBSID0gNTAwMCkNCg0KDQpjYXQoIlF1ZXN0aW9uIEI6IFRoZSBCaWFzLSBDb3JyZWN0aW9uIGFuZCBBY2NlbGVyYXRpb24gKEJDYSkgIGJvb3RzdHJhcCBkZXJpdmVkIGZyb20gdGhlIGJvb3QgbGlicmFyeSBjb21tYW5kIGlzOiBcbiIgKQ0KYm9vdC5jaShib290X3Jlc3VsdCwgdHlwZSA9ICJiY2EiKQ0KDQpjYXQoIlRoZSBib290c3RyYXBwZWQgTUxFIFBhcmFtZXRlciBpczogIiwgYm9vdF9tbGVfcGVyX21lYW5zLCAgIlxuIikNCg0KYGBgDQpUaGUgaGFuZCBjYWxjdWxhdGVkIEJDYSA5NSVDSSBhdCAoYHIgYmNhX21hbnVhbGApIGlzIGNvbXBhcmFibGUgYW5kIGhpZ2hseSBzaW1pbGFyIHRvIHRoZSBib290KCkgbGlicmFyeSBib290c3RyYXAgQkNhIDk1JSBDSSBhdCAoIDMuMjEyLCAgNS44MDcgKS4gDQoNCg0KDQoNCmQpLiBVc2UgdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSB0byBjb25zdHJ1Y3QgYSA5NSUgYXN5bXB0b3RpYyBjb25maWRlbmNlIGludGVydmFsIGZvciAkXG11X3tMTn0gPSBcbWF0aGJie0V9W1hdJC4NCg0KKipBcHByb2FjaGluZyBhbiBBc3ltcHRvdGljIENvbmZpZGVuY2UgSW50ZXJ2YWwqKg0KICBUaGUgYXN5bXB0b3RpYyBjb25maWRlbmNlIGludGVydmFsIGlzIGEgbm9uLWJvb3RzdHJhcCBjb25maWRlbmNlIGludGVydmFsIGFwcHJvYWNoLiBJdCB1c2VzIGEgIHBpdm90YWwgcXVhbnRpdGllcyB0byANClBpdm90YWwgcXVhbnRpdGllcyBiYXNlZCBjb25maWRlbmNlIGludGVydmFscyBkbyBub3QgZGVwZW5kIG9uIHRoZSBwYXJhbWV0ZXIgZm9yIGl0cyBjb25zdHJ1Y3Rpb24uIFdlIHVzZSBleGFjdCBkaXN0cmlidXRpb25zIHdob3NlIG5vcm1hbCwgdCBhbmQgJFxjaGleMiQgZGlzdHJpYnV0aW9ucyBhcmUgaW5kZXBlbmRlbnQgb2YgdW5rbm93biBwYXJhbWV0ZXJzICRcbXUkIGFuZCAkXHNpZ21hJCBpbiB0aGUgZGlzdHJpYnV0aW9uLg0KDQpgYGANCklkZW50aWZ5IGFuZCBjYWxjdWxhdGUgY29tcG9uZXRzIG9mIHRoZSBwaXZvdGFsIHF1YW5pdHkNCkNhbGN1bGF0ZSB0aGUgc3RhbmRhcmQgZXJyb3IsIHZhcmlhbmNlIGFuZCBtZWFuIHBhcmFtZXRlcnMuDQpJZGVudGlmeSB0aGUgYWxwaGEgbGV2ZWwgZm9yIDk1JSBjb25maWRlbmNlICgwLjA1KQ0KQ2FsY3VsYXRlIHRoZSBjcml0aWNhbCB2YWx1ZSAoei0gY3JpdGljYWwpDQpVc2UgeiBjcml0aWNhbCB2YWx1ZXMgdG8gY29tcHV0ZSB0aGUgaW50ZXJ2YWxzIGJhc2VkIG9uIHRoZSBtZWFuIHBhcmFtZXRlcg0KQ2FsY3VsYXRlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzDQpgYGANCg0KDQpgYGB7cn0NCiMgQXN5bXB0b3RpYyBDb25maWRlbmNlIEludGVydmFscyAoQ0xULUJhc2VkKSAtLS0NCg0KI0FzeW1wdG90aWMgQ29uZmlkZW5jZSBpbnRlcnZhbHMNCnNvaWxyYXcgPSBzb3J0KGMoMC44NSwgMS4yMywgMC45MiwgMy40NSwgMi4xMSwgMS41NiwgNC44OSwgMi4zNCwgMS43OCwgNi43MiwgMC45NSwgMS4zNCwgOC45MSwgDQoyLjY3LCAxLjg5LCA1LjQzLCAxLjEyLCAzLjc4LCAyLjQ1LCA3LjY1LCAxLjA1LCAxLjQ1LCAxMi4zNCwgMi44OSwgMi4wMSwgNC41NiwgDQoxLjIzLCA0LjMyLCAyLjY3LCA5Ljg3LCAwLjk5LCAxLjU2LCAxNS4yMywgMy4xMiwgMi4zNCwgMy44OSwgMS4zNCwgNS42NywgMi44OSwgDQoxMS40NSwgMS4xMiwgMS42NywgMTguOTAsIDMuNDUsIDIuNTYsIDMuNDUsIDEuNDUsIDYuNzgsIDMuMTIsIDE0LjU2LCAxLjIzLCAxLjc4LCANCjIyLjM0LCAzLjc4LCAyLjc4KSkNCg0Kc29pbCA9IGxvZyhzb2lscmF3KQ0KDQpuID1sZW5ndGgoc29pbCkNCg0KIyNGaW5kaW5nIG11IGhhdCBhbmQgcGFyYW1ldGVycyBmb3IgYXN5bXB0b3RpYyANCm11X2FzeW1faGF0ID0gbWVhbihzb2lsKQ0Kc2lnX3NxX2hhdF9hc3ltID0gc3VtKChzb2lsIC0gbWVhbihzb2lsKSleMikvbiAjIE1heGltdW0gTGlrZWxpaG9vZCBFc3RpbWF0ZSAoTUxFKSBmb3IgdmFyaWFuY2UNCg0KI1BvaW50IGVzdGltYXRlIChMb2dub3JtYWwgbWVhbikNCnRoZXRhX2hhdCA9IGV4cChtdV9hc3ltX2hhdCArIChzaWdfc3FfaGF0X2FzeW0vMikpDQoNCiMgU1RBTkRBUkQgRVJST1IgDQojIFdlIGZpbmQgdGhlIFNFIGZvciB0aGUgbG9nLW1lYW4sIHRvIGFjY291bnQgZm9yIHVuY2VydGFpbnR5IGluIGJvdGggbXUgYW5kIHNpZ21hIHNxdWFyZWQNCiMgdG8gbWVhc3VyZSB0aGUgYWNjdXJhY3kgb2YgYSBzYW1wbGUgbWVhbiBhbmQgdG8gY2FsY3VsYXRlIENJcw0Kd29iYmxlX211ID0gc2lnX3NxX2hhdF9hc3ltIC8gbg0Kd29iYmxlX3NpZzIgPSAoc2lnX3NxX2hhdF9hc3ltXjIpIC8gKDIgKiBuKQ0KDQpzZV9hc3ltID0gc3FydCh3b2JibGVfbXUgKyB3b2JibGVfc2lnMikNCg0KIyB0aGUgYXN5bXB0b3RpYyBwYXJhbWV0ZXIgLSBtZWFuDQp4X2Jhcl9hc3ltID0gbXVfYXN5bV9oYXQgKyAoc2lnX3NxX2hhdF9hc3ltIC8gMikNCg0KI0dldCB0aGUgY3JpdGljYWwgdmFsdWUgKHogc2NvcmUpDQoNCnpfY3JpdF9hc3ltPSBxbm9ybSgwLjk3NSkNCg0KIyBDYWxjdWxhdGUgdGhlIHVwcGVyIGFuZCBsb3dlciBhc3ltIGNpIChTdGlsbCBpbiBMT0ctU0NBTEUpDQphc3lfY2kubG93ID0geF9iYXJfYXN5bSAtICh6X2NyaXRfYXN5bSAqIHNlX2FzeW0pDQphc3lfY2kudXAgID0geF9iYXJfYXN5bSArICh6X2NyaXRfYXN5bSAqIHNlX2FzeW0pDQphc3lfY2kgPSBjKGFzeV9jaS5sb3csIGFzeV9jaS51cCkNCg0KDQojIFRyYW5zZm9ybWF0aW9uIHRoZSBsb2cgdG8gdGhlIG9yaWdpbmFsIG5vbi1sb2cgdW5pdHMNCmZpbmFsX2FzeV9jaSA8LSBleHAoYXN5X2NpKQ0KDQpjYXQoIlBvaW50IEVzdGltYXRlIChNTEUgTWVhbik6IiwgdGhldGFfaGF0LCAiXG4iKQ0KY2F0KCI5NSUgQXN5bXB0b3RpYyBDSSAoT3JpZ2luYWwgU2NhbGUpOiBbIiwgZmluYWxfYXN5X2NpWzFdLCAiLCIsIGZpbmFsX2FzeV9jaVsyXSwgIl1cbiIpDQoNCmBgYA0KDQoNCg0KDQpmKS4gQXNzdW1pbmcgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGNvbnN0cnVjdGVkIGluIHRoZSBwcmV2aW91cyBwYXJ0cyBhcmUgdmFsaWQsIGV2YWx1YXRlIHRoZWlyIHBlcmZvcm1hbmNlIGJ5IGNvbXBhcmluZyB0aGVpciB3aWR0aHMsIHN5bW1ldHJ5LCBzdGFiaWxpdHksIGFuZCBzZW5zaXRpdml0eSB0byBkaXN0cmlidXRpb25hbCBza2V3bmVzcy4gVGhlbiwgcHJvdmlkZSBhIHdlbGzigJFyZWFzb25lZCByZWNvbW1lbmRhdGlvbiByZWdhcmRpbmcgd2hpY2ggbWV0aG9kIGlzIG1vc3Qgc3VpdGFibGUgZm9yIHRoaXMgYW5hbHlzaXMuDQo8L3A+DQoNCmBgYHtyfQ0KYm9vdC5jaShib290X3Jlc3VsdCwgdHlwZT1jKCJwZXJjIiwgImJjYSIpKQ0KI0NvbXBhcmluZyB0aGUgYXN5bXB0b3RpYyBkaXN0cmlidXRpb24NCmNhdCgiOTUlIEFzeW1wdG90aWMgQ0k6ICIsDQogICAgIlsiLCBmaW5hbF9hc3lfY2lbMV0sICIsIiwgZmluYWxfYXN5X2NpWzJdLCAiXVxuIFxuIikNCiMjRklYQSBhc3ltcHRvdGljIENJDQpjYXQoIlRoZSBib290c3RyYXBwZWQgTUxFIFBhcmFtZXRlciBpczogIiwgYm9vdF9tbGVfcGVyX21lYW5zLCAiXG4iICkNCmNhdCgiVGhlIGphY2trbmlmZSBwYXJhbWV0ZXIgaXMgIiwgbWVhbl9qYWNrKQ0KDQoNCiNUZXN0aW5nIHdpZHRoIG9mIHRoZSBpbnRlcnZhbHMNCnBlcj0gNS41ODcgLSAzLjEwNg0KcGVyDQpCYyA9IDUuODA3IC0gMy4yMTINCkJjDQpBc3kgPSA1LjQ1Mjk4MiAtIDMuMjYyODY4DQpBc3kNCnBlciA+IEJjDQoNCkFzeSA+IEJjDQoNCkFzeSA+IHBlcg0KDQojVGVzdCBzeW1tZXRyeSBmcm9tIHBhcmFtZXRlcg0KDQoNCiNob3cgZmFyIEJDYSBpbnRlcnZhbHMgZnJvbSBtZWFuDQoNCjUuODMxODQ4IC0gYm9vdF9tbGVfcGVyX21lYW5zICMxLjU5MzY4Nw0KDQpib290X21sZV9wZXJfbWVhbnMtIDMuMjQzMzEwICMwLjk5NDg1MTINCg0KI2hvdyBmYXIgcGVyYyBpbnRlcnZhbHMgZnJvbSBtZWFuDQpib290X21sZV9wZXJfbWVhbnMgLSAgMy4xMjQgIzEuMTE0MTYxDQo1LjYyNCAtIGJvb3RfbWxlX3Blcl9tZWFucyAjIDEuMzg1ODM5DQoNCiNIb3cgZmFyIGFzeW0gaW50ZXJ2YWxzIGFyZSBmcm9tIG1lYW4NCg0KeF9iYXJfYXN5bQ0KYXN5X2NpDQp4X2Jhcl9hc3ltIC0gYXN5X2NpDQoNCiMgMC4yNTY3NzgxIC0wLjI1Njc3ODENCg0KYGBgDQoNCkNvbnNpZGVyaW5nIHRoZSBpbnRlcnZhbHMgb2YgdGhlIHBlcmNlbnRpbGUgYm9vdHN0cmFwIDk1JSBDSSwgQkNhIGJvb3RzdHJhcCA5NSUgQ0kgYW5kIHRoZSBhc3ltcHRvdGljIDk1JUNJLCB3ZSBjb25zaWRlciB0aGUgd2lkdGggb2YgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwsIGFuZCB0aGUgdGVzdCdzIGFiaWxpdHkgdG8gb3ZlcmNvbWUgYmlhcyB0byByZWFjaCB0aGUgZ3JlYXRlc3QgbGV2ZWwgb2YgYWNjdXJhY3kuIA0KDQoNCldlIGtub3cgdGhpcyBpcyBhIHNrZXdlZCBkaXN0cmlidXRpb24sIHRoZSBwZXJjZW50aWxlIGJvb3RzdHJhcCBDSSBoYXMgc29tZSBzdHJlbmd0aCBpbiBhIHNrZXdlZCBkaXN0cmlidXRpb24sIGJ1dCBpcyBiZXN0IHN1aXRlZCBmb3Igcm91Z2hseSBzeW1tZXRyaWMgZGlzdHJpYnV0aW9uLiBUaGUgc2tldyBpbiB0aGlzIGxvZ25vcm1hbCBkaXN0cmlidXRpb24gZG9lcyBub3QgaGF2ZSBleHRyZW1lIHNrZXcsIHdoaWNoIGlzIGFsc28gc2hvd24gaW4gdGhlIHBlcmNlbnRpbGUgQ0kncyAoYHIgcGVyYCkgc2ltaWxhciBwZXJmb3JtYW5jZSBhcyBhbGwgMyBjb25maWRlbmNlIGludGVydmFsIHRlc3RzLCBlc3BlY2lhbGx5IHRvIHRoZSB3aWR0aCBvZiB0aGUgQkNhIENJIChgciBCY2ApLiANCg0KDQpUaGUgcGVyY2VudGlsZSdzIHZlcnkgc2xpZ2h0IGluYWJpbGl0eSB0byBiZXN0IGZvbGxvdyBhIHNrZXdlZCBkaXN0cmlidXRpb24gY29uZmlkZW5jZSBpbnRlcnZhbCB3aXRoIGJpYXMgZW5kcyBmcm9tIHRoZSBtZWFuIHBhcmFtZXRlcnMgbWF5IHNsaWdodGx5IGFydGlmaWNpYWxseSBjbG9zZXIgc29tZSBvZiB0aGUgdHJ1ZSB2YXJpYXRpb24gYW1vbmcgdGhlIHBhcmFtZXRlciBjYXB0dXJlZCBkdXJpbmcgYSBib290c3RyYXAuDQpUaGUgcGVyY2VudGlsZSBpbnRlcnZhbCdzIGRpc3RhbmNlcyBmcm9tIHRoZWlyIG1lYW4gYXJlIGAgciBib290X21sZV9wZXJfbWVhbnMgLSAgMy4xMjRgIGFuZCBgciA1LjYyNCAtIGJvb3RfbWxlX3Blcl9tZWFuc2AuDQoNCg0KQXMgd2UgIGtub3cgdGhlIEJDYSBjYW4gY2FwdHVyZSBza2V3bmVzcyBpbiBpdHMgY29uZmlkZW5jZSBpbnRlcnZhbHMsIGFueSBpbmNyZWFzZXMgaW4gd2lkdGgsIG1vc3QgbGlrZWx5IGNhcHR1cmUgdGhlIHRydWUgc2tld25lc3MgaW4gdGhlIGRpc3RyaWJ1dGlvbiByYXRoZXIgdGhhbiBhbnkgYXJ0aWZpY2lhbCBjbG9zZW5lc3Mgb3Igd2lkZW5pbmcgdW5saWtlIHRoZSBwZXJjZW50aWxlIGNpLiAgDQoNCkFsdGhvdWdoIHNtYWxsZXIgY29uZmlkZW5jZSBpbnRlcnZhbHMsIGxpa2UgdGhlIG9uZSBvYnNlcnZlZCBpbiB0aGUgcGVyY2VudGlsZSAgYXJlIHR5cGljYWxseSBtb3JlIHByZWNpc2VzLCB2YXJpYXRpb24gdGhhdCBhbGxvd3MgZm9yIHBvc3NpYmxlIG9taXRpb24gYW5kIHJlLWludHJvZHVjdGlvbiBvZiBvdXRsaWVycyBkdXJpbmcgdGhlIHJlcGV0aXRpdmUgamFja2tuaWZlIHRlc3QsIGNhbiBvdmVyYWxsIGhlbHAgbGVhZCB0byBtb3JlIHRydWUgcmVwcmVzZW50YXRpb25zIG9mIHRoZSBkaXN0cmlidXRpb24gYXMgaW5jbHVkaW5nIGJpYXMgaXMgYSBzdHJvbmcgY29udGVuZGVyIHdoZW4gYXNzZXNzaW5nIHRoZSByZWFsaXN0aWMgdXNlIG9mIGEgZGF0YXNldC4gVGhlIEJDYSBpcyB0aGUgc3Ryb25nZXN0IENJIHRlc3QgYXNzZXNzZWQgaW4gdGhlIG1vZGVsIHRoYXQgY2FuIGhhbmRlbCBib3RoIHNrZXduZXNzIGFuZCBiaWFzLCBtYWtpbmcgaXQgdGhlIG1vcmUgcHJlZmVycmVkIHRlc3QgZGVzcGl0ZSBpdHMgbGFyZ2VyIENJIGF0ICgzLjIxMiwgNS44MDcpIGFuZCBkaXN0YW5jZSBmcm9tIGl0cyBtZWFuIGF0IGByIEJjIGBgLg0KDQoNCipBc3Nlc3NpbmcgQXN5bXB0b3RpYyBDSSBQZXJmb3JtYW5jZSoNCg0KQW4gYXN5bXB0b3RpYyBDSSB1c2VzIGV4YWN0IGRpc3RyaWJ1dGlvbnMsIHRoYXQgYXNzdW1lIGEgc2hhcGUsIGluIHRoaXMgY2FzZSBhIG5vcm1hbCBkaXN0cmlidXRpb24uIFRoZSBzb2lsIG1pbmVyYWwgZGF0YXNldCBkb2VzIG5vdCBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uLiBUaGUgYXN5bXB0b3RpYyBpbmFiaWxpdHkgdG8gZm9sbG93IGEgc2tld2VkIGRpc3RyaWJ1dGlvbiBsZWF2ZXMgZm9yY2UgbGFjayBvZiBzeW1tZXRyeSBpbiBjYXB0dXJpbmcgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZW5kcyBmcm9tIHRoZSBtZWFuIHBhcmFtZXRlcnMuIFRoZSBwZXJjZW50aWxlIGludGVydmFsJ3MgZGlzdGFuY2VzIGxvb2sgYXMgc3ltbWV0cmljYWxseSBhbHRob3VnaCBkdWUgdG8gdGhlIHNrZXcgb2YgdGhlIGRpc3RyaWJ1dGlvbiB0aGlzIGlzIGFuIGFydGlmaWNpYWwgbmFycm93aW5nIG9mIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHRoZSBtZWFuIHBhcmFtZXRlciBhbmQgY29uZmlkZW5jZSBpbnRlcnZhbCBlbmRzLiBUaGUgZGlzdGFuY2VzIGZyb20gdGhlIG1lYW4gcGFyYW1ldGVyIGZvciB0aGUgYXN5bXB0b3RpYyBkaXN0cmlidXRpb24gYXJlIHJvdWdobHkgZXF1YWwgd2hlbiBjb25zaWRlcmVkIGluIHRoZSBkaXN0YW5jZSBhdCB0aGUgYWJzb2x1dGUgdmFsdWUgYCByIHhfYmFyX2FzeW0gLSBhc3lfY2lgLiBUaGUgc2tld25lc3Mgb2YgdGhlIHRydWUgZGlzdHJpYnV0aW9uIGlzIG5vdCByZWZsZWN0ZWQgaW4gdGhlIGFzeW1wdG90aWMgZGlzdHJpYnV0aW9uLCBtYWtpbmcgaXQgdGhlIGxlYXN0IHVzZWZ1bCBDSSB0ZXN0IG1lYXN1cmVkIGluIHRoaXMgYXNzZXNzbWVudC4gTm90IG9ubHkgaXMgdGhlIGRpc3RhbmNlIGZyb20gdGhlIG1lYW4gcGFyYW1ldGVyIGFydGlmaWNpYWxseSBuYXJyb3csIHNvIGlzIHRoZSB3aWR0aCBvZiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBhdCBgciBBc3lgIHdpdGggYSBjb25maWRlbmNlIGludGVydmFsIG9mIGByIGFzeV9jaWAuDQo=