Assignment Objectives

  • Enhance understanding the procedure of likelihood-based chi-square hypothesis testing .

  • Implement the procedures for detecting overfitting/underfitting issues in practical applications.

Policies of Using AI Tools

Policy on AI Tool Use: Please adhere to the AI tool policy specified in the course syllabus. The direct copying of AI-generated content is strictly prohibited. All submitted work must reflect your own understanding; where external tools are consulted, content must be thoroughly rephrased and synthesized in your own words.

Code Inclusion Requirement: Any code included in your essay must be properly commented to explain the purpose and/or expected output of key code lines. Submitting AI-generated code without meaningful, student-added comments will not be accepted.

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}\]


Question: Reliability Application

A mid-sized manufacturing company producing industrial conveyor systems began experiencing unexpected downtime in one of its distribution facilities, prompting concern about the reliability of a newly sourced batch of ball bearings used in the motor assemblies. These bearings, supplied by a vendor adopting cost-saving production methods, were installed across multiple units operating under continuous load conditions. After several months, maintenance logs revealed a pattern of increasing failures, with components lasting anywhere from a few dozen to over 150 hours before breakdown. To investigate, the engineering team collected time-to-failure data from 50 identical bearings and conducted a Weibull analysis within the framework of Reliability Engineering. The 50 time-to-failure (survival time) are:

12.4, 18.7, 25.3, 30.1, 33.5, 35.2, 38.9, 40.3, 42.7, 45.1, 47.6, 49.8, 52.4, 55.0, 
57.3, 60.2, 62.8, 65.1, 67.9, 70.5, 72.3, 75.6, 78.2, 80.9, 83.4, 85.7, 88.1, 90.6, 
93.2, 95.8, 98.4, 101.0, 104.5, 107.3, 110.6, 113.2, 116.8, 120.1, 123.7, 127.4,
130.9, 134.5, 138.2, 142.0, 146.3, 150.7, 155.2, 160.8, 168.4, 175.9

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.]

wbearing = sort(c(12.4, 18.7, 25.3, 30.1, 33.5, 35.2, 38.9, 40.3, 42.7, 45.1, 47.6, 49.8, 52.4, 55.0, 
57.3, 60.2, 62.8, 65.1, 67.9, 70.5, 72.3, 75.6, 78.2, 80.9, 83.4, 85.7, 88.1, 90.6, 
93.2, 95.8, 98.4, 101.0, 104.5, 107.3, 110.6, 113.2, 116.8, 120.1, 123.7, 127.4,
130.9, 134.5, 138.2, 142.0, 146.3, 150.7, 155.2, 160.8, 168.4, 175.9))


#prepare weilbull distrubbtion log likelihood to use optim()
weil_loglik= function(params){
  
  lambda = params[1]
  beta = params[2]
  n = length(wbearing)
  
  if (lambda <= 0 || beta <= 0 ) return(-Inf)

  #log likelihood formula
  beta_shape = n * log(beta)
  scale_norm = n * beta * log(lambda) #normalizes the distrubution on scale parameter
  log_data_sum = (beta -1) * sum(log(wbearing)) #sums the logs
  exponential_kernel = sum((wbearing/lambda)^beta) #exponential kernel
  log_lik = beta_shape + log_data_sum - scale_norm - exponential_kernel
  
  return(log_lik)
}


#maximizing the likelihood to find the MLE
mle_weibull = optim(par = c(mean(wbearing), 1),
                     fn = weil_loglik,
                     hessian= TRUE,#output the hessian matrix
                     control = list(fnscale= -1) #fnsalce = -1 maximizes the likelihood
                     
                     )

# 3. Extract the results
hat_lambda <- mle_weibull$par[1]
hat_beta   <- mle_weibull$par[2]

cat("MLE for Lambda (Scale):", hat_lambda, 
    "\nMLE for Beta (Shape):", hat_beta)
MLE for Lambda (Scale): 99.02759 
MLE for Beta (Shape): 2.205876

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.]

#defining the exponential log likelihood
exp_loglik = function(lambda){
  
  n = length(wbearing)
  e_log =-n * log(lambda) -sum(wbearing)/lambda
  return(e_log)
}

# exponential gradient (score function)

exp_gradient = function(lambda){
  n = length(wbearing)
  deriv_lambda = -n / lambda + sum(wbearing)/ (lambda^2) #derivative in respect to lambda
  return(deriv_lambda)
  
}

#finding the MLE for exponential lambda

hat_lambda_exp = mean(wbearing)

#store max log like

loglik_exp_max = exp_loglik(hat_lambda_exp)

cat("Exponential MLE for Lambda:", hat_lambda_exp, 
    "\nMax Log-Likelihood (Null Model):", loglik_exp_max)
Exponential MLE for Lambda: 87.61 
Max Log-Likelihood (Null Model): -273.6448

c). Perform the likelihood ratio \(\chi^2\) test on \(\beta = 1\). What is the p-value? [Hint: Use the results in a) and b).]

#we can now measure the distance between the two models
# The likelihood ratio test asks, "is the improvement in the 'height' of the log likelihood from the exponential model to the weibull model large enough to be statistically significant


#use the (weibull model) maximum log likelihood (from part a) 

loglik_weibull_max = mle_weibull$value

# calculate the likelihood ratio test
  #find the difference between the log likelihood maximum and log_weillbull maximum
  #is the more complex model better than the simpler model
#we use the logs and -2 to force a chi square distribution 

like_ratio_test_statistic = -2 * (loglik_exp_max - loglik_weibull_max)

#calculate p value for test statistic from chiq square distrubtion

pval_lr_test = 1 - pchisq(like_ratio_test_statistic, df=1)


cat("Likelihood ratio test statistic:", like_ratio_test_statistic, 
    "\np-value (LRT):", pval_lr_test)
Likelihood ratio test statistic: 34.44995 
p-value (LRT): 4.373535e-09

d). Perform the Wald \(\chi^2\) on the same hypothesis \(\beta = 1\). What is the p-value? [Hint: You need to find the observed Fisher information matrix (i.e., the negative Hessian matrix from optim()) based on the Weibull distribution. The inverse of the negative observed Hessian matrix is the covariance matrix.]

#the observed fisher information(negative hessian)
#(the hessian is the matrix of the second derivative 


fisher_info = -mle_weibull$hessian

#run a variance covariance matrix (inverse of the fisher information)

var_cov_matrix = solve(fisher_info)

#extract the variance for beta
#since params[2] was beta, the variance of beta is the 2nd row, 2nd column
var_beta = var_cov_matrix[2,2]


## Wald test statistic
    #we use wald to determine if the variable is significant and should be used in the final model 
# Formula: (Estimate - Null)^2 / Variance

wald_statistic = (hat_beta- 1)^2 /var_beta

#p value from wald chi square distrubution

p_val_wald = 1 - pchisq(wald_statistic, df = 1)

cat("Wald Statistic:", wald_statistic, 
    "\np-value:", p_val_wald)
Wald Statistic: 23.10901 
p-value: 1.530721e-06

e). Write a summary of the above analyses to address the following:

  • Whether the two tests generated the same results.

  • Which model is recommended for the data.

  • Draw the density curve based on the MLE(s) of the parameter(s) and describe the distribution of the time-to-failure.

Both the Likelihood Ratio Test (LR=34.4499523, p= 4.3735351^{-9} ) and Wald Test (W= 23.1090057, p = 1.5307208^{-6}) are statistically significant. We can concluded that the slope is statistically different than 1 and that the converyer belt bearings do not fail randomly. The estimated shape parameter at 2.21 suggests the conveyers increasingly fail overtime. Considering the moderate sample of 50, the Likelihood ratio test (LRT) is the preferred test to use. LRT is most reliable for accuracy and closest to nominal Type I error rates as well as robust in being invariant to parameter transformations. The sample size does not leave computational concern. The confirmation that both LRT and Wald are significant suggests a strong relationship, although the Wald test performs poorly in skewness and nonlinear parameters which the weilbull distribution tends to hold. A drop from the LRT from being 34.4499523 to W= 23.1090057, may suggest the weilbull test could not strongly handle the distribution’s skewness. If there is discrepancy between knowing to use the simple exponential or more complex weibull model, use the weibull because it better explains the distribution relationship as the exponential model underfits the data.

# set range of time values for the x-axis
time_seq =seq(0, 200, length.out = 1000)

#calculate density values for both models using the MLEs from  Part A and Part B
weibull_dens= dweibull(time_seq, shape = hat_beta, scale = hat_lambda)
exp_dens =dexp(time_seq, rate = 1/hat_lambda_exp)


plot(time_seq, weibull_dens, type = "l", col = "darkred", lwd = 3,
     main = "Bearing Time-to-Failure: Weibull vs. Exponential",
     xlab = "Time (hours)", ylab = "Density",
     ylim = c(0, max(weibull_dens) * 1.1))


lines(time_seq, exp_dens, col = "blue", lwd = 2, lty = 2) # Add the Exponential curve for comparison

# histogram --> actual data to see the 'fit'
hist(wbearing, prob = TRUE, add = TRUE, col = rgb(0.5, 0.5, 0.5, 0.3), border = "white")

# legend
legend("topright", legend = c("Fitted Weibull (MLE)", "Fitted Exponential (Null)"),
       col = c("darkred", "blue"), lty = c(1, 2), lwd = 2)

LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMTE6IERldGVjdGluZyBPdmVyZml0dGluZyBhbmQgT3ZlcmZpdHRpbmcgSXNzdWVzIg0KYXV0aG9yOiAiRXphbmEgUml2ZXJzICINCmRhdGU6ICIgNC0xMzogIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIGhpZ2hsaWdodDogbW9ub2Nocm9tZQ0KICAgIHRoZW1lOiBzcGFjZWxhYg0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIGZpZ193aWR0aDogMw0KICAgIGZpZ19oZWlnaHQ6IDMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCiNUT0M6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICJUYWJsZSBvZiBDb250ZW50cyI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuMmVtOw0KICBkaXNwbGF5OiBibG9jazsNCiAgY29sb3I6IG5hdnk7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCg0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLw0KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLw0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTVweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KDQpib2R5IHtiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmZmZmOw0KICAgICAgY29sb3I6ICMwMDAwMDA7DQogICAgICBmb250LWZhbWlseTogQXJpYWwsIHNhbnMtc2VyaWY7DQogICAgICBmb250LXNpemU6IDFyZW07DQogICAgICBsaW5lLWhlaWdodDogMS42Ow0KICAgICAgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KDQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogIGxpYnJhcnkocGxvdGx5KQ0KfQ0KDQppZiAoIXJlcXVpcmUoIlZHQU0iKSkgew0KICBpbnN0YWxsLnBhY2thZ2VzKCJWR0FNIikNCiAgbGlicmFyeShWR0FNKQ0KfQ0KaWYgKCFyZXF1aXJlKCJib290IikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiYm9vdCIpDQogIGxpYnJhcnkoYm9vdCkNCn0NCmlmICghcmVxdWlyZSgiZWZmc2l6ZSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImVmZnNpemUiKQ0KICBsaWJyYXJ5KGVmZnNpemUpDQp9DQojIyBsaWJyYXJ5KGVmZnNpemUpDQojIyMjIFZHQU0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdHMgPSBUUlVFLCAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQQ0KICAgICAgICAgICAgICAgICAgICAgICkgIA0KYGBgDQogDQogXA0KIA0KIyMgKipBc3NpZ25tZW50IE9iamVjdGl2ZXMqKiANCg0KPHA+DQoqIEVuaGFuY2UgdW5kZXJzdGFuZGluZyB0aGUgcHJvY2VkdXJlIG9mIGxpa2VsaWhvb2QtYmFzZWQgY2hpLXNxdWFyZSBoeXBvdGhlc2lzIHRlc3RpbmcgLg0KDQoqIEltcGxlbWVudCB0aGUgcHJvY2VkdXJlcyBmb3IgZGV0ZWN0aW5nIG92ZXJmaXR0aW5nL3VuZGVyZml0dGluZyBpc3N1ZXMgaW4gcHJhY3RpY2FsIGFwcGxpY2F0aW9ucy4NCjwvcD4NCg0KDQojIyAqKlBvbGljaWVzIG9mIFVzaW5nIEFJIFRvb2xzKioNCg0KPHA+DQoqKlBvbGljeSBvbiBBSSBUb29sIFVzZSoqOiBQbGVhc2UgYWRoZXJlIHRvIHRoZSBBSSB0b29sIHBvbGljeSBzcGVjaWZpZWQgaW4gdGhlIGNvdXJzZSBzeWxsYWJ1cy4gVGhlIGRpcmVjdCBjb3B5aW5nIG9mIEFJLWdlbmVyYXRlZCBjb250ZW50IGlzIHN0cmljdGx5IHByb2hpYml0ZWQuIEFsbCBzdWJtaXR0ZWQgd29yayBtdXN0IHJlZmxlY3QgeW91ciBvd24gdW5kZXJzdGFuZGluZzsgd2hlcmUgZXh0ZXJuYWwgdG9vbHMgYXJlIGNvbnN1bHRlZCwgY29udGVudCBtdXN0IGJlIHRob3JvdWdobHkgcmVwaHJhc2VkIGFuZCBzeW50aGVzaXplZCBpbiB5b3VyIG93biB3b3Jkcy4NCjwvcD4NCg0KPHA+DQoqKkNvZGUgSW5jbHVzaW9uIFJlcXVpcmVtZW50Kio6IEFueSBjb2RlIGluY2x1ZGVkIGluIHlvdXIgZXNzYXkgbXVzdCBiZSBwcm9wZXJseSBjb21tZW50ZWQgdG8gZXhwbGFpbiB0aGUgcHVycG9zZSBhbmQvb3IgZXhwZWN0ZWQgb3V0cHV0IG9mIGtleSBjb2RlIGxpbmVzLiBTdWJtaXR0aW5nIEFJLWdlbmVyYXRlZCBjb2RlIHdpdGhvdXQgbWVhbmluZ2Z1bCwgc3R1ZGVudC1hZGRlZCBjb21tZW50cyB3aWxsIG5vdCBiZSBhY2NlcHRlZC4NCjwvcD4NCg0KDQojIyBUZXN0aW5nIE92ZXJmaXR0aW5nL1VuZGVyZml0dGluZw0KDQpJbiBNYWNoaW5lIExlYXJuaW5nIGFuZCBTdGF0aXN0aWNzLCBvdmVyZml0dGluZyBvY2N1cnMgd2hlbiBhIG1vZGVsIGlzIHRvbyBjb21wbGV4IGFuZCBsZWFybnMgbm9pc2UsIGxlYWRpbmcgdG8gcG9vciBwZXJmb3JtYW5jZSBvbiBuZXcgZGF0YSwgd2hpbGUgdW5kZXJmaXR0aW5nIGhhcHBlbnMgd2hlbiBhIG1vZGVsIGlzIHRvbyBzaW1wbGUgdG8gY2FwdHVyZSBpbXBvcnRhbnQgcGF0dGVybnMsIHJlc3VsdGluZyBpbiBoaWdoIGVycm9ycyBvdmVyYWxsOyBib3RoIGlzc3VlcyBhcmUgZXhwbGFpbmVkIGJ5IHRoZSBCaWFz4oCTVmFyaWFuY2UgVHJhZGVvZmYgYW5kIGNhbiBjYXVzZSB1bnJlbGlhYmxlIHByZWRpY3Rpb25zIGluIHJlYWwtd29ybGQgYXBwbGljYXRpb25zLg0KDQoNClRoZSBwcm9iYWJpbGl0eSBkZW5zaXR5IGZ1bmN0aW9uIChQREYpIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBpczoNCg0KJCQNCmYodDsgXGxhbWJkYSwgXGJldGEpID0gXGZyYWN7XGJldGF9e1xsYW1iZGF9IFxsZWZ0KCBcZnJhY3t0fXtcbGFtYmRhfSBccmlnaHQpXntcYmV0YS0xfSBcZXhwXGxlZnRbIC1cbGVmdCggXGZyYWN7dH17XGxhbWJkYX0gXHJpZ2h0KV5cYmV0YSBccmlnaHRdLCBccXVhZCB0IFxnZSAwDQokJA0Kd2hlcmUgJFxsYW1iZGEgPiAwJCBpcyB0aGUgc2NhbGUgcGFyYW1ldGVyIChjaGFyYWN0ZXJpc3RpYyBsaWZlKSBhbmQgJFxiZXRhID4gMCQgaXMgdGhlIHNoYXBlIHBhcmFtZXRlci4NCg0KV2hlbiAkXGJldGEgPSAxJCwgdGhlIFdlaWJ1bGwgUERGIHNpbXBsaWZpZXMgdG8gdGhlIGV4cG9uZW50aWFsIFBERjoNCg0KJCQNCmYodDsgXGxhbWJkYSkgPSBcZnJhY3sxfXtcbGFtYmRhfSBcZXhwXGxlZnQoIC1cZnJhY3t0fXtcbGFtYmRhfSBccmlnaHQpDQokJA0Kd2l0aCBjb25zdGFudCBoYXphcmQgcmF0ZSAkaCh0KSA9IDEvXGxhbWJkYSQuDQoNCg0KPHA+PGZvbnQgY29sb3IgPSAiZGFya3JlZCI+KipUaGlzIGFzc2lnbm1lbnQgZm9jdXNlcyBvbiBwZXJmb3JtaW5nIGEgaHlwb3RoZXNpcyB0ZXN0IGZvciB0aGUgc2hhcGUgcGFyYW1ldGVyICgkXGJldGEkKSBvZiB0aGUgV2VpYnVsbCBkaXN0cmlidXRpb24gd2l0aGluIGEgcmVsaWFiaWxpdHkgbW9kZSoqPC9mb250PjwvcD4NCg0KDQpcYmVnaW57YWxpZ259DQpIXzAmOiBcYmV0YSA9IDEgXHF1YWQgXHRleHR7KEV4cG9uZW50aWFsIG1vZGVsLCBzaW1wbGVyKX0gXFwNCkhfMSY6IFxiZXRhIFxuZXEgMSBccXVhZCBcdGV4dHsoV2VpYnVsbCBtb2RlbCwgbW9yZSBjb21wbGV4KX0NClxlbmR7YWxpZ259DQoNCg0KXA0KDQojIyAqKlF1ZXN0aW9uOiBSZWxpYWJpbGl0eSBBcHBsaWNhdGlvbioqDQoNCjxwPg0KQSBtaWQtc2l6ZWQgbWFudWZhY3R1cmluZyBjb21wYW55IHByb2R1Y2luZyBpbmR1c3RyaWFsIGNvbnZleW9yIHN5c3RlbXMgYmVnYW4gZXhwZXJpZW5jaW5nIHVuZXhwZWN0ZWQgZG93bnRpbWUgaW4gb25lIG9mIGl0cyBkaXN0cmlidXRpb24gZmFjaWxpdGllcywgcHJvbXB0aW5nIGNvbmNlcm4gYWJvdXQgdGhlIHJlbGlhYmlsaXR5IG9mIGEgbmV3bHkgc291cmNlZCBiYXRjaCBvZiBiYWxsIGJlYXJpbmdzIHVzZWQgaW4gdGhlIG1vdG9yIGFzc2VtYmxpZXMuIFRoZXNlIGJlYXJpbmdzLCBzdXBwbGllZCBieSBhIHZlbmRvciBhZG9wdGluZyBjb3N0LXNhdmluZyBwcm9kdWN0aW9uIG1ldGhvZHMsIHdlcmUgaW5zdGFsbGVkIGFjcm9zcyBtdWx0aXBsZSB1bml0cyBvcGVyYXRpbmcgdW5kZXIgY29udGludW91cyBsb2FkIGNvbmRpdGlvbnMuIEFmdGVyIHNldmVyYWwgbW9udGhzLCBtYWludGVuYW5jZSBsb2dzIHJldmVhbGVkIGEgcGF0dGVybiBvZiBpbmNyZWFzaW5nIGZhaWx1cmVzLCB3aXRoIGNvbXBvbmVudHMgbGFzdGluZyBhbnl3aGVyZSBmcm9tIGEgZmV3IGRvemVuIHRvIG92ZXIgMTUwIGhvdXJzIGJlZm9yZSBicmVha2Rvd24uIFRvIGludmVzdGlnYXRlLCB0aGUgZW5naW5lZXJpbmcgdGVhbSBjb2xsZWN0ZWQgdGltZS10by1mYWlsdXJlIGRhdGEgZnJvbSA1MCBpZGVudGljYWwgYmVhcmluZ3MgYW5kIGNvbmR1Y3RlZCBhIFdlaWJ1bGwgYW5hbHlzaXMgd2l0aGluIHRoZSBmcmFtZXdvcmsgb2YgUmVsaWFiaWxpdHkgRW5naW5lZXJpbmcuIFRoZSA1MCB0aW1lLXRvLWZhaWx1cmUgKHN1cnZpdmFsIHRpbWUpIGFyZToNCg0KYGBgDQoxMi40LCAxOC43LCAyNS4zLCAzMC4xLCAzMy41LCAzNS4yLCAzOC45LCA0MC4zLCA0Mi43LCA0NS4xLCA0Ny42LCA0OS44LCA1Mi40LCA1NS4wLCANCjU3LjMsIDYwLjIsIDYyLjgsIDY1LjEsIDY3LjksIDcwLjUsIDcyLjMsIDc1LjYsIDc4LjIsIDgwLjksIDgzLjQsIDg1LjcsIDg4LjEsIDkwLjYsIA0KOTMuMiwgOTUuOCwgOTguNCwgMTAxLjAsIDEwNC41LCAxMDcuMywgMTEwLjYsIDExMy4yLCAxMTYuOCwgMTIwLjEsIDEyMy43LCAxMjcuNCwNCjEzMC45LCAxMzQuNSwgMTM4LjIsIDE0Mi4wLCAxNDYuMywgMTUwLjcsIDE1NS4yLCAxNjAuOCwgMTY4LjQsIDE3NS45DQpgYGANCjwvcD4NCg0KVGhpcyBhc3NpZ25tZW50IGZvY3VzZXMgb24gaHlwb3RoZXNpcyAkSF8wOiBcYmV0YSA9IDEkIChleHBvbmVudGlhbCkgYWdhaW5zdCAkSF8xOiBcYmV0YSBcbmVxIDEkIChXZWlidWxsKS4gVGhpcyBmcmFtZXdvcmsgZGV0ZWN0cyBvdmVyZml0dGluZyAoZml0dGluZyBhIFdlaWJ1bGwgd2hlbiBleHBvbmVudGlhbCBpcyB0cnVlKSBhbmQgdW5kZXJmaXR0aW5nIChmaXR0aW5nIGV4cG9uZW50aWFsIHdoZW4gV2VpYnVsbCB3aXRoICRcYmV0YSBcbmVxIDEkIGlzIHRydWUpLiANCg0KDQo8cD4NCmEpLiBGaW5kIHRoZSBNTEUgb2YgdGhlIFdlaWJ1bGwgcGFyYW1ldGVycyAkXGxhbWJkYSQgKHNjYWxlKSBhbmQgJFxiZXRhJCAoc2hhcGUpLCBkZW5vdGVkIGJ5ICRcaGF0e1xsYW1iZGF9JCBhbmQgJFxoYXR7XGJldGF9JCwgcmVzcGVjdGl2ZWx5LCB1c2luZyB0aGUgYG9wdGltKClgIHByb2NlZHVyZS4gWypIaW50OiBZb3Ugc2hvdWxkIHByb3ZpZGUgZXhwbGljaXQgZXhwcmVzc2lvbnMgZm9yIHRoZSBsb2ctbGlrZWxpaG9vZCBhbmQgZ3JhZGllbnQgZnVuY3Rpb25zIG9mIHRoZSBXZWlidWxsIGRpc3RyaWJ1dGlvbiBwYXJhbWV0ZXJzLipdDQoNCmBgYHtyfQ0KDQp3YmVhcmluZyA9IHNvcnQoYygxMi40LCAxOC43LCAyNS4zLCAzMC4xLCAzMy41LCAzNS4yLCAzOC45LCA0MC4zLCA0Mi43LCA0NS4xLCA0Ny42LCA0OS44LCA1Mi40LCA1NS4wLCANCjU3LjMsIDYwLjIsIDYyLjgsIDY1LjEsIDY3LjksIDcwLjUsIDcyLjMsIDc1LjYsIDc4LjIsIDgwLjksIDgzLjQsIDg1LjcsIDg4LjEsIDkwLjYsIA0KOTMuMiwgOTUuOCwgOTguNCwgMTAxLjAsIDEwNC41LCAxMDcuMywgMTEwLjYsIDExMy4yLCAxMTYuOCwgMTIwLjEsIDEyMy43LCAxMjcuNCwNCjEzMC45LCAxMzQuNSwgMTM4LjIsIDE0Mi4wLCAxNDYuMywgMTUwLjcsIDE1NS4yLCAxNjAuOCwgMTY4LjQsIDE3NS45KSkNCg0KDQojcHJlcGFyZSB3ZWlsYnVsbCBkaXN0cnViYnRpb24gbG9nIGxpa2VsaWhvb2QgdG8gdXNlIG9wdGltKCkNCndlaWxfbG9nbGlrPSBmdW5jdGlvbihwYXJhbXMpew0KICANCiAgbGFtYmRhID0gcGFyYW1zWzFdDQogIGJldGEgPSBwYXJhbXNbMl0NCiAgbiA9IGxlbmd0aCh3YmVhcmluZykNCiAgDQogIGlmIChsYW1iZGEgPD0gMCB8fCBiZXRhIDw9IDAgKSByZXR1cm4oLUluZikNCg0KICAjbG9nIGxpa2VsaWhvb2QgZm9ybXVsYQ0KICBiZXRhX3NoYXBlID0gbiAqIGxvZyhiZXRhKQ0KICBzY2FsZV9ub3JtID0gbiAqIGJldGEgKiBsb2cobGFtYmRhKSAjbm9ybWFsaXplcyB0aGUgZGlzdHJ1YnV0aW9uIG9uIHNjYWxlIHBhcmFtZXRlcg0KICBsb2dfZGF0YV9zdW0gPSAoYmV0YSAtMSkgKiBzdW0obG9nKHdiZWFyaW5nKSkgI3N1bXMgdGhlIGxvZ3MNCiAgZXhwb25lbnRpYWxfa2VybmVsID0gc3VtKCh3YmVhcmluZy9sYW1iZGEpXmJldGEpICNleHBvbmVudGlhbCBrZXJuZWwNCiAgbG9nX2xpayA9IGJldGFfc2hhcGUgKyBsb2dfZGF0YV9zdW0gLSBzY2FsZV9ub3JtIC0gZXhwb25lbnRpYWxfa2VybmVsDQogIA0KICByZXR1cm4obG9nX2xpaykNCn0NCg0KDQojbWF4aW1pemluZyB0aGUgbGlrZWxpaG9vZCB0byBmaW5kIHRoZSBNTEUNCm1sZV93ZWlidWxsID0gb3B0aW0ocGFyID0gYyhtZWFuKHdiZWFyaW5nKSwgMSksDQogICAgICAgICAgICAgICAgICAgICBmbiA9IHdlaWxfbG9nbGlrLA0KICAgICAgICAgICAgICAgICAgICAgaGVzc2lhbj0gVFJVRSwjb3V0cHV0IHRoZSBoZXNzaWFuIG1hdHJpeA0KICAgICAgICAgICAgICAgICAgICAgY29udHJvbCA9IGxpc3QoZm5zY2FsZT0gLTEpICNmbnNhbGNlID0gLTEgbWF4aW1pemVzIHRoZSBsaWtlbGlob29kDQogICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICkNCg0KIyAzLiBFeHRyYWN0IHRoZSByZXN1bHRzDQpoYXRfbGFtYmRhIDwtIG1sZV93ZWlidWxsJHBhclsxXQ0KaGF0X2JldGEgICA8LSBtbGVfd2VpYnVsbCRwYXJbMl0NCg0KY2F0KCJNTEUgZm9yIExhbWJkYSAoU2NhbGUpOiIsIGhhdF9sYW1iZGEsIA0KICAgICJcbk1MRSBmb3IgQmV0YSAoU2hhcGUpOiIsIGhhdF9iZXRhKQ0KDQoNCmBgYA0KDQpiKS4gRmluZCB0aGUgTUxFIG9mIHRoZSBleHBvbmVudGlhbCBwYXJhbWV0ZXIgJFxsYW1iZGEkIChzY2FsZSksIGRlbm90ZWQgYnkgJFxoYXR7XGxhbWJkYX0kLCB1c2luZyBhbnkgcHJvY2VkdXJlLiBbKkhpbnQ6IFlvdSBzaG91bGQgcHJvdmlkZSBleHBsaWNpdCBleHByZXNzaW9ucyBmb3IgdGhlIGxvZy1saWtlbGlob29kIGFuZCBncmFkaWVudCBmdW5jdGlvbnMgb2YgdGhlIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiBwYXJhbWV0ZXJzLipdDQoNCg0KDQpgYGB7cn0NCg0KI2RlZmluaW5nIHRoZSBleHBvbmVudGlhbCBsb2cgbGlrZWxpaG9vZA0KZXhwX2xvZ2xpayA9IGZ1bmN0aW9uKGxhbWJkYSl7DQogIA0KICBuID0gbGVuZ3RoKHdiZWFyaW5nKQ0KICBlX2xvZyA9LW4gKiBsb2cobGFtYmRhKSAtc3VtKHdiZWFyaW5nKS9sYW1iZGENCiAgcmV0dXJuKGVfbG9nKQ0KfQ0KDQojIGV4cG9uZW50aWFsIGdyYWRpZW50IChzY29yZSBmdW5jdGlvbikNCg0KZXhwX2dyYWRpZW50ID0gZnVuY3Rpb24obGFtYmRhKXsNCiAgbiA9IGxlbmd0aCh3YmVhcmluZykNCiAgZGVyaXZfbGFtYmRhID0gLW4gLyBsYW1iZGEgKyBzdW0od2JlYXJpbmcpLyAobGFtYmRhXjIpICNkZXJpdmF0aXZlIGluIHJlc3BlY3QgdG8gbGFtYmRhDQogIHJldHVybihkZXJpdl9sYW1iZGEpDQogIA0KfQ0KDQojZmluZGluZyB0aGUgTUxFIGZvciBleHBvbmVudGlhbCBsYW1iZGENCg0KaGF0X2xhbWJkYV9leHAgPSBtZWFuKHdiZWFyaW5nKQ0KDQojc3RvcmUgbWF4IGxvZyBsaWtlDQoNCmxvZ2xpa19leHBfbWF4ID0gZXhwX2xvZ2xpayhoYXRfbGFtYmRhX2V4cCkNCg0KY2F0KCJFeHBvbmVudGlhbCBNTEUgZm9yIExhbWJkYToiLCBoYXRfbGFtYmRhX2V4cCwgDQogICAgIlxuTWF4IExvZy1MaWtlbGlob29kIChOdWxsIE1vZGVsKToiLCBsb2dsaWtfZXhwX21heCkNCg0KYGBgDQoNCmMpLiBQZXJmb3JtIHRoZSBsaWtlbGlob29kIHJhdGlvICRcY2hpXjIkIHRlc3Qgb24gJFxiZXRhID0gMSQuIFdoYXQgaXMgdGhlIHAtdmFsdWU/IFsqSGludDogVXNlIHRoZSByZXN1bHRzIGluIGEpIGFuZCBiKSouXSANCg0KDQpgYGB7cn0NCg0KI3dlIGNhbiBub3cgbWVhc3VyZSB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgdHdvIG1vZGVscw0KIyBUaGUgbGlrZWxpaG9vZCByYXRpbyB0ZXN0IGFza3MsICJpcyB0aGUgaW1wcm92ZW1lbnQgaW4gdGhlICdoZWlnaHQnIG9mIHRoZSBsb2cgbGlrZWxpaG9vZCBmcm9tIHRoZSBleHBvbmVudGlhbCBtb2RlbCB0byB0aGUgd2VpYnVsbCBtb2RlbCBsYXJnZSBlbm91Z2ggdG8gYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudA0KDQoNCiN1c2UgdGhlICh3ZWlidWxsIG1vZGVsKSBtYXhpbXVtIGxvZyBsaWtlbGlob29kIChmcm9tIHBhcnQgYSkgDQoNCmxvZ2xpa193ZWlidWxsX21heCA9IG1sZV93ZWlidWxsJHZhbHVlDQoNCiMgY2FsY3VsYXRlIHRoZSBsaWtlbGlob29kIHJhdGlvIHRlc3QNCiAgI2ZpbmQgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgbG9nIGxpa2VsaWhvb2QgbWF4aW11bSBhbmQgbG9nX3dlaWxsYnVsbCBtYXhpbXVtDQogICNpcyB0aGUgbW9yZSBjb21wbGV4IG1vZGVsIGJldHRlciB0aGFuIHRoZSBzaW1wbGVyIG1vZGVsDQojd2UgdXNlIHRoZSBsb2dzIGFuZCAtMiB0byBmb3JjZSBhIGNoaSBzcXVhcmUgZGlzdHJpYnV0aW9uIA0KDQpsaWtlX3JhdGlvX3Rlc3Rfc3RhdGlzdGljID0gLTIgKiAobG9nbGlrX2V4cF9tYXggLSBsb2dsaWtfd2VpYnVsbF9tYXgpDQoNCiNjYWxjdWxhdGUgcCB2YWx1ZSBmb3IgdGVzdCBzdGF0aXN0aWMgZnJvbSBjaGlxIHNxdWFyZSBkaXN0cnVidGlvbg0KDQpwdmFsX2xyX3Rlc3QgPSAxIC0gcGNoaXNxKGxpa2VfcmF0aW9fdGVzdF9zdGF0aXN0aWMsIGRmPTEpDQoNCg0KY2F0KCJMaWtlbGlob29kIHJhdGlvIHRlc3Qgc3RhdGlzdGljOiIsIGxpa2VfcmF0aW9fdGVzdF9zdGF0aXN0aWMsIA0KICAgICJcbnAtdmFsdWUgKExSVCk6IiwgcHZhbF9scl90ZXN0KQ0KDQoNCmBgYA0KDQpkKS4gUGVyZm9ybSB0aGUgV2FsZCAkXGNoaV4yJCBvbiB0aGUgc2FtZSBoeXBvdGhlc2lzICRcYmV0YSA9IDEkLiBXaGF0IGlzIHRoZSBwLXZhbHVlPyBbKkhpbnQ6IFlvdSBuZWVkIHRvIGZpbmQgdGhlIG9ic2VydmVkIEZpc2hlciBpbmZvcm1hdGlvbiBtYXRyaXggKGkuZS4sIHRoZSBuZWdhdGl2ZSBIZXNzaWFuIG1hdHJpeCBmcm9tIGBvcHRpbSgpYCkgYmFzZWQgb24gdGhlIFdlaWJ1bGwgZGlzdHJpYnV0aW9uLiBUaGUgaW52ZXJzZSBvZiB0aGUgPGZvbnQgY29sb3IgPSAiYmx1ZSI+bmVnYXRpdmU8L2ZvbnQ+IG9ic2VydmVkIEhlc3NpYW4gbWF0cml4IGlzIHRoZSBjb3ZhcmlhbmNlIG1hdHJpeCouXSANCg0KDQpgYGB7cn0NCg0KI3RoZSBvYnNlcnZlZCBmaXNoZXIgaW5mb3JtYXRpb24obmVnYXRpdmUgaGVzc2lhbikNCiModGhlIGhlc3NpYW4gaXMgdGhlIG1hdHJpeCBvZiB0aGUgc2Vjb25kIGRlcml2YXRpdmUgDQoNCg0KZmlzaGVyX2luZm8gPSAtbWxlX3dlaWJ1bGwkaGVzc2lhbg0KDQojcnVuIGEgdmFyaWFuY2UgY292YXJpYW5jZSBtYXRyaXggKGludmVyc2Ugb2YgdGhlIGZpc2hlciBpbmZvcm1hdGlvbikNCg0KdmFyX2Nvdl9tYXRyaXggPSBzb2x2ZShmaXNoZXJfaW5mbykNCg0KI2V4dHJhY3QgdGhlIHZhcmlhbmNlIGZvciBiZXRhDQojc2luY2UgcGFyYW1zWzJdIHdhcyBiZXRhLCB0aGUgdmFyaWFuY2Ugb2YgYmV0YSBpcyB0aGUgMm5kIHJvdywgMm5kIGNvbHVtbg0KdmFyX2JldGEgPSB2YXJfY292X21hdHJpeFsyLDJdDQoNCg0KIyMgV2FsZCB0ZXN0IHN0YXRpc3RpYw0KICAgICN3ZSB1c2Ugd2FsZCB0byBkZXRlcm1pbmUgaWYgdGhlIHZhcmlhYmxlIGlzIHNpZ25pZmljYW50IGFuZCBzaG91bGQgYmUgdXNlZCBpbiB0aGUgZmluYWwgbW9kZWwgDQojIEZvcm11bGE6IChFc3RpbWF0ZSAtIE51bGwpXjIgLyBWYXJpYW5jZQ0KDQp3YWxkX3N0YXRpc3RpYyA9IChoYXRfYmV0YS0gMSleMiAvdmFyX2JldGENCg0KI3AgdmFsdWUgZnJvbSB3YWxkIGNoaSBzcXVhcmUgZGlzdHJ1YnV0aW9uDQoNCnBfdmFsX3dhbGQgPSAxIC0gcGNoaXNxKHdhbGRfc3RhdGlzdGljLCBkZiA9IDEpDQoNCmNhdCgiV2FsZCBTdGF0aXN0aWM6Iiwgd2FsZF9zdGF0aXN0aWMsIA0KICAgICJcbnAtdmFsdWU6IiwgcF92YWxfd2FsZCkNCg0KYGBgDQoNCg0KDQoNCg0KZSkuIFdyaXRlIGEgc3VtbWFyeSBvZiB0aGUgYWJvdmUgYW5hbHlzZXMgdG8gYWRkcmVzcyB0aGUgZm9sbG93aW5nOg0KDQoqIFdoZXRoZXIgdGhlIHR3byB0ZXN0cyBnZW5lcmF0ZWQgdGhlIHNhbWUgcmVzdWx0cy4NCg0KKiBXaGljaCBtb2RlbCBpcyByZWNvbW1lbmRlZCBmb3IgdGhlIGRhdGEuDQoNCiogRHJhdyB0aGUgZGVuc2l0eSBjdXJ2ZSBiYXNlZCBvbiB0aGUgTUxFKHMpIG9mIHRoZSBwYXJhbWV0ZXIocykgYW5kIGRlc2NyaWJlIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHRpbWUtdG8tZmFpbHVyZS4NCjwvcD4NCg0KDQpCb3RoIHRoZSBMaWtlbGlob29kIFJhdGlvIFRlc3QgKExSPWByIGxpa2VfcmF0aW9fdGVzdF9zdGF0aXN0aWNgLCBwPSBgciBwdmFsX2xyX3Rlc3RgICkgYW5kIFdhbGQgVGVzdCAoVz0gYHIgd2FsZF9zdGF0aXN0aWNgLCBwID0gYHIgcF92YWxfd2FsZGApIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiANCldlIGNhbiBjb25jbHVkZWQgdGhhdCB0aGUgc2xvcGUgaXMgc3RhdGlzdGljYWxseSBkaWZmZXJlbnQgdGhhbiAxIGFuZCB0aGF0IHRoZSBjb252ZXJ5ZXIgYmVsdCBiZWFyaW5ncyBkbyBub3QgZmFpbCByYW5kb21seS4gVGhlIGVzdGltYXRlZCBzaGFwZSBwYXJhbWV0ZXIgYXQgMi4yMSBzdWdnZXN0cyB0aGUgY29udmV5ZXJzIGluY3JlYXNpbmdseSBmYWlsIG92ZXJ0aW1lLg0KQ29uc2lkZXJpbmcgdGhlIG1vZGVyYXRlIHNhbXBsZSBvZiA1MCwgdGhlIExpa2VsaWhvb2QgcmF0aW8gdGVzdCAoTFJUKSBpcyB0aGUgcHJlZmVycmVkIHRlc3QgdG8gdXNlLiBMUlQgaXMgbW9zdCByZWxpYWJsZSBmb3IgYWNjdXJhY3kgYW5kIGNsb3Nlc3QgdG8gbm9taW5hbCBUeXBlIEkgZXJyb3IgcmF0ZXMgYXMgd2VsbCBhcyByb2J1c3QgaW4gYmVpbmcgaW52YXJpYW50IHRvIHBhcmFtZXRlciB0cmFuc2Zvcm1hdGlvbnMuIFRoZSBzYW1wbGUgc2l6ZSBkb2VzIG5vdCBsZWF2ZSBjb21wdXRhdGlvbmFsIGNvbmNlcm4uIFRoZSBjb25maXJtYXRpb24gdGhhdCBib3RoIExSVCBhbmQgV2FsZCBhcmUgc2lnbmlmaWNhbnQgDQpzdWdnZXN0cyBhIHN0cm9uZyByZWxhdGlvbnNoaXAsIGFsdGhvdWdoIHRoZSBXYWxkIHRlc3QgcGVyZm9ybXMgcG9vcmx5IGluIHNrZXduZXNzIGFuZCBub25saW5lYXIgcGFyYW1ldGVycyB3aGljaCB0aGUgd2VpbGJ1bGwgZGlzdHJpYnV0aW9uIHRlbmRzIHRvIGhvbGQuIEEgZHJvcCBmcm9tIHRoZSBMUlQgZnJvbSBiZWluZyBgciBsaWtlX3JhdGlvX3Rlc3Rfc3RhdGlzdGljYCB0byBXPSBgciB3YWxkX3N0YXRpc3RpY2AsIG1heSBzdWdnZXN0IHRoZSB3ZWlsYnVsbCB0ZXN0IGNvdWxkIG5vdCBzdHJvbmdseSBoYW5kbGUgdGhlIGRpc3RyaWJ1dGlvbidzIHNrZXduZXNzLiBJZiB0aGVyZSBpcyBkaXNjcmVwYW5jeSBiZXR3ZWVuIGtub3dpbmcgdG8gdXNlIHRoZSBzaW1wbGUgZXhwb25lbnRpYWwgb3IgbW9yZSBjb21wbGV4IHdlaWJ1bGwgbW9kZWwsIHVzZSB0aGUgd2VpYnVsbCBiZWNhdXNlIGl0IGJldHRlciBleHBsYWlucyB0aGUgZGlzdHJpYnV0aW9uIHJlbGF0aW9uc2hpcCBhcyB0aGUgZXhwb25lbnRpYWwgbW9kZWwgdW5kZXJmaXRzIHRoZSBkYXRhLg0KDQoNCmBgYHtyfQ0KDQojIHNldCByYW5nZSBvZiB0aW1lIHZhbHVlcyBmb3IgdGhlIHgtYXhpcw0KdGltZV9zZXEgPXNlcSgwLCAyMDAsIGxlbmd0aC5vdXQgPSAxMDAwKQ0KDQojY2FsY3VsYXRlIGRlbnNpdHkgdmFsdWVzIGZvciBib3RoIG1vZGVscyB1c2luZyB0aGUgTUxFcyBmcm9tICBQYXJ0IEEgYW5kIFBhcnQgQg0Kd2VpYnVsbF9kZW5zPSBkd2VpYnVsbCh0aW1lX3NlcSwgc2hhcGUgPSBoYXRfYmV0YSwgc2NhbGUgPSBoYXRfbGFtYmRhKQ0KZXhwX2RlbnMgPWRleHAodGltZV9zZXEsIHJhdGUgPSAxL2hhdF9sYW1iZGFfZXhwKQ0KDQoNCnBsb3QodGltZV9zZXEsIHdlaWJ1bGxfZGVucywgdHlwZSA9ICJsIiwgY29sID0gImRhcmtyZWQiLCBsd2QgPSAzLA0KICAgICBtYWluID0gIkJlYXJpbmcgVGltZS10by1GYWlsdXJlOiBXZWlidWxsIHZzLiBFeHBvbmVudGlhbCIsDQogICAgIHhsYWIgPSAiVGltZSAoaG91cnMpIiwgeWxhYiA9ICJEZW5zaXR5IiwNCiAgICAgeWxpbSA9IGMoMCwgbWF4KHdlaWJ1bGxfZGVucykgKiAxLjEpKQ0KDQoNCmxpbmVzKHRpbWVfc2VxLCBleHBfZGVucywgY29sID0gImJsdWUiLCBsd2QgPSAyLCBsdHkgPSAyKSAjIEFkZCB0aGUgRXhwb25lbnRpYWwgY3VydmUgZm9yIGNvbXBhcmlzb24NCg0KIyBoaXN0b2dyYW0gLS0+IGFjdHVhbCBkYXRhIHRvIHNlZSB0aGUgJ2ZpdCcNCmhpc3Qod2JlYXJpbmcsIHByb2IgPSBUUlVFLCBhZGQgPSBUUlVFLCBjb2wgPSByZ2IoMC41LCAwLjUsIDAuNSwgMC4zKSwgYm9yZGVyID0gIndoaXRlIikNCg0KIyBsZWdlbmQNCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQgPSBjKCJGaXR0ZWQgV2VpYnVsbCAoTUxFKSIsICJGaXR0ZWQgRXhwb25lbnRpYWwgKE51bGwpIiksDQogICAgICAgY29sID0gYygiZGFya3JlZCIsICJibHVlIiksIGx0eSA9IGMoMSwgMiksIGx3ZCA9IDIpDQoNCg0KDQpgYGANCg0KDQoNCg0KDQoNCg0KDQoNCg0K