Assignment Objectives
Enhance understanding the procedure of Bootstrap hypothesis
testing.
Implement the procedures for detecting overfitting/underfitting
issues in practical applications using bootstrap likelihood ratio
test.
Testing Overfitting/Underfitting
In Machine Learning and Statistics, overfitting occurs when a model
is too complex and learns noise, leading to poor performance on new
data, while underfitting happens when a model is too simple to capture
important patterns, resulting in high errors overall; both issues are
explained by the Bias–Variance Tradeoff and can cause unreliable
predictions in real-world applications.
The probability density function (PDF) of the Weibull distribution
is:
\[
f(t; \lambda, \beta) = \frac{\beta}{\lambda} \left( \frac{t}{\lambda}
\right)^{\beta-1} \exp\left[ -\left( \frac{t}{\lambda} \right)^\beta
\right], \quad t \ge 0
\] where \(\lambda > 0\) is
the scale parameter (characteristic life) and \(\beta > 0\) is the shape parameter.
When \(\beta = 1\), the Weibull PDF
simplifies to the exponential PDF:
\[
f(t; \lambda) = \frac{1}{\lambda} \exp\left( -\frac{t}{\lambda} \right)
\] with constant hazard rate \(h(t) =
1/\lambda\).
This assignment focuses on performing a
hypothesis test for the shape parameter (\(\beta\)) of the Weibull distribution within
a reliability mode
\[\begin{align}
H_0&: \beta = 1 \quad \text{(Exponential model, simpler)} \\
H_1&: \beta \neq 1 \quad \text{(Weibull model, more complex)}
\end{align}\]
Steps of the BLRT
Fit models under \(H_0\) and
\(H_1\)} to the original data, compute
\(\Lambda_{\text{obs}}\).
Generate bootstrap samples under \(H_0\)}:
- Estimate parameters under \(H_0\)
from the original data.
- Generate \(B\) datasets by sampling
from the model under \(H_0\)
(parametric bootstrap) or by resampling residuals/cases (nonparametric
bootstrap; parametric is common for BLRT).
For each bootstrap sample \(b =
1,\dots,B\):
- Fit \(H_0\) and \(H_1\) models.
- Compute \(\Lambda_b = -2[\ell_{0,b} -
\ell_{1,b}]\).
Approximate p-value:
\[
p = \frac{1}{B} \sum_{b=1}^B I(\Lambda_b \ge \Lambda_{\text{obs}})
\] (Often a small adjustment is made for stability: \((1 + \#\{\Lambda_b \ge
\Lambda_{\text{obs}}\})/(B+1)\)).
Question: Reliability Application
A wind energy company monitors the reliability of gearboxes in 75
identical wind turbines located in a coastal wind farm. The gearbox is a
critical component; its failure often leads to costly downtime and
repairs. Previous studies suggest that the hazard rate (failure risk)
may increase over time due to mechanical wear (fatigue, pitting, bearing
degradation). Engineers want to test whether the failure time
distribution follows an exponential model (constant hazard, random
failures) or a Weibull model with shape parameter \(k>1\) (increasing hazard, indicative of
aging/degradation). The failure times (in months) are:
5.2, 7.8, 9.1, 11.3, 12.5, 13.0, 14.2, 15.1, 15.9, 16.7, 17.2, 17.8, 18.4, 18.9,
19.3, 19.7, 20.2, 20.6, 21.0, 21.5, 21.9, 22.3, 22.7, 23.1, 23.5, 23.9, 24.3, 24.7,
25.1, 25.5, 25.9, 26.3, 26.7, 27.1, 27.5, 27.9, 28.3, 28.7, 29.1, 29.5, 29.9, 30.3,
30.7, 31.1, 31.5, 31.9, 32.3, 32.7, 33.1, 33.5, 33.9, 34.3, 34.7, 35.1, 35.5, 35.9,
36.3, 36.7, 37.1, 37.5, 37.9, 38.3, 38.7, 39.1, 39.5, 39.9, 40.3, 40.7, 41.1, 41.5,
41.9, 42.3, 42.7, 43.1, 43.5
This assignment focuses on hypothesis \(H_0: \beta = 1\) (exponential) against
\(H_1: \beta \neq 1\) (Weibull). This
framework detects overfitting (fitting a Weibull when exponential is
true) and underfitting (fitting exponential when Weibull with \(\beta \neq 1\) is true).
a). Find the MLE of the Weibull parameters \(\lambda\) (scale) and \(\beta\) (shape), denoted by \(\hat{\lambda}\) and \(\hat{\beta}\), respectively, using the
optim() procedure. [Hint: You should provide explicit
expressions for the log-likelihood and gradient functions of the Weibull
distribution parameters.]
Answer to Question 1 Part A
We are provided with the probability density function (PDF) of the
Weibull distribution:
\[
f(t; \lambda, \beta) = \frac{\beta}{\lambda} \left( \frac{t}{\lambda}
\right)^{\beta-1} \exp\left[ -\left( \frac{t}{\lambda} \right)^\beta
\right], \quad t \ge 0
\]
We can use this to find the likelihood function:
\[
L(\lambda, \beta)=\prod_{i=1}^nf(t_i ; \lambda, \beta)=\prod_{i=1}^n
\frac{\beta}{\lambda} \left( \frac{t_i}{\lambda} \right)^{\beta-1}
\exp\left[ -\left( \frac{t_i}{\lambda} \right)^\beta \right]
\]
Therefore the log-likelihood function is:
$$
\[\begin{aligned}
\ell(\lambda, \beta) &= \log(L(\lambda, \beta)) \\
&=
\sum_{i=1}^n\left[\log\beta-\log\lambda+(\beta-1)\log(t_i/\lambda)-(t_i/\lambda)^\beta\right]
\\
&= n\log\beta-n\log\lambda+(\beta-1)\sum_{i=1}^n\log
t_i-\sum_{i=1}^n(t_i/\lambda)^\beta
\end{aligned}\]
$$
Using the log-likelihood function we can take the partial derivatives
of \(\lambda\) and \(\beta\) to find the gradient functions:
$$
\[\begin{aligned}
\frac{\partial\ell}{\partial\lambda}
&=-\frac{n\beta}{\lambda}+\frac{\beta}{\lambda}\sum_{i=1}^n(t_i/\lambda)^\beta
\\
\frac{\partial\ell}{\partial\beta}
&=\frac{n}{\beta}-n\log\lambda+\sum_{i=1}^n\log t_i-\sum_{i=1}^n\log
t_i-\sum_{i=1}^n(t_i/\lambda)^\beta\log(t_i/\lambda)
\end{aligned}\]
$$
We can then use our log-likelihood function and gradient functions to
find \(\hat{\lambda}\) and \(\hat{\beta}\):
turbine <- c( 5.2, 7.8, 9.1, 11.3, 12.5, 13.0, 14.2, 15.1, 15.9, 16.7, 17.2, 17.8, 18.4, 18.9,
19.3, 19.7, 20.2, 20.6, 21.0, 21.5, 21.9, 22.3, 22.7, 23.1, 23.5, 23.9, 24.3, 24.7,
25.1, 25.5, 25.9, 26.3, 26.7, 27.1, 27.5, 27.9, 28.3, 28.7, 29.1, 29.5, 29.9, 30.3,
30.7, 31.1, 31.5, 31.9, 32.3, 32.7, 33.1, 33.5, 33.9, 34.3, 34.7, 35.1, 35.5, 35.9,
36.3, 36.7, 37.1, 37.5, 37.9, 38.3, 38.7, 39.1, 39.5, 39.9, 40.3, 40.7, 41.1, 41.5,
41.9, 42.3, 42.7, 43.1, 43.5)
loglik_weibull <- function(par, x){ #Used to impute log-likelihood
lambda <- par[1]
beta <- par[2]
if (lambda <= 0 || beta <= 0) return (Inf)
n <- length(x)
ll <- n*log(beta)-n*beta*log(lambda)+(beta-1)*sum(log(x))-sum((x/lambda)^beta)
return(-ll)
}
grad_weibull <- function(par, x){ #Used to impute gradient functions
lambda <- par[1]
beta <- par[2]
if (lambda <= 0 || beta <= 0) return (c(Inf, Inf))
n <- length(x)
term <- (x/lambda)^beta
d_lambda <- -n*beta/lambda+(beta/lambda)*sum(term)
d_beta <- n/beta-n*log(lambda)+sum(log(x))-sum(term*log(x/lambda))
return(-c(d_lambda, d_beta))
}
result <- optim( #Used to compute MLEs
par=c(1,1),
fn=loglik_weibull,
gr=grad_weibull,
x=turbine,
method="L-BFGS-B",
lower=c(1e-6, 1e-6)
)
result
$par
[1] 31.41820 3.37078
$value
[1] 275.103
$counts
function gradient
22 22
$convergence
[1] 0
$message
[1] "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH"
lambda_hat <- result$par[1] #Gets MLEs from optim function
beta_hat <- result$par[2]
lambda_hat
[1] 31.4182
[1] 3.37078
The MLE of the Weibull parameters are \(\hat{\lambda}=31.41820\) and \(\hat{\beta}=3.37078\).
b). Find the MLE of the exponential parameter \(\lambda\) (scale), denoted by \(\hat{\lambda}\), using any procedure.
[Hint: You should provide explicit expressions for the
log-likelihood and gradient functions of the exponential distribution
parameters.]
Answer to Question 1 Part B
We are provided with the probability density function (PDF) of the
Weibull distribution when \(\beta=1\):
\[
f(t; \lambda) = \frac{1}{\lambda} \exp\left( -\frac{t}{\lambda} \right)
\]
We can use this to find the likelihood function:
\[
L(\lambda)=\prod_{i=1}^nf(t;
\lambda)=\prod_{i=1}^n\frac{1}{\lambda}e^{-t_i/\lambda}
\]
Then we can find the log-likelihood function:
\[
\ell(\lambda)=\log
L(\lambda)=\sum_{i=1}^n\left[-\log\lambda-\frac{t_i}{\lambda}\right] =
-n\log\lambda-\frac{1}{\lambda}\sum_{i=1}^n t_i
\]
We can then find the gradient function and solve for \(\hat{\lambda}\):
$$
\[\begin{aligned}
&\frac{\partial\ell}{\partial\lambda}=-\frac{n}{\lambda}+\frac{1}{\lambda^2}\sum_{i=1}^n
t_i \\
&\Rightarrow -\frac{n}{\lambda}+\frac{1}{\lambda^2}\sum_{i=1}^n
t_i=0 \\
&\Rightarrow -n\lambda+\sum_{i=1}^n t_i =0 \\
&\Rightarrow \lambda=\frac{1}{n}\sum_{i=1}^n t_i
\end{aligned}\]
$$
Therefore,
\[
\hat{\lambda}=\frac{1}{n}\sum_{i=1}^n t_i
\]
We can use this to find \(\hat{\lambda}\):
lambda_hat2 = mean(turbine) #Gets lambda MLE
lambda_hat2
[1] 28.18533
The MLE of the Weibull parameter when \(\beta=1\) is \(\hat{\lambda}=28.18533\).
c). Use a) and b) to perform the regular likelihood ratio \(\chi^2\) test for \(\beta = 1\) and report the p-value.
Answer to Question 1 Part C
ll_weibull <- function(x, lambda, beta){ #Computes Weibull log-likelihood
n <- length(x)
n*log(beta)-n*beta*log(lambda)+(beta-1)*sum(log(x))-sum((x/lambda)^beta)
}
ll_exp <- function(x, lambda){ #Computes exponential log-likelihood
n <- length(x)
-n*log(lambda)-sum(x)/lambda
}
lambda_hat_weibull <- 31.41820 #Plugs in MLEs
beta_hat_weibull <- 3.37078
lambda_hat_exp <- 28.18533
ll1 <- ll_weibull(turbine, lambda_hat_weibull, beta_hat_weibull) #Gets maximized log-likelihoods
ll0 <- ll_exp(turbine, lambda_hat_exp)
LR <- 2*(ll1 - ll0) #Computes likelihood ratio
LR
[1] 100.6144
p_value <- 1 - pchisq(LR, df=1) #Gets p-value
p_value
[1] 0
The p-value is approximately zero.
d). Use the BLRT algorithm to perform a bootstrap likelihood ratio
test and report the bootstrap p-value. Note that you are expected to
translate the BLRT algorithm into R code to perform the BLRT. [Hint:
The chi-square distribution should not be used in this part of the
analysis.]
Answer to Question 1 Part D
set.seed(123)
B <- 1000
n <- length(turbine)
LR_boot <- numeric(B)
for (b in 1:B){
x_boot <- rexp(n, rate = 1/lambda_hat2)
lambda_exp_star <- mean(x_boot)
fit <- optim(
par = c(1,1),
fn = loglik_weibull,
gr = grad_weibull,
x = x_boot,
method = "L-BFGS-B",
lower = c(1e-6, 1e-6)
)
lambda_weib_star <- fit$par[1]
beta_weib_star <- fit$par[2]
ll0_star <- ll_exp(x_boot, lambda_exp_star)
ll1_star <- ll_weibull(x_boot, lambda_weib_star, beta_weib_star)
LR_boot[b] <- 2*(ll1_star-ll0_star)
}
p_value2 <- (sum(LR_boot >= LR) + 1) / (B + 1)
p_value2
[1] 0.000999001
The p-value is 0.000999001.
e). Write a summary of the above analyses to address the
following:
Answer to Question 1 Part E:
Both tests indicated that \(\beta \ne
1\) (at the 0.05 significance level) given that the p-values for
the tests were \(\text{p-value}= 0 <
0.05\) and \(\text{p-value}=
0.000999001 < 0.05\). Therefore, the Weibull model would be
recommended for this data given that we have evidence that \(\beta \ne 1\).
LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMTI6IEJvb3RzdHJhcCBMaWtlbGlob29kIFJhdGlvIFRlc3QgKEJMUlQpIg0KYXV0aG9yOiAiR3JhY2UgTGlwcGVydCAiDQpkYXRlOiAiIER1ZTogNC8yMS8yMDI2Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIGhpZ2hsaWdodDogbW9ub2Nocm9tZQ0KICAgIHRoZW1lOiBzcGFjZWxhYg0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCiNUT0M6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICJUYWJsZSBvZiBDb250ZW50cyI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuMmVtOw0KICBkaXNwbGF5OiBibG9jazsNCiAgY29sb3I6IG5hdnk7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCg0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLw0KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLw0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTVweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KDQpib2R5IHtiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOw0KICAgICAgY29sb3I6ICMwMDAwMDA7DQogICAgICBmb250LWZhbWlseTogQXJpYWwsIHNhbnMtc2VyaWY7DQogICAgICBmb250LXNpemU6IDFyZW07DQogICAgICBsaW5lLWhlaWdodDogMS42Ow0KICAgICAgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KDQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogIGxpYnJhcnkocGxvdGx5KQ0KfQ0KDQppZiAoIXJlcXVpcmUoIlZHQU0iKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJWR0FNIikNCiAgbGlicmFyeShWR0FNKQ0KfQ0KIyMjIyBWR0FNDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgICMgaW5jbHVkZSBjb2RlIGNodW5rIGluIHRoZSBvdXRwdXQgZmlsZQ0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICAjIHNvbWV0aW1lcywgeW91IGNvZGUgbWF5IHByb2R1Y2Ugd2FybmluZyBtZXNzYWdlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZSB3YXJuaW5nIG1lc3NhZ2VzIGluDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhlIG91dHB1dCBmaWxlLiANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwgICAgIyB5b3UgY2FuIGFsc28gZGVjaWRlIHdoZXRoZXIgdG8gaW5jbHVkZSB0aGUgb3V0cHV0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gdGhlIG91dHB1dCBmaWxlLg0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkENCiAgICAgICAgICAgICAgICAgICAgICApICANCmBgYA0KIA0KIFwNCiANCiMjICoqQXNzaWdubWVudCBPYmplY3RpdmVzKiogDQoNCjxwPg0KKiBFbmhhbmNlIHVuZGVyc3RhbmRpbmcgdGhlIHByb2NlZHVyZSBvZiBCb290c3RyYXAgaHlwb3RoZXNpcyB0ZXN0aW5nLg0KDQoqIEltcGxlbWVudCB0aGUgcHJvY2VkdXJlcyBmb3IgZGV0ZWN0aW5nIG92ZXJmaXR0aW5nL3VuZGVyZml0dGluZyBpc3N1ZXMgaW4gcHJhY3RpY2FsIGFwcGxpY2F0aW9ucyB1c2luZyBib290c3RyYXAgbGlrZWxpaG9vZCByYXRpbyB0ZXN0Lg0KPC9wPg0KDQoNCiMjICoqUG9saWNpZXMgb2YgVXNpbmcgQUkgVG9vbHMqKg0KDQo8cD4NCioqUG9saWN5IG9uIEFJIFRvb2wgVXNlKio6IFBsZWFzZSBhZGhlcmUgdG8gdGhlIEFJIHRvb2wgcG9saWN5IHNwZWNpZmllZCBpbiB0aGUgY291cnNlIHN5bGxhYnVzLiBUaGUgZGlyZWN0IGNvcHlpbmcgb2YgQUktZ2VuZXJhdGVkIGNvbnRlbnQgaXMgc3RyaWN0bHkgcHJvaGliaXRlZC4gQWxsIHN1Ym1pdHRlZCB3b3JrIG11c3QgcmVmbGVjdCB5b3VyIG93biB1bmRlcnN0YW5kaW5nOyB3aGVyZSBleHRlcm5hbCB0b29scyBhcmUgY29uc3VsdGVkLCBjb250ZW50IG11c3QgYmUgdGhvcm91Z2hseSByZXBocmFzZWQgYW5kIHN5bnRoZXNpemVkIGluIHlvdXIgb3duIHdvcmRzLg0KPC9wPg0KDQo8cD4NCioqQ29kZSBJbmNsdXNpb24gUmVxdWlyZW1lbnQqKjogQW55IGNvZGUgaW5jbHVkZWQgaW4geW91ciBlc3NheSBtdXN0IGJlIHByb3Blcmx5IGNvbW1lbnRlZCB0byBleHBsYWluIHRoZSBwdXJwb3NlIGFuZC9vciBleHBlY3RlZCBvdXRwdXQgb2Yga2V5IGNvZGUgbGluZXMuIFN1Ym1pdHRpbmcgQUktZ2VuZXJhdGVkIGNvZGUgd2l0aG91dCBtZWFuaW5nZnVsLCBzdHVkZW50LWFkZGVkIGNvbW1lbnRzIHdpbGwgbm90IGJlIGFjY2VwdGVkLg0KPC9wPg0KDQoNCg0KDQojIyBUZXN0aW5nIE92ZXJmaXR0aW5nL1VuZGVyZml0dGluZw0KDQpJbiBNYWNoaW5lIExlYXJuaW5nIGFuZCBTdGF0aXN0aWNzLCBvdmVyZml0dGluZyBvY2N1cnMgd2hlbiBhIG1vZGVsIGlzIHRvbyBjb21wbGV4IGFuZCBsZWFybnMgbm9pc2UsIGxlYWRpbmcgdG8gcG9vciBwZXJmb3JtYW5jZSBvbiBuZXcgZGF0YSwgd2hpbGUgdW5kZXJmaXR0aW5nIGhhcHBlbnMgd2hlbiBhIG1vZGVsIGlzIHRvbyBzaW1wbGUgdG8gY2FwdHVyZSBpbXBvcnRhbnQgcGF0dGVybnMsIHJlc3VsdGluZyBpbiBoaWdoIGVycm9ycyBvdmVyYWxsOyBib3RoIGlzc3VlcyBhcmUgZXhwbGFpbmVkIGJ5IHRoZSBCaWFz4oCTVmFyaWFuY2UgVHJhZGVvZmYgYW5kIGNhbiBjYXVzZSB1bnJlbGlhYmxlIHByZWRpY3Rpb25zIGluIHJlYWwtd29ybGQgYXBwbGljYXRpb25zLg0KDQoNClRoZSBwcm9iYWJpbGl0eSBkZW5zaXR5IGZ1bmN0aW9uIChQREYpIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBpczoNCg0KJCQNCmYodDsgXGxhbWJkYSwgXGJldGEpID0gXGZyYWN7XGJldGF9e1xsYW1iZGF9IFxsZWZ0KCBcZnJhY3t0fXtcbGFtYmRhfSBccmlnaHQpXntcYmV0YS0xfSBcZXhwXGxlZnRbIC1cbGVmdCggXGZyYWN7dH17XGxhbWJkYX0gXHJpZ2h0KV5cYmV0YSBccmlnaHRdLCBccXVhZCB0IFxnZSAwDQokJA0Kd2hlcmUgJFxsYW1iZGEgPiAwJCBpcyB0aGUgc2NhbGUgcGFyYW1ldGVyIChjaGFyYWN0ZXJpc3RpYyBsaWZlKSBhbmQgJFxiZXRhID4gMCQgaXMgdGhlIHNoYXBlIHBhcmFtZXRlci4NCg0KV2hlbiAkXGJldGEgPSAxJCwgdGhlIFdlaWJ1bGwgUERGIHNpbXBsaWZpZXMgdG8gdGhlIGV4cG9uZW50aWFsIFBERjoNCg0KJCQNCmYodDsgXGxhbWJkYSkgPSBcZnJhY3sxfXtcbGFtYmRhfSBcZXhwXGxlZnQoIC1cZnJhY3t0fXtcbGFtYmRhfSBccmlnaHQpDQokJA0Kd2l0aCBjb25zdGFudCBoYXphcmQgcmF0ZSAkaCh0KSA9IDEvXGxhbWJkYSQuDQoNCg0KPHA+PGZvbnQgY29sb3IgPSAiZGFya3JlZCI+KipUaGlzIGFzc2lnbm1lbnQgZm9jdXNlcyBvbiBwZXJmb3JtaW5nIGEgaHlwb3RoZXNpcyB0ZXN0IGZvciB0aGUgc2hhcGUgcGFyYW1ldGVyICgkXGJldGEkKSBvZiB0aGUgV2VpYnVsbCBkaXN0cmlidXRpb24gd2l0aGluIGEgcmVsaWFiaWxpdHkgbW9kZSoqPC9mb250PjwvcD4NCg0KDQpcYmVnaW57YWxpZ259DQpIXzAmOiBcYmV0YSA9IDEgXHF1YWQgXHRleHR7KEV4cG9uZW50aWFsIG1vZGVsLCBzaW1wbGVyKX0gXFwNCkhfMSY6IFxiZXRhIFxuZXEgMSBccXVhZCBcdGV4dHsoV2VpYnVsbCBtb2RlbCwgbW9yZSBjb21wbGV4KX0NClxlbmR7YWxpZ259DQoNCg0KDQojIyBTdGVwcyBvZiB0aGUgQkxSVA0KDQoNCiogRml0IG1vZGVscyB1bmRlciAkSF8wJCBhbmQgJEhfMSR9IHRvIHRoZSBvcmlnaW5hbCBkYXRhLCBjb21wdXRlICRcTGFtYmRhX3tcdGV4dHtvYnN9fSQuDQoNCiogR2VuZXJhdGUgYm9vdHN0cmFwIHNhbXBsZXMgdW5kZXIgJEhfMCR9OiANCiAgKyBFc3RpbWF0ZSBwYXJhbWV0ZXJzIHVuZGVyICRIXzAkIGZyb20gdGhlIG9yaWdpbmFsIGRhdGEuDQogICsgR2VuZXJhdGUgJEIkIGRhdGFzZXRzIGJ5IHNhbXBsaW5nIGZyb20gdGhlIG1vZGVsIHVuZGVyICRIXzAkIChwYXJhbWV0cmljIGJvb3RzdHJhcCkgb3IgYnkgcmVzYW1wbGluZyByZXNpZHVhbHMvY2FzZXMgKG5vbnBhcmFtZXRyaWMgYm9vdHN0cmFwOyBwYXJhbWV0cmljIGlzIGNvbW1vbiBmb3IgQkxSVCkuDQoNCiogRm9yIGVhY2ggYm9vdHN0cmFwIHNhbXBsZSAkYiA9IDEsXGRvdHMsQiQ6DQogICsgRml0ICRIXzAkIGFuZCAkSF8xJCBtb2RlbHMuDQogICsgQ29tcHV0ZSAkXExhbWJkYV9iID0gLTJbXGVsbF97MCxifSAtIFxlbGxfezEsYn1dJC4NCg0KKiBBcHByb3hpbWF0ZSBwLXZhbHVlOg0KDQokJA0KICBwID0gXGZyYWN7MX17Qn0gXHN1bV97Yj0xfV5CIEkoXExhbWJkYV9iIFxnZSBcTGFtYmRhX3tcdGV4dHtvYnN9fSkNCiQkDQooT2Z0ZW4gYSBzbWFsbCBhZGp1c3RtZW50IGlzIG1hZGUgZm9yIHN0YWJpbGl0eTogJCgxICsgXCNce1xMYW1iZGFfYiBcZ2UgXExhbWJkYV97XHRleHR7b2JzfX1cfSkvKEIrMSkkKS4NCg0KDQoNClwNCg0KIyMgKipRdWVzdGlvbjogUmVsaWFiaWxpdHkgQXBwbGljYXRpb24qKg0KDQo8cD4NCkEgd2luZCBlbmVyZ3kgY29tcGFueSBtb25pdG9ycyB0aGUgcmVsaWFiaWxpdHkgb2YgZ2VhcmJveGVzIGluIDc1IGlkZW50aWNhbCB3aW5kIHR1cmJpbmVzIGxvY2F0ZWQgaW4gYSBjb2FzdGFsIHdpbmQgZmFybS4gVGhlIGdlYXJib3ggaXMgYSBjcml0aWNhbCBjb21wb25lbnQ7IGl0cyBmYWlsdXJlIG9mdGVuIGxlYWRzIHRvIGNvc3RseSBkb3dudGltZSBhbmQgcmVwYWlycy4gUHJldmlvdXMgc3R1ZGllcyBzdWdnZXN0IHRoYXQgdGhlIGhhemFyZCByYXRlIChmYWlsdXJlIHJpc2spIG1heSBpbmNyZWFzZSBvdmVyIHRpbWUgZHVlIHRvIG1lY2hhbmljYWwgd2VhciAoZmF0aWd1ZSwgcGl0dGluZywgYmVhcmluZyBkZWdyYWRhdGlvbikuIEVuZ2luZWVycyB3YW50IHRvIHRlc3Qgd2hldGhlciB0aGUgZmFpbHVyZSB0aW1lIGRpc3RyaWJ1dGlvbiBmb2xsb3dzIGFuIGV4cG9uZW50aWFsIG1vZGVsIChjb25zdGFudCBoYXphcmQsIHJhbmRvbSBmYWlsdXJlcykgb3IgYSBXZWlidWxsIG1vZGVsIHdpdGggc2hhcGUgcGFyYW1ldGVyICRrPjEkIChpbmNyZWFzaW5nIGhhemFyZCwgaW5kaWNhdGl2ZSBvZiBhZ2luZy9kZWdyYWRhdGlvbikuIFRoZSBmYWlsdXJlIHRpbWVzIChpbiBtb250aHMpIGFyZToNCg0KYGBgDQogICA1LjIsICA3LjgsICA5LjEsIDExLjMsIDEyLjUsIDEzLjAsIDE0LjIsIDE1LjEsIDE1LjksIDE2LjcsIDE3LjIsIDE3LjgsIDE4LjQsIDE4LjksIA0KICAxOS4zLCAxOS43LCAyMC4yLCAyMC42LCAyMS4wLCAyMS41LCAyMS45LCAyMi4zLCAyMi43LCAyMy4xLCAyMy41LCAyMy45LCAyNC4zLCAyNC43LCANCiAgMjUuMSwgMjUuNSwgMjUuOSwgMjYuMywgMjYuNywgMjcuMSwgMjcuNSwgMjcuOSwgMjguMywgMjguNywgMjkuMSwgMjkuNSwgMjkuOSwgMzAuMywgDQogIDMwLjcsIDMxLjEsIDMxLjUsIDMxLjksIDMyLjMsIDMyLjcsIDMzLjEsIDMzLjUsIDMzLjksIDM0LjMsIDM0LjcsIDM1LjEsIDM1LjUsIDM1LjksIA0KICAzNi4zLCAzNi43LCAzNy4xLCAzNy41LCAzNy45LCAzOC4zLCAzOC43LCAzOS4xLCAzOS41LCAzOS45LCA0MC4zLCA0MC43LCA0MS4xLCA0MS41LA0KICA0MS45LCA0Mi4zLCA0Mi43LCA0My4xLCA0My41DQpgYGANCjwvcD4NCg0KVGhpcyBhc3NpZ25tZW50IGZvY3VzZXMgb24gaHlwb3RoZXNpcyAkSF8wOiBcYmV0YSA9IDEkIChleHBvbmVudGlhbCkgYWdhaW5zdCAkSF8xOiBcYmV0YSBcbmVxIDEkIChXZWlidWxsKS4gVGhpcyBmcmFtZXdvcmsgZGV0ZWN0cyBvdmVyZml0dGluZyAoZml0dGluZyBhIFdlaWJ1bGwgd2hlbiBleHBvbmVudGlhbCBpcyB0cnVlKSBhbmQgdW5kZXJmaXR0aW5nIChmaXR0aW5nIGV4cG9uZW50aWFsIHdoZW4gV2VpYnVsbCB3aXRoICRcYmV0YSBcbmVxIDEkIGlzIHRydWUpLiANCg0KDQo8cD4NCmEpLiBGaW5kIHRoZSBNTEUgb2YgdGhlIFdlaWJ1bGwgcGFyYW1ldGVycyAkXGxhbWJkYSQgKHNjYWxlKSBhbmQgJFxiZXRhJCAoc2hhcGUpLCBkZW5vdGVkIGJ5ICRcaGF0e1xsYW1iZGF9JCBhbmQgJFxoYXR7XGJldGF9JCwgcmVzcGVjdGl2ZWx5LCB1c2luZyB0aGUgYG9wdGltKClgIHByb2NlZHVyZS4gWypIaW50OiBZb3Ugc2hvdWxkIHByb3ZpZGUgZXhwbGljaXQgZXhwcmVzc2lvbnMgZm9yIHRoZSBsb2ctbGlrZWxpaG9vZCBhbmQgZ3JhZGllbnQgZnVuY3Rpb25zIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBwYXJhbWV0ZXJzLipdDQoNCiMgQW5zd2VyIHRvIFF1ZXN0aW9uIDEgUGFydCBBDQoNCldlIGFyZSBwcm92aWRlZCB3aXRoIHRoZSBwcm9iYWJpbGl0eSBkZW5zaXR5IGZ1bmN0aW9uIChQREYpIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbjoNCg0KJCQNCmYodDsgXGxhbWJkYSwgXGJldGEpID0gXGZyYWN7XGJldGF9e1xsYW1iZGF9IFxsZWZ0KCBcZnJhY3t0fXtcbGFtYmRhfSBccmlnaHQpXntcYmV0YS0xfSBcZXhwXGxlZnRbIC1cbGVmdCggXGZyYWN7dH17XGxhbWJkYX0gXHJpZ2h0KV5cYmV0YSBccmlnaHRdLCBccXVhZCB0IFxnZSAwDQokJA0KDQpXZSBjYW4gdXNlIHRoaXMgdG8gZmluZCB0aGUgbGlrZWxpaG9vZCBmdW5jdGlvbjoNCg0KJCQNCkwoXGxhbWJkYSwgXGJldGEpPVxwcm9kX3tpPTF9Xm5mKHRfaSA7IFxsYW1iZGEsIFxiZXRhKT1ccHJvZF97aT0xfV5uIFxmcmFje1xiZXRhfXtcbGFtYmRhfSBcbGVmdCggXGZyYWN7dF9pfXtcbGFtYmRhfSBccmlnaHQpXntcYmV0YS0xfSBcZXhwXGxlZnRbIC1cbGVmdCggXGZyYWN7dF9pfXtcbGFtYmRhfSBccmlnaHQpXlxiZXRhIFxyaWdodF0NCiQkDQoNClRoZXJlZm9yZSB0aGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24gaXM6DQoNCiQkDQpcYmVnaW57YWxpZ25lZH0NCg0KXGVsbChcbGFtYmRhLCBcYmV0YSkgJj0gXGxvZyhMKFxsYW1iZGEsIFxiZXRhKSkgXFwNCiY9IFxzdW1fe2k9MX1eblxsZWZ0W1xsb2dcYmV0YS1cbG9nXGxhbWJkYSsoXGJldGEtMSlcbG9nKHRfaS9cbGFtYmRhKS0odF9pL1xsYW1iZGEpXlxiZXRhXHJpZ2h0XSBcXA0KJj0gblxsb2dcYmV0YS1uXGxvZ1xsYW1iZGErKFxiZXRhLTEpXHN1bV97aT0xfV5uXGxvZyB0X2ktXHN1bV97aT0xfV5uKHRfaS9cbGFtYmRhKV5cYmV0YQ0KDQpcZW5ke2FsaWduZWR9DQokJA0KDQpVc2luZyB0aGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24gd2UgY2FuIHRha2UgdGhlIHBhcnRpYWwgZGVyaXZhdGl2ZXMgb2YgJFxsYW1iZGEkIGFuZCAkXGJldGEkIHRvIGZpbmQgdGhlIGdyYWRpZW50IGZ1bmN0aW9uczoNCg0KJCQNClxiZWdpbnthbGlnbmVkfQ0KDQpcZnJhY3tccGFydGlhbFxlbGx9e1xwYXJ0aWFsXGxhbWJkYX0gJj0tXGZyYWN7blxiZXRhfXtcbGFtYmRhfStcZnJhY3tcYmV0YX17XGxhbWJkYX1cc3VtX3tpPTF9Xm4odF9pL1xsYW1iZGEpXlxiZXRhIFxcDQoNClxmcmFje1xwYXJ0aWFsXGVsbH17XHBhcnRpYWxcYmV0YX0gJj1cZnJhY3tufXtcYmV0YX0tblxsb2dcbGFtYmRhK1xzdW1fe2k9MX1eblxsb2cgdF9pLVxzdW1fe2k9MX1eblxsb2cgdF9pLVxzdW1fe2k9MX1ebih0X2kvXGxhbWJkYSleXGJldGFcbG9nKHRfaS9cbGFtYmRhKQ0KDQpcZW5ke2FsaWduZWR9DQokJA0KDQpXZSBjYW4gdGhlbiB1c2Ugb3VyIGxvZy1saWtlbGlob29kIGZ1bmN0aW9uIGFuZCBncmFkaWVudCBmdW5jdGlvbnMgdG8gZmluZCAkXGhhdHtcbGFtYmRhfSQgYW5kICRcaGF0e1xiZXRhfSQ6DQoNCmBgYHtyfQ0KdHVyYmluZSA8LSBjKCAgNS4yLCAgNy44LCAgOS4xLCAxMS4zLCAxMi41LCAxMy4wLCAxNC4yLCAxNS4xLCAxNS45LCAxNi43LCAxNy4yLCAxNy44LCAxOC40LCAxOC45LCANCiAgMTkuMywgMTkuNywgMjAuMiwgMjAuNiwgMjEuMCwgMjEuNSwgMjEuOSwgMjIuMywgMjIuNywgMjMuMSwgMjMuNSwgMjMuOSwgMjQuMywgMjQuNywgDQogIDI1LjEsIDI1LjUsIDI1LjksIDI2LjMsIDI2LjcsIDI3LjEsIDI3LjUsIDI3LjksIDI4LjMsIDI4LjcsIDI5LjEsIDI5LjUsIDI5LjksIDMwLjMsIA0KICAzMC43LCAzMS4xLCAzMS41LCAzMS45LCAzMi4zLCAzMi43LCAzMy4xLCAzMy41LCAzMy45LCAzNC4zLCAzNC43LCAzNS4xLCAzNS41LCAzNS45LCANCiAgMzYuMywgMzYuNywgMzcuMSwgMzcuNSwgMzcuOSwgMzguMywgMzguNywgMzkuMSwgMzkuNSwgMzkuOSwgNDAuMywgNDAuNywgNDEuMSwgNDEuNSwNCiAgNDEuOSwgNDIuMywgNDIuNywgNDMuMSwgNDMuNSkNCg0KbG9nbGlrX3dlaWJ1bGwgPC0gZnVuY3Rpb24ocGFyLCB4KXsgI1VzZWQgdG8gaW1wdXRlIGxvZy1saWtlbGlob29kDQogIGxhbWJkYSA8LSBwYXJbMV0NCiAgYmV0YSA8LSBwYXJbMl0NCiAgaWYgKGxhbWJkYSA8PSAwIHx8IGJldGEgPD0gMCkgcmV0dXJuIChJbmYpDQogIG4gPC0gbGVuZ3RoKHgpDQogIGxsIDwtIG4qbG9nKGJldGEpLW4qYmV0YSpsb2cobGFtYmRhKSsoYmV0YS0xKSpzdW0obG9nKHgpKS1zdW0oKHgvbGFtYmRhKV5iZXRhKQ0KICANCiAgcmV0dXJuKC1sbCkNCn0NCg0KZ3JhZF93ZWlidWxsIDwtIGZ1bmN0aW9uKHBhciwgeCl7ICNVc2VkIHRvIGltcHV0ZSBncmFkaWVudCBmdW5jdGlvbnMNCiAgbGFtYmRhIDwtIHBhclsxXQ0KICBiZXRhIDwtIHBhclsyXQ0KICBpZiAobGFtYmRhIDw9IDAgfHwgYmV0YSA8PSAwKSByZXR1cm4gKGMoSW5mLCBJbmYpKQ0KICBuIDwtIGxlbmd0aCh4KQ0KICB0ZXJtIDwtICh4L2xhbWJkYSleYmV0YQ0KICBkX2xhbWJkYSA8LSAtbipiZXRhL2xhbWJkYSsoYmV0YS9sYW1iZGEpKnN1bSh0ZXJtKQ0KICBkX2JldGEgPC0gbi9iZXRhLW4qbG9nKGxhbWJkYSkrc3VtKGxvZyh4KSktc3VtKHRlcm0qbG9nKHgvbGFtYmRhKSkNCiAgDQogIHJldHVybigtYyhkX2xhbWJkYSwgZF9iZXRhKSkNCn0NCg0KcmVzdWx0IDwtIG9wdGltKCAjVXNlZCB0byBjb21wdXRlIE1MRXMNCiAgcGFyPWMoMSwxKSwNCiAgZm49bG9nbGlrX3dlaWJ1bGwsDQogIGdyPWdyYWRfd2VpYnVsbCwNCiAgeD10dXJiaW5lLA0KICBtZXRob2Q9IkwtQkZHUy1CIiwNCiAgbG93ZXI9YygxZS02LCAxZS02KQ0KKQ0KcmVzdWx0DQoNCmxhbWJkYV9oYXQgPC0gcmVzdWx0JHBhclsxXSAjR2V0cyBNTEVzIGZyb20gb3B0aW0gZnVuY3Rpb24NCmJldGFfaGF0IDwtIHJlc3VsdCRwYXJbMl0NCg0KbGFtYmRhX2hhdA0KYmV0YV9oYXQNCmBgYA0KDQpUaGUgTUxFIG9mIHRoZSBXZWlidWxsIHBhcmFtZXRlcnMgYXJlICRcaGF0e1xsYW1iZGF9PTMxLjQxODIwJCBhbmQgJFxoYXR7XGJldGF9PTMuMzcwNzgkLg0KDQpiKS4gRmluZCB0aGUgTUxFIG9mIHRoZSBleHBvbmVudGlhbCBwYXJhbWV0ZXIgJFxsYW1iZGEkIChzY2FsZSksIGRlbm90ZWQgYnkgJFxoYXR7XGxhbWJkYX0kLCB1c2luZyBhbnkgcHJvY2VkdXJlLiBbKkhpbnQ6IFlvdSBzaG91bGQgcHJvdmlkZSBleHBsaWNpdCBleHByZXNzaW9ucyBmb3IgdGhlIGxvZy1saWtlbGlob29kIGFuZCBncmFkaWVudCBmdW5jdGlvbnMgb2YgdGhlIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiBwYXJhbWV0ZXJzLipdDQoNCiMgQW5zd2VyIHRvIFF1ZXN0aW9uIDEgUGFydCBCDQoNCldlIGFyZSBwcm92aWRlZCB3aXRoIHRoZSBwcm9iYWJpbGl0eSBkZW5zaXR5IGZ1bmN0aW9uIChQREYpIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiB3aGVuICRcYmV0YT0xJDoNCg0KJCQNCmYodDsgXGxhbWJkYSkgPSBcZnJhY3sxfXtcbGFtYmRhfSBcZXhwXGxlZnQoIC1cZnJhY3t0fXtcbGFtYmRhfSBccmlnaHQpDQokJA0KDQpXZSBjYW4gdXNlIHRoaXMgdG8gZmluZCB0aGUgbGlrZWxpaG9vZCBmdW5jdGlvbjoNCg0KJCQNCkwoXGxhbWJkYSk9XHByb2Rfe2k9MX1ebmYodDsgXGxhbWJkYSk9XHByb2Rfe2k9MX1eblxmcmFjezF9e1xsYW1iZGF9ZV57LXRfaS9cbGFtYmRhfQ0KJCQNCg0KVGhlbiB3ZSBjYW4gZmluZCB0aGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb246DQoNCiQkDQpcZWxsKFxsYW1iZGEpPVxsb2cgTChcbGFtYmRhKT1cc3VtX3tpPTF9Xm5cbGVmdFstXGxvZ1xsYW1iZGEtXGZyYWN7dF9pfXtcbGFtYmRhfVxyaWdodF0gPSAtblxsb2dcbGFtYmRhLVxmcmFjezF9e1xsYW1iZGF9XHN1bV97aT0xfV5uIHRfaQ0KJCQNCg0KV2UgY2FuIHRoZW4gZmluZCB0aGUgZ3JhZGllbnQgZnVuY3Rpb24gYW5kIHNvbHZlIGZvciAkXGhhdHtcbGFtYmRhfSQ6DQoNCiQkDQpcYmVnaW57YWxpZ25lZH0NCiZcZnJhY3tccGFydGlhbFxlbGx9e1xwYXJ0aWFsXGxhbWJkYX09LVxmcmFje259e1xsYW1iZGF9K1xmcmFjezF9e1xsYW1iZGFeMn1cc3VtX3tpPTF9Xm4gdF9pIFxcDQoNCiZcUmlnaHRhcnJvdyAtXGZyYWN7bn17XGxhbWJkYX0rXGZyYWN7MX17XGxhbWJkYV4yfVxzdW1fe2k9MX1ebiB0X2k9MCBcXA0KDQomXFJpZ2h0YXJyb3cgLW5cbGFtYmRhK1xzdW1fe2k9MX1ebiB0X2kgPTAgXFwNCg0KJlxSaWdodGFycm93IFxsYW1iZGE9XGZyYWN7MX17bn1cc3VtX3tpPTF9Xm4gdF9pDQoNClxlbmR7YWxpZ25lZH0NCiQkDQoNClRoZXJlZm9yZSwNCg0KJCQNClxoYXR7XGxhbWJkYX09XGZyYWN7MX17bn1cc3VtX3tpPTF9Xm4gdF9pDQokJA0KDQpXZSBjYW4gdXNlIHRoaXMgdG8gZmluZCAkXGhhdHtcbGFtYmRhfSQ6DQoNCmBgYHtyfQ0KDQpsYW1iZGFfaGF0MiA9IG1lYW4odHVyYmluZSkgI0dldHMgbGFtYmRhIE1MRQ0KDQpsYW1iZGFfaGF0Mg0KDQpgYGANCg0KVGhlIE1MRSBvZiB0aGUgV2VpYnVsbCBwYXJhbWV0ZXIgd2hlbiAkXGJldGE9MSQgaXMgJFxoYXR7XGxhbWJkYX09MjguMTg1MzMkLg0KDQpjKS4gVXNlIGEpIGFuZCBiKSB0byBwZXJmb3JtIHRoZSByZWd1bGFyIGxpa2VsaWhvb2QgcmF0aW8gJFxjaGleMiQgdGVzdCBmb3IgJFxiZXRhID0gMSQgYW5kIHJlcG9ydCB0aGUgcC12YWx1ZS4NCg0KIyBBbnN3ZXIgdG8gUXVlc3Rpb24gMSBQYXJ0IEMNCg0KYGBge3J9DQpsbF93ZWlidWxsIDwtIGZ1bmN0aW9uKHgsIGxhbWJkYSwgYmV0YSl7ICNDb21wdXRlcyBXZWlidWxsIGxvZy1saWtlbGlob29kDQogIG4gPC0gbGVuZ3RoKHgpDQogIG4qbG9nKGJldGEpLW4qYmV0YSpsb2cobGFtYmRhKSsoYmV0YS0xKSpzdW0obG9nKHgpKS1zdW0oKHgvbGFtYmRhKV5iZXRhKQ0KfQ0KDQpsbF9leHAgPC0gZnVuY3Rpb24oeCwgbGFtYmRhKXsgI0NvbXB1dGVzIGV4cG9uZW50aWFsIGxvZy1saWtlbGlob29kDQogIG4gPC0gbGVuZ3RoKHgpDQogIC1uKmxvZyhsYW1iZGEpLXN1bSh4KS9sYW1iZGENCn0NCg0KbGFtYmRhX2hhdF93ZWlidWxsIDwtIDMxLjQxODIwICNQbHVncyBpbiBNTEVzDQpiZXRhX2hhdF93ZWlidWxsIDwtIDMuMzcwNzgNCmxhbWJkYV9oYXRfZXhwIDwtIDI4LjE4NTMzDQoNCmxsMSA8LSBsbF93ZWlidWxsKHR1cmJpbmUsIGxhbWJkYV9oYXRfd2VpYnVsbCwgYmV0YV9oYXRfd2VpYnVsbCkgI0dldHMgbWF4aW1pemVkIGxvZy1saWtlbGlob29kcw0KbGwwIDwtIGxsX2V4cCh0dXJiaW5lLCBsYW1iZGFfaGF0X2V4cCkNCg0KTFIgPC0gMioobGwxIC0gbGwwKSAjQ29tcHV0ZXMgbGlrZWxpaG9vZCByYXRpbw0KTFINCg0KcF92YWx1ZSA8LSAxIC0gcGNoaXNxKExSLCBkZj0xKSAjR2V0cyBwLXZhbHVlDQpwX3ZhbHVlDQpgYGANCg0KVGhlIHAtdmFsdWUgaXMgYXBwcm94aW1hdGVseSB6ZXJvLg0KDQpkKS4gVXNlIHRoZSBCTFJUIGFsZ29yaXRobSB0byBwZXJmb3JtIGEgYm9vdHN0cmFwIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCBhbmQgcmVwb3J0IHRoZSBib290c3RyYXAgcC12YWx1ZS4gTm90ZSB0aGF0IHlvdSBhcmUgZXhwZWN0ZWQgdG8gdHJhbnNsYXRlIHRoZSBCTFJUIGFsZ29yaXRobSBpbnRvIFIgY29kZSB0byBwZXJmb3JtIHRoZSBCTFJULiBbKkhpbnQ6IFRoZSBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbiBzaG91bGQgbm90IGJlIHVzZWQgaW4gdGhpcyBwYXJ0IG9mIHRoZSBhbmFseXNpcy4qXQ0KDQojIEFuc3dlciB0byBRdWVzdGlvbiAxIFBhcnQgRA0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykNCkIgPC0gMTAwMA0KbiA8LSBsZW5ndGgodHVyYmluZSkNCkxSX2Jvb3QgPC0gbnVtZXJpYyhCKQ0KDQpmb3IgKGIgaW4gMTpCKXsNCiAgeF9ib290IDwtIHJleHAobiwgcmF0ZSA9IDEvbGFtYmRhX2hhdDIpDQogIGxhbWJkYV9leHBfc3RhciA8LSBtZWFuKHhfYm9vdCkNCiAgZml0IDwtIG9wdGltKA0KICAgIHBhciA9IGMoMSwxKSwNCiAgICBmbiA9IGxvZ2xpa193ZWlidWxsLA0KICAgIGdyID0gZ3JhZF93ZWlidWxsLA0KICAgIHggPSB4X2Jvb3QsDQogICAgbWV0aG9kID0gIkwtQkZHUy1CIiwNCiAgICBsb3dlciA9IGMoMWUtNiwgMWUtNikNCiAgKQ0KICBsYW1iZGFfd2VpYl9zdGFyIDwtIGZpdCRwYXJbMV0NCiAgYmV0YV93ZWliX3N0YXIgPC0gZml0JHBhclsyXQ0KICANCiAgbGwwX3N0YXIgPC0gbGxfZXhwKHhfYm9vdCwgbGFtYmRhX2V4cF9zdGFyKQ0KICBsbDFfc3RhciA8LSBsbF93ZWlidWxsKHhfYm9vdCwgbGFtYmRhX3dlaWJfc3RhciwgYmV0YV93ZWliX3N0YXIpDQogIExSX2Jvb3RbYl0gPC0gMioobGwxX3N0YXItbGwwX3N0YXIpDQp9DQoNCnBfdmFsdWUyIDwtIChzdW0oTFJfYm9vdCA+PSBMUikgKyAxKSAvIChCICsgMSkNCg0KcF92YWx1ZTINCmBgYA0KDQpUaGUgcC12YWx1ZSBpcyAwLjAwMDk5OTAwMS4NCg0KZSkuIFdyaXRlIGEgc3VtbWFyeSBvZiB0aGUgYWJvdmUgYW5hbHlzZXMgdG8gYWRkcmVzcyB0aGUgZm9sbG93aW5nOg0KDQoqIFdoZXRoZXIgdGhlIHR3byB0ZXN0cyBnZW5lcmF0ZWQgdGhlIHNhbWUgcmVzdWx0cy4NCg0KKiBXaGljaCBtb2RlbCBpcyByZWNvbW1lbmRlZCBmb3IgdGhlIGRhdGEuDQoNCiMgQW5zd2VyIHRvIFF1ZXN0aW9uIDEgUGFydCBFOg0KDQpCb3RoIHRlc3RzIGluZGljYXRlZCB0aGF0ICRcYmV0YSBcbmUgMSQgKGF0IHRoZSAwLjA1IHNpZ25pZmljYW5jZSBsZXZlbCkgZ2l2ZW4gdGhhdCB0aGUgcC12YWx1ZXMgZm9yIHRoZSB0ZXN0cyB3ZXJlICRcdGV4dHtwLXZhbHVlfT0gMCA8IDAuMDUkIGFuZCAkXHRleHR7cC12YWx1ZX09IDAuMDAwOTk5MDAxIDwgMC4wNSQuICBUaGVyZWZvcmUsIHRoZSBXZWlidWxsIG1vZGVsIHdvdWxkIGJlIHJlY29tbWVuZGVkIGZvciB0aGlzIGRhdGEgZ2l2ZW4gdGhhdCB3ZSBoYXZlIGV2aWRlbmNlIHRoYXQgJFxiZXRhIFxuZSAxJC4NCg0KPC9wPg0KDQoNCg0K