Assignment Objectives
Comprehend the likelihood function and its properties.
Master the maximum likelihood estimation framework and required
components.
Understand the plug-in principle underlying MLE.
Implement maximum likelihood estimation procedures in R.
Question 1: Derive gradient (first order partial derivative)
of likelihood function
Assume that \(\{x_1, x_2, \cdots, x_n \}
\to \text{ gamma }(\alpha, \beta)\) with density function given
by
\[
f(x \mid \alpha, \beta) = \frac{1}{\Gamma(\alpha)\beta^\alpha}
x^{\alpha-1} e^{-x/\beta} \ \ \text{for} \ \ x > 0,
\]
Derive the gradient of the log-likelihood function
with respect to the gamma distribution parameters \(\alpha\) and \(\beta\). To this end,
a). Write out the full log-likelihood function based
on the given data and the density function provided above.
Answer to Question 1 Part A
The Gamma distribution is defined by the probability density
function:
\[
f(x \mid \alpha, \beta) = \frac{1}{\Gamma(\alpha)\beta^\alpha}
x^{\alpha-1} e^{-x/\beta} \ \ \text{for} \ \ x > 0
\]
where \(\alpha > 0\) is the shape
parameter and \(\beta>0\) is the
scale parameter.
Therefore the likelihood function is:
\[
L(\alpha,\beta \mid
x)=\prod_{i=1}^{n}{f(x_i\mid\alpha,\beta)}=\prod_{i=1}^{n}{\frac{1}{\Gamma(\alpha)\beta^{\alpha}}x_i^{\alpha-1}e^{-x_i/\beta}}
\]
And the log-likelihood function is:
\[
\ell(\alpha,\beta\mid x)=\ln{L(\alpha,\beta \mid
x)}=\sum_{i=1}^{n}{\ln{\left[\frac{1}{\Gamma(\alpha)\beta^{\alpha}}x_i^{\alpha-1}e^{-x_i/\beta}\right]}}
\]
This can be further simplified to:
$$
\[\begin{aligned}
\ell(\alpha,\beta\mid x) &=
\sum_{i=1}^{n}{\ln{\left[\frac{1}{\Gamma(\alpha)\beta^{\alpha}}x_i^{\alpha-1}e^{-x_i/\beta}\right]}}
\\\\
&=
\sum_{i=1}^{n}{\left[\ln{1}-(\ln{\Gamma(\alpha)}+\alpha\ln{\beta})+(\alpha-1)\ln{x_i}-\frac{x_i}{\beta}\right]}\\\\
&=
-n\ln{\Gamma(\alpha)}-n\alpha\ln{\beta}+(\alpha-1)\sum_{i=1}^{n}{\ln{x_i}}-\frac{1}{\beta}\sum_{i=1}^{n}{x_i}
\end{aligned}\]
$$
Therefore, the simplifed log-liklihood function is:
\[
\ell(\alpha,\beta\mid
x)=-n\ln{\Gamma(\alpha)}-n\alpha\ln{\beta}+(\alpha-1)\sum_{i=1}^{n}{\ln{x_i}}-\frac{1}{\beta}\sum_{i=1}^{n}{x_i}
\]
b). Derive the score functions (the gradient of the log-likelihood)
from the full log-likelihood function in part (a).
Answer to Question 1 Part B
To find the first score function we will differentiate with respect
\(\beta\).
$$
\[\begin{aligned}
\frac{\partial\ell}{\partial\beta} &=
\frac{\partial}{\partial\beta}\left[-n\ln{\Gamma(\alpha)}-n\alpha\ln{\beta}+(\alpha-1)\sum_{i=1}^{n}{\ln{x_i}}-\frac{1}{\beta}\sum_{i=1}^{n}{x_i}\right]\\\\
&= -n\alpha\frac{1}{\beta}+\frac{1}{\beta^2}\sum_{i=1}^{n}{x_i}
\end{aligned}\]
$$
To find the second score function we will differentiate with respect
of \(\alpha\):
$$
\[\begin{aligned}
\frac{\partial\ell}{\partial\alpha} &=
\frac{\partial}{\partial\alpha}
\left[-n\ln{\Gamma(\alpha)}-n\alpha\ln{\beta}+(\alpha-1)\sum_{i=1}^{n}{\ln{x_i}}-\frac{1}{\beta}\sum_{i=1}^{n}{x_i}\right]
\\\\
&= -n\frac{\Gamma
(\alpha)\psi_0(\alpha)}{\Gamma(\alpha)}-n\ln{\beta}+\sum_{i=1}^{n}{\ln{x_i}}
\end{aligned}\]
$$
Question 2: Birth data set
The following R code reads in a data set containing, for each of 7
days, the lengths of time in hours spent by women in the delivery suite
while giving birth (without a ceasarian section) at John Radcliffe
Hospital in Oxford, England. The data are taken from Davison
(Statistical Models. Cambridge University Press, 2003).
2.1, 3.4, 4.25, 5.6, 6.4, 7.3, 8.5, 8.75, 8.9, 9.5, 9.75, 10, 10.4, 10.4, 16, 19,
4, 4.1, 5, 5.5, 5.7, 6.5, 7.25, 7.3, 7.5, 8.2, 8.5, 9.75, 11, 11.2, 15, 16.5, 2.6,
3.6, 3.6, 6.4, 6.8, 7.5, 7.5, 8.25, 8.5, 10.4, 10.75, 14.25, 14.5, 1.5, 4.7, 4.7,
7.2, 7.25, 8.1, 8.5, 9.2, 9.5, 10.7, 11.5, 2.5, 2.5, 3.4, 4.2, 5.9, 6.25, 7.3, 7.5,
7.8, 8.3, 8.3, 10.25, 12.9, 14.3, 4, 4, 5.25, 6.1, 6.5, 6.9, 7, 8.45, 9.25, 10.1,
10.2, 12.75, 14.6, 2, 2.7, 2.75, 3.4, 4.2, 4.3, 4.9, 6.25, 7, 9, 9.25, 10.7
Assume the data are generated from a gamma distribution. The
objective is to use these data and the designated algorithm to find the
maximum likelihood estimates (MLEs) of the parameters \(\alpha\) and \(\beta\).
a). Find the MLEs of \(\alpha\) and
\(\beta\), denoted by \(\hat{\alpha}\) and \(\hat{\beta}\), using gradient-based
optimization via the R function optim() with the gradient
vector derived in Question 1.
Answer to Question 2 Part A
birth <- c(2.1, 3.4, 4.25, 5.6, 6.4, 7.3, 8.5, 8.75, 8.9, 9.5, 9.75, 10, 10.4, 10.4, 16, 19,
4, 4.1, 5, 5.5, 5.7, 6.5, 7.25, 7.3, 7.5, 8.2, 8.5, 9.75, 11, 11.2, 15, 16.5, 2.6,
3.6, 3.6, 6.4, 6.8, 7.5, 7.5, 8.25, 8.5, 10.4, 10.75, 14.25, 14.5, 1.5, 4.7, 4.7,
7.2, 7.25, 8.1, 8.5, 9.2, 9.5, 10.7, 11.5, 2.5, 2.5, 3.4, 4.2, 5.9, 6.25, 7.3, 7.5,
7.8, 8.3, 8.3, 10.25, 12.9, 14.3, 4, 4, 5.25, 6.1, 6.5, 6.9, 7, 8.45, 9.25, 10.1,
10.2, 12.75, 14.6, 2, 2.7, 2.75, 3.4, 4.2, 4.3, 4.9, 6.25, 7, 9, 9.25, 10.7)
#Used to enter log-logistic function
gamma.loglik <- function(params, data) {
shape <- params[1] # Used to get initial parameters
scale <- params[2]
n <- length(data) # Used to get sample size
loglik <- -n*log(gamma(shape))-n*shape*log(scale)+(shape-1)*sum(log(data))-(1/scale)*sum(data)
return(loglik) # Return negative for minimization
}
# Used to enter gradient functions
gamma.score <- function(params, data) {
shape <- params[1] #Used to get initial parameters
scale <- params[2]
n <- length(data) #Used to get sample size
# Gradient for shape parameter
grad_shape <- -n*digamma(shape)-n*log(scale)+sum(log(data))
# Gradient for scale parameter
grad_scale <- -n*shape*(1/scale)+(1/(scale**2))*sum(data)
return(c(grad_shape, grad_scale))
}
# Entering initial guessed parameters
initial.params <- c(shape = 2.2, scale = 1.5)
# Using optim and previous functions to get results
mle.result <- optim(
par = initial.params,
fn = gamma.loglik,
gr = gamma.score,
data = birth,
method = "L-BFGS-B",
lower = c(1e-6, 1e-6),
hessian = TRUE,
control = list(trace = FALSE,
fnscale = -1,
maxit = 500,
abstol = 1e-8)
)
##
mle.result #printing mle.result determined earlier
$par
shape scale
4.387881 1.760111
$value
[1] -251.1173
$counts
function gradient
15 15
$convergence
[1] 0
$message
[1] "CONVERGENCE: REL_REDUCTION_OF_F <= FACTR*EPSMCH"
$hessian
shape scale
shape -24.30316 -53.97386
scale -53.97386 -134.55458
Therefore the MLE estimations for \(\alpha\) and \(\beta\) are \(\hat{\alpha}=4.387881\) and \(\hat{\beta}=1.760111\).
b). Apply the method of moments to obtain estimators for \(\alpha\) and \(\beta\). Denote these moment estimators as
\(\tilde{\alpha}\) and \(\tilde{\beta}\).
Answer to Question 2 Part B
As determined in the 5th Week Lecture, the method of moment
estimators for a gamma distribution are:
$$
\[\begin{aligned}
\hat{\mu} &= \frac{1}{n}\sum_{i=1}^{n}{X_i}=\bar{X}\\\\
\hat{\sigma^2} &=
\frac{1}{n}\sum_{i=1}^{n}{X_i^2-\bar{X}^2}=\frac{1}{n}\sum_{i=1}^{n}{(X_i-\bar{X})^2}
\end{aligned}\]
$$
We can use these method of moment estimators to obtain estimators for
\(\alpha\) and \(\beta\) for our datset:
# Method of Moments estimation
mom_mu <- mean(birth) #Used to get moments from sample
mom_sigma_sq <- mean(birth^2) - mom_mu^2
mom_sigma <- sqrt(mom_sigma_sq)
cat("MoM estimates: μ_tilde =", round(mom_mu, 3), #Used to print moments
", σ_tilde =", round(mom_sigma, 3), "\n")
MoM estimates: μ_tilde = 7.723 , σ_tilde = 3.549
Therefore the MME estimations for \(\alpha\) and \(\beta\) are \(\tilde{\alpha}=7.723\) and \(\tilde{\beta}=3.549\).
c). Conduct a brief literature review comparing the method of moments
estimation (MME) and maximum likelihood estimation (MLE). Synthesize the
key advantages and limitations of each, concluding with a practical
recommendation.
Answer to Question 2 Part C
Method of moments estimation and maximum likelihood estimation are
both methods of estimating the parameters of a distribution using sample
data. Method of moments attempts to estimate these parameters by
matching moments of the sample to moments of a theoretical probability
model. Alternatively, maximum likelihood estimation considers how likely
certain parameter values are given the sampled data. Given that MME only
considers a few specific moments, it is less powerful, but also less
computationally intense. Alternatively, MLE is more computationally
intense but more powerful method of estimating parameters. MME would
most likely be better if you just need a rough estimate of the
parameters, while MLE might be better if you need a result that takes
into account the entire shape of a probability distribution.
LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgNDogTWF4aW11bSBMaWtlbGlob29kIEVzdGltYXRpb24iDQphdXRob3I6ICJHcmFjZSBMaXBwZXJ0ICINCmRhdGU6ICIgRHVlOiAzLzMvMjAyNiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogbm8NCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCiAgd29yZF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAga2VlcF9tZDogeWVzDQplZGl0b3Jfb3B0aW9uczogDQogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQojVE9DOjpiZWZvcmUgew0KICBjb250ZW50OiAiVGFibGUgb2YgQ29udGVudHMiOw0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1zaXplOiAxLjJlbTsNCiAgZGlzcGxheTogYmxvY2s7DQogIGNvbG9yOiBuYXZ5Ow0KICBtYXJnaW4tYm90dG9tOiAxMHB4Ow0KfQ0KDQoNCmRpdiNUT0MgbGkgeyAgICAgLyogdGFibGUgb2YgY29udGVudCAgKi8NCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOw0KICAgIGJhY2tncm91bmQtaW1hZ2U6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXJlcGVhdDpub25lOw0KICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsNCn0NCg0KaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8NCiAgZm9udC1zaXplOiAyMnB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgY29sb3I6IERhcmtSZWQ7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KfQ0KDQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE1cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogc3lzdGVtLXVpOw0KICBjb2xvcjogbmF2eTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOw0KICBjb2xvcjogRGFya0JsdWU7DQogIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjBweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE4cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDMgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMTZweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovDQouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7DQogIGNvbnRlbnQ6ICIuIjsNCg0KYm9keSB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KLmhpZ2hsaWdodG1lIHsgYmFja2dyb3VuZC1jb2xvcjp5ZWxsb3c7IH0NCg0KcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0NCg0KfQ0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQppZiAoIXJlcXVpcmUoInBhbmRlciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJwYW5kZXIiKQ0KICAgbGlicmFyeShwYW5kZXIpDQp9DQppZiAoIXJlcXVpcmUoImdncGxvdDIiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCiAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KICBsaWJyYXJ5KHRpZHl2ZXJzZSkNCn0NCg0KaWYgKCFyZXF1aXJlKCJwbG90bHkiKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KICBsaWJyYXJ5KHBsb3RseSkNCn0NCiMjIyMNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQ0KICAgICAgICAgICAgICAgICAgICAgICkgIA0KYGBgDQogDQpcDQogDQojIyAqKkFzc2lnbm1lbnQgT2JqZWN0aXZlcyoqIA0KDQoqIENvbXByZWhlbmQgdGhlIGxpa2VsaWhvb2QgZnVuY3Rpb24gYW5kIGl0cyBwcm9wZXJ0aWVzLg0KDQoqIE1hc3RlciB0aGUgbWF4aW11bSBsaWtlbGlob29kIGVzdGltYXRpb24gZnJhbWV3b3JrIGFuZCByZXF1aXJlZCBjb21wb25lbnRzLg0KDQoqIFVuZGVyc3RhbmQgdGhlIHBsdWctaW4gcHJpbmNpcGxlIHVuZGVybHlpbmcgTUxFLg0KDQoqIEltcGxlbWVudCBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGlvbiBwcm9jZWR1cmVzIGluIFIuDQoNClwNCg0KIyMgKipQb2xpY2llcyBvZiBVc2luZyBBSSBUb29scyoqDQoNCioqUG9saWN5IG9uIEFJIFRvb2wgVXNlKio6IFN0dWRlbnRzIG11c3QgYWRoZXJlIHRvIHRoZSBBSSB0b29sIHBvbGljeSBzcGVjaWZpZWQgaW4gdGhlIGNvdXJzZSBzeWxsYWJ1cy4gVGhlIGRpcmVjdCBjb3B5aW5nIG9mIEFJLWdlbmVyYXRlZCBjb250ZW50IGlzIHN0cmljdGx5IHByb2hpYml0ZWQuIEFsbCBzdWJtaXR0ZWQgd29yayBtdXN0IHJlZmxlY3QgeW91ciBvd24gdW5kZXJzdGFuZGluZzsgd2hlcmUgZXh0ZXJuYWwgdG9vbHMgYXJlIGNvbnN1bHRlZCwgY29udGVudCBtdXN0IGJlIHRob3JvdWdobHkgcmVwaHJhc2VkIGFuZCBzeW50aGVzaXplZCBpbiB5b3VyIG93biB3b3Jkcy4NCg0KKipDb2RlIEluY2x1c2lvbiBSZXF1aXJlbWVudCoqOiBBbnkgY29kZSBpbmNsdWRlZCBpbiB5b3VyIGVzc2F5IG11c3QgYmUgcHJvcGVybHkgY29tbWVudGVkIHRvIGV4cGxhaW4gdGhlIHB1cnBvc2UgYW5kL29yIGV4cGVjdGVkIG91dHB1dCBvZiBrZXkgY29kZSBsaW5lcy4gU3VibWl0dGluZyBBSS1nZW5lcmF0ZWQgY29kZSB3aXRob3V0IG1lYW5pbmdmdWwsIHN0dWRlbnQtYWRkZWQgY29tbWVudHMgd2lsbCBub3QgYmUgYWNjZXB0ZWQuDQoNClwNCg0KKipHYW1tYSBEaXN0cmlidXRpb24gUmV2aXNpdGVkKioNCg0KTGV0ICRYJCBiZSB0aGUgdHdvIHBhcmFtZXRlciBHYW1tYSByYW5kb20gdmFyaWFibGUgd2l0aCBkZW5zaXR5IGZ1bmN0aW9uDQoNCiQkDQpmKHggXG1pZCBcYWxwaGEsIFxiZXRhKSA9IFxmcmFjezF9e1xHYW1tYShcYWxwaGEpXGJldGFeXGFscGhhfSB4XntcYWxwaGEtMX0gZV57LXgvXGJldGF9ICBcIFwgXHRleHR7Zm9yfSBcIFwgIHggPiAwLA0KJCQNCg0Kd2hlcmUgd2l0aCAkXGFscGhhID4gMCQgKHNoYXBlKSwgJFxiZXRhPjAkIChzY2FsZSksIGFuZA0KDQokJA0KXEdhbW1hKFxhbHBoYSkgPSBcaW50X3swfV57XGluZnR5fSB0XntcYWxwaGEtMX0gZV57LXR9IFwsIGR0LCBccXVhZCBcYWxwaGEgPiAwLg0KJCQNCg0KJFxHYW1tYSh4KSQgY2FuIGJlIGNvbXB1dGVkIGluIFIgdXNpbmcgdGhlIGBnYW1tYSgpYCBmdW5jdGlvbi4gVGhlIGRlcml2YXRpdmUgb2YgJFxHYW1tYSh4KSQgYXJlIGdpdmVuIHJlc3BlY3RpdmVseSBieQ0KDQokJA0KXEdhbW1hXlxwcmltZSh6KSA9IFxHYW1tYSAoeilccHNpXzAoeikNCiQkDQoNCndoZXJlICRccHNpXzAoeikgPSBcZnJhY3tkfXtken0gXGxuIFxHYW1tYXt6fSQuIEluIFIsIHRoZSBkaWdhbW1hIGZ1bmN0aW9uICRccHNpXzAoeikkIGlzIGV2YWx1YXRlZCBieSBgZGlnYW1tYSgpYC4NCg0KDQoNClwNCg0KPGZvbnQgY29sb3IgPSAiYmx1ZSI+VGhpcyBhc3NpZ25tZW50IGZvY3VzZXMgb24gZmluZGluZyBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGUgb2YgcGFyYW1ldGVycyAkXGFscGhhJCBhbmQgJFxiZXRhJCBiYXNlZCBvbiBhIHJlYWwtd29ybGQgYXBwbGljYXRpb24gZGF0YSBzZXQuPC9mb250Pg0KDQoNClwNCg0KIyMgKipRdWVzdGlvbiAxOiBEZXJpdmUgZ3JhZGllbnQgKGZpcnN0IG9yZGVyIHBhcnRpYWwgZGVyaXZhdGl2ZSkgb2YgbGlrZWxpaG9vZCBmdW5jdGlvbioqDQoNCkFzc3VtZSB0aGF0ICRce3hfMSwgeF8yLCBcY2RvdHMsIHhfbiBcfSBcdG8gXHRleHR7IGdhbW1hIH0oXGFscGhhLCBcYmV0YSkkIHdpdGggZGVuc2l0eSBmdW5jdGlvbiBnaXZlbiBieQ0KDQokJA0KZih4IFxtaWQgXGFscGhhLCBcYmV0YSkgPSBcZnJhY3sxfXtcR2FtbWEoXGFscGhhKVxiZXRhXlxhbHBoYX0geF57XGFscGhhLTF9IGVeey14L1xiZXRhfSAgXCBcIFx0ZXh0e2Zvcn0gXCBcICB4ID4gMCwNCiQkDQoNCkRlcml2ZSB0aGUgZ3JhZGllbnQgb2YgdGhlICoqbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24qKiB3aXRoIHJlc3BlY3QgdG8gdGhlIGdhbW1hIGRpc3RyaWJ1dGlvbiBwYXJhbWV0ZXJzICRcYWxwaGEkIGFuZCAkXGJldGEkLiBUbyB0aGlzIGVuZCwNCg0KDQphKS4gV3JpdGUgb3V0IHRoZSBmdWxsICoqbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24qKiBiYXNlZCBvbiB0aGUgZ2l2ZW4gZGF0YSBhbmQgdGhlIGRlbnNpdHkgZnVuY3Rpb24gcHJvdmlkZWQgYWJvdmUuDQoNCiMgQW5zd2VyIHRvIFF1ZXN0aW9uIDEgUGFydCBBDQoNClRoZSBHYW1tYSBkaXN0cmlidXRpb24gaXMgZGVmaW5lZCBieSB0aGUgcHJvYmFiaWxpdHkgZGVuc2l0eSBmdW5jdGlvbjoNCg0KJCQNCmYoeCBcbWlkIFxhbHBoYSwgXGJldGEpID0gXGZyYWN7MX17XEdhbW1hKFxhbHBoYSlcYmV0YV5cYWxwaGF9IHhee1xhbHBoYS0xfSBlXnsteC9cYmV0YX0gIFwgXCBcdGV4dHtmb3J9IFwgXCAgeCA+IDANCiQkDQoNCndoZXJlICRcYWxwaGEgPiAwJCBpcyB0aGUgc2hhcGUgcGFyYW1ldGVyIGFuZCAkXGJldGE+MCQgaXMgdGhlIHNjYWxlIHBhcmFtZXRlci4NCg0KVGhlcmVmb3JlIHRoZSBsaWtlbGlob29kIGZ1bmN0aW9uIGlzOg0KDQokJA0KTChcYWxwaGEsXGJldGEgXG1pZCB4KT1ccHJvZF97aT0xfV57bn17Zih4X2lcbWlkXGFscGhhLFxiZXRhKX09XHByb2Rfe2k9MX1ee259e1xmcmFjezF9e1xHYW1tYShcYWxwaGEpXGJldGFee1xhbHBoYX19eF9pXntcYWxwaGEtMX1lXnsteF9pL1xiZXRhfX0NCiQkDQoNCkFuZCB0aGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24gaXM6DQoNCiQkDQpcZWxsKFxhbHBoYSxcYmV0YVxtaWQgeCk9XGxue0woXGFscGhhLFxiZXRhIFxtaWQgeCl9PVxzdW1fe2k9MX1ee259e1xsbntcbGVmdFtcZnJhY3sxfXtcR2FtbWEoXGFscGhhKVxiZXRhXntcYWxwaGF9fXhfaV57XGFscGhhLTF9ZV57LXhfaS9cYmV0YX1ccmlnaHRdfX0NCiQkDQoNClRoaXMgY2FuIGJlIGZ1cnRoZXIgc2ltcGxpZmllZCB0bzoNCg0KJCQNClxiZWdpbnthbGlnbmVkfQ0KDQpcZWxsKFxhbHBoYSxcYmV0YVxtaWQgeCkgJj0gXHN1bV97aT0xfV57bn17XGxue1xsZWZ0W1xmcmFjezF9e1xHYW1tYShcYWxwaGEpXGJldGFee1xhbHBoYX19eF9pXntcYWxwaGEtMX1lXnsteF9pL1xiZXRhfVxyaWdodF19fSBcXFxcDQoNCiY9IFxzdW1fe2k9MX1ee259e1xsZWZ0W1xsbnsxfS0oXGxue1xHYW1tYShcYWxwaGEpfStcYWxwaGFcbG57XGJldGF9KSsoXGFscGhhLTEpXGxue3hfaX0tXGZyYWN7eF9pfXtcYmV0YX1ccmlnaHRdfVxcXFwNCg0KJj0gLW5cbG57XEdhbW1hKFxhbHBoYSl9LW5cYWxwaGFcbG57XGJldGF9KyhcYWxwaGEtMSlcc3VtX3tpPTF9XntufXtcbG57eF9pfX0tXGZyYWN7MX17XGJldGF9XHN1bV97aT0xfV57bn17eF9pfQ0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KVGhlcmVmb3JlLCB0aGUgc2ltcGxpZmVkIGxvZy1saWtsaWhvb2QgZnVuY3Rpb24gaXM6DQoNCiQkDQpcZWxsKFxhbHBoYSxcYmV0YVxtaWQgeCk9LW5cbG57XEdhbW1hKFxhbHBoYSl9LW5cYWxwaGFcbG57XGJldGF9KyhcYWxwaGEtMSlcc3VtX3tpPTF9XntufXtcbG57eF9pfX0tXGZyYWN7MX17XGJldGF9XHN1bV97aT0xfV57bn17eF9pfQ0KJCQNCg0KDQoNCmIpLiBEZXJpdmUgdGhlIHNjb3JlIGZ1bmN0aW9ucyAodGhlIGdyYWRpZW50IG9mIHRoZSBsb2ctbGlrZWxpaG9vZCkgZnJvbSB0aGUgZnVsbCAqKmxvZy1saWtlbGlob29kIGZ1bmN0aW9uKiogaW4gcGFydCAoYSkuDQoNCiMgQW5zd2VyIHRvIFF1ZXN0aW9uIDEgUGFydCBCDQoNClRvIGZpbmQgdGhlIGZpcnN0IHNjb3JlIGZ1bmN0aW9uIHdlIHdpbGwgZGlmZmVyZW50aWF0ZSB3aXRoIHJlc3BlY3QgJFxiZXRhJC4NCg0KJCQNClxiZWdpbnthbGlnbmVkfQ0KDQpcZnJhY3tccGFydGlhbFxlbGx9e1xwYXJ0aWFsXGJldGF9ICY9IFxmcmFje1xwYXJ0aWFsfXtccGFydGlhbFxiZXRhfVxsZWZ0Wy1uXGxue1xHYW1tYShcYWxwaGEpfS1uXGFscGhhXGxue1xiZXRhfSsoXGFscGhhLTEpXHN1bV97aT0xfV57bn17XGxue3hfaX19LVxmcmFjezF9e1xiZXRhfVxzdW1fe2k9MX1ee259e3hfaX1ccmlnaHRdXFxcXA0KDQomPSAtblxhbHBoYVxmcmFjezF9e1xiZXRhfStcZnJhY3sxfXtcYmV0YV4yfVxzdW1fe2k9MX1ee259e3hfaX0NCg0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KVG8gZmluZCB0aGUgc2Vjb25kIHNjb3JlIGZ1bmN0aW9uIHdlIHdpbGwgZGlmZmVyZW50aWF0ZSB3aXRoIHJlc3BlY3Qgb2YgJFxhbHBoYSQ6DQoNCiQkDQpcYmVnaW57YWxpZ25lZH0NCg0KXGZyYWN7XHBhcnRpYWxcZWxsfXtccGFydGlhbFxhbHBoYX0gJj0gXGZyYWN7XHBhcnRpYWx9e1xwYXJ0aWFsXGFscGhhfSBcbGVmdFstblxsbntcR2FtbWEoXGFscGhhKX0tblxhbHBoYVxsbntcYmV0YX0rKFxhbHBoYS0xKVxzdW1fe2k9MX1ee259e1xsbnt4X2l9fS1cZnJhY3sxfXtcYmV0YX1cc3VtX3tpPTF9XntufXt4X2l9XHJpZ2h0XSBcXFxcDQoNCiY9IC1uXGZyYWN7XEdhbW1hIChcYWxwaGEpXHBzaV8wKFxhbHBoYSl9e1xHYW1tYShcYWxwaGEpfS1uXGxue1xiZXRhfStcc3VtX3tpPTF9XntufXtcbG57eF9pfX0NCg0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KDQpcDQoNCiMjICoqUXVlc3Rpb24gMjogQmlydGggZGF0YSBzZXQqKg0KDQpUaGUgZm9sbG93aW5nIFIgY29kZSByZWFkcyBpbiBhIGRhdGEgc2V0IGNvbnRhaW5pbmcsIGZvciBlYWNoIG9mIDcgZGF5cywgdGhlIGxlbmd0aHMgb2YgdGltZSBpbiBob3VycyBzcGVudCBieQ0Kd29tZW4gaW4gdGhlIGRlbGl2ZXJ5IHN1aXRlIHdoaWxlIGdpdmluZyBiaXJ0aCAod2l0aG91dCBhIGNlYXNhcmlhbiBzZWN0aW9uKSBhdCBKb2huIFJhZGNsaWZmZSBIb3NwaXRhbCBpbg0KT3hmb3JkLCBFbmdsYW5kLiBUaGUgZGF0YSBhcmUgdGFrZW4gZnJvbSBEYXZpc29uIChTdGF0aXN0aWNhbCBNb2RlbHMuIENhbWJyaWRnZSBVbml2ZXJzaXR5IFByZXNzLCAyMDAzKS4NCg0KYGBgDQoyLjEsIDMuNCwgNC4yNSwgNS42LCA2LjQsIDcuMywgOC41LCA4Ljc1LCA4LjksIDkuNSwgOS43NSwgMTAsIDEwLjQsIDEwLjQsIDE2LCAxOSwNCjQsIDQuMSwgNSwgNS41LCA1LjcsIDYuNSwgNy4yNSwgNy4zLCA3LjUsIDguMiwgOC41LCA5Ljc1LCAxMSwgMTEuMiwgMTUsIDE2LjUsIDIuNiwgDQozLjYsIDMuNiwgNi40LCA2LjgsIDcuNSwgNy41LCA4LjI1LCA4LjUsIDEwLjQsIDEwLjc1LCAxNC4yNSwgMTQuNSwgMS41LCA0LjcsIDQuNywgDQo3LjIsIDcuMjUsIDguMSwgOC41LCA5LjIsIDkuNSwgMTAuNywgMTEuNSwgMi41LCAyLjUsIDMuNCwgNC4yLCA1LjksIDYuMjUsIDcuMywgNy41LCANCjcuOCwgOC4zLCA4LjMsIDEwLjI1LCAxMi45LCAxNC4zLCA0LCA0LCA1LjI1LCA2LjEsIDYuNSwgNi45LCA3LCA4LjQ1LCA5LjI1LCAxMC4xLCANCjEwLjIsIDEyLjc1LCAxNC42LCAyLCAyLjcsIDIuNzUsIDMuNCwgNC4yLCA0LjMsIDQuOSwgNi4yNSwgNywgOSwgOS4yNSwgMTAuNw0KYGBgDQoNCkFzc3VtZSB0aGUgZGF0YSBhcmUgZ2VuZXJhdGVkIGZyb20gYSBnYW1tYSBkaXN0cmlidXRpb24uIFRoZSBvYmplY3RpdmUgaXMgdG8gdXNlIHRoZXNlIGRhdGEgYW5kIHRoZSBkZXNpZ25hdGVkIGFsZ29yaXRobSB0byBmaW5kIHRoZSBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGVzIChNTEVzKSBvZiB0aGUgcGFyYW1ldGVycyAkXGFscGhhJCBhbmQgJFxiZXRhJC4NCg0KDQphKS4gRmluZCB0aGUgTUxFcyBvZiAkXGFscGhhJCBhbmQgJFxiZXRhJCwgZGVub3RlZCBieSAkXGhhdHtcYWxwaGF9JCBhbmQgJFxoYXR7XGJldGF9JCwgIHVzaW5nIGdyYWRpZW50LWJhc2VkIG9wdGltaXphdGlvbiB2aWEgdGhlIFIgZnVuY3Rpb24gYG9wdGltKClgIHdpdGggdGhlIGdyYWRpZW50IHZlY3RvciBkZXJpdmVkIGluIFF1ZXN0aW9uIDEuDQoNCiMgQW5zd2VyIHRvIFF1ZXN0aW9uIDIgUGFydCBBDQoNCmBgYHtyfQ0KYmlydGggPC0gYygyLjEsIDMuNCwgNC4yNSwgNS42LCA2LjQsIDcuMywgOC41LCA4Ljc1LCA4LjksIDkuNSwgOS43NSwgMTAsIDEwLjQsIDEwLjQsIDE2LCAxOSwNCjQsIDQuMSwgNSwgNS41LCA1LjcsIDYuNSwgNy4yNSwgNy4zLCA3LjUsIDguMiwgOC41LCA5Ljc1LCAxMSwgMTEuMiwgMTUsIDE2LjUsIDIuNiwgDQozLjYsIDMuNiwgNi40LCA2LjgsIDcuNSwgNy41LCA4LjI1LCA4LjUsIDEwLjQsIDEwLjc1LCAxNC4yNSwgMTQuNSwgMS41LCA0LjcsIDQuNywgDQo3LjIsIDcuMjUsIDguMSwgOC41LCA5LjIsIDkuNSwgMTAuNywgMTEuNSwgMi41LCAyLjUsIDMuNCwgNC4yLCA1LjksIDYuMjUsIDcuMywgNy41LCANCjcuOCwgOC4zLCA4LjMsIDEwLjI1LCAxMi45LCAxNC4zLCA0LCA0LCA1LjI1LCA2LjEsIDYuNSwgNi45LCA3LCA4LjQ1LCA5LjI1LCAxMC4xLCANCjEwLjIsIDEyLjc1LCAxNC42LCAyLCAyLjcsIDIuNzUsIDMuNCwgNC4yLCA0LjMsIDQuOSwgNi4yNSwgNywgOSwgOS4yNSwgMTAuNykNCg0KI1VzZWQgdG8gZW50ZXIgbG9nLWxvZ2lzdGljIGZ1bmN0aW9uDQpnYW1tYS5sb2dsaWsgPC0gZnVuY3Rpb24ocGFyYW1zLCBkYXRhKSB7DQogIHNoYXBlIDwtIHBhcmFtc1sxXSAgIyBVc2VkIHRvIGdldCBpbml0aWFsIHBhcmFtZXRlcnMNCiAgc2NhbGUgPC0gcGFyYW1zWzJdDQogIG4gPC0gbGVuZ3RoKGRhdGEpICAgIyBVc2VkIHRvIGdldCBzYW1wbGUgc2l6ZQ0KICANCg0KICBsb2dsaWsgPC0gLW4qbG9nKGdhbW1hKHNoYXBlKSktbipzaGFwZSpsb2coc2NhbGUpKyhzaGFwZS0xKSpzdW0obG9nKGRhdGEpKS0oMS9zY2FsZSkqc3VtKGRhdGEpIA0KICANCiAgcmV0dXJuKGxvZ2xpaykgICAgIyBSZXR1cm4gbmVnYXRpdmUgZm9yIG1pbmltaXphdGlvbg0KfQ0KDQoNCiMgVXNlZCB0byBlbnRlciBncmFkaWVudCBmdW5jdGlvbnMNCg0KZ2FtbWEuc2NvcmUgPC0gZnVuY3Rpb24ocGFyYW1zLCBkYXRhKSB7DQogIHNoYXBlIDwtIHBhcmFtc1sxXSAjVXNlZCB0byBnZXQgaW5pdGlhbCBwYXJhbWV0ZXJzDQogIHNjYWxlIDwtIHBhcmFtc1syXQ0KICBuIDwtIGxlbmd0aChkYXRhKSAjVXNlZCB0byBnZXQgc2FtcGxlIHNpemUNCiAgDQogICMgR3JhZGllbnQgZm9yIHNoYXBlIHBhcmFtZXRlcg0KICBncmFkX3NoYXBlIDwtICAtbipkaWdhbW1hKHNoYXBlKS1uKmxvZyhzY2FsZSkrc3VtKGxvZyhkYXRhKSkNCiAgDQogICMgR3JhZGllbnQgZm9yIHNjYWxlIHBhcmFtZXRlcg0KICBncmFkX3NjYWxlIDwtIC1uKnNoYXBlKigxL3NjYWxlKSsoMS8oc2NhbGUqKjIpKSpzdW0oZGF0YSkNCiAgDQogIHJldHVybihjKGdyYWRfc2hhcGUsIGdyYWRfc2NhbGUpKQ0KfQ0KDQoNCiMgRW50ZXJpbmcgaW5pdGlhbCBndWVzc2VkIHBhcmFtZXRlcnMNCmluaXRpYWwucGFyYW1zIDwtIGMoc2hhcGUgPSAyLjIsIHNjYWxlID0gMS41KSAgDQoNCg0KIyBVc2luZyBvcHRpbSBhbmQgcHJldmlvdXMgZnVuY3Rpb25zIHRvIGdldCByZXN1bHRzDQptbGUucmVzdWx0IDwtIG9wdGltKA0KICBwYXIgPSBpbml0aWFsLnBhcmFtcywNCiAgZm4gPSBnYW1tYS5sb2dsaWssDQogIGdyID0gZ2FtbWEuc2NvcmUsDQogIGRhdGEgPSBiaXJ0aCwNCiAgbWV0aG9kID0gIkwtQkZHUy1CIiwNCiAgbG93ZXIgPSBjKDFlLTYsIDFlLTYpLA0KICBoZXNzaWFuID0gVFJVRSwNCiAgY29udHJvbCA9IGxpc3QodHJhY2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgZm5zY2FsZSA9IC0xLA0KICAgICAgICAgICAgICAgICBtYXhpdCA9IDUwMCwNCiAgICAgICAgICAgICAgICAgYWJzdG9sID0gMWUtOCkNCikNCiMjDQptbGUucmVzdWx0ICNwcmludGluZyBtbGUucmVzdWx0IGRldGVybWluZWQgZWFybGllcg0KDQpgYGANCg0KVGhlcmVmb3JlIHRoZSBNTEUgZXN0aW1hdGlvbnMgZm9yICRcYWxwaGEkIGFuZCAkXGJldGEkIGFyZSAkXGhhdHtcYWxwaGF9PTQuMzg3ODgxJCBhbmQgJFxoYXR7XGJldGF9PTEuNzYwMTExJC4NCg0KYikuIEFwcGx5IHRoZSBtZXRob2Qgb2YgbW9tZW50cyB0byBvYnRhaW4gZXN0aW1hdG9ycyBmb3IgJFxhbHBoYSQgYW5kICRcYmV0YSQuIERlbm90ZSB0aGVzZSBtb21lbnQgZXN0aW1hdG9ycyBhcyAkXHRpbGRle1xhbHBoYX0kIGFuZCAkXHRpbGRle1xiZXRhfSQuDQoNCiMgQW5zd2VyIHRvIFF1ZXN0aW9uIDIgUGFydCBCDQoNCkFzIGRldGVybWluZWQgaW4gdGhlIDV0aCBXZWVrIExlY3R1cmUsIHRoZSBtZXRob2Qgb2YgbW9tZW50IGVzdGltYXRvcnMgZm9yIGEgZ2FtbWEgZGlzdHJpYnV0aW9uIGFyZToNCg0KJCQNClxiZWdpbnthbGlnbmVkfQ0KDQpcaGF0e1xtdX0gJj0gXGZyYWN7MX17bn1cc3VtX3tpPTF9XntufXtYX2l9PVxiYXJ7WH1cXFxcDQpcaGF0e1xzaWdtYV4yfSAmPSBcZnJhY3sxfXtufVxzdW1fe2k9MX1ee259e1hfaV4yLVxiYXJ7WH1eMn09XGZyYWN7MX17bn1cc3VtX3tpPTF9XntufXsoWF9pLVxiYXJ7WH0pXjJ9DQoNCg0KXGVuZHthbGlnbmVkfQ0KJCQNCg0KV2UgY2FuIHVzZSB0aGVzZSBtZXRob2Qgb2YgbW9tZW50IGVzdGltYXRvcnMgdG8gb2J0YWluIGVzdGltYXRvcnMgZm9yICRcYWxwaGEkIGFuZCAkXGJldGEkIGZvciBvdXIgZGF0c2V0Og0KDQpgYGB7cn0NCiMgTWV0aG9kIG9mIE1vbWVudHMgZXN0aW1hdGlvbg0KbW9tX211IDwtIG1lYW4oYmlydGgpICNVc2VkIHRvIGdldCBtb21lbnRzIGZyb20gc2FtcGxlDQptb21fc2lnbWFfc3EgPC0gbWVhbihiaXJ0aF4yKSAtIG1vbV9tdV4yDQptb21fc2lnbWEgPC0gc3FydChtb21fc2lnbWFfc3EpDQoNCmNhdCgiTW9NIGVzdGltYXRlczogzrxfdGlsZGUgPSIsIHJvdW5kKG1vbV9tdSwgMyksICNVc2VkIHRvIHByaW50IG1vbWVudHMNCiAgICAiLCDPg190aWxkZSA9Iiwgcm91bmQobW9tX3NpZ21hLCAzKSwgIlxuIikNCmBgYA0KDQpUaGVyZWZvcmUgdGhlIE1NRSBlc3RpbWF0aW9ucyBmb3IgJFxhbHBoYSQgYW5kICRcYmV0YSQgYXJlICRcdGlsZGV7XGFscGhhfT03LjcyMyQgYW5kICRcdGlsZGV7XGJldGF9PTMuNTQ5JC4NCg0KYykuIENvbmR1Y3QgYSBicmllZiBsaXRlcmF0dXJlIHJldmlldyBjb21wYXJpbmcgdGhlIG1ldGhvZCBvZiBtb21lbnRzIGVzdGltYXRpb24gKE1NRSkgYW5kIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0aW9uIChNTEUpLiBTeW50aGVzaXplIHRoZSBrZXkgYWR2YW50YWdlcyBhbmQgbGltaXRhdGlvbnMgb2YgZWFjaCwgY29uY2x1ZGluZyB3aXRoIGEgcHJhY3RpY2FsIHJlY29tbWVuZGF0aW9uLg0KDQojIEFuc3dlciB0byBRdWVzdGlvbiAyIFBhcnQgQw0KDQpNZXRob2Qgb2YgbW9tZW50cyBlc3RpbWF0aW9uIGFuZCBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGlvbiBhcmUgYm90aCBtZXRob2RzIG9mIGVzdGltYXRpbmcgdGhlIHBhcmFtZXRlcnMgb2YgYSBkaXN0cmlidXRpb24gdXNpbmcgc2FtcGxlIGRhdGEuICBNZXRob2Qgb2YgbW9tZW50cyBhdHRlbXB0cyB0byBlc3RpbWF0ZSB0aGVzZSBwYXJhbWV0ZXJzIGJ5IG1hdGNoaW5nIG1vbWVudHMgb2YgdGhlIHNhbXBsZSB0byBtb21lbnRzIG9mIGEgdGhlb3JldGljYWwgcHJvYmFiaWxpdHkgbW9kZWwuICBBbHRlcm5hdGl2ZWx5LCBtYXhpbXVtIGxpa2VsaWhvb2QgZXN0aW1hdGlvbiBjb25zaWRlcnMgaG93IGxpa2VseSBjZXJ0YWluIHBhcmFtZXRlciB2YWx1ZXMgYXJlIGdpdmVuIHRoZSBzYW1wbGVkIGRhdGEuICBHaXZlbiB0aGF0IE1NRSBvbmx5IGNvbnNpZGVycyBhIGZldyBzcGVjaWZpYyBtb21lbnRzLCBpdCBpcyBsZXNzIHBvd2VyZnVsLCBidXQgYWxzbyBsZXNzIGNvbXB1dGF0aW9uYWxseSBpbnRlbnNlLiAgQWx0ZXJuYXRpdmVseSwgTUxFIGlzIG1vcmUgY29tcHV0YXRpb25hbGx5IGludGVuc2UgYnV0IG1vcmUgcG93ZXJmdWwgbWV0aG9kIG9mIGVzdGltYXRpbmcgcGFyYW1ldGVycy4gIE1NRSB3b3VsZCBtb3N0IGxpa2VseSBiZSBiZXR0ZXIgaWYgeW91IGp1c3QgbmVlZCBhIHJvdWdoIGVzdGltYXRlIG9mIHRoZSBwYXJhbWV0ZXJzLCB3aGlsZSBNTEUgbWlnaHQgYmUgYmV0dGVyIGlmIHlvdSBuZWVkIGEgcmVzdWx0IHRoYXQgdGFrZXMgaW50byBhY2NvdW50IHRoZSBlbnRpcmUgc2hhcGUgb2YgYSBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24uICANCg0KDQoNCg0K