Final Exam Guidelines

  • Coverage: The major concepts and inference procedures—such as sampling distributions, confidence intervals, and hypothesis testing—are covered and implemented using both classical parametric likelihood-based methods and modern non-parametric approaches, including the bootstrap and kernel density estimation.

  • Part A requires derivation of selected likelihood-based functions for performing various types of inference, with sufficient detail to enable translation of these derivations into code for numerical analysis.

  • Your code for the problems in Part B must align with your derivations in Part A and be well commented where necessary.

  • In Part B, all numerical results must be interpreted from a practical perspective.


Policies of Using AI Tools

  • Policy on AI Tool Use: Students must 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.


Working Model for the Final Exam

Caution: Please follow the suggested expressions and guided steps to complete the exam. Other approaches such as transformation for trivialize the problems that will not meet the exam objectives.

The Kumaraswamy distribution is a two-parameter continuous probability distribution defined on the interval (0, 1). It is often used as an alternative to the Beta distribution due to its simple closed-form expressions for the cumulative distribution function (CDF) and quantile function. It is commonly used in

  • Hydrology: Modeling rainfall, streamflow, or other bounded natural phenomena

  • Economics: Income shares, proportions, or bounded indices

  • Monte Carlo simulation: Efficient random variate generation (via inverse transform)

  • Machine learning: Output layer for bounded targets, prior distributions in Bayesian models

  • Reliability engineering: Modeling failure rates of systems with bounded lifetimes


Let \(X\) be the Kumaraswamy random variable with Cumulative Distribution Function (CDF)

\[ F(x; a, b) = 1 - (1 - x^a)^b \]

where \(a > 0\) and \(b > 0\) unknown parameters and \(0 < x < 1\).

The following are two special case of the Kumaraswamy distribution:

  1. Uniform Distribution: When \(a = 1\) and \(b = 1\), the Kumaraswamy distribution becomes a uniform distribution over \([0, 1]\) with CDF \(F(x) = x\).

  2. Power Distribution: when \(b = 1\) and \(a > 0\), the Kumaraswamy distribution becomes a power distribution over \([0, 1]\) with CDF \(F(x) = x^a\).

This final exam focuses on inferences of Kumaraswamy distribution and related data analysis.

Part A: Methodological Derivations


Problem A1:

Show that the density function of the Kumaraswamy distribution is

\[ f(x; a, b) = ab \, x^{a-1} (1 - x^a)^{b-1}. \]

 Problem A1

Problem A1


Problem A2:

Let \(\{x_1, x_2, \cdots, x_n \}\) be an i.i.d. random sample taken from a population that follows the above 2-parameter Kumaraswamy distribution. Write out the loglikelihood function of \(a\) and \(b\), denoted by \(\ell(a,b)\), based on the above random sample and derive the gradient vector \([\ell_a^\prime(a,b), \ell_b^\prime(a,b)]\), the first order partial derivative of the log-likelihood with respect to parameters \(a\) and \(b\).

 Problem A2

Problem A2

 Problem A2

Problem A2


Problem A3:

Based on the gradients functions obtained in the above problem A2, derive the observed Fisher Information matrix (i.e, the negative Hessian Matrix).

 Problem A3

Problem A3

 Problem A3

Problem A3


Problem A4:

Consider power distribution \(F(x) = x^a, (a >0 \quad \text{ and }\quad x \in (0,1))\), a special case of the Kumaraswamy distribution with \(b = 1\), and a random sample from this distribution \(\{ x_1, x_2, \cdots, x_n\}\). Derive the MLE and MME of \(a\) respectively. [Hint: To find the MME, you need to compute the moment of the power distribution; that is, \(E[X^k] = \int_0^1 x^k F'(x) dx\). Note that both the MLE and the MME have closed-form expressions.]

 Problem A4

Problem A4

 Problem A4

Problem A4

 Problem A4

Problem A4


Problem A5:

Using the same setting as in Problem A4, find the asymptotic (Wald) confidence interval for \(a\). [Hint: Compute the Fisher information for \(a\), then take its reciprocal to obtain the variance.]

 Problem A5

Problem A5


Problem A6:

Using the same setting as in Problem A4, perform a likelihood ratio test for the hypothesis \(H_0 :a=1\) (i.e., the power distribution reduces to a uniform distribution). [Hint: Evaluate the log-likelihood function at the maximum likelihood estimate \(\hat{a}\) and at \(a=1\), then use these values to construct the LRT test statistic.]

 Problem A6

Problem A6


Part B: Numerical Analysis

All code must be well commented and adhere to best coding practices

Working Dataset: A small reservoir supplies water to a town. During the dry season (50 days), engineers record the fraction of usable storage filled each morning. Values near 0 mean the reservoir is nearly empty; values near 1 mean it’s full. The distribution tends to be right‑skewed (mostly low levels due to drought) but with occasional replenishment.

The following 50 data points (ordered for clarity) represent the daily proportion of usable storage:

0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22,
0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32,
0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42,
0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52,
0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.78


Problem B1:

Fit the Kumaraswamy distribution to the above data. Use the derivations in Problem A2 to find the MLE of \(a\) and \(b\). Please copy the key formulas before coding.

Formulas:

Gradient Vector for Kumaraswamy distribution log likelihoods.

Gradient Vector \(\ell'_b(a,b)\)

\[ \ell'_b(a,b) = \frac{n}{b} + \sum^n_{i=1} ln(1-X^a_i) \] \[ \ell'_a(a,b) = \frac{n}{a} +\sum^n_{i=1} ln(X_i) +(b-1)\sum^n_{i=1}\frac{X^a_i lnX_i}{1-X^a_i} \]

storage= sort(c(0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.20, 0.21, 0.22,
0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.30, 0.31, 0.32,
0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.40, 0.41, 0.42,
0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.50, 0.51, 0.52,
0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.60, 0.61, 0.78))

hist(storage) #histogram of dataset

#Find MLE of a and b

#Gradient for log_b(a,b)


#n= length(storage)

#function to find values of a and b based on the dataset alone


#finding the gradient of b
grad_bfunc =function(params, data) {
  a <- params[1]
  b <- params[2]
  
  n <- length(data)
  
#n/b + sum(log(1-x^a))
  sum_term=  sum(log(1- data^a)) #n/b + sum(data)
  gradient_b = -((n/b) + sum_term)
  
  return(gradient_b)
}


grad_afunc = function(params, data) #building log likelihood for gradient vector
{
  
  a <- params[1]
  b <- params[2]
  n = length(data)
  
  first =(n/a) #first term of gradient equation for a
  logdata= sum(log(data)) #loging all summed data in the dataset
  b1= (b-1)
      num_a = ((data^a)* log(data)) #numerator of last term
      dom_a = (1- (data^a)) #denominator of last term
  last_term_ga= sum(num_a/dom_a) #finalized fracttion for last term to be put into gradient equation
  
  grad_a = -(first + logdata + b1 * last_term_ga) #gradient term for a using all data (no bootstraps, etc. just loop)
 
return(grad_a)
   
}

#placing a and b fradients in the same function to later compare in optim() and possible matrix building
combined_kum_gradient= function(params, data){
  a <- params[1]
  b <- params[2]
  n = length(data)
##################if you choose to block or change everything in between  
 # grad_a
#  gradient_b
  
#  return(c(grad_a, gradient_b))
########################################    
  
  ga <- grad_afunc(params, data)
  gb <- grad_bfunc(params, data)

  # Return them together as a vector for the optimizer
  return(c(ga, gb))
  
}


# Negative Log-Likelihood (Target for Optimization)
kumar_loglik = function(params, data) {
  a <- params[1]
  b <- params[2]
  n <- length(data)
  
  # Based on your derivation in A2
  logl = n*log(a) + n*log(b) + (a-1)*sum(log(data)) +   (b-1)*sum(log(1 - data^a))
  
  return(-logl) # We return negative because optim() minimizes by default
}

test_params= c(1,1)


mle.result= optim(
  par = test_params,    #intial guess (starting value for vector intial guess) . This must be a vector intial guesses for a and b
  fn = kumar_loglik, # checks height of likelihood surface
  gr = combined_kum_gradient, # gradient uphill should be the combined gradient
  data = storage,
  method = "L-BFGS-B", #constraints the box
  hessian = TRUE,
  lower = c(1e-5, 1e-5), # keeps the parameters positive #would remove control if this was in the code
  control = list(trace = FALSE,
                 fnscale = 1, #minimized the negative log likelihood function --> fnscale = -1 maximizes the function
                 maxit = 500,
                 abstol = 1e-8)
)
  

# Extract MLEs a and b
mle_a <- mle.result$par[1]
mle_b <- mle.result$par[2]
cat("MLE for a:", mle_a, "\nMLE for b:", mle_b)
MLE for a: 0.9593218 
MLE for b: 1.999172
# Testing your combined function with a guess of a=1, b=1

combined_kum_gradient(params = test_params, data = storage)
[1]   3.23001 -24.56262

The MLE predicted \(\hat{a}\) is 0.9593218 and the MLE predicted \(\hat{b}\) is 1.9991723. The histogram of storage appears to have some right tail and unimodal distribution characteristics.


Problem B2:

Fit the power distribution to the above data using the derived of \(a\) obtained in Problem A4 to test the following hypothesis using likelihood ratio procedure at significance level \(\alpha = 0.05\):

\[ H_0: b = 1 \quad \text{ versus } \quad H_a: b \ne 1. \] $$

= -

$$ When we use log likelihood ratio tests we compared if the complex nested equation is better at explaining the model than the simple nested equation. Here we compare the power distribution (b=1) MLE to the full Kumaraswamy model.

#Likelihood ratio procedure on the data at alpha =0.05
#using power distribution of MLE where b =1 

storage
 [1] 0.12 0.14 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27
[16] 0.28 0.29 0.30 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.40 0.41 0.42
[31] 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.50 0.51 0.52 0.53 0.54 0.55 0.56 0.57
[46] 0.58 0.59 0.60 0.61 0.78
n=length(storage)

# - n/ (sum(data)*log(data))

mle_a_power= -n/ (sum(log(storage))) #MLE for a calculation

cat("MLE for a in the special case power distrubution:", mle_a_power)
MLE for a in the special case power distrubution: 0.9393197
#When we use loglikelihood ratio tests we compared if the complex nested equation is better at explaining the model than the simple nested equation. Here we compare the power distribution (b=1) MLE to the full kumaraswamy model

# The loglikelihood model for kumaraswamy a

loglike_kumar = -kumar_loglik(c(mle_a, mle_b), storage) # full unrestriced model 

loglike_power = -kumar_loglik(c(mle_a_power, 1), storage) #restricted model log likelihood power distribution


LRT_statistic = 2* (loglike_kumar - loglike_power) #likelihood ratio statistic for the log kumaraswamy and likelihood for power distrubution


p_val = 1- pchisq(LRT_statistic, df=1)

cat("The likelihood ratio test statistic is", LRT_statistic, "p=", p_val, ".")
The likelihood ratio test statistic is 16.00457 p= 6.318993e-05 .

State the statistical decision clearly. What is the practical implication of the testing result?

As the p value is less than \(\alpha=0.005\), (p=6.3189934^{-5}), we reject the null hypothesis ($H_o: b=1 $) that the less complex power distribution log likelihood model better suits the distribution. The Kumaraswamy distribution should be used to model the daily storage water data.


Problem B3:

Use the procedure and code from Problem B1 to estimate the MLEs of \(a\) and \(b\), and then complete the following analyses:

(1). Obtain the bootstrap sampling distributions of \(\hat{a}\) and \(\hat{b}\) and plot each distribution using Gaussian kernel density curves.

#Bootstrap MLE for a and b

B=9999
boot_a = numeric(B) #allows number of bootstraps for a
boot_b = numeric(B) #allows number of bootstraps for b
n=length(storage)

set.seed(123)

for(i in 1:B) #begin bootstrap to find mle a and b
{
  
boot_sample= sample(storage, size=n, replace= TRUE )  #resample with replacement
  
#Estimate MLEs for bootstrap sample 
  #using optim 

boot_mle= optim(
    par = c(mle_a * runif(1, 0.9, 1.1), mle_b * runif(1, 0.9, 1.1)), # Jitter starting values #par = c(mle_a, mle_b), # Start at the original MLEs for speed
    fn = kumar_loglik,  # checks height of likelihood surface
    gr = combined_kum_gradient,  # gradient uphill should be the combined gradient
    data = boot_sample,
    method = "L-BFGS-B", #contraints box
    lower = c(1e-5, 1e-5) # keeps the parameters positive #would remove control if this was in the code
  
)
boot_a[i] <- boot_mle$par[1] #output a MLE parameter
boot_b[i] <- boot_mle$par[2] #output b MLE parameter

}


#gaussian kernel building for a hat
plot(density(boot_a, kernel= "gaussian"), main = "Bootstrap Distrubution of a hat",
     xlab="a hat", col= "skyblue", lwd=2)
abline(v= mle_a, col= "red", lty=2)#reference for original MLE

#gaussian kernel density for b hat

plot(density(boot_b, kernel = "gaussian"), main="Bootstrap Distrubution of b hat",
     xlab= "b hat", col= "darkgreen", lwd=2)
abline(v = mle_b, col = "red", lty = 2)

The bootstrapped sampling distribution of a is 1.0214885. The bootstrapped sampling distribution of b is 1.9411152.

(2). Construct both the \(95\%\) bootstrap confidence interval and the Wald confidence interval for \(b\). Do these intervals agree with the results obtained in Problem B2? [Compute the standard error of \(\hat{b}\) using the observed Fisher information matrix, i.e., the inverse of the negative Hessian obtained from optim()]

Wald Equation \[ \hat{b} + z_{\alpha/2} * \sqrt([I_n(\hat{b}]_{2,2})) \]

## Bootstrapped Confidence Intervals

#boot_ci_a= quantile(boot_a, probs= c(0.025, 0.975))
#boot_ci_b = quantile(boot_b, probs= c(0.025, 0.975))

#cat("The bootstrapped confidence interval")

#Bootstrapped Normal Confidence Interval

alpha <- 0.05
z_critical <- qnorm(1 - alpha/2)
dis_crit_cal=boot_a + z_critical * (boot_a/sqrt(n))

# Calculate Bootstrap Standard Error (se_boot)
se_boot_a = sd(boot_a)
se_boot_b = sd(boot_b)

# Z critical value for 95%

z= qnorm(0.975)

#Confidence level for parameter a
ci_boot_a = c(LCI= mle_a - z*se_boot_a,  #lower confidence level
              #estimate= mle_a, #the value the CI is centered around
              UCL= mle_a + z*se_boot_a #upper confidence level
              )
cat("The bootstraped normal confidence interval for parameter a=", mle_a, "is, [", ci_boot_a, "].")
The bootstraped normal confidence interval for parameter a= 0.9593218 is, [ 0.8521865 1.066457 ].
ci_boot_b = c(LCI= mle_b - z*se_boot_b,  #lower confidence level
              #estimate= mle_b, #the value the CI is centered around
              UCL= mle_b + z*se_boot_b #upper confidence level
              )
cat("\n The bootstraped normal confidence interval for parameter b=", mle_b, "is, [", ci_boot_b, "].")

 The bootstraped normal confidence interval for parameter b= 1.999172 is, [ 1.776119 2.222225 ].
#Percentile CI Boootstraps
boot_percentile_a = as.numeric(quantile(boot_a, probs= c(0.025, 0.975)))
boot_percentile_b = as.numeric(quantile(boot_b, probs= c(0.025, 0.975)))

cat("\n The bootstrapped percentile 95% confidence interval for parameter a= is, [", boot_percentile_a, "].")

 The bootstrapped percentile 95% confidence interval for parameter a= is, [ 0.8681103 1.04955 ].
cat("\n The bootstraped percentile 95% confidence interval for parameter b is, [", boot_percentile_b, "].")

 The bootstraped percentile 95% confidence interval for parameter b is, [ 1.810586 2.188767 ].
###########Wald CI 
#Compute the Wald CI using observed Fisher information



fisher_info= solve(mle.result$hessian) #take the inverse of the mle.result matrix
#have values before this matrix in the equatinn as well as we describe some of the formula below
  #variance(Theta1)    #covariance(Theta1, Theta2)
  #cov(Theta1, Theta2) # variance(theta2)
#inside the hessian matrix for wald which is the inverse of the fisher matrix  * the matrix of hat\theta1 - inverse theta10 (on top of) hat\theta2 - theta20

#the inverse of
  #variance(hat\a)    #covariance(\hat\a, \hat\b) 
  #cov(\hat\a, \hat\b) # variance(\hat\a)

#we are only the b parameter

#calculate the standard error specific to wald b
se_wald_b = sqrt(fisher_info[2,2]) #standard error wald

z= qnorm(0.975)
wald_ci_b = c(LCI= mle_b- z*se_wald_b, UCL= mle_b + z*se_wald_b)

cat("\n The Wald Confidence Interval for b is [", wald_ci_b, "].")

 The Wald Confidence Interval for b is [ 1.44504 2.553304 ].

We are comparing the Wald Confidence interval to a bootstrap sampling confidence interval. To better capture the skewness of this Kumaraswamy distribution we compare the bootstrapped Percentile Confidence Interval to the Wald Confidence Interval. The Percentile 95%CI for parameter b is [1.8105856, 2.188767] (width = 0.378181) . The Wald Confidence interval is [1.4450403, 2.5533043] (width= 1.108264). The bootstrapped percentile CI has a far smaller interval than the Wald Confidence interval suggesting the Wald test is not the best test to use on the distribution as it assumes a normal sampling distribution, which is best suited here. The Wald 95%CI is underperforming the bootstrapped Normal 95%CI as well [1.7761192, 2.2222254]. Our desire is to have a small confidence interval as long as the distribution is well represented by the interval used.

In Problem B2, we rejected the null hypothesis that the simpler model suits the distribution, concluding the Kumaraswamy distribution better models the daily storage water data. Considering this more complex model, most likely has more complex distribution shape that is not well represented by a normal distribution even when overcoming for some robustness, the better suited bootstrapped percentile ci agrees with the complexity of the dataset.

(3). Based on the bootstrap sampling distributions from part (1) of this problem, assess whether the validity of the Wald confidence interval is supported.

While the bootstrapped confidence intervals do not include 0, we can assume our parameters a and b has significance. The bootstrap kernel figure for \(\hat{a}\) range about from 0.83-1.10 with a MLE value of 1.0214885. The bootstrap kernel figure for \(\hat{b}\) ranges from about 1.8 to 2.2 with an MLE value of 1.9411152. As the Wald confidence interval [1.4450403, 2.5533043] is between kernel’s ranges for the entire encompassing dataset therefore capturing an interval within a plausible range although it is way less valid than its bootstrapped percentile Confidence Interval.A percentile confidence interval is preferred for the storage distribution. The Wald CI assumption for normality and symmetry cannot well capture the true shape of the distribution. As the distribution appears to have some unimodal shape and slight tail, rather than a strong symmetrical shape centered around its MLE. The wider Wald confidence interval highlights its uncertiany to measure deviations from normal shape well.


Problem B4:

In the introduction to the working model for this exam, the Kumaraswamy distribution reduces to the uniform distribution on (0,1). In this problem, we perform a likelihood ratio test for the following hypothesis to assess whether the data come from the uniform distribution on (0,1):

\[ H_0: a = 1\quad \& \quad b = 1\quad \text{ versus } \quad H_a: a \ne 1 \quad \text{or} \quad b \ne 1 \quad \text{or}\quad (a \ne 1 \quad \& \quad b \ne 1). \]

Provide a practical interpretation of the above test result. [Hint: \(H_a\) basically says that there is no constraints for \(a\) and \(b\). Please review the lecture note for module 11 on the likelihood ratio test before coding.]


Here we compare the Kumaraswamy distribution to another special case uniform distribution model where the distribution ranges between 0 and 1.

\[ LRT_{uni(1,1)}= 2[\ell(\hat{a}, \hat{b})-\ell(1,1)] \]

n= length(storage)

#unrestricted original log likelihood from kumaraswamy distribution

logL_unrestricted = -kumar_loglik(c(mle_a, mle_b), storage) #presents joint probability of entire dataset give a and b parameters

#log likelihood for Uniform (a=1, b=1)
logL_restricted= -kumar_loglik(c(1,1), storage) #the parameters for 1 and 1 for both  a and b

#log ratio test statistic

LRT_stat_unicomparison = 2 * (logL_unrestricted - logL_restricted) 

pval_unicompLRT= 1- pchisq(LRT_stat_unicomparison, df=2)

cat("The log likelihood ratio considering the special case kumaswamy uniform distrubutio (a=1, b=1) is", LRT_stat_unicomparison, "(p=", pval_unicompLRT, ").")
The log likelihood ratio considering the special case kumaswamy uniform distrubutio (a=1, b=1) is 16.20465 (p= 0.0003028339 ).

When assessing the stronger model using the Likelihood Ratio Test, the more complex Kumaraswamy distribution does a better job at modelling the water storage distribution than the uniform model. If comparing whether to use the restricted uniform distribution or the unrestricted Kumaraswamy distribution, use the Kumaraswamy distribution (LRT= 16.2046521, p= 3.0283391^{-4}). Perhaps the slight right skewness of the model is not well represented by the uniform distribution suggesting daily water intake is not evenly distributed nor random.

It appears both the Kumaraswamy outperforms the uniform and power distribution models.

Note: Please download the template and insert your work into it to complete the exam.

LS0tDQp0aXRsZTogIlNUQSA1MDYgRmluYWwgRXhhbWluYXRpb24gU3ByaW5nICINCmF1dGhvcjogIiBFemFuYSBSaXZlcnMiDQpkYXRlOiAiIER1ZTogTWF5IDUgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vDQogICAgdG9jX2NvbGxhcHNlZDogeWVzDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogeWVzDQogICAgc21vb3RoX3Njcm9sbDogeWVzDQogICAgaGlnaGxpZ2h0OiBtb25vY2hyb21lDQogICAgdGhlbWU6IHNwYWNlbGFiDQogICAgc2VsZl9jb250YWluZWQ6IGZhbHNlDQogICAgbGliX2RpcjogbGlicw0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCiNUT0M6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICJUYWJsZSBvZiBDb250ZW50cyI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuMmVtOw0KICBkaXNwbGF5OiBibG9jazsNCiAgY29sb3I6IG5hdnk7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCg0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLw0KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLw0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTVweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCg0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGZpZy5yZXRpbmEgPSAxLCBkcGkgPSA3MCkNCg0KaWYgKCFyZXF1aXJlKCJrbml0ciIpKSB7DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpDQogICBsaWJyYXJ5KGtuaXRyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJwYW5kZXIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygicGFuZGVyIikNCiAgIGxpYnJhcnkocGFuZGVyKQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpDQogIGxpYnJhcnkoZ2dwbG90MikNCn0NCmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikNCiAgbGlicmFyeSh0aWR5dmVyc2UpDQp9DQoNCmlmICghcmVxdWlyZSgicGxvdGx5IikpIHsNCiAgaW5zdGFsbC5wYWNrYWdlcygicGxvdGx5IikNCiAgbGlicmFyeShwbG90bHkpDQp9DQojIyMjDQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgICAgICMgaW5jbHVkZSBjb2RlIGNodW5rIGluIHRoZSBvdXRwdXQgZmlsZQ0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICAjIHNvbWV0aW1lcywgeW91IGNvZGUgbWF5IHByb2R1Y2Ugd2FybmluZyBtZXNzYWdlcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZSB3YXJuaW5nIG1lc3NhZ2VzIGluDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhlIG91dHB1dCBmaWxlLiANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwgICAgIyB5b3UgY2FuIGFsc28gZGVjaWRlIHdoZXRoZXIgdG8gaW5jbHVkZSB0aGUgb3V0cHV0DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gdGhlIG91dHB1dCBmaWxlLg0KICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkENCiAgICAgICAgICAgICAgICAgICAgICApICANCmBgYA0KIA0KIFwNCiANCiMjICoqRmluYWwgRXhhbSBHdWlkZWxpbmVzKiogDQoNCiogKipDb3ZlcmFnZSoqOiBUaGUgbWFqb3IgY29uY2VwdHMgYW5kIGluZmVyZW5jZSBwcm9jZWR1cmVz4oCUc3VjaCBhcyBzYW1wbGluZyBkaXN0cmlidXRpb25zLCBjb25maWRlbmNlIGludGVydmFscywgYW5kIGh5cG90aGVzaXMgdGVzdGluZ+KAlGFyZSBjb3ZlcmVkIGFuZCBpbXBsZW1lbnRlZCB1c2luZyBib3RoIGNsYXNzaWNhbCBwYXJhbWV0cmljIGxpa2VsaWhvb2QtYmFzZWQgbWV0aG9kcyBhbmQgbW9kZXJuIG5vbi1wYXJhbWV0cmljIGFwcHJvYWNoZXMsIGluY2x1ZGluZyB0aGUgYm9vdHN0cmFwIGFuZCBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0aW9uLg0KDQoqICoqUGFydCBBKiogcmVxdWlyZXMgZGVyaXZhdGlvbiBvZiBzZWxlY3RlZCBsaWtlbGlob29kLWJhc2VkIGZ1bmN0aW9ucyBmb3IgcGVyZm9ybWluZyB2YXJpb3VzIHR5cGVzIG9mIGluZmVyZW5jZSwgd2l0aCBzdWZmaWNpZW50IGRldGFpbCB0byBlbmFibGUgdHJhbnNsYXRpb24gb2YgdGhlc2UgZGVyaXZhdGlvbnMgaW50byBjb2RlIGZvciBudW1lcmljYWwgYW5hbHlzaXMuDQoNCiogWW91ciBjb2RlIGZvciB0aGUgcHJvYmxlbXMgaW4gKipQYXJ0IEIqKiBtdXN0IGFsaWduIHdpdGggeW91ciBkZXJpdmF0aW9ucyBpbiAqKlBhcnQgQSoqIGFuZCBiZSB3ZWxsIGNvbW1lbnRlZCB3aGVyZSBuZWNlc3NhcnkuDQoNCiogSW4gKipQYXJ0IEIqKiwgYWxsIG51bWVyaWNhbCByZXN1bHRzIG11c3QgYmUgaW50ZXJwcmV0ZWQgZnJvbSBhIHByYWN0aWNhbCBwZXJzcGVjdGl2ZS4NCg0KDQpcDQoNCiMjICoqUG9saWNpZXMgb2YgVXNpbmcgQUkgVG9vbHMqKg0KDQoqICoqUG9saWN5IG9uIEFJIFRvb2wgVXNlKio6IFN0dWRlbnRzIG11c3QgYWRoZXJlIHRvIHRoZSBBSSB0b29sIHBvbGljeSBzcGVjaWZpZWQgaW4gdGhlIGNvdXJzZSBzeWxsYWJ1cy4gVGhlIGRpcmVjdCBjb3B5aW5nIG9mIEFJLWdlbmVyYXRlZCBjb250ZW50IGlzIHN0cmljdGx5IHByb2hpYml0ZWQuIEFsbCBzdWJtaXR0ZWQgd29yayBtdXN0IHJlZmxlY3QgeW91ciBvd24gdW5kZXJzdGFuZGluZzsgd2hlcmUgZXh0ZXJuYWwgdG9vbHMgYXJlIGNvbnN1bHRlZCwgY29udGVudCBtdXN0IGJlIHRob3JvdWdobHkgcmVwaHJhc2VkIGFuZCBzeW50aGVzaXplZCBpbiB5b3VyIG93biB3b3Jkcy4NCg0KKiAqKkNvZGUgSW5jbHVzaW9uIFJlcXVpcmVtZW50Kio6IEFueSBjb2RlIGluY2x1ZGVkIGluIHlvdXIgZXNzYXkgbXVzdCBiZSBwcm9wZXJseSBjb21tZW50ZWQgdG8gZXhwbGFpbiB0aGUgcHVycG9zZSBhbmQvb3IgZXhwZWN0ZWQgb3V0cHV0IG9mIGtleSBjb2RlIGxpbmVzLiBTdWJtaXR0aW5nIEFJLWdlbmVyYXRlZCBjb2RlIHdpdGhvdXQgbWVhbmluZ2Z1bCwgc3R1ZGVudC1hZGRlZCBjb21tZW50cyB3aWxsIG5vdCBiZSBhY2NlcHRlZC4NCg0KXA0KDQojIyAqKldvcmtpbmcgTW9kZWwgZm9yIHRoZSBGaW5hbCBFeGFtKioNCg0KPGZvbnQgY29sb3IgPSAib3JhbmdlIj4qKkNhdXRpb24qKjogKlBsZWFzZSBmb2xsb3cgdGhlIHN1Z2dlc3RlZCBleHByZXNzaW9ucyBhbmQgZ3VpZGVkIHN0ZXBzIHRvIGNvbXBsZXRlIHRoZSBleGFtLiBPdGhlciBhcHByb2FjaGVzIHN1Y2ggYXMgdHJhbnNmb3JtYXRpb24gZm9yIHRyaXZpYWxpemUgdGhlIHByb2JsZW1zIHRoYXQgd2lsbCBub3QgbWVldCB0aGUgZXhhbSBvYmplY3RpdmVzLio8L2ZvbnQ+DQoNCg0KVGhlICoqS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uKiogaXMgYSB0d28tcGFyYW1ldGVyIGNvbnRpbnVvdXMgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uIGRlZmluZWQgb24gdGhlIGludGVydmFsICgwLCAxKS4gSXQgaXMgb2Z0ZW4gdXNlZCBhcyBhbiBhbHRlcm5hdGl2ZSB0byB0aGUgQmV0YSBkaXN0cmlidXRpb24gZHVlIHRvIGl0cyBzaW1wbGUgY2xvc2VkLWZvcm0gZXhwcmVzc2lvbnMgZm9yIHRoZSBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiAoQ0RGKSBhbmQgcXVhbnRpbGUgZnVuY3Rpb24uIEl0IGlzIGNvbW1vbmx5IHVzZWQgaW4gDQoNCiogKipIeWRyb2xvZ3kqKjogTW9kZWxpbmcgcmFpbmZhbGwsIHN0cmVhbWZsb3csIG9yIG90aGVyIGJvdW5kZWQgbmF0dXJhbCBwaGVub21lbmENCg0KKiAqKkVjb25vbWljcyoqOiBJbmNvbWUgc2hhcmVzLCBwcm9wb3J0aW9ucywgb3IgYm91bmRlZCBpbmRpY2VzDQoNCiogKipNb250ZSBDYXJsbyBzaW11bGF0aW9uKio6IEVmZmljaWVudCByYW5kb20gdmFyaWF0ZSBnZW5lcmF0aW9uICh2aWEgaW52ZXJzZSB0cmFuc2Zvcm0pDQoNCiogKipNYWNoaW5lIGxlYXJuaW5nKio6IE91dHB1dCBsYXllciBmb3IgYm91bmRlZCB0YXJnZXRzLCBwcmlvciBkaXN0cmlidXRpb25zIGluIEJheWVzaWFuIG1vZGVscw0KDQoqICoqUmVsaWFiaWxpdHkgZW5naW5lZXJpbmcqKjogTW9kZWxpbmcgZmFpbHVyZSByYXRlcyBvZiBzeXN0ZW1zIHdpdGggYm91bmRlZCBsaWZldGltZXMNCg0KXA0KDQpMZXQgJFgkIGJlIHRoZSBLdW1hcmFzd2FteSByYW5kb20gdmFyaWFibGUgd2l0aCBDdW11bGF0aXZlIERpc3RyaWJ1dGlvbiBGdW5jdGlvbiAoQ0RGKSAgDQoNCiQkDQpGKHg7IGEsIGIpID0gMSAtICgxIC0geF5hKV5iDQokJA0KDQp3aGVyZSAkYSA+IDAkIGFuZCAkYiA+IDAkIHVua25vd24gcGFyYW1ldGVycyBhbmQgJDAgPCB4IDwgMSQuIA0KDQpUaGUgZm9sbG93aW5nIGFyZSB0d28gc3BlY2lhbCBjYXNlIG9mIHRoZSBLdW1hcmFzd2FteSBkaXN0cmlidXRpb246DQoNCjEuICoqVW5pZm9ybSBEaXN0cmlidXRpb24qKjogV2hlbiAkYSA9IDEkIGFuZCAkYiA9IDEkLCB0aGUgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIGJlY29tZXMgYSB1bmlmb3JtIGRpc3RyaWJ1dGlvbiBvdmVyICRbMCwgMV0kIHdpdGggQ0RGICRGKHgpID0geCQuDQoNCg0KMi4gKipQb3dlciBEaXN0cmlidXRpb24qKjogd2hlbiAkYiA9IDEkIGFuZCAkYSA+IDAkLCB0aGUgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIGJlY29tZXMgYSBwb3dlciBkaXN0cmlidXRpb24gb3ZlciAkWzAsIDFdJCB3aXRoIENERiAkRih4KSA9IHheYSQuIA0KDQpUaGlzIGZpbmFsIGV4YW0gZm9jdXNlcyBvbiBpbmZlcmVuY2VzIG9mIEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiBhbmQgcmVsYXRlZCBkYXRhIGFuYWx5c2lzLg0KDQoNCiMjIFBhcnQgQTogTWV0aG9kb2xvZ2ljYWwgRGVyaXZhdGlvbnMNCg0KXA0KDQojIyMgKipQcm9ibGVtIEExKio6IA0KU2hvdyB0aGF0IHRoZSBkZW5zaXR5IGZ1bmN0aW9uIG9mIHRoZSBLdW1hcmFzd2FteSBkaXN0cmlidXRpb24gaXMNCg0KJCQNCmYoeDsgYSwgYikgPSBhYiBcLCB4XnthLTF9ICgxIC0geF5hKV57Yi0xfS4NCiQkDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5hbGlnbj0iY2VudGVyIiwgZmlnLmNhcD0iIFByb2JsZW0gQTEifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vaS5wb3N0aW1nLmNjLzR4cjl5OWJjL1Byb2JsZW0tQTEuanBnIikNCg0KYGBgDQoNCg0KXA0KDQojIyMgKipQcm9ibGVtIEEyKio6IA0KTGV0ICRce3hfMSwgeF8yLCBcY2RvdHMsIHhfbiBcfSQgYmUgYW4gaS5pLmQuIHJhbmRvbSBzYW1wbGUgdGFrZW4gZnJvbSBhIHBvcHVsYXRpb24gdGhhdCBmb2xsb3dzIHRoZSBhYm92ZSAyLXBhcmFtZXRlciBLdW1hcmFzd2FteSBkaXN0cmlidXRpb24uIFdyaXRlIG91dCB0aGUgbG9nbGlrZWxpaG9vZCBmdW5jdGlvbiBvZiAkYSQgYW5kICRiJCwgZGVub3RlZCBieSAkXGVsbChhLGIpJCwgYmFzZWQgb24gdGhlIGFib3ZlIHJhbmRvbSBzYW1wbGUgYW5kICoqZGVyaXZlKiogdGhlIGdyYWRpZW50IHZlY3RvciAkW1xlbGxfYV5ccHJpbWUoYSxiKSwgXGVsbF9iXlxwcmltZShhLGIpXSQsIHRoZSBmaXJzdCBvcmRlciBwYXJ0aWFsIGRlcml2YXRpdmUgb2YgdGhlIGxvZy1saWtlbGlob29kIHdpdGggcmVzcGVjdCB0byBwYXJhbWV0ZXJzICRhJCBhbmQgJGIkLg0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5hbGlnbj0iY2VudGVyIiwgZmlnLmNhcD0iIFByb2JsZW0gQTIifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vaS5wb3N0aW1nLmNjL1BmNFl5TmhnL1Byb2JsZW0tQTItcHQxLmpwZyIpDQoNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI1MCUiLCBmaWcuYWxpZ249ImNlbnRlciIsIGZpZy5jYXA9IiBQcm9ibGVtIEEyIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL2kucG9zdGltZy5jYy9id0ducVRueC9Qcm9ibGVtLUEyLXB0Mi5qcGciKQ0KDQpgYGANCg0KDQpcDQoNCiMjIyAqKlByb2JsZW0gQTMqKjogDQpCYXNlZCBvbiB0aGUgZ3JhZGllbnRzIGZ1bmN0aW9ucyBvYnRhaW5lZCBpbiB0aGUgYWJvdmUgcHJvYmxlbSBBMiwgKipkZXJpdmUqKiB0aGUgb2JzZXJ2ZWQgRmlzaGVyIEluZm9ybWF0aW9uIG1hdHJpeCAoaS5lLCB0aGUgbmVnYXRpdmUgSGVzc2lhbiBNYXRyaXgpLg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI1MCUiLCBmaWcuYWxpZ249ImNlbnRlciIsIGZpZy5jYXA9IiBQcm9ibGVtIEEzIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL2kucG9zdGltZy5jYy9XMURac25aSC9Qcm9ibGVtLUEzLXB0MS5qcGciKQ0KDQpgYGANCg0KDQpgYGB7ciwgZWNobz1GQUxTRSwgb3V0LndpZHRoPSI1MCUiLCBmaWcuYWxpZ249ImNlbnRlciIsIGZpZy5jYXA9IiBQcm9ibGVtIEEzIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL2kucG9zdGltZy5jYy8yU3FXQ3dXSi9Qcm9ibGVtLUEzLXB0Mi5qcGciKQ0KDQpgYGANCg0KXA0KDQojIyMgKipQcm9ibGVtIEE0Kio6IA0KDQpDb25zaWRlciBwb3dlciBkaXN0cmlidXRpb24gJEYoeCkgPSB4XmEsIChhID4wIFxxdWFkIFx0ZXh0eyBhbmQgfVxxdWFkIHggXGluICgwLDEpKSQsIGEgc3BlY2lhbCBjYXNlIG9mIHRoZSBLdW1hcmFzd2FteSBkaXN0cmlidXRpb24gd2l0aCAkYiA9IDEkLCBhbmQgYSByYW5kb20gc2FtcGxlIGZyb20gdGhpcyBkaXN0cmlidXRpb24gJFx7IHhfMSwgeF8yLCBcY2RvdHMsIHhfblx9JC4gKipEZXJpdmUqKiB0aGUgTUxFIGFuZCBNTUUgb2YgJGEkIHJlc3BlY3RpdmVseS4gWypIaW50OiBUbyBmaW5kIHRoZSBNTUUsIHlvdSBuZWVkIHRvIGNvbXB1dGUgdGhlIG1vbWVudCBvZiB0aGUgcG93ZXIgZGlzdHJpYnV0aW9uOyB0aGF0IGlzLCAkRVtYXmtdID0gXGludF8wXjEgeF5rIEYnKHgpIGR4JC4gTm90ZSB0aGF0IGJvdGggdGhlIE1MRSBhbmQgdGhlIE1NRSBoYXZlIGNsb3NlZC1mb3JtIGV4cHJlc3Npb25zLipdDQoNCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIiwgZmlnLmFsaWduPSJjZW50ZXIiLCBmaWcuY2FwPSIgUHJvYmxlbSBBNCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9pLnBvc3RpbWcuY2MvalNXZlJYZjgvUHJvYmxlbS1BNC1wdDEuanBnIikNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCBvdXQud2lkdGg9IjUwJSIsIGZpZy5hbGlnbj0iY2VudGVyIiwgZmlnLmNhcD0iIFByb2JsZW0gQTQifQ0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoImh0dHBzOi8vaS5wb3N0aW1nLmNjL1lDSlcwV2ZCL1Byb2JsZW0tQTQtcHQyLmpwZyIpDQoNCmBgYA0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIiwgZmlnLmFsaWduPSJjZW50ZXIiLCBmaWcuY2FwPSIgUHJvYmxlbSBBNCJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9pLnBvc3RpbWcuY2MvM3hQdk52Q3cvUHJvYmxlbS1BNC1wdDMuanBnIikNCg0KYGBgDQoNCg0KXA0KDQojIyMgKipQcm9ibGVtIEE1Kio6DQoNClVzaW5nIHRoZSBzYW1lIHNldHRpbmcgYXMgaW4gKipQcm9ibGVtIEE0KiosIGZpbmQgdGhlIGFzeW1wdG90aWMgKFdhbGQpIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yICRhJC4gWypIaW50OiBDb21wdXRlIHRoZSBGaXNoZXIgaW5mb3JtYXRpb24gZm9yICRhJCwgdGhlbiB0YWtlIGl0cyByZWNpcHJvY2FsIHRvIG9idGFpbiB0aGUgdmFyaWFuY2UqLl0NCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIiwgZmlnLmFsaWduPSJjZW50ZXIiLCBmaWcuY2FwPSIgUHJvYmxlbSBBNSJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9pLnBvc3RpbWcuY2MvRkgyTHpMZ1IvUHJvYmxlbS1BNS5qcGciKQ0KDQpgYGANCg0KXA0KDQojIyMgKipQcm9ibGVtIEE2Kio6DQoNClVzaW5nIHRoZSBzYW1lIHNldHRpbmcgYXMgaW4gKipQcm9ibGVtIEE0KiosIHBlcmZvcm0gYSBsaWtlbGlob29kIHJhdGlvIHRlc3QgZm9yIHRoZSBoeXBvdGhlc2lzICRIXzAgOmE9MSQgKGkuZS4sIHRoZSBwb3dlciBkaXN0cmlidXRpb24gcmVkdWNlcyB0byBhIHVuaWZvcm0gZGlzdHJpYnV0aW9uKS4gWypIaW50OiBFdmFsdWF0ZSB0aGUgbG9nLWxpa2VsaWhvb2QgZnVuY3Rpb24gYXQgdGhlIG1heGltdW0gbGlrZWxpaG9vZCBlc3RpbWF0ZSAkXGhhdHthfSQgYW5kIGF0ICRhPTEkLCB0aGVuIHVzZSB0aGVzZSB2YWx1ZXMgdG8gY29uc3RydWN0IHRoZSBMUlQgdGVzdCBzdGF0aXN0aWMuKl0NCg0KYGBge3IsIGVjaG89RkFMU0UsIG91dC53aWR0aD0iNTAlIiwgZmlnLmFsaWduPSJjZW50ZXIiLCBmaWcuY2FwPSIgUHJvYmxlbSBBNiJ9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9pLnBvc3RpbWcuY2MvalNHNzI3UUwvUHJvYmxlbS1BNi5qcGciKQ0KDQpgYGANCg0KDQoNClwNCg0KIyMgUGFydCBCOiBOdW1lcmljYWwgQW5hbHlzaXMNCg0KKipBbGwgY29kZSBtdXN0IGJlIHdlbGwgY29tbWVudGVkIGFuZCBhZGhlcmUgdG8gYmVzdCBjb2RpbmcgcHJhY3RpY2VzKioNCg0KKipXb3JraW5nIERhdGFzZXQqKjogQSBzbWFsbCByZXNlcnZvaXIgc3VwcGxpZXMgd2F0ZXIgdG8gYSB0b3duLiBEdXJpbmcgdGhlIGRyeSBzZWFzb24gKDUwIGRheXMpLCBlbmdpbmVlcnMgcmVjb3JkIHRoZSBmcmFjdGlvbiBvZiB1c2FibGUgc3RvcmFnZSBmaWxsZWQgZWFjaCBtb3JuaW5nLiBWYWx1ZXMgbmVhciAwIG1lYW4gdGhlIHJlc2Vydm9pciBpcyBuZWFybHkgZW1wdHk7IHZhbHVlcyBuZWFyIDEgbWVhbiBpdCdzIGZ1bGwuIFRoZSBkaXN0cmlidXRpb24gdGVuZHMgdG8gYmUgcmlnaHTigJFza2V3ZWQgKG1vc3RseSBsb3cgbGV2ZWxzIGR1ZSB0byBkcm91Z2h0KSBidXQgd2l0aCBvY2Nhc2lvbmFsIHJlcGxlbmlzaG1lbnQuDQoNClRoZSBmb2xsb3dpbmcgNTAgZGF0YSBwb2ludHMgKG9yZGVyZWQgZm9yIGNsYXJpdHkpIHJlcHJlc2VudCB0aGUgZGFpbHkgcHJvcG9ydGlvbiBvZiB1c2FibGUgc3RvcmFnZToNCg0KYGBgDQowLjEyLCAwLjE0LCAwLjE1LCAwLjE2LCAwLjE3LCAwLjE4LCAwLjE5LCAwLjIwLCAwLjIxLCAwLjIyLA0KMC4yMywgMC4yNCwgMC4yNSwgMC4yNiwgMC4yNywgMC4yOCwgMC4yOSwgMC4zMCwgMC4zMSwgMC4zMiwNCjAuMzMsIDAuMzQsIDAuMzUsIDAuMzYsIDAuMzcsIDAuMzgsIDAuMzksIDAuNDAsIDAuNDEsIDAuNDIsDQowLjQzLCAwLjQ0LCAwLjQ1LCAwLjQ2LCAwLjQ3LCAwLjQ4LCAwLjQ5LCAwLjUwLCAwLjUxLCAwLjUyLA0KMC41MywgMC41NCwgMC41NSwgMC41NiwgMC41NywgMC41OCwgMC41OSwgMC42MCwgMC42MSwgMC43OA0KYGBgDQoNClwNCg0KIyMjICoqUHJvYmxlbSBCMSoqOg0KDQpGaXQgdGhlIEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiB0byB0aGUgYWJvdmUgZGF0YS4gVXNlIHRoZSBkZXJpdmF0aW9ucyBpbiAqKlByb2JsZW0gQTIqKiB0byBmaW5kIHRoZSBNTEUgb2YgJGEkIGFuZCAkYiQuICoqUGxlYXNlIGNvcHkgdGhlIGtleSBmb3JtdWxhcyBiZWZvcmUgY29kaW5nLioqDQoNCkZvcm11bGFzOg0KDQpHcmFkaWVudCBWZWN0b3IgZm9yIEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiBsb2cgbGlrZWxpaG9vZHMuDQoNCkdyYWRpZW50IFZlY3RvciAkXGVsbCdfYihhLGIpJA0KDQokJA0KXGVsbCdfYihhLGIpID0gXGZyYWN7bn17Yn0gKyBcc3VtXm5fe2k9MX0gbG4oMS1YXmFfaSkNCiQkDQokJA0KXGVsbCdfYShhLGIpID0gXGZyYWN7bn17YX0gK1xzdW1ebl97aT0xfSBsbihYX2kpICsoYi0xKVxzdW1ebl97aT0xfVxmcmFje1heYV9pIGxuWF9pfXsxLVheYV9pfQ0KJCQNCg0KYGBge3J9DQoNCnN0b3JhZ2U9IHNvcnQoYygwLjEyLCAwLjE0LCAwLjE1LCAwLjE2LCAwLjE3LCAwLjE4LCAwLjE5LCAwLjIwLCAwLjIxLCAwLjIyLA0KMC4yMywgMC4yNCwgMC4yNSwgMC4yNiwgMC4yNywgMC4yOCwgMC4yOSwgMC4zMCwgMC4zMSwgMC4zMiwNCjAuMzMsIDAuMzQsIDAuMzUsIDAuMzYsIDAuMzcsIDAuMzgsIDAuMzksIDAuNDAsIDAuNDEsIDAuNDIsDQowLjQzLCAwLjQ0LCAwLjQ1LCAwLjQ2LCAwLjQ3LCAwLjQ4LCAwLjQ5LCAwLjUwLCAwLjUxLCAwLjUyLA0KMC41MywgMC41NCwgMC41NSwgMC41NiwgMC41NywgMC41OCwgMC41OSwgMC42MCwgMC42MSwgMC43OCkpDQoNCmhpc3Qoc3RvcmFnZSkgI2hpc3RvZ3JhbSBvZiBkYXRhc2V0DQoNCiNGaW5kIE1MRSBvZiBhIGFuZCBiDQoNCiNHcmFkaWVudCBmb3IgbG9nX2IoYSxiKQ0KDQoNCiNuPSBsZW5ndGgoc3RvcmFnZSkNCg0KI2Z1bmN0aW9uIHRvIGZpbmQgdmFsdWVzIG9mIGEgYW5kIGIgYmFzZWQgb24gdGhlIGRhdGFzZXQgYWxvbmUNCg0KDQojZmluZGluZyB0aGUgZ3JhZGllbnQgb2YgYg0KZ3JhZF9iZnVuYyA9ZnVuY3Rpb24ocGFyYW1zLCBkYXRhKSB7DQogIGEgPC0gcGFyYW1zWzFdDQogIGIgPC0gcGFyYW1zWzJdDQogIA0KICBuIDwtIGxlbmd0aChkYXRhKQ0KICANCiNuL2IgKyBzdW0obG9nKDEteF5hKSkNCiAgc3VtX3Rlcm09ICBzdW0obG9nKDEtIGRhdGFeYSkpICNuL2IgKyBzdW0oZGF0YSkNCiAgZ3JhZGllbnRfYiA9IC0oKG4vYikgKyBzdW1fdGVybSkNCiAgDQogIHJldHVybihncmFkaWVudF9iKQ0KfQ0KDQoNCmdyYWRfYWZ1bmMgPSBmdW5jdGlvbihwYXJhbXMsIGRhdGEpICNidWlsZGluZyBsb2cgbGlrZWxpaG9vZCBmb3IgZ3JhZGllbnQgdmVjdG9yDQp7DQogIA0KICBhIDwtIHBhcmFtc1sxXQ0KICBiIDwtIHBhcmFtc1syXQ0KICBuID0gbGVuZ3RoKGRhdGEpDQogIA0KICBmaXJzdCA9KG4vYSkgI2ZpcnN0IHRlcm0gb2YgZ3JhZGllbnQgZXF1YXRpb24gZm9yIGENCiAgbG9nZGF0YT0gc3VtKGxvZyhkYXRhKSkgI2xvZ2luZyBhbGwgc3VtbWVkIGRhdGEgaW4gdGhlIGRhdGFzZXQNCiAgYjE9IChiLTEpDQogICAgICBudW1fYSA9ICgoZGF0YV5hKSogbG9nKGRhdGEpKSAjbnVtZXJhdG9yIG9mIGxhc3QgdGVybQ0KICAgICAgZG9tX2EgPSAoMS0gKGRhdGFeYSkpICNkZW5vbWluYXRvciBvZiBsYXN0IHRlcm0NCiAgbGFzdF90ZXJtX2dhPSBzdW0obnVtX2EvZG9tX2EpICNmaW5hbGl6ZWQgZnJhY3R0aW9uIGZvciBsYXN0IHRlcm0gdG8gYmUgcHV0IGludG8gZ3JhZGllbnQgZXF1YXRpb24NCiAgDQogIGdyYWRfYSA9IC0oZmlyc3QgKyBsb2dkYXRhICsgYjEgKiBsYXN0X3Rlcm1fZ2EpICNncmFkaWVudCB0ZXJtIGZvciBhIHVzaW5nIGFsbCBkYXRhIChubyBib290c3RyYXBzLCBldGMuIGp1c3QgbG9vcCkNCiANCnJldHVybihncmFkX2EpDQogICANCn0NCg0KI3BsYWNpbmcgYSBhbmQgYiBmcmFkaWVudHMgaW4gdGhlIHNhbWUgZnVuY3Rpb24gdG8gbGF0ZXIgY29tcGFyZSBpbiBvcHRpbSgpIGFuZCBwb3NzaWJsZSBtYXRyaXggYnVpbGRpbmcNCmNvbWJpbmVkX2t1bV9ncmFkaWVudD0gZnVuY3Rpb24ocGFyYW1zLCBkYXRhKXsNCiAgYSA8LSBwYXJhbXNbMV0NCiAgYiA8LSBwYXJhbXNbMl0NCiAgbiA9IGxlbmd0aChkYXRhKQ0KIyMjIyMjIyMjIyMjIyMjIyMjaWYgeW91IGNob29zZSB0byBibG9jayBvciBjaGFuZ2UgZXZlcnl0aGluZyBpbiBiZXR3ZWVuICANCiAjIGdyYWRfYQ0KIyAgZ3JhZGllbnRfYg0KICANCiMgIHJldHVybihjKGdyYWRfYSwgZ3JhZGllbnRfYikpDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjICAgIA0KICANCiAgZ2EgPC0gZ3JhZF9hZnVuYyhwYXJhbXMsIGRhdGEpDQogIGdiIDwtIGdyYWRfYmZ1bmMocGFyYW1zLCBkYXRhKQ0KDQogICMgUmV0dXJuIHRoZW0gdG9nZXRoZXIgYXMgYSB2ZWN0b3IgZm9yIHRoZSBvcHRpbWl6ZXINCiAgcmV0dXJuKGMoZ2EsIGdiKSkNCiAgDQp9DQoNCg0KIyBOZWdhdGl2ZSBMb2ctTGlrZWxpaG9vZCAoVGFyZ2V0IGZvciBPcHRpbWl6YXRpb24pDQprdW1hcl9sb2dsaWsgPSBmdW5jdGlvbihwYXJhbXMsIGRhdGEpIHsNCiAgYSA8LSBwYXJhbXNbMV0NCiAgYiA8LSBwYXJhbXNbMl0NCiAgbiA8LSBsZW5ndGgoZGF0YSkNCiAgDQogICMgQmFzZWQgb24geW91ciBkZXJpdmF0aW9uIGluIEEyDQogIGxvZ2wgPSBuKmxvZyhhKSArIG4qbG9nKGIpICsgKGEtMSkqc3VtKGxvZyhkYXRhKSkgKyAgIChiLTEpKnN1bShsb2coMSAtIGRhdGFeYSkpDQogIA0KICByZXR1cm4oLWxvZ2wpICMgV2UgcmV0dXJuIG5lZ2F0aXZlIGJlY2F1c2Ugb3B0aW0oKSBtaW5pbWl6ZXMgYnkgZGVmYXVsdA0KfQ0KDQp0ZXN0X3BhcmFtcz0gYygxLDEpDQoNCg0KbWxlLnJlc3VsdD0gb3B0aW0oDQogIHBhciA9IHRlc3RfcGFyYW1zLCAgICAjaW50aWFsIGd1ZXNzIChzdGFydGluZyB2YWx1ZSBmb3IgdmVjdG9yIGludGlhbCBndWVzcykgLiBUaGlzIG11c3QgYmUgYSB2ZWN0b3IgaW50aWFsIGd1ZXNzZXMgZm9yIGEgYW5kIGINCiAgZm4gPSBrdW1hcl9sb2dsaWssICMgY2hlY2tzIGhlaWdodCBvZiBsaWtlbGlob29kIHN1cmZhY2UNCiAgZ3IgPSBjb21iaW5lZF9rdW1fZ3JhZGllbnQsICMgZ3JhZGllbnQgdXBoaWxsIHNob3VsZCBiZSB0aGUgY29tYmluZWQgZ3JhZGllbnQNCiAgZGF0YSA9IHN0b3JhZ2UsDQogIG1ldGhvZCA9ICJMLUJGR1MtQiIsICNjb25zdHJhaW50cyB0aGUgYm94DQogIGhlc3NpYW4gPSBUUlVFLA0KICBsb3dlciA9IGMoMWUtNSwgMWUtNSksICMga2VlcHMgdGhlIHBhcmFtZXRlcnMgcG9zaXRpdmUgI3dvdWxkIHJlbW92ZSBjb250cm9sIGlmIHRoaXMgd2FzIGluIHRoZSBjb2RlDQogIGNvbnRyb2wgPSBsaXN0KHRyYWNlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgIGZuc2NhbGUgPSAxLCAjbWluaW1pemVkIHRoZSBuZWdhdGl2ZSBsb2cgbGlrZWxpaG9vZCBmdW5jdGlvbiAtLT4gZm5zY2FsZSA9IC0xIG1heGltaXplcyB0aGUgZnVuY3Rpb24NCiAgICAgICAgICAgICAgICAgbWF4aXQgPSA1MDAsDQogICAgICAgICAgICAgICAgIGFic3RvbCA9IDFlLTgpDQopDQogIA0KDQojIEV4dHJhY3QgTUxFcyBhIGFuZCBiDQptbGVfYSA8LSBtbGUucmVzdWx0JHBhclsxXQ0KbWxlX2IgPC0gbWxlLnJlc3VsdCRwYXJbMl0NCmNhdCgiTUxFIGZvciBhOiIsIG1sZV9hLCAiXG5NTEUgZm9yIGI6IiwgbWxlX2IpDQoNCg0KIyBUZXN0aW5nIHlvdXIgY29tYmluZWQgZnVuY3Rpb24gd2l0aCBhIGd1ZXNzIG9mIGE9MSwgYj0xDQoNCmNvbWJpbmVkX2t1bV9ncmFkaWVudChwYXJhbXMgPSB0ZXN0X3BhcmFtcywgZGF0YSA9IHN0b3JhZ2UpDQpgYGANClRoZSBNTEUgcHJlZGljdGVkICRcaGF0e2F9JCBpcyBgciBtbGVfYWAgYW5kIHRoZSBNTEUgcHJlZGljdGVkICRcaGF0e2J9JCBpcyBgciBtbGVfYmAuDQpUaGUgaGlzdG9ncmFtIG9mIHN0b3JhZ2UgYXBwZWFycyB0byBoYXZlIHNvbWUgcmlnaHQgdGFpbCBhbmQgdW5pbW9kYWwgZGlzdHJpYnV0aW9uIGNoYXJhY3RlcmlzdGljcy4NCg0KXA0KDQojIyMgKipQcm9ibGVtIEIyKio6DQoNCkZpdCB0aGUgKipwb3dlciBkaXN0cmlidXRpb24qKiB0byB0aGUgYWJvdmUgZGF0YSB1c2luZyB0aGUgZGVyaXZlZCAgb2YgJGEkIG9idGFpbmVkIGluICoqUHJvYmxlbSBBNCoqIHRvIHRlc3QgdGhlIGZvbGxvd2luZyBoeXBvdGhlc2lzIHVzaW5nIGxpa2VsaWhvb2QgcmF0aW8gcHJvY2VkdXJlIGF0IHNpZ25pZmljYW5jZSBsZXZlbCAkXGFscGhhID0gMC4wNSQ6DQoNCiQkDQpIXzA6IGIgPSAxIFxxdWFkIFx0ZXh0eyB2ZXJzdXMgfSBccXVhZCBIX2E6IGIgXG5lIDEuDQokJA0KJCQNCg0KXGhhdHthX3tNTEV9fSA9IC1cZnJhY3tufXtcc3VtXm5fe2k9MX1sbnhfaX0NCg0KJCQNCldoZW4gd2UgdXNlIGxvZyBsaWtlbGlob29kIHJhdGlvIHRlc3RzIHdlIGNvbXBhcmVkIGlmIHRoZSBjb21wbGV4IG5lc3RlZCBlcXVhdGlvbiBpcyBiZXR0ZXIgYXQgZXhwbGFpbmluZyB0aGUgbW9kZWwgdGhhbiB0aGUgc2ltcGxlIG5lc3RlZCBlcXVhdGlvbi4gSGVyZSB3ZSBjb21wYXJlIHRoZSBwb3dlciBkaXN0cmlidXRpb24gKGI9MSkgTUxFIHRvIHRoZSBmdWxsIEt1bWFyYXN3YW15IG1vZGVsLg0KDQpgYGB7cn0NCiNMaWtlbGlob29kIHJhdGlvIHByb2NlZHVyZSBvbiB0aGUgZGF0YSBhdCBhbHBoYSA9MC4wNQ0KI3VzaW5nIHBvd2VyIGRpc3RyaWJ1dGlvbiBvZiBNTEUgd2hlcmUgYiA9MSANCg0Kc3RvcmFnZQ0KDQpuPWxlbmd0aChzdG9yYWdlKQ0KDQojIC0gbi8gKHN1bShkYXRhKSpsb2coZGF0YSkpDQoNCm1sZV9hX3Bvd2VyPSAtbi8gKHN1bShsb2coc3RvcmFnZSkpKSAjTUxFIGZvciBhIGNhbGN1bGF0aW9uDQoNCmNhdCgiTUxFIGZvciBhIGluIHRoZSBzcGVjaWFsIGNhc2UgcG93ZXIgZGlzdHJ1YnV0aW9uOiIsIG1sZV9hX3Bvd2VyKQ0KDQojV2hlbiB3ZSB1c2UgbG9nbGlrZWxpaG9vZCByYXRpbyB0ZXN0cyB3ZSBjb21wYXJlZCBpZiB0aGUgY29tcGxleCBuZXN0ZWQgZXF1YXRpb24gaXMgYmV0dGVyIGF0IGV4cGxhaW5pbmcgdGhlIG1vZGVsIHRoYW4gdGhlIHNpbXBsZSBuZXN0ZWQgZXF1YXRpb24uIEhlcmUgd2UgY29tcGFyZSB0aGUgcG93ZXIgZGlzdHJpYnV0aW9uIChiPTEpIE1MRSB0byB0aGUgZnVsbCBrdW1hcmFzd2FteSBtb2RlbA0KDQojIFRoZSBsb2dsaWtlbGlob29kIG1vZGVsIGZvciBrdW1hcmFzd2FteSBhDQoNCmxvZ2xpa2Vfa3VtYXIgPSAta3VtYXJfbG9nbGlrKGMobWxlX2EsIG1sZV9iKSwgc3RvcmFnZSkgIyBmdWxsIHVucmVzdHJpY2VkIG1vZGVsIA0KDQpsb2dsaWtlX3Bvd2VyID0gLWt1bWFyX2xvZ2xpayhjKG1sZV9hX3Bvd2VyLCAxKSwgc3RvcmFnZSkgI3Jlc3RyaWN0ZWQgbW9kZWwgbG9nIGxpa2VsaWhvb2QgcG93ZXIgZGlzdHJpYnV0aW9uDQoNCg0KTFJUX3N0YXRpc3RpYyA9IDIqIChsb2dsaWtlX2t1bWFyIC0gbG9nbGlrZV9wb3dlcikgI2xpa2VsaWhvb2QgcmF0aW8gc3RhdGlzdGljIGZvciB0aGUgbG9nIGt1bWFyYXN3YW15IGFuZCBsaWtlbGlob29kIGZvciBwb3dlciBkaXN0cnVidXRpb24NCg0KDQpwX3ZhbCA9IDEtIHBjaGlzcShMUlRfc3RhdGlzdGljLCBkZj0xKQ0KDQpjYXQoIlRoZSBsaWtlbGlob29kIHJhdGlvIHRlc3Qgc3RhdGlzdGljIGlzIiwgTFJUX3N0YXRpc3RpYywgInA9IiwgcF92YWwsICIuIikNCg0KYGBgDQoNClN0YXRlIHRoZSBzdGF0aXN0aWNhbCBkZWNpc2lvbiBjbGVhcmx5LiBXaGF0IGlzIHRoZSBwcmFjdGljYWwgaW1wbGljYXRpb24gb2YgdGhlIHRlc3RpbmcgcmVzdWx0Pw0KDQpBcyB0aGUgcCB2YWx1ZSBpcyBsZXNzIHRoYW4gJFxhbHBoYT0wLjAwNSQsIChwPWByIHBfdmFsYCksIHdlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzICgkSF9vOiBiPTEgJCkgdGhhdCB0aGUgbGVzcyBjb21wbGV4IHBvd2VyIGRpc3RyaWJ1dGlvbiBsb2cgbGlrZWxpaG9vZCBtb2RlbCBiZXR0ZXIgc3VpdHMgdGhlIGRpc3RyaWJ1dGlvbi4gVGhlIEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiBzaG91bGQgYmUgdXNlZCB0byBtb2RlbCB0aGUgZGFpbHkgc3RvcmFnZSB3YXRlciBkYXRhLg0KDQoNCg0KDQoNClwNCg0KIyMjICoqUHJvYmxlbSBCMyoqOg0KDQpVc2UgdGhlIHByb2NlZHVyZSBhbmQgY29kZSBmcm9tICoqUHJvYmxlbSBCMSoqIHRvIGVzdGltYXRlIHRoZSBNTEVzIG9mICRhJCBhbmQgJGIkLCBhbmQgdGhlbiBjb21wbGV0ZSB0aGUgZm9sbG93aW5nIGFuYWx5c2VzOg0KDQooMSkuIE9idGFpbiB0aGUgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMgb2YgJFxoYXR7YX0kIGFuZCAkXGhhdHtifSQgYW5kIHBsb3QgZWFjaCBkaXN0cmlidXRpb24gdXNpbmcgKipHYXVzc2lhbiBrZXJuZWwgZGVuc2l0eSBjdXJ2ZXMqKi4NCg0KYGBge3J9DQoNCiNCb290c3RyYXAgTUxFIGZvciBhIGFuZCBiDQoNCkI9OTk5OQ0KYm9vdF9hID0gbnVtZXJpYyhCKSAjYWxsb3dzIG51bWJlciBvZiBib290c3RyYXBzIGZvciBhDQpib290X2IgPSBudW1lcmljKEIpICNhbGxvd3MgbnVtYmVyIG9mIGJvb3RzdHJhcHMgZm9yIGINCm49bGVuZ3RoKHN0b3JhZ2UpDQoNCnNldC5zZWVkKDEyMykNCg0KZm9yKGkgaW4gMTpCKSAjYmVnaW4gYm9vdHN0cmFwIHRvIGZpbmQgbWxlIGEgYW5kIGINCnsNCiAgDQpib290X3NhbXBsZT0gc2FtcGxlKHN0b3JhZ2UsIHNpemU9biwgcmVwbGFjZT0gVFJVRSApICAjcmVzYW1wbGUgd2l0aCByZXBsYWNlbWVudA0KICANCiNFc3RpbWF0ZSBNTEVzIGZvciBib290c3RyYXAgc2FtcGxlIA0KICAjdXNpbmcgb3B0aW0gDQoNCmJvb3RfbWxlPSBvcHRpbSgNCiAgICBwYXIgPSBjKG1sZV9hICogcnVuaWYoMSwgMC45LCAxLjEpLCBtbGVfYiAqIHJ1bmlmKDEsIDAuOSwgMS4xKSksICMgSml0dGVyIHN0YXJ0aW5nIHZhbHVlcyAjcGFyID0gYyhtbGVfYSwgbWxlX2IpLCAjIFN0YXJ0IGF0IHRoZSBvcmlnaW5hbCBNTEVzIGZvciBzcGVlZA0KICAgIGZuID0ga3VtYXJfbG9nbGlrLCAgIyBjaGVja3MgaGVpZ2h0IG9mIGxpa2VsaWhvb2Qgc3VyZmFjZQ0KICAgIGdyID0gY29tYmluZWRfa3VtX2dyYWRpZW50LCAgIyBncmFkaWVudCB1cGhpbGwgc2hvdWxkIGJlIHRoZSBjb21iaW5lZCBncmFkaWVudA0KICAgIGRhdGEgPSBib290X3NhbXBsZSwNCiAgICBtZXRob2QgPSAiTC1CRkdTLUIiLCAjY29udHJhaW50cyBib3gNCiAgICBsb3dlciA9IGMoMWUtNSwgMWUtNSkgIyBrZWVwcyB0aGUgcGFyYW1ldGVycyBwb3NpdGl2ZSAjd291bGQgcmVtb3ZlIGNvbnRyb2wgaWYgdGhpcyB3YXMgaW4gdGhlIGNvZGUNCiAgDQopDQpib290X2FbaV0gPC0gYm9vdF9tbGUkcGFyWzFdICNvdXRwdXQgYSBNTEUgcGFyYW1ldGVyDQpib290X2JbaV0gPC0gYm9vdF9tbGUkcGFyWzJdICNvdXRwdXQgYiBNTEUgcGFyYW1ldGVyDQoNCn0NCg0KDQojZ2F1c3NpYW4ga2VybmVsIGJ1aWxkaW5nIGZvciBhIGhhdA0KcGxvdChkZW5zaXR5KGJvb3RfYSwga2VybmVsPSAiZ2F1c3NpYW4iKSwgbWFpbiA9ICJCb290c3RyYXAgRGlzdHJ1YnV0aW9uIG9mIGEgaGF0IiwNCiAgICAgeGxhYj0iYSBoYXQiLCBjb2w9ICJza3libHVlIiwgbHdkPTIpDQphYmxpbmUodj0gbWxlX2EsIGNvbD0gInJlZCIsIGx0eT0yKSNyZWZlcmVuY2UgZm9yIG9yaWdpbmFsIE1MRQ0KDQojZ2F1c3NpYW4ga2VybmVsIGRlbnNpdHkgZm9yIGIgaGF0DQoNCnBsb3QoZGVuc2l0eShib290X2IsIGtlcm5lbCA9ICJnYXVzc2lhbiIpLCBtYWluPSJCb290c3RyYXAgRGlzdHJ1YnV0aW9uIG9mIGIgaGF0IiwNCiAgICAgeGxhYj0gImIgaGF0IiwgY29sPSAiZGFya2dyZWVuIiwgbHdkPTIpDQphYmxpbmUodiA9IG1sZV9iLCBjb2wgPSAicmVkIiwgbHR5ID0gMikNCg0KYGBgDQoNClRoZSBib290c3RyYXBwZWQgc2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mIGEgaXMgYHIgYm9vdF9hW2ldYC4gVGhlIGJvb3RzdHJhcHBlZCBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgYiBpcyBgciBib290X2JbaV1gLg0KDQoNCigyKS4gIENvbnN0cnVjdCBib3RoIHRoZSAkOTVcJSQgKipib290c3RyYXAgY29uZmlkZW5jZSBpbnRlcnZhbCoqIGFuZCB0aGUgKipXYWxkIGNvbmZpZGVuY2UgaW50ZXJ2YWwqKiBmb3IgJGIkLiBEbyB0aGVzZSBpbnRlcnZhbHMgYWdyZWUgd2l0aCB0aGUgcmVzdWx0cyBvYnRhaW5lZCBpbiAqKlByb2JsZW0gQjIqKj8gWypDb21wdXRlIHRoZSBzdGFuZGFyZCBlcnJvciBvZiAkXGhhdHtifSQgdXNpbmcgdGhlIG9ic2VydmVkIEZpc2hlciBpbmZvcm1hdGlvbiBtYXRyaXgsIGkuZS4sIHRoZSBpbnZlcnNlIG9mIHRoZSBuZWdhdGl2ZSBIZXNzaWFuIG9idGFpbmVkIGZyb20gb3B0aW0oKSpdDQoNCldhbGQgRXF1YXRpb24NCiQkDQpcaGF0e2J9ICsgel97XGFscGhhLzJ9ICogXHNxcnQoW0lfbihcaGF0e2J9XV97MiwyfSkpDQokJA0KDQoNCmBgYHtyfQ0KDQojIyBCb290c3RyYXBwZWQgQ29uZmlkZW5jZSBJbnRlcnZhbHMNCg0KI2Jvb3RfY2lfYT0gcXVhbnRpbGUoYm9vdF9hLCBwcm9icz0gYygwLjAyNSwgMC45NzUpKQ0KI2Jvb3RfY2lfYiA9IHF1YW50aWxlKGJvb3RfYiwgcHJvYnM9IGMoMC4wMjUsIDAuOTc1KSkNCg0KI2NhdCgiVGhlIGJvb3RzdHJhcHBlZCBjb25maWRlbmNlIGludGVydmFsIikNCg0KI0Jvb3RzdHJhcHBlZCBOb3JtYWwgQ29uZmlkZW5jZSBJbnRlcnZhbA0KDQphbHBoYSA8LSAwLjA1DQp6X2NyaXRpY2FsIDwtIHFub3JtKDEgLSBhbHBoYS8yKQ0KZGlzX2NyaXRfY2FsPWJvb3RfYSArIHpfY3JpdGljYWwgKiAoYm9vdF9hL3NxcnQobikpDQoNCiMgQ2FsY3VsYXRlIEJvb3RzdHJhcCBTdGFuZGFyZCBFcnJvciAoc2VfYm9vdCkNCnNlX2Jvb3RfYSA9IHNkKGJvb3RfYSkNCnNlX2Jvb3RfYiA9IHNkKGJvb3RfYikNCg0KIyBaIGNyaXRpY2FsIHZhbHVlIGZvciA5NSUNCg0Kej0gcW5vcm0oMC45NzUpDQoNCiNDb25maWRlbmNlIGxldmVsIGZvciBwYXJhbWV0ZXIgYQ0KY2lfYm9vdF9hID0gYyhMQ0k9IG1sZV9hIC0geipzZV9ib290X2EsICAjbG93ZXIgY29uZmlkZW5jZSBsZXZlbA0KICAgICAgICAgICAgICAjZXN0aW1hdGU9IG1sZV9hLCAjdGhlIHZhbHVlIHRoZSBDSSBpcyBjZW50ZXJlZCBhcm91bmQNCiAgICAgICAgICAgICAgVUNMPSBtbGVfYSArIHoqc2VfYm9vdF9hICN1cHBlciBjb25maWRlbmNlIGxldmVsDQogICAgICAgICAgICAgICkNCmNhdCgiVGhlIGJvb3RzdHJhcGVkIG5vcm1hbCBjb25maWRlbmNlIGludGVydmFsIGZvciBwYXJhbWV0ZXIgYT0iLCBtbGVfYSwgImlzLCBbIiwgY2lfYm9vdF9hLCAiXS4iKQ0KDQpjaV9ib290X2IgPSBjKExDST0gbWxlX2IgLSB6KnNlX2Jvb3RfYiwgICNsb3dlciBjb25maWRlbmNlIGxldmVsDQogICAgICAgICAgICAgICNlc3RpbWF0ZT0gbWxlX2IsICN0aGUgdmFsdWUgdGhlIENJIGlzIGNlbnRlcmVkIGFyb3VuZA0KICAgICAgICAgICAgICBVQ0w9IG1sZV9iICsgeipzZV9ib290X2IgI3VwcGVyIGNvbmZpZGVuY2UgbGV2ZWwNCiAgICAgICAgICAgICAgKQ0KY2F0KCJcbiBUaGUgYm9vdHN0cmFwZWQgbm9ybWFsIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHBhcmFtZXRlciBiPSIsIG1sZV9iLCAiaXMsIFsiLCBjaV9ib290X2IsICJdLiIpDQoNCg0KI1BlcmNlbnRpbGUgQ0kgQm9vb3RzdHJhcHMNCmJvb3RfcGVyY2VudGlsZV9hID0gYXMubnVtZXJpYyhxdWFudGlsZShib290X2EsIHByb2JzPSBjKDAuMDI1LCAwLjk3NSkpKQ0KYm9vdF9wZXJjZW50aWxlX2IgPSBhcy5udW1lcmljKHF1YW50aWxlKGJvb3RfYiwgcHJvYnM9IGMoMC4wMjUsIDAuOTc1KSkpDQoNCmNhdCgiXG4gVGhlIGJvb3RzdHJhcHBlZCBwZXJjZW50aWxlIDk1JSBjb25maWRlbmNlIGludGVydmFsIGZvciBwYXJhbWV0ZXIgYT0gaXMsIFsiLCBib290X3BlcmNlbnRpbGVfYSwgIl0uIikNCg0KY2F0KCJcbiBUaGUgYm9vdHN0cmFwZWQgcGVyY2VudGlsZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgcGFyYW1ldGVyIGIgaXMsIFsiLCBib290X3BlcmNlbnRpbGVfYiwgIl0uIikNCg0KDQojIyMjIyMjIyMjI1dhbGQgQ0kgDQojQ29tcHV0ZSB0aGUgV2FsZCBDSSB1c2luZyBvYnNlcnZlZCBGaXNoZXIgaW5mb3JtYXRpb24NCg0KDQoNCmZpc2hlcl9pbmZvPSBzb2x2ZShtbGUucmVzdWx0JGhlc3NpYW4pICN0YWtlIHRoZSBpbnZlcnNlIG9mIHRoZSBtbGUucmVzdWx0IG1hdHJpeA0KI2hhdmUgdmFsdWVzIGJlZm9yZSB0aGlzIG1hdHJpeCBpbiB0aGUgZXF1YXRpbm4gYXMgd2VsbCBhcyB3ZSBkZXNjcmliZSBzb21lIG9mIHRoZSBmb3JtdWxhIGJlbG93DQogICN2YXJpYW5jZShUaGV0YTEpICAgICNjb3ZhcmlhbmNlKFRoZXRhMSwgVGhldGEyKQ0KICAjY292KFRoZXRhMSwgVGhldGEyKSAjIHZhcmlhbmNlKHRoZXRhMikNCiNpbnNpZGUgdGhlIGhlc3NpYW4gbWF0cml4IGZvciB3YWxkIHdoaWNoIGlzIHRoZSBpbnZlcnNlIG9mIHRoZSBmaXNoZXIgbWF0cml4ICAqIHRoZSBtYXRyaXggb2YgaGF0XHRoZXRhMSAtIGludmVyc2UgdGhldGExMCAob24gdG9wIG9mKSBoYXRcdGhldGEyIC0gdGhldGEyMA0KDQojdGhlIGludmVyc2Ugb2YNCiAgI3ZhcmlhbmNlKGhhdFxhKSAgICAjY292YXJpYW5jZShcaGF0XGEsIFxoYXRcYikgDQogICNjb3YoXGhhdFxhLCBcaGF0XGIpICMgdmFyaWFuY2UoXGhhdFxhKQ0KDQojd2UgYXJlIG9ubHkgdGhlIGIgcGFyYW1ldGVyDQoNCiNjYWxjdWxhdGUgdGhlIHN0YW5kYXJkIGVycm9yIHNwZWNpZmljIHRvIHdhbGQgYg0Kc2Vfd2FsZF9iID0gc3FydChmaXNoZXJfaW5mb1syLDJdKSAjc3RhbmRhcmQgZXJyb3Igd2FsZA0KDQp6PSBxbm9ybSgwLjk3NSkNCndhbGRfY2lfYiA9IGMoTENJPSBtbGVfYi0geipzZV93YWxkX2IsIFVDTD0gbWxlX2IgKyB6KnNlX3dhbGRfYikNCg0KY2F0KCJcbiBUaGUgV2FsZCBDb25maWRlbmNlIEludGVydmFsIGZvciBiIGlzIFsiLCB3YWxkX2NpX2IsICJdLiIpDQpgYGANCldlIGFyZSBjb21wYXJpbmcgdGhlIFdhbGQgQ29uZmlkZW5jZSBpbnRlcnZhbCB0byBhIGJvb3RzdHJhcCBzYW1wbGluZyBjb25maWRlbmNlIGludGVydmFsLiBUbyBiZXR0ZXIgY2FwdHVyZSB0aGUgc2tld25lc3Mgb2YgdGhpcyBLdW1hcmFzd2FteSBkaXN0cmlidXRpb24gd2UgY29tcGFyZSB0aGUgYm9vdHN0cmFwcGVkIFBlcmNlbnRpbGUgQ29uZmlkZW5jZSBJbnRlcnZhbCB0byB0aGUgV2FsZCBDb25maWRlbmNlIEludGVydmFsLiBUaGUgUGVyY2VudGlsZSA5NSVDSSBmb3IgcGFyYW1ldGVyIGIgaXMgW2ByIGJvb3RfcGVyY2VudGlsZV9iYF0gKHdpZHRoID0gIDAuMzc4MTgxKSAuIFRoZSBXYWxkIENvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgW2ByIHdhbGRfY2lfYmBdICh3aWR0aD0gMS4xMDgyNjQpLiBUaGUgYm9vdHN0cmFwcGVkIHBlcmNlbnRpbGUgQ0kgaGFzIGEgZmFyIHNtYWxsZXIgaW50ZXJ2YWwgdGhhbiB0aGUgV2FsZCBDb25maWRlbmNlIGludGVydmFsIHN1Z2dlc3RpbmcgdGhlIFdhbGQgdGVzdCBpcyBub3QgdGhlIGJlc3QgdGVzdCB0byB1c2Ugb24gdGhlIGRpc3RyaWJ1dGlvbiBhcyBpdCBhc3N1bWVzIGEgbm9ybWFsIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiwgd2hpY2ggaXMgYmVzdCBzdWl0ZWQgaGVyZS4gVGhlIFdhbGQgOTUlQ0kgaXMgdW5kZXJwZXJmb3JtaW5nIHRoZSBib290c3RyYXBwZWQgTm9ybWFsIDk1JUNJIGFzIHdlbGwgW2ByIGNpX2Jvb3RfYmBdLiBPdXIgZGVzaXJlIGlzIHRvIGhhdmUgYSBzbWFsbCBjb25maWRlbmNlIGludGVydmFsIGFzIGxvbmcgYXMgdGhlIGRpc3RyaWJ1dGlvbiBpcyB3ZWxsIHJlcHJlc2VudGVkIGJ5IHRoZSBpbnRlcnZhbCB1c2VkLg0KDQoNCkluIFByb2JsZW0gQjIsIHdlIHJlamVjdGVkIHRoZSBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGUgc2ltcGxlciBtb2RlbCBzdWl0cyB0aGUgZGlzdHJpYnV0aW9uLCBjb25jbHVkaW5nIHRoZSBLdW1hcmFzd2FteSBkaXN0cmlidXRpb24gYmV0dGVyIG1vZGVscyB0aGUgZGFpbHkgc3RvcmFnZSB3YXRlciBkYXRhLiBDb25zaWRlcmluZyB0aGlzIG1vcmUgY29tcGxleCBtb2RlbCwgbW9zdCBsaWtlbHkgaGFzIG1vcmUgY29tcGxleCBkaXN0cmlidXRpb24gc2hhcGUgdGhhdCBpcyBub3Qgd2VsbCByZXByZXNlbnRlZCBieSBhIG5vcm1hbCBkaXN0cmlidXRpb24gZXZlbiB3aGVuIG92ZXJjb21pbmcgZm9yIHNvbWUgcm9idXN0bmVzcywgdGhlIGJldHRlciBzdWl0ZWQgYm9vdHN0cmFwcGVkIHBlcmNlbnRpbGUgY2kgYWdyZWVzIHdpdGggdGhlIGNvbXBsZXhpdHkgb2YgdGhlIGRhdGFzZXQuIA0KDQogDQoNCg0KKDMpLiBCYXNlZCBvbiB0aGUgYm9vdHN0cmFwIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbnMgZnJvbSBwYXJ0ICgxKSBvZiB0aGlzIHByb2JsZW0sIGFzc2VzcyB3aGV0aGVyIHRoZSB2YWxpZGl0eSBvZiB0aGUgV2FsZCBjb25maWRlbmNlIGludGVydmFsIGlzIHN1cHBvcnRlZC4NCg0KDQpXaGlsZSB0aGUgYm9vdHN0cmFwcGVkIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGRvIG5vdCBpbmNsdWRlIDAsIHdlIGNhbiBhc3N1bWUgb3VyIHBhcmFtZXRlcnMgYSBhbmQgYiBoYXMgc2lnbmlmaWNhbmNlLiBUaGUgYm9vdHN0cmFwIGtlcm5lbCBmaWd1cmUgZm9yICRcaGF0e2F9JCByYW5nZSBhYm91dCBmcm9tIDAuODMtMS4xMCB3aXRoIGEgTUxFIHZhbHVlIG9mIGByIGJvb3RfYVtpXWAuIFRoZSBib290c3RyYXAga2VybmVsIGZpZ3VyZSBmb3IgJFxoYXR7Yn0kIHJhbmdlcyBmcm9tIGFib3V0IDEuOCB0byAyLjIgd2l0aCBhbiBNTEUgdmFsdWUgb2YgYHIgYm9vdF9iW2ldYC4gQXMgdGhlIFdhbGQgY29uZmlkZW5jZSBpbnRlcnZhbCBbYHIgd2FsZF9jaV9iYF0gIGlzIGJldHdlZW4ga2VybmVsJ3MgcmFuZ2VzIGZvciB0aGUgZW50aXJlIGVuY29tcGFzc2luZyBkYXRhc2V0IHRoZXJlZm9yZSBjYXB0dXJpbmcgYW4gaW50ZXJ2YWwgd2l0aGluIGEgcGxhdXNpYmxlIHJhbmdlIGFsdGhvdWdoIGl0IGlzIHdheSBsZXNzIHZhbGlkIHRoYW4gaXRzIGJvb3RzdHJhcHBlZCBwZXJjZW50aWxlIENvbmZpZGVuY2UgSW50ZXJ2YWwuQSBwZXJjZW50aWxlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgaXMgcHJlZmVycmVkIGZvciB0aGUgc3RvcmFnZSBkaXN0cmlidXRpb24uIA0KVGhlIFdhbGQgQ0kgYXNzdW1wdGlvbiBmb3Igbm9ybWFsaXR5IGFuZCBzeW1tZXRyeSBjYW5ub3Qgd2VsbCBjYXB0dXJlIHRoZSB0cnVlIHNoYXBlIG9mIHRoZSBkaXN0cmlidXRpb24uIEFzIHRoZSBkaXN0cmlidXRpb24gYXBwZWFycyB0byBoYXZlIHNvbWUgdW5pbW9kYWwgc2hhcGUgYW5kIHNsaWdodCB0YWlsLCByYXRoZXIgdGhhbiBhIHN0cm9uZyBzeW1tZXRyaWNhbCBzaGFwZSBjZW50ZXJlZCBhcm91bmQgaXRzIE1MRS4gVGhlIHdpZGVyIFdhbGQgY29uZmlkZW5jZSBpbnRlcnZhbCBoaWdobGlnaHRzIGl0cyB1bmNlcnRpYW55IHRvIG1lYXN1cmUgZGV2aWF0aW9ucyBmcm9tIG5vcm1hbCBzaGFwZSB3ZWxsLg0KDQpcDQoNCiMjIyAqKlByb2JsZW0gQjQqKjoNCg0KSW4gdGhlIGludHJvZHVjdGlvbiB0byB0aGUgd29ya2luZyBtb2RlbCBmb3IgdGhpcyBleGFtLCB0aGUgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIHJlZHVjZXMgdG8gdGhlIHVuaWZvcm0gZGlzdHJpYnV0aW9uIG9uICgwLDEpLiBJbiB0aGlzIHByb2JsZW0sIHdlIHBlcmZvcm0gYSAqKmxpa2VsaWhvb2QgcmF0aW8gdGVzdCoqIGZvciB0aGUgZm9sbG93aW5nIGh5cG90aGVzaXMgdG8gYXNzZXNzIHdoZXRoZXIgdGhlIGRhdGEgY29tZSBmcm9tIHRoZSB1bmlmb3JtIGRpc3RyaWJ1dGlvbiBvbiAoMCwxKToNCg0KJCQNCkhfMDogYSA9IDFccXVhZCBcJiBccXVhZCBiID0gMVxxdWFkIFx0ZXh0eyB2ZXJzdXMgfSBccXVhZCBIX2E6IGEgXG5lIDEgXHF1YWQgXHRleHR7b3J9IFxxdWFkIGIgXG5lIDEgXHF1YWQgXHRleHR7b3J9XHF1YWQgKGEgXG5lIDEgXHF1YWQgXCYgXHF1YWQgYiBcbmUgMSkuDQokJA0KDQpQcm92aWRlIGEgcHJhY3RpY2FsIGludGVycHJldGF0aW9uIG9mIHRoZSBhYm92ZSB0ZXN0IHJlc3VsdC4gWypIaW50OiAkSF9hJCBiYXNpY2FsbHkgc2F5cyB0aGF0IHRoZXJlIGlzIG5vIGNvbnN0cmFpbnRzIGZvciAkYSQgYW5kICRiJC4gUGxlYXNlIHJldmlldyB0aGUgbGVjdHVyZSBub3RlIGZvciBtb2R1bGUgMTEgIG9uIHRoZSBsaWtlbGlob29kIHJhdGlvIHRlc3QgYmVmb3JlIGNvZGluZy4qXQ0KDQpcDQoNCkhlcmUgd2UgY29tcGFyZSB0aGUgS3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uIHRvIGFub3RoZXIgc3BlY2lhbCBjYXNlIHVuaWZvcm0gZGlzdHJpYnV0aW9uIG1vZGVsIHdoZXJlIHRoZSBkaXN0cmlidXRpb24gcmFuZ2VzIGJldHdlZW4gMCBhbmQgMS4gIA0KDQokJA0KTFJUX3t1bmkoMSwxKX09IDJbXGVsbChcaGF0e2F9LCBcaGF0e2J9KS1cZWxsKDEsMSldDQokJA0KDQpgYGB7cn0NCm49IGxlbmd0aChzdG9yYWdlKQ0KDQojdW5yZXN0cmljdGVkIG9yaWdpbmFsIGxvZyBsaWtlbGlob29kIGZyb20ga3VtYXJhc3dhbXkgZGlzdHJpYnV0aW9uDQoNCmxvZ0xfdW5yZXN0cmljdGVkID0gLWt1bWFyX2xvZ2xpayhjKG1sZV9hLCBtbGVfYiksIHN0b3JhZ2UpICNwcmVzZW50cyBqb2ludCBwcm9iYWJpbGl0eSBvZiBlbnRpcmUgZGF0YXNldCBnaXZlIGEgYW5kIGIgcGFyYW1ldGVycw0KDQojbG9nIGxpa2VsaWhvb2QgZm9yIFVuaWZvcm0gKGE9MSwgYj0xKQ0KbG9nTF9yZXN0cmljdGVkPSAta3VtYXJfbG9nbGlrKGMoMSwxKSwgc3RvcmFnZSkgI3RoZSBwYXJhbWV0ZXJzIGZvciAxIGFuZCAxIGZvciBib3RoICBhIGFuZCBiDQoNCiNsb2cgcmF0aW8gdGVzdCBzdGF0aXN0aWMNCg0KTFJUX3N0YXRfdW5pY29tcGFyaXNvbiA9IDIgKiAobG9nTF91bnJlc3RyaWN0ZWQgLSBsb2dMX3Jlc3RyaWN0ZWQpIA0KDQpwdmFsX3VuaWNvbXBMUlQ9IDEtIHBjaGlzcShMUlRfc3RhdF91bmljb21wYXJpc29uLCBkZj0yKQ0KDQpjYXQoIlRoZSBsb2cgbGlrZWxpaG9vZCByYXRpbyBjb25zaWRlcmluZyB0aGUgc3BlY2lhbCBjYXNlIGt1bWFzd2FteSB1bmlmb3JtIGRpc3RydWJ1dGlvIChhPTEsIGI9MSkgaXMiLCBMUlRfc3RhdF91bmljb21wYXJpc29uLCAiKHA9IiwgcHZhbF91bmljb21wTFJULCAiKS4iKQ0KDQpgYGANCldoZW4gYXNzZXNzaW5nIHRoZSBzdHJvbmdlciBtb2RlbCB1c2luZyB0aGUgTGlrZWxpaG9vZCBSYXRpbyBUZXN0LCB0aGUgbW9yZSBjb21wbGV4IEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiBkb2VzIGEgYmV0dGVyIGpvYiBhdCBtb2RlbGxpbmcgdGhlIHdhdGVyIHN0b3JhZ2UgZGlzdHJpYnV0aW9uIHRoYW4gdGhlIHVuaWZvcm0gbW9kZWwuIElmIGNvbXBhcmluZyB3aGV0aGVyIHRvIHVzZSB0aGUgcmVzdHJpY3RlZCB1bmlmb3JtIGRpc3RyaWJ1dGlvbiBvciB0aGUgdW5yZXN0cmljdGVkIEt1bWFyYXN3YW15IGRpc3RyaWJ1dGlvbiwgdXNlIHRoZSBLdW1hcmFzd2FteSBkaXN0cmlidXRpb24gKExSVD0gYHIgTFJUX3N0YXRfdW5pY29tcGFyaXNvbmAsIHA9IGByIHB2YWxfdW5pY29tcExSVGApLiBQZXJoYXBzIHRoZSBzbGlnaHQgcmlnaHQgc2tld25lc3Mgb2YgdGhlIG1vZGVsIGlzIG5vdCB3ZWxsIHJlcHJlc2VudGVkIGJ5IHRoZSB1bmlmb3JtIGRpc3RyaWJ1dGlvbiBzdWdnZXN0aW5nIGRhaWx5IHdhdGVyIGludGFrZSBpcyBub3QgZXZlbmx5IGRpc3RyaWJ1dGVkIG5vciByYW5kb20uDQoNCg0KSXQgYXBwZWFycyBib3RoIHRoZSBLdW1hcmFzd2FteSBvdXRwZXJmb3JtcyB0aGUgdW5pZm9ybSBhbmQgcG93ZXIgZGlzdHJpYnV0aW9uIG1vZGVscy4gDQoNCjxmb250IGNvbG9yID0gInJlZCI+KipOb3RlKio6IFBsZWFzZSBkb3dubG9hZCB0aGUgdGVtcGxhdGUgYW5kIGluc2VydCB5b3VyIHdvcmsgaW50byBpdCB0byBjb21wbGV0ZSB0aGUgZXhhbS4gPC9mb250Pg0KDQoNCg0KDQo=