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:
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
[1] 2.595
Asy = 5.452982 - 3.262868
Asy
[1] 2.190114
[1] FALSE
[1] FALSE
[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
[1] 1.182606 1.696163
[1] 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=