1.) Log Density Derivation
Here we are examining the log-logistic (or Fisk) distribution, a
popular distribution when dealing with non-negative and rightly skewed
data (think survival analysis or income distributions for example).
Using R’s built-in D function, I was
able to quickly find this distribution’s relative probability density
function (PDF), after already being provided its cumulative distribution
function (CDF). These calculations are predicated on the fact that a
distribution’s PDF is simply the first derivative of its CDF. Since a
derivative is the rate of change of a function at a given point,
deriving a CDF across the entirety of its bounds allows for an
understanding of how relative probability changes throughout. Below are
the Fisk distribution’s PDF and CDF, denoted by f(x) and F(x)
respectively.
CDF_function = function(x, alpha, beta){
1/(1+(x/alpha)^(-beta))
}
CDF_expression = expression(
1/(1+(x/alpha)^(-beta))
)
# Creating both an expression object and function object since the deriv function I am about to use only takes expression objects
# Will use D function to see the returned PDF in algebraic form
# Will use deriv function to get an expression that can be used for evaluations
## PDF = first derivative of CDF
PDFD = D(CDF_expression, "x")
#PDFD # = ((x/alpha)^((-beta) - 1) * ((-beta) * (1/alpha))/(1 + ((x/alpha)^(-beta)))^2)
# Wrote this down, did some additional algebra before writing up Latex below
PDF_Function = function(x, alpha, beta){
ifelse(x <= 0, 0,
(beta/alpha) * (x/alpha)^(beta - 1) / (1 + (x/alpha)^beta)^2)
}
# Had to include the ifelse component because x will always be positive in the scenario of our data (recovery times) and in accordance with the properties of the Fisk distribution
# I previously did NOT have that ifelse component and my visual confirmation further along was not effective
PDF_deriv = deriv(CDF_expression, "x")
\[{\Large F(x) = \frac{1}{1 +
(x/\alpha)^{-\beta}}} \hspace{0.5cm}\Large , \hspace{0.5cm}
X>=0 \]
\[{\Large f(x) = \frac{\beta}{\alpha} *
\frac{(x/\alpha)^{\beta-1}}{\alpha(1+(x/\alpha)^\beta)^2}}
\hspace{0.5cm}\Large , \hspace{0.5cm}X>=0 \]
2.) Recovery Time Distribution
The dataset we have on hand is composed of 50 different patients’
observed recovery times (in days) following a particular knee surgery
procedure. We will operate the analysis of this dataset under the
assumption that the underlying population of knee surgery recovery times
is distributed in a log-logistic manner. Below are both the summary
statistics and a histogram of the dataset’s values.
Days = c(8.23, 12.74, 14.83, 16.61, 18.16, 19.55, 20.80, 21.94, 23.00, 23.98, 24.89, 25.75, 26.56,
27.34, 28.08, 28.79, 29.48, 30.15, 30.81, 31.45, 32.08, 32.70, 33.31, 33.92, 34.53, 35.13,
35.73, 36.33, 36.93, 37.53, 38.14, 38.75, 39.37, 40.00, 40.64, 41.29, 41.95, 42.63, 43.33,
44.05, 44.79, 45.56, 46.36, 47.20, 48.08, 49.02, 50.03, 51.12, 52.32, 53.65)
# n = 50
Data_Days = data.frame(Days)
sum_stats_table = function(variable){
table = cbind(
round(min(variable),2),
round(quantile(variable, 0.25),2),
round(median(variable),2),
round(mean(variable),2),
round(quantile(variable, 0.75),2),
round(max(variable),2)
)
colnames(table) = c("Min", "Q1", "Med", "Mean", "Q3", "Max")
rownames(table) = NULL
return(table)
}
# I created a table for summary statistics of a variable, can use this moving forward instead of manually putting the summary stats in table form
Summary_Table = sum_stats_table(variable = Days)
kable(Summary_Table,align = "c",
caption = "<span style='color:##000000;'>Summary Stats of Recovery Times</span>") %>%
kable_styling(
bootstrap_options = c("striped", "bordered"),
full_width = FALSE,
position = "center")
Summary Stats of Recovery Times
|
Min
|
Q1
|
Med
|
Mean
|
Q3
|
Max
|
|
8.23
|
26.75
|
34.83
|
34.19
|
42.46
|
53.65
|
hist(Days,
main = "Distribution of Recovery Times",
xlab = "Recovery Time (Days)",
ylab = "Count",
)
box(lwd=3)

2a.) Moment Estimation
As stated above, we are operating under the assumption of our data
stemming from a Fisk distribution. Therefore, there are two population
parameters of interest, \(\alpha\)
(rate of scale) and \(\beta\) (rate of
shape), which we would like to use our sample data to estimate.
Using moment estimation, general formula tells us that the kth moment
(\(m_k\)) of a distribution can be
found by summing said dataset’s values (each raised to the k power) and
then divided by the sample size. Additionally, and more specifically to
the Fisk distribution, we can directly equate the different moments of a
distribution to functions of the \(\alpha\) and \(\beta\) parameters. The formulas and
calculations of the first two moments (\(m_1\) and \(m_2\)) are below.
## Reference Section 4.2 example 2 from lecture notes
# Mean of log logistic distribution = (alpha * pi)
# / (beta * sin(alpha/beta))
## Reference formula from Section 3.1
# moment 1 = mean of data # = 34.1922 = (alpha * pi)
# / (beta * sin(alpha/beta))
# moment 2 = mean of (data squared) = 1288.845
Moment1 = mean(Days)
Moment2 = mean(Days^2)
\[\Large Moment 1 = {\alpha^1*\Gamma(1 +
1/\beta) * \Gamma(1 - 1/\beta)} = \bar{x} \approx
34.1922 \]
\[\Large Moment 2 = {\alpha^2*\Gamma(1 +
2/\beta) * \Gamma(1 - 2/\beta)} = \bar{x^2} \approx
1288.84483 \]
Utilizing our dataset’s first two moments, we then create a system of
equations via R’s uniroot and custom
function capabilities, to estimate
\(\alpha\) and \(\beta\) though numerical methods. Numerical
methods are needed since pure algebraic tactics are unable to solve the
inequalities for this distribution. Since we are finding
estimates of the broader population parameters of a Fisk
distributed population, we label these estimates \(\hat{\alpha}\) and \(\hat{\beta}\) to represent \(\alpha\) and \(\beta\) respectively.
## From assignment instructions:
## (alpha^k) * beta function (1 + (k/beta), 1 - (k/beta))
# Capital B denotes the beta function
Beta_Hat = uniroot(function(Beta){
# The uniroot function tells us what value of specific variable will lead our function to equal zero or approach zero
# In this case, we are finding f(beta) = 0 because there is not an algebraic way to find a difference of zero between sample variance and theoretical variance
A = (pi/Beta)/
sin(pi/Beta)
# One portion of Fisk Distribution variance formula
B = (2*pi/Beta)/
sin(2*pi/Beta)
# Other portion of Fisk Distribution variance formula
Alpha_Beta = Moment1 / A
Alpha_Beta^2 * (B - A^2) - (Moment2 - Moment1^2)
}, lower = 2.000001, upper = 2000000)$root
# Set lower bound of search to 2.000001 because, per properties of Fisk Distribution moments, beta must be greater than moment 2 in order for variance to exist
# upper bound set arbitrarily
Alpha_Hat = Moment1 / ((pi/Beta_Hat)/sin(pi/Beta_Hat))
invisible(
Alpha_Hat
)
invisible(
Beta_Hat
)
\[\Large \hat{\alpha} \approx
32.65\] \[\Large \hat{\beta} \approx
6.01\]
To confirm relative accuracy of our estimates, below I overlaid the
Fisk distribution’s PDF with given alpha and beta parameters over top
our available sample data of patient recovery times. There is moderate
overlap between our distribution curve and histogram data. This leads me
to believe that there very well could be an underestimate of our \(\alpha\) parameter, as the value of \(\alpha\) traditionally controls the
horizontal location of a curve’s peak and decline.
hist(Days,
main = "Distribution of Recovery Times",
xlab = "Recovery Time (Days)",
ylab = "Probability Density",
ylim = c(0, 0.05),
breaks = 10,
prob = TRUE)
curve(PDF_Function(x , alpha = 32.65431, beta = 6.006248),
col = "red",
lwd = 3,
add = TRUE)
legend("topright",
legend = "Fisk (32.65, 6.07)",
col = "red",
lwd = 3,
box.lwd=3)
box(lwd=3)

2b.)
Given the inherent variation that exists in sampling, I chose to
execute a bootstrapping sequence. I performed 1,000 iterations of
samples (n = 50 each time) for both our parameters estimators, \(\hat{\alpha}\) and \(\hat{\beta}\).
Pictured below are the sampling distributions for both parameters,
each of them with a Gaussian kernel density curve layered above and said
curve’s respective bandwidth notated in parentheses. Bandwidths were
chosen in accordance with Silverman’s standard formula and calculated
via a custom-built R function.
# Bootstrap Calculations
set.seed(100)
Alpha_Bootstraps = 0
Beta_Bootstraps = 0
# Set these variables equal to zero as they will be constantly updated throughout the for loop's iterations
for(i in 1:1000){
ith_Sample = sample(Days, size = length(Days), replace = TRUE)
# Always use replacement when bootstrapping
ith_Moment1 = mean(ith_Sample)
ith_Moment2 = mean(ith_Sample^2)
# Copied function from part 2a: removed comments as process is the same for each bootstrap sample
# updated variable names for the bootstrap procedure
Boot_Beta_Hat = uniroot(function(Beta){
A = (pi/Beta)/
sin(pi/Beta)
B = (2*pi/Beta)/
sin(2*pi/Beta)
Alpha_Beta = ith_Moment1 / A
Alpha_Beta^2 * (B - A^2) - (ith_Moment2 - ith_Moment1^2)
}, lower = 2.000001, upper = 2000000)$root
Boot_Alpha_Hat = ith_Moment1 / ((pi/Beta_Hat)/sin(pi/Beta_Hat))
Alpha_Bootstraps[i] = Boot_Alpha_Hat
Beta_Bootstraps[i] = Boot_Beta_Hat
}
## Create custom function for finding Gaussian bw quickly in future
Gaussian_BW = function(Data){
IQR = quantile(Data, 0.75) - quantile(Data, 0.25)
Min_Part = min(sd(Data),(IQR/1.34))
BW = 0.9 * Min_Part * (length(Data)^(-0.2))
return(BW)
}
invisible(
Gaussian_BW(Data = Alpha_Bootstraps) # = 0.3183099
)
hist(Alpha_Bootstraps,
main = "Bootstrap Distribution of Alpha Hat",
xlab = "Sampling Means",
ylab = "Probability Density",
prob = TRUE
)
# bandwidth calculations below
Gaussian = density(Alpha_Bootstraps, bw = 0.3183099, kernel = "gaussian")
lines(Gaussian,
lwd = 3,
col = "blue"
)
legend("topright",
legend = "Gaussian (0.32)",
col = "blue",
lwd = 3,
box.lwd=3)
box(lwd=3)

invisible(
Gaussian_BW(Data = Beta_Bootstraps) # = 0.1303286
)
hist(Beta_Bootstraps,
main = "Bootstrap Distribution of Beta Hat",
xlab = "Sampling Means",
ylab = "Probability Density",
prob = TRUE,
ylim = c(0,0.7)
)
box(lwd=3)
Gaussian = density(Beta_Bootstraps, bw = 0.1303286, kernel = "gaussian")
lines(Gaussian,
lwd = 3,
col = "blue"
)
legend("topright",
legend = "Gaussian (0.13)",
col = "blue",
lwd = 3,
box.lwd=3)

What the bootstrap distribution for \(\hat{\alpha}\) and \(\hat{\beta}\) display is a far
greater resemblance with their Gaussian PDF estimations than
what was seen above, comparing our data to the curve of a standard Fisk
distribution with said values for \(\alpha\) and \(\beta\).
Two possible suggestions that this relevation brings are: perhaps the
population from which these sampled surgery recovery times came from is
not truly as Fisk distributed as we initially believed, or as stated
previously there could be an underestimate of the \(\alpha\) parameter.
LS0tCnRpdGxlOiAiTW9tZW50IEVzdGltYXRpb24gTWV0aG9kcyIKYXV0aG9yOiAiQ2hyaXMgQmFobSIKZGF0ZTogImByIGZvcm1hdChTeXMuRGF0ZSgpLCAnJUIgJWQsICVZJylgIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OgogICAgICBjb2xsYXBzZWQ6IHRydWUKICAgICAgc21vb3RoX3Njcm9sbDogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfd2lkdGg6IDYKICAgIGZpZ19oZWlnaHQ6IDQKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiBsdW1lbgogICAgaGlnaGxpZ2h0OiB0YW5nbwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogdHJ1ZQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgd29yZF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2RlcHRoOiA0Ci0tLQoKYGBge2NzcywgZWNobyA9IEZBTFNFfQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDI0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya1JlZDsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDIwcHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmgyIHsgLyogSGVhZGVyIDIgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMThweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICAgIGZvbnQtc2l6ZTogMTRweDsKICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IGRhcmtyZWQ7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgovKiBBZGQgZG90cyBhZnRlciBudW1iZXJlZCBoZWFkZXJzICovCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsKICBjb250ZW50OiAiLiI7Cn0KYGBgCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IAojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4KCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0CiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikgICAgICAgICAgICAgICAgICAjIHdoZXRoZXIgYSBwYWNrYWdlIHdhcyBpbnN0YWxsZWQgaW4KICAgbGlicmFyeShrbml0cikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91ciBtYWNoaW5lLiBJZiBub3QsIGluc3RhbGwgaXQgYW5kCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5LgoKaWYgKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIHtsaWJyYXJ5KHRpZHl2c2Vyc2UpfSAKCmlmICghcmVxdWlyZShHR2FsbHkpKSB7bGlicmFyeShHR2FsbHkpfSAKCmlmICghcmVxdWlyZShrYWJsZUV4dHJhKSkge2xpYnJhcnkoa2FibGVFeHRyYSl9IAoKaWYgKCFyZXF1aXJlKGdncGxvdDIpKSB7bGlicmFyeShnZ3Bsb3QyKX0gCgppZiAoIXJlcXVpcmUoY2FyKSkge2xpYnJhcnkoY2FyKX0gCgppZiAoIXJlcXVpcmUoZHBseXIpKSB7bGlicmFyeShkcGx5cil9IAoKaWYgKCFyZXF1aXJlKHBhbmRlcikpIHtsaWJyYXJ5KHBhbmRlcil9IAoKaWYgKCFyZXF1aXJlKGZvcmVjYXN0KSkge2xpYnJhcnkoZm9yZWNhc3QpfSAKCmlmICghcmVxdWlyZShsdWJyaWRhdGUpKSB7bGlicmFyeShsdWJyaWRhdGUpfSAKCmlmICghcmVxdWlyZSgic2NhbGVzIikpIHsKaW5zdGFsbC5wYWNrYWdlcygic2NhbGVzIikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCmxpYnJhcnkoInNjYWxlcyIpIAp9Cgprbml0cjo6b3B0c19jaHVuayRzZXQoCgllY2hvID0gVFJVRSwKCW1lc3NhZ2UgPSBGQUxTRSwKCXdhcm5pbmcgPSBGQUxTRSwKCWNvbW1lbnQgPSBOQSwKCXJlc3VsdHMgPSBUUlVFLAoJZmlnLmFsaWduID0gImNlbnRlciIKKQpgYGAKCgojIDEuKSBMb2cgRGVuc2l0eSBEZXJpdmF0aW9uCkhlcmUgd2UgYXJlIGV4YW1pbmluZyB0aGUgbG9nLWxvZ2lzdGljIChvciBGaXNrKSBkaXN0cmlidXRpb24sIGEgcG9wdWxhciBkaXN0cmlidXRpb24gd2hlbiBkZWFsaW5nIHdpdGggbm9uLW5lZ2F0aXZlIGFuZCByaWdodGx5IHNrZXdlZCBkYXRhICh0aGluayBzdXJ2aXZhbCBhbmFseXNpcyBvciBpbmNvbWUgZGlzdHJpYnV0aW9ucyBmb3IgZXhhbXBsZSkuIAoKVXNpbmcgUidzIGJ1aWx0LWluIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+RDwvc3Bhbj4gIGZ1bmN0aW9uLCBJIHdhcyBhYmxlIHRvIHF1aWNrbHkgZmluZCB0aGlzIGRpc3RyaWJ1dGlvbidzIHJlbGF0aXZlIHByb2JhYmlsaXR5IGRlbnNpdHkgZnVuY3Rpb24gKFBERiksIGFmdGVyIGFscmVhZHkgYmVpbmcgcHJvdmlkZWQgaXRzIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uIChDREYpLiBUaGVzZSBjYWxjdWxhdGlvbnMgYXJlIHByZWRpY2F0ZWQgb24gdGhlIGZhY3QgdGhhdCBhIGRpc3RyaWJ1dGlvbidzIFBERiBpcyBzaW1wbHkgdGhlIGZpcnN0IGRlcml2YXRpdmUgb2YgaXRzIENERi4gU2luY2UgYSBkZXJpdmF0aXZlIGlzIHRoZSByYXRlIG9mIGNoYW5nZSBvZiBhIGZ1bmN0aW9uIGF0IGEgZ2l2ZW4gcG9pbnQsIGRlcml2aW5nIGEgQ0RGIGFjcm9zcyB0aGUgZW50aXJldHkgb2YgaXRzIGJvdW5kcyBhbGxvd3MgZm9yIGFuIHVuZGVyc3RhbmRpbmcgb2YgaG93IHJlbGF0aXZlIHByb2JhYmlsaXR5IGNoYW5nZXMgdGhyb3VnaG91dC4gQmVsb3cgYXJlIHRoZSBGaXNrIGRpc3RyaWJ1dGlvbidzIFBERiBhbmQgQ0RGLCBkZW5vdGVkIGJ5IGYoeCkgYW5kIEYoeCkgcmVzcGVjdGl2ZWx5LgoKCmBgYHtyfQpDREZfZnVuY3Rpb24gPSBmdW5jdGlvbih4LCBhbHBoYSwgYmV0YSl7CjEvKDErKHgvYWxwaGEpXigtYmV0YSkpCn0KCkNERl9leHByZXNzaW9uID0gZXhwcmVzc2lvbigKICAxLygxKyh4L2FscGhhKV4oLWJldGEpKQogICkKCgojIENyZWF0aW5nIGJvdGggYW4gZXhwcmVzc2lvbiBvYmplY3QgYW5kIGZ1bmN0aW9uIG9iamVjdCBzaW5jZSB0aGUgZGVyaXYgZnVuY3Rpb24gSSBhbSBhYm91dCB0byB1c2Ugb25seSB0YWtlcyBleHByZXNzaW9uIG9iamVjdHMKICAKICAjIFdpbGwgdXNlIEQgZnVuY3Rpb24gdG8gc2VlIHRoZSByZXR1cm5lZCBQREYgaW4gYWxnZWJyYWljIGZvcm0KICAjIFdpbGwgdXNlIGRlcml2IGZ1bmN0aW9uIHRvIGdldCBhbiBleHByZXNzaW9uIHRoYXQgY2FuIGJlIHVzZWQgZm9yIGV2YWx1YXRpb25zCgojIyBQREYgPSBmaXJzdCBkZXJpdmF0aXZlIG9mIENERgpQREZEID0gRChDREZfZXhwcmVzc2lvbiwgIngiKQojUERGRCAgIyA9ICgoeC9hbHBoYSleKCgtYmV0YSkgLSAxKSAqICgoLWJldGEpICogKDEvYWxwaGEpKS8oMSArICgoeC9hbHBoYSleKC1iZXRhKSkpXjIpCiAgIyBXcm90ZSB0aGlzIGRvd24sIGRpZCBzb21lIGFkZGl0aW9uYWwgYWxnZWJyYSBiZWZvcmUgd3JpdGluZyB1cCBMYXRleCBiZWxvdwoKUERGX0Z1bmN0aW9uID0gZnVuY3Rpb24oeCwgYWxwaGEsIGJldGEpewogIGlmZWxzZSh4IDw9IDAsIDAsCiAgICAgICAgIChiZXRhL2FscGhhKSAqICh4L2FscGhhKV4oYmV0YSAtIDEpIC8gKDEgKyAoeC9hbHBoYSleYmV0YSleMikKfQogICMgSGFkIHRvIGluY2x1ZGUgdGhlIGlmZWxzZSBjb21wb25lbnQgYmVjYXVzZSB4IHdpbGwgYWx3YXlzIGJlIHBvc2l0aXZlIGluIHRoZSBzY2VuYXJpbyBvZiBvdXIgZGF0YSAocmVjb3ZlcnkgdGltZXMpIGFuZCBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIHByb3BlcnRpZXMgb2YgdGhlIEZpc2sgZGlzdHJpYnV0aW9uCiAgICAjIEkgcHJldmlvdXNseSBkaWQgTk9UIGhhdmUgdGhhdCBpZmVsc2UgY29tcG9uZW50IGFuZCBteSB2aXN1YWwgY29uZmlybWF0aW9uIGZ1cnRoZXIgYWxvbmcgd2FzIG5vdCBlZmZlY3RpdmUKCgpQREZfZGVyaXYgPSBkZXJpdihDREZfZXhwcmVzc2lvbiwgIngiKQoKYGBgCgoKJCR7XExhcmdlIEYoeCkgPSBcZnJhY3sxfXsxICsgKHgvXGFscGhhKV57LVxiZXRhfX19IFxoc3BhY2V7MC41Y219XExhcmdlICwgXGhzcGFjZXswLjVjbX0gWD49MCAgJCQKPGJyPgoKCiQke1xMYXJnZSBmKHgpID0gXGZyYWN7XGJldGF9e1xhbHBoYX0gKiBcZnJhY3soeC9cYWxwaGEpXntcYmV0YS0xfX17XGFscGhhKDErKHgvXGFscGhhKV5cYmV0YSleMn19IFxoc3BhY2V7MC41Y219XExhcmdlICwgXGhzcGFjZXswLjVjbX1YPj0wICAkJAo8YnI+CgoKIyAyLikgUmVjb3ZlcnkgVGltZSBEaXN0cmlidXRpb24KVGhlIGRhdGFzZXQgd2UgaGF2ZSBvbiBoYW5kIGlzIGNvbXBvc2VkIG9mIDUwIGRpZmZlcmVudCBwYXRpZW50cycgb2JzZXJ2ZWQgcmVjb3ZlcnkgdGltZXMgKGluIGRheXMpIGZvbGxvd2luZyBhIHBhcnRpY3VsYXIga25lZSBzdXJnZXJ5IHByb2NlZHVyZS4gV2Ugd2lsbCBvcGVyYXRlIHRoZSBhbmFseXNpcyBvZiB0aGlzIGRhdGFzZXQgdW5kZXIgdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgdW5kZXJseWluZyBwb3B1bGF0aW9uIG9mIGtuZWUgc3VyZ2VyeSByZWNvdmVyeSB0aW1lcyBpcyBkaXN0cmlidXRlZCBpbiBhIGxvZy1sb2dpc3RpYyBtYW5uZXIuIEJlbG93IGFyZSBib3RoIHRoZSBzdW1tYXJ5IHN0YXRpc3RpY3MgYW5kIGEgaGlzdG9ncmFtIG9mIHRoZSBkYXRhc2V0J3MgdmFsdWVzLgoKYGBge3IsIGZpZy5oZWlnaHQ9NX0KRGF5cyA9IGMoOC4yMywgMTIuNzQsIDE0LjgzLCAxNi42MSwgMTguMTYsIDE5LjU1LCAyMC44MCwgMjEuOTQsIDIzLjAwLCAyMy45OCwgMjQuODksIDI1Ljc1LCAyNi41NiwgCjI3LjM0LCAyOC4wOCwgMjguNzksIDI5LjQ4LCAzMC4xNSwgMzAuODEsIDMxLjQ1LCAzMi4wOCwgMzIuNzAsIDMzLjMxLCAzMy45MiwgMzQuNTMsIDM1LjEzLCAKMzUuNzMsIDM2LjMzLCAzNi45MywgMzcuNTMsIDM4LjE0LCAzOC43NSwgMzkuMzcsIDQwLjAwLCA0MC42NCwgNDEuMjksIDQxLjk1LCA0Mi42MywgNDMuMzMsIAo0NC4wNSwgNDQuNzksIDQ1LjU2LCA0Ni4zNiwgNDcuMjAsIDQ4LjA4LCA0OS4wMiwgNTAuMDMsIDUxLjEyLCA1Mi4zMiwgNTMuNjUpCiAgIyBuID0gNTAKRGF0YV9EYXlzID0gZGF0YS5mcmFtZShEYXlzKQoKc3VtX3N0YXRzX3RhYmxlID0gZnVuY3Rpb24odmFyaWFibGUpewogIHRhYmxlID0gY2JpbmQoCiAgICByb3VuZChtaW4odmFyaWFibGUpLDIpLAogICAgcm91bmQocXVhbnRpbGUodmFyaWFibGUsIDAuMjUpLDIpLAogICAgcm91bmQobWVkaWFuKHZhcmlhYmxlKSwyKSwKICAgIHJvdW5kKG1lYW4odmFyaWFibGUpLDIpLAogICAgcm91bmQocXVhbnRpbGUodmFyaWFibGUsIDAuNzUpLDIpLAogICAgcm91bmQobWF4KHZhcmlhYmxlKSwyKQogICkKICBjb2xuYW1lcyh0YWJsZSkgPSBjKCJNaW4iLCAiUTEiLCAiTWVkIiwgIk1lYW4iLCAiUTMiLCAiTWF4IikKICByb3duYW1lcyh0YWJsZSkgPSBOVUxMCiAgcmV0dXJuKHRhYmxlKQp9CiAgIyBJIGNyZWF0ZWQgYSB0YWJsZSBmb3Igc3VtbWFyeSBzdGF0aXN0aWNzIG9mIGEgdmFyaWFibGUsIGNhbiB1c2UgdGhpcyBtb3ZpbmcgZm9yd2FyZCBpbnN0ZWFkIG9mIG1hbnVhbGx5IHB1dHRpbmcgdGhlIHN1bW1hcnkgc3RhdHMgaW4gdGFibGUgZm9ybQoKClN1bW1hcnlfVGFibGUgPSBzdW1fc3RhdHNfdGFibGUodmFyaWFibGUgPSBEYXlzKQprYWJsZShTdW1tYXJ5X1RhYmxlLGFsaWduID0gImMiLAogICAgICBjYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojIzAwMDAwMDsnPlN1bW1hcnkgU3RhdHMgb2YgUmVjb3ZlcnkgVGltZXM8L3NwYW4+IikgJT4lCiAga2FibGVfc3R5bGluZygKICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJib3JkZXJlZCIpLAogICAgZnVsbF93aWR0aCA9IEZBTFNFLAogICAgcG9zaXRpb24gPSAiY2VudGVyIikKCgpoaXN0KERheXMsIAogICAgIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIFJlY292ZXJ5IFRpbWVzIiwKICAgICB4bGFiID0gIlJlY292ZXJ5IFRpbWUgKERheXMpIiwKICAgICB5bGFiID0gIkNvdW50IiwKKQpib3gobHdkPTMpCgpgYGAKCiMjIDJhLikgTW9tZW50IEVzdGltYXRpb24KCkFzIHN0YXRlZCBhYm92ZSwgd2UgYXJlIG9wZXJhdGluZyB1bmRlciB0aGUgYXNzdW1wdGlvbiBvZiBvdXIgZGF0YSBzdGVtbWluZyBmcm9tIGEgRmlzayBkaXN0cmlidXRpb24uIFRoZXJlZm9yZSwgdGhlcmUgYXJlIHR3byBwb3B1bGF0aW9uIHBhcmFtZXRlcnMgb2YgaW50ZXJlc3QsICRcYWxwaGEkIChyYXRlIG9mIHNjYWxlKSBhbmQgJFxiZXRhJCAocmF0ZSBvZiBzaGFwZSksIHdoaWNoIHdlIHdvdWxkIGxpa2UgdG8gdXNlIG91ciBzYW1wbGUgZGF0YSB0byBlc3RpbWF0ZS4gCgpVc2luZyBtb21lbnQgZXN0aW1hdGlvbiwgZ2VuZXJhbCBmb3JtdWxhIHRlbGxzIHVzIHRoYXQgdGhlIGt0aCBtb21lbnQgKCRtX2skKSBvZiBhIGRpc3RyaWJ1dGlvbiBjYW4gYmUgZm91bmQgYnkgc3VtbWluZyBzYWlkIGRhdGFzZXQncyB2YWx1ZXMgKGVhY2ggcmFpc2VkIHRvIHRoZSBrIHBvd2VyKSBhbmQgdGhlbiBkaXZpZGVkIGJ5IHRoZSBzYW1wbGUgc2l6ZS4gQWRkaXRpb25hbGx5LCBhbmQgbW9yZSBzcGVjaWZpY2FsbHkgdG8gdGhlIEZpc2sgZGlzdHJpYnV0aW9uLCB3ZSBjYW4gZGlyZWN0bHkgZXF1YXRlIHRoZSBkaWZmZXJlbnQgbW9tZW50cyBvZiBhIGRpc3RyaWJ1dGlvbiB0byBmdW5jdGlvbnMgb2YgdGhlICRcYWxwaGEkIGFuZCAkXGJldGEkIHBhcmFtZXRlcnMuIFRoZSBmb3JtdWxhcyBhbmQgY2FsY3VsYXRpb25zIG9mIHRoZSBmaXJzdCB0d28gbW9tZW50cyAoJG1fMSQgYW5kICRtXzIkKSBhcmUgYmVsb3cuCgpgYGB7cn0KIyMgUmVmZXJlbmNlIFNlY3Rpb24gNC4yIGV4YW1wbGUgMiBmcm9tIGxlY3R1cmUgbm90ZXMKCiMgTWVhbiBvZiBsb2cgbG9naXN0aWMgZGlzdHJpYnV0aW9uID0gKGFscGhhICogcGkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgIC8gKGJldGEgKiBzaW4oYWxwaGEvYmV0YSkpCgojIyBSZWZlcmVuY2UgZm9ybXVsYSBmcm9tIFNlY3Rpb24gMy4xCiMgbW9tZW50IDEgPSBtZWFuIG9mIGRhdGEgIyA9IDM0LjE5MjIgPSAoYWxwaGEgKiBwaSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjICAgICAgLyAoYmV0YSAqIHNpbihhbHBoYS9iZXRhKSkKCiMgbW9tZW50IDIgPSBtZWFuIG9mIChkYXRhIHNxdWFyZWQpID0gMTI4OC44NDUKCk1vbWVudDEgPSBtZWFuKERheXMpCk1vbWVudDIgPSBtZWFuKERheXNeMikKYGBgCgokJFxMYXJnZSBNb21lbnQgMSA9IHtcYWxwaGFeMSpcR2FtbWEoMSArIDEvXGJldGEpICogXEdhbW1hKDEgLSAxL1xiZXRhKX0gPSAgXGJhcnt4fSBcYXBwcm94IGByIE1vbWVudDFgICAkJAoKJCRcTGFyZ2UgTW9tZW50IDIgPSB7XGFscGhhXjIqXEdhbW1hKDEgKyAyL1xiZXRhKSAqIFxHYW1tYSgxIC0gMi9cYmV0YSl9ID0gIFxiYXJ7eF4yfSBcYXBwcm94IGByIE1vbWVudDJgICAkJAoKVXRpbGl6aW5nIG91ciBkYXRhc2V0J3MgZmlyc3QgdHdvIG1vbWVudHMsIHdlIHRoZW4gY3JlYXRlIGEgc3lzdGVtIG9mIGVxdWF0aW9ucyB2aWEgUidzIDxzcGFuIHN0eWxlPSJjb2xvcjpibHVlOyI+dW5pcm9vdDwvc3Bhbj4gIGFuZCBjdXN0b20gPHNwYW4gc3R5bGU9ImNvbG9yOmJsdWU7Ij5mdW5jdGlvbjwvc3Bhbj4gY2FwYWJpbGl0aWVzLCB0byBlc3RpbWF0ZSAkXGFscGhhJCBhbmQgJFxiZXRhJCB0aG91Z2ggbnVtZXJpY2FsIG1ldGhvZHMuIE51bWVyaWNhbCBtZXRob2RzIGFyZSBuZWVkZWQgc2luY2UgcHVyZSBhbGdlYnJhaWMgdGFjdGljcyBhcmUgdW5hYmxlIHRvIHNvbHZlIHRoZSBpbmVxdWFsaXRpZXMgZm9yIHRoaXMgZGlzdHJpYnV0aW9uLiBTaW5jZSB3ZSBhcmUgZmluZGluZyAqZXN0aW1hdGVzKiBvZiB0aGUgYnJvYWRlciBwb3B1bGF0aW9uIHBhcmFtZXRlcnMgb2YgYSBGaXNrIGRpc3RyaWJ1dGVkIHBvcHVsYXRpb24sIHdlIGxhYmVsIHRoZXNlIGVzdGltYXRlcyAkXGhhdHtcYWxwaGF9JCBhbmQgJFxoYXR7XGJldGF9JCB0byByZXByZXNlbnQgJFxhbHBoYSQgYW5kICRcYmV0YSQgcmVzcGVjdGl2ZWx5LgoKYGBge3J9CiMjIEZyb20gYXNzaWdubWVudCBpbnN0cnVjdGlvbnM6CiMjIChhbHBoYV5rKSAqIGJldGEgZnVuY3Rpb24gKDEgKyAoay9iZXRhKSwgMSAtIChrL2JldGEpKQogICMgQ2FwaXRhbCBCIGRlbm90ZXMgdGhlIGJldGEgZnVuY3Rpb24KCgpCZXRhX0hhdCA9IHVuaXJvb3QoZnVuY3Rpb24oQmV0YSl7CiAgICAjIFRoZSB1bmlyb290IGZ1bmN0aW9uIHRlbGxzIHVzIHdoYXQgdmFsdWUgb2Ygc3BlY2lmaWMgdmFyaWFibGUgd2lsbCBsZWFkIG91ciBmdW5jdGlvbiB0byBlcXVhbCB6ZXJvIG9yIGFwcHJvYWNoIHplcm8KICAgICMgSW4gdGhpcyBjYXNlLCB3ZSBhcmUgZmluZGluZyBmKGJldGEpID0gMCBiZWNhdXNlIHRoZXJlIGlzIG5vdCBhbiBhbGdlYnJhaWMgd2F5IHRvIGZpbmQgYSBkaWZmZXJlbmNlIG9mIHplcm8gYmV0d2VlbiBzYW1wbGUgdmFyaWFuY2UgYW5kIHRoZW9yZXRpY2FsIHZhcmlhbmNlCiAgCiAgQSA9IChwaS9CZXRhKS8KICAgICAgICBzaW4ocGkvQmV0YSkKICAgICMgT25lIHBvcnRpb24gb2YgRmlzayBEaXN0cmlidXRpb24gdmFyaWFuY2UgZm9ybXVsYQogIAogIEIgPSAoMipwaS9CZXRhKS8KICAgICAgc2luKDIqcGkvQmV0YSkKICAgICMgT3RoZXIgcG9ydGlvbiBvZiBGaXNrIERpc3RyaWJ1dGlvbiB2YXJpYW5jZSBmb3JtdWxhCiAgCiAgQWxwaGFfQmV0YSA9IE1vbWVudDEgLyBBCiAgQWxwaGFfQmV0YV4yICogKEIgLSBBXjIpIC0gKE1vbWVudDIgLSBNb21lbnQxXjIpCn0sIGxvd2VyID0gMi4wMDAwMDEsIHVwcGVyID0gMjAwMDAwMCkkcm9vdAogICMgU2V0IGxvd2VyIGJvdW5kIG9mIHNlYXJjaCB0byAyLjAwMDAwMSBiZWNhdXNlLCBwZXIgcHJvcGVydGllcyBvZiBGaXNrIERpc3RyaWJ1dGlvbiBtb21lbnRzLCBiZXRhIG11c3QgYmUgZ3JlYXRlciB0aGFuIG1vbWVudCAyIGluIG9yZGVyIGZvciB2YXJpYW5jZSB0byBleGlzdAogICMgdXBwZXIgYm91bmQgc2V0IGFyYml0cmFyaWx5CgpBbHBoYV9IYXQgPSBNb21lbnQxIC8gKChwaS9CZXRhX0hhdCkvc2luKHBpL0JldGFfSGF0KSkKCmludmlzaWJsZSgKICBBbHBoYV9IYXQKKQoKaW52aXNpYmxlKAogIEJldGFfSGF0CikKYGBgCgoKJCRcTGFyZ2UgXGhhdHtcYWxwaGF9IFxhcHByb3ggYHIgcm91bmQoQWxwaGFfSGF0LDIpYCQkCiQkXExhcmdlIFxoYXR7XGJldGF9IFxhcHByb3ggYHIgcm91bmQoQmV0YV9IYXQsMilgJCQKClRvIGNvbmZpcm0gcmVsYXRpdmUgYWNjdXJhY3kgb2Ygb3VyIGVzdGltYXRlcywgYmVsb3cgSSBvdmVybGFpZCB0aGUgRmlzayBkaXN0cmlidXRpb24ncyBQREYgd2l0aCBnaXZlbiBhbHBoYSBhbmQgYmV0YSBwYXJhbWV0ZXJzIG92ZXIgdG9wIG91ciBhdmFpbGFibGUgc2FtcGxlIGRhdGEgb2YgcGF0aWVudCByZWNvdmVyeSB0aW1lcy4gVGhlcmUgaXMgbW9kZXJhdGUgb3ZlcmxhcCBiZXR3ZWVuIG91ciBkaXN0cmlidXRpb24gY3VydmUgYW5kIGhpc3RvZ3JhbSBkYXRhLiBUaGlzIGxlYWRzIG1lIHRvIGJlbGlldmUgdGhhdCB0aGVyZSB2ZXJ5IHdlbGwgY291bGQgYmUgYW4gdW5kZXJlc3RpbWF0ZSBvZiBvdXIgJFxhbHBoYSQgcGFyYW1ldGVyLCBhcyB0aGUgdmFsdWUgb2YgJFxhbHBoYSQgdHJhZGl0aW9uYWxseSBjb250cm9scyB0aGUgaG9yaXpvbnRhbCBsb2NhdGlvbiBvZiBhIGN1cnZlJ3MgcGVhayBhbmQgZGVjbGluZS4KCmBgYHtyLCBmaWcuaGVpZ2h0PTV9Cmhpc3QoRGF5cywgCiAgICAgbWFpbiA9ICJEaXN0cmlidXRpb24gb2YgUmVjb3ZlcnkgVGltZXMiLAogICAgIHhsYWIgPSAiUmVjb3ZlcnkgVGltZSAoRGF5cykiLAogICAgIHlsYWIgPSAiUHJvYmFiaWxpdHkgRGVuc2l0eSIsCiAgICAgeWxpbSA9IGMoMCwgMC4wNSksCiAgICAgYnJlYWtzID0gMTAsCiAgICAgcHJvYiA9IFRSVUUpCgoKY3VydmUoUERGX0Z1bmN0aW9uKHggLCBhbHBoYSA9IDMyLjY1NDMxLCBiZXRhID0gNi4wMDYyNDgpLCAKICAgICAgY29sID0gInJlZCIsCiAgICAgIGx3ZCA9IDMsCiAgICAgIGFkZCA9IFRSVUUpCgpsZWdlbmQoInRvcHJpZ2h0IiwKICAgICAgIGxlZ2VuZCA9ICJGaXNrICgzMi42NSwgNi4wNykiLAogICAgICAgY29sID0gInJlZCIsCiAgICAgICBsd2QgPSAzLAogICAgICAgYm94Lmx3ZD0zKQoKYm94KGx3ZD0zKQpgYGAKCgojIyAyYi4pIApHaXZlbiB0aGUgaW5oZXJlbnQgdmFyaWF0aW9uIHRoYXQgZXhpc3RzIGluIHNhbXBsaW5nLCBJIGNob3NlIHRvIGV4ZWN1dGUgYSBib290c3RyYXBwaW5nIHNlcXVlbmNlLiBJIHBlcmZvcm1lZCAxLDAwMCBpdGVyYXRpb25zIG9mIHNhbXBsZXMgKG4gPSA1MCBlYWNoIHRpbWUpIGZvciBib3RoIG91ciBwYXJhbWV0ZXJzIGVzdGltYXRvcnMsICRcaGF0e1xhbHBoYX0kIGFuZCAkXGhhdHtcYmV0YX0kLiAKClBpY3R1cmVkIGJlbG93IGFyZSB0aGUgc2FtcGxpbmcgZGlzdHJpYnV0aW9ucyBmb3IgYm90aCBwYXJhbWV0ZXJzLCBlYWNoIG9mIHRoZW0gd2l0aCBhIEdhdXNzaWFuIGtlcm5lbCBkZW5zaXR5IGN1cnZlIGxheWVyZWQgYWJvdmUgYW5kIHNhaWQgY3VydmUncyByZXNwZWN0aXZlIGJhbmR3aWR0aCBub3RhdGVkIGluIHBhcmVudGhlc2VzLiBCYW5kd2lkdGhzIHdlcmUgY2hvc2VuIGluIGFjY29yZGFuY2Ugd2l0aCBTaWx2ZXJtYW4ncyBzdGFuZGFyZCBmb3JtdWxhIGFuZCBjYWxjdWxhdGVkIHZpYSBhIGN1c3RvbS1idWlsdCBSIGZ1bmN0aW9uLgoKYGBge3J9CiMgQm9vdHN0cmFwIENhbGN1bGF0aW9ucwpzZXQuc2VlZCgxMDApCgpBbHBoYV9Cb290c3RyYXBzID0gMApCZXRhX0Jvb3RzdHJhcHMgPSAwCiAgIyBTZXQgdGhlc2UgdmFyaWFibGVzIGVxdWFsIHRvIHplcm8gYXMgdGhleSB3aWxsIGJlIGNvbnN0YW50bHkgdXBkYXRlZCB0aHJvdWdob3V0IHRoZSBmb3IgbG9vcCdzIGl0ZXJhdGlvbnMKCmZvcihpIGluIDE6MTAwMCl7CiAgaXRoX1NhbXBsZSA9IHNhbXBsZShEYXlzLCBzaXplID0gbGVuZ3RoKERheXMpLCByZXBsYWNlID0gVFJVRSkKICAgICMgQWx3YXlzIHVzZSByZXBsYWNlbWVudCB3aGVuIGJvb3RzdHJhcHBpbmcKICBpdGhfTW9tZW50MSA9IG1lYW4oaXRoX1NhbXBsZSkKICBpdGhfTW9tZW50MiA9IG1lYW4oaXRoX1NhbXBsZV4yKQogIAojIENvcGllZCBmdW5jdGlvbiBmcm9tIHBhcnQgMmE6IHJlbW92ZWQgY29tbWVudHMgYXMgcHJvY2VzcyBpcyB0aGUgc2FtZSBmb3IgZWFjaCBib290c3RyYXAgc2FtcGxlCiAgICAjIHVwZGF0ZWQgdmFyaWFibGUgbmFtZXMgZm9yIHRoZSBib290c3RyYXAgcHJvY2VkdXJlCiAgICBCb290X0JldGFfSGF0ID0gdW5pcm9vdChmdW5jdGlvbihCZXRhKXsKICAgIEEgPSAocGkvQmV0YSkvCiAgICAgICAgICBzaW4ocGkvQmV0YSkKICAgIAogICAgQiA9ICgyKnBpL0JldGEpLwogICAgICAgIHNpbigyKnBpL0JldGEpCiAgICAKICAgIEFscGhhX0JldGEgPSBpdGhfTW9tZW50MSAvIEEKICAgIEFscGhhX0JldGFeMiAqIChCIC0gQV4yKSAtIChpdGhfTW9tZW50MiAtIGl0aF9Nb21lbnQxXjIpCiAgfSwgbG93ZXIgPSAyLjAwMDAwMSwgdXBwZXIgPSAyMDAwMDAwKSRyb290CiAgCiAgQm9vdF9BbHBoYV9IYXQgPSBpdGhfTW9tZW50MSAvICgocGkvQmV0YV9IYXQpL3NpbihwaS9CZXRhX0hhdCkpCiAgCiAgQWxwaGFfQm9vdHN0cmFwc1tpXSA9IEJvb3RfQWxwaGFfSGF0CiAgQmV0YV9Cb290c3RyYXBzW2ldID0gQm9vdF9CZXRhX0hhdAp9CmBgYAoKCmBgYHtyLCBmaWcuaGVpZ2h0PTV9CgojIyBDcmVhdGUgY3VzdG9tIGZ1bmN0aW9uIGZvciBmaW5kaW5nIEdhdXNzaWFuIGJ3IHF1aWNrbHkgaW4gZnV0dXJlCkdhdXNzaWFuX0JXID0gZnVuY3Rpb24oRGF0YSl7CiAgSVFSID0gcXVhbnRpbGUoRGF0YSwgMC43NSkgLSBxdWFudGlsZShEYXRhLCAwLjI1KQogIE1pbl9QYXJ0ID0gbWluKHNkKERhdGEpLChJUVIvMS4zNCkpCiAgQlcgPSAwLjkgKiBNaW5fUGFydCAqIChsZW5ndGgoRGF0YSleKC0wLjIpKQogIHJldHVybihCVykKfQoKaW52aXNpYmxlKAogIEdhdXNzaWFuX0JXKERhdGEgPSBBbHBoYV9Cb290c3RyYXBzKSAjID0gMC4zMTgzMDk5CikKCgpoaXN0KEFscGhhX0Jvb3RzdHJhcHMsCiAgICAgbWFpbiA9ICJCb290c3RyYXAgRGlzdHJpYnV0aW9uIG9mIEFscGhhIEhhdCIsCiAgICAgeGxhYiA9ICJTYW1wbGluZyBNZWFucyIsCiAgICAgeWxhYiA9ICJQcm9iYWJpbGl0eSBEZW5zaXR5IiwKICAgICBwcm9iID0gVFJVRQogICAgICkKCiMgYmFuZHdpZHRoIGNhbGN1bGF0aW9ucyBiZWxvdwpHYXVzc2lhbiA9IGRlbnNpdHkoQWxwaGFfQm9vdHN0cmFwcywgYncgPSAwLjMxODMwOTksIGtlcm5lbCA9ICJnYXVzc2lhbiIpCmxpbmVzKEdhdXNzaWFuLAogICAgICBsd2QgPSAzLAogICAgICBjb2wgPSAiYmx1ZSIKICAgICAgKQoKbGVnZW5kKCJ0b3ByaWdodCIsCiAgICAgICBsZWdlbmQgPSAiR2F1c3NpYW4gKDAuMzIpIiwKICAgICAgIGNvbCA9ICJibHVlIiwKICAgICAgIGx3ZCA9IDMsCiAgICAgICBib3gubHdkPTMpCgpib3gobHdkPTMpCmBgYAoKYGBge3IsIGZpZy5oZWlnaHQ9NX0KCmludmlzaWJsZSgKICBHYXVzc2lhbl9CVyhEYXRhID0gQmV0YV9Cb290c3RyYXBzKSAjID0gMC4xMzAzMjg2CikKCmhpc3QoQmV0YV9Cb290c3RyYXBzLAogICAgIG1haW4gPSAiQm9vdHN0cmFwIERpc3RyaWJ1dGlvbiBvZiBCZXRhIEhhdCIsCiAgICAgeGxhYiA9ICJTYW1wbGluZyBNZWFucyIsCiAgICAgeWxhYiA9ICJQcm9iYWJpbGl0eSBEZW5zaXR5IiwKICAgICBwcm9iID0gVFJVRSwKICAgICB5bGltID0gYygwLDAuNykKICAgICApCmJveChsd2Q9MykKCkdhdXNzaWFuID0gZGVuc2l0eShCZXRhX0Jvb3RzdHJhcHMsIGJ3ID0gMC4xMzAzMjg2LCBrZXJuZWwgPSAiZ2F1c3NpYW4iKQpsaW5lcyhHYXVzc2lhbiwKICAgICAgbHdkID0gMywKICAgICAgY29sID0gImJsdWUiCiAgICAgICkKCmxlZ2VuZCgidG9wcmlnaHQiLAogICAgICAgbGVnZW5kID0gIkdhdXNzaWFuICgwLjEzKSIsCiAgICAgICBjb2wgPSAiYmx1ZSIsCiAgICAgICBsd2QgPSAzLAogICAgICAgYm94Lmx3ZD0zKQoKYGBgCgpXaGF0IHRoZSBib290c3RyYXAgZGlzdHJpYnV0aW9uIGZvciAkXGhhdHtcYWxwaGF9JCBhbmQgJFxoYXR7XGJldGF9JCBkaXNwbGF5IGlzIGEgZmFyICpncmVhdGVyKiByZXNlbWJsYW5jZSB3aXRoIHRoZWlyIEdhdXNzaWFuIFBERiBlc3RpbWF0aW9ucyB0aGFuIHdoYXQgd2FzIHNlZW4gYWJvdmUsIGNvbXBhcmluZyBvdXIgZGF0YSB0byB0aGUgY3VydmUgb2YgYSBzdGFuZGFyZCBGaXNrIGRpc3RyaWJ1dGlvbiB3aXRoIHNhaWQgdmFsdWVzIGZvciAkXGFscGhhJCBhbmQgJFxiZXRhJC4gCgpUd28gcG9zc2libGUgc3VnZ2VzdGlvbnMgdGhhdCB0aGlzIHJlbGV2YXRpb24gYnJpbmdzIGFyZTogcGVyaGFwcyB0aGUgcG9wdWxhdGlvbiBmcm9tIHdoaWNoIHRoZXNlIHNhbXBsZWQgc3VyZ2VyeSByZWNvdmVyeSB0aW1lcyBjYW1lIGZyb20gaXMgbm90IHRydWx5IGFzIEZpc2sgZGlzdHJpYnV0ZWQgYXMgd2UgaW5pdGlhbGx5IGJlbGlldmVkLCBvciBhcyBzdGF0ZWQgcHJldmlvdXNseSB0aGVyZSBjb3VsZCBiZSBhbiB1bmRlcmVzdGltYXRlIG9mIHRoZSAkXGFscGhhJCBwYXJhbWV0ZXIuCg==