Assignment Objectives

  • Master the fundamental concepts of point estimation and performance metrics

  • Understand the theoretical foundation of the method of moments estimator (MME)

  • Implement MME in R, incorporating numerical approximation methods


Use of 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.


Log-logistic Distribution

The log-logistic distribution (also known as the Fisk distribution) is a continuous probability distribution that is particularly useful in contexts where data exhibit non-negative, skewed behavior and where the hazard rate is unimodal (increases to a peak and then decreases). It has been widely used in the areas such as survival analysis and reliability engineering, environmental science, economics, pharmacology, finance and risk management, etc.

For given shape parameter \(\beta\) and scale parameter \(\alpha\), the cumulative distribution function

\[ F(x) = \frac{1}{1+(x/\alpha)^{-\beta}} \]

As an exercise, you can derive the density in the following form

\[ f(x) = \frac{(\beta/\alpha)(x/\alpha)^{\beta-1}}{[1+(x/\alpha)^\beta]^2}, \ \ \text{ for } \ \ x > 0. \]

After some algebra, we can find the \(k\)th moment

\[ \mu_k = E[X^k] = \alpha^k B\left(1+\frac{k}{\beta}, 1 - \frac{k}{\beta} \right). \]

This assignment will focus on finding MME of parameters \(\alpha\) and \(\beta\) based on a real-world application data set.


Question 1: Derive the log-logistic density function

Given the CDF of the two-parameter log-logistic distribution

\[ F(x) = \frac{1}{1+(x/\alpha)^{-\beta}}. \]

The probability density function is the derivative of the cumulative distribution function of the log-logistic function.

cdf = expression((1) /(1 + (x/alpha))^(-beta)) #write the CDF formula as an expression 
pdf = D(cdf, "x") #take the derivative of the cdf

print(pdf)
-((1) * ((1 + (x/alpha))^((-beta) - 1) * ((-beta) * (1/alpha)))/((1 + 
    (x/alpha))^(-beta))^2)


Question 2: Distribution of Recovery Time from A Surgery

Time to recovery (in days) after a specific knee surgery procedure. This follows a typical log-logistic pattern in medical survival/recovery analysis:

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

Based on the above data to perform the following analysis.

  1. Using method of moment estimation to estimate \(\alpha\) and \(\beta\), denoted by \(\hat{\alpha}\) and \(\hat{\beta}\), respectively.
recovery = 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)

hist(recovery)

s.recovery= sort(recovery)
#a

length(recovery) #n = 50
[1] 50
m1 = mean(recovery) #sample mean x_bar=34.1922
m2 =mean(recovery^2) #second moment #1288

mom_beta <- function(beta, m1, m2)
{
  term1 <- ( 2 * pi/ beta) /sin(2 * pi/beta)  #second moment
  term2 <- ((pi / beta) /sin (pi /beta))^2  #square of mean divided by alpha squared
  
  return(term1 / term2 - (m2 / m1^2))
}
#info found: ://efaidnbmnnnibpcajpcglclefindmkaj/https://www.math.wm.edu/~leemis/chart/UDR/PDFs/Loglogistic.pdf

#nonlinear function must solve for beta
    sol_beta <- uniroot(mom_beta, interval = c(2.1, 20), m1 = m1, m2 = m2)$root
#subsitute beta to find alpha
    sol_alpha <- m1 / ((pi / sol_beta) / sin(pi / sol_beta))
    
# Print Results
cat("Estimated Alpha (Scale/Median):", sol_alpha, "\n") #Estimated Alpha (Scale/Median): 32.6543 
Estimated Alpha (Scale/Median): 32.6543 
cat("Estimated Beta (Shape/Width):", sol_beta, "\n")  #Estimated Beta (Shape/Width): 6.006232 
Estimated Beta (Shape/Width): 6.006232 

Estimated Alpha (Scale/Median): 32.6543 Estimated Beta (Shape/Width): 6.006232

The median recovery time for a patient is 32.65 days. As a lower beta value at 6 we know that recovery time over all in our sample have similar times. In other words the shape of our distribution is not very wide, suggesting there is large variety of time differences in the data; this does not occur.

  1. Since the moment estimates \(\hat{\alpha}\) and \(\hat{\beta}\) are random, construct bootstrap sampling distributions for each. To visualize these distributions, plot separate bootstrap histograms for \(\hat{\alpha}\) and \(\hat{\beta}\). hen, overlay a smooth density curve on each histogram using Gaussian kernel density estimation. Finally, describe the patterns of these density curves.
set.seed(325)

boot_alpha = NULL
boot_beta = NULL

for(i in 1:1000)
{
  sample_i = sample(recovery, size=50, replace = TRUE) #random sample from the sample recovery
  
  #calculate moments from the specific samples
  
m1_i = mean(sample_i)  #first moment
m2_i = mean(sample_i^2) #second moment
  
  boot_beta[i] = uniroot(mom_beta, interval = c(2.1, 20), m1 = m1_i, m2 = m2_i)$root
#subsitute beta to find alpha
  boot_alpha[i] = m1_i / ((pi /boot_beta[i]) / sin(pi / boot_beta[i]))


}



# Create data frame for plotting
boot_results <- data.frame(alpha = boot_alpha, beta = boot_beta)
# Plotting the boot straps of alpha and beta parameters (boot_results data frame)
bootsggp <- ggplot(boot_results) +
  #Graph the Alpha density
  geom_density(aes(x = alpha, color = "alpha"), size = 1) +
  # Graph the Beta density
  geom_density(aes(x = beta, color = "beta"), size = 1) +
  
  labs(title = "Bootstrap Distributions for Alpha (Recovery time) and Beta Log-Logistic Parameters",
       x = "Estimate Value", 
       y = "Density") +
  scale_color_manual(name = "Parameters", 
                     values = c("alpha" = "red", "beta" = "blue")) +
  theme_minimal() +
  theme(plot.title = element_text(hjust = 0.5))

# Interactive graph
ggplotly(bootsggp)

This graph places the distributions of both the alpha distribution and the beta distribution on the same place. We see the estimated bootstrap value of the beta (\(\beta\) = 5.837965) is far lower than the estimated bootstrap alpha (\(\alpha\) = 30.89606). Additionally the alpha take on a wider range of values than the beta distribution, suggesting the beta value has more precision in our distribution. In other words, the shape of our data set, or how similar our data set to like recovery times is likely more consistent than the spread of our data, the distance between the ends of our data.

Additionally, our bootstrap estimated alpha values are similar to the moment of estimation value of 32.6542985 as well as the beta bootstrap and moment of estimation at 6.0062322, suggesting both the moment of estimations hold little bias.

The Bootstrap Parameter’s Alpha and Beta graphed separately with their respective kernels are below.

#To visualize these distributions, plot separate bootstrap histograms for $\hat{\alpha}$ and $\hat{\beta}$.  hen, overlay a smooth density curve on each histogram using Gaussian kernel density estimation. Finally, describe the patterns of these density curves.

#graphing the Bootstrap Parameter's separately with their respective kernels

# Plotting Parameter Alpha (Scale)
p_alpha <- ggplot(boot_results, aes(x = alpha)) +
  # The raw data (Histogram)
  geom_histogram(aes(y = ..density..), bins = 30, fill = "gray80", color = "white") +
  # The Smoothing Line (Gaussian Kernel)
  geom_density(color = "red", size = 1, kernel = "gaussian") +
  labs(title = "Bootstrap Distribution for Alpha - Recovery Time",
       subtitle = "Red line = Gaussian Kernel Smoothing",
       x = "Alpha (Days)", y = "Density") +
  theme_minimal()

# Separate plot for Parameter Beta (Shape)
p_beta <- ggplot(boot_results, aes(x = beta)) +
  # The raw data (Histogram)
  geom_histogram(aes(y = ..density..), bins = 30, fill = "gray80", color = "white") +
  # The Smoothing Line (Gaussian Kernel)
  geom_density(color = "blue", size = 1, kernel = "gaussian") +
  labs(title = "Bootstrap Distribution for Beta",
       subtitle = "Blue line = Gaussian Kernel Smoothing",
       x = "Beta (Shape Parameter)", y = "Density") +
  theme_minimal()

#Print interactive graphs
ggplotly(p_alpha) 
ggplotly(p_beta)

The alpha parameter, the parameter providing scale for the bootstrap distribution with its gaussian kernel looks approximately normal, meeting the assumption of mean of a bootstrap distribution. In other words, the bootstrap distribution looks as expected.

The beta parameter also looks to take a generally normal distribution, although may have slight skew. May suggest our normal based approximation may have some noise in the data, may not be the best estimation possible. An additional recommendation could be to alter the bandwidth of the smoothing of the Gaussian kernel, although the kernel looks generally smooth.

In respect to the recovery time data set, knee surgery recovery time, alpha, is about 31 days, and through the beta value, this is a consistent number across most patients.

LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMzogTWV0aG9kcyBvZiBNb21lbnQgRXN0aW1hdGlvbiINCmF1dGhvcjogIkV6YW5hIFJpdmVycyINCmRhdGU6ICIgRHVlOiAyLTI0LTI2Ig0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIHRvY19mbG9hdDogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiBubw0KICAgIHRvY19jb2xsYXBzZWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIHNtb290aF9zY3JvbGw6IHllcw0KICAgIHRoZW1lOiBsdW1lbg0KICBwZGZfZG9jdW1lbnQ6IA0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiA0DQogICAgZmlnX2NhcHRpb246IHllcw0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiAzDQogICAgZmlnX2hlaWdodDogMw0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCmVkaXRvcl9vcHRpb25zOiANCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQ0KLS0tDQoNCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0NCiNUT0M6OmJlZm9yZSB7DQogIGNvbnRlbnQ6ICJUYWJsZSBvZiBDb250ZW50cyI7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LXNpemU6IDEuMmVtOw0KICBkaXNwbGF5OiBibG9jazsNCiAgY29sb3I6IG5hdnk7DQogIG1hcmdpbi1ib3R0b206IDEwcHg7DQp9DQoNCg0KZGl2I1RPQyBsaSB7ICAgICAvKiB0YWJsZSBvZiBjb250ZW50ICAqLw0KICAgIGxpc3Qtc3R5bGU6dXBwZXItcm9tYW47DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7ICAgIC8qIGxldmVsIDEgaGVhZGVyIG9mIHRpdGxlICAqLw0KICBmb250LXNpemU6IDIycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMTVweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiBzeXN0ZW0tdWk7DQogIGNvbG9yOiBuYXZ5Ow0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICBmb250LXNpemU6IDE4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KDQpib2R5IHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQ0KDQpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQ0KDQp9DQpgYGANCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgDQojIHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIG91dHB1dCBmaWxlcy4NCmlmICghcmVxdWlyZSgia25pdHIiKSkgew0KICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQ0KICAgbGlicmFyeShrbml0cikNCn0NCmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoInBhbmRlciIpDQogICBsaWJyYXJ5KHBhbmRlcikNCn0NCmlmICghcmVxdWlyZSgiZ2dwbG90MiIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICBsaWJyYXJ5KGdncGxvdDIpDQp9DQppZiAoIXJlcXVpcmUoInRpZHl2ZXJzZSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpDQogIGxpYnJhcnkodGlkeXZlcnNlKQ0KfQ0KDQppZiAoIXJlcXVpcmUoInBsb3RseSIpKSB7DQogIGluc3RhbGwucGFja2FnZXMoInBsb3RseSIpDQogIGxpYnJhcnkocGxvdGx5KQ0KfQ0KIyMjIw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUNCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsICAgIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91IGNhbiBjaG9vc2UgdG8gaW5jbHVkZSB0aGUgd2FybmluZyBtZXNzYWdlcyBpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgZmlsZS4gDQogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICAgICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGluIHRoZSBvdXRwdXQgZmlsZS4NCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BDQogICAgICAgICAgICAgICAgICAgICAgKSAgDQpgYGANCiANCiBcDQogDQojIyAqKkFzc2lnbm1lbnQgT2JqZWN0aXZlcyoqIA0KDQoqIE1hc3RlciB0aGUgZnVuZGFtZW50YWwgY29uY2VwdHMgb2YgcG9pbnQgZXN0aW1hdGlvbiBhbmQgcGVyZm9ybWFuY2UgbWV0cmljcw0KDQoqIFVuZGVyc3RhbmQgdGhlIHRoZW9yZXRpY2FsIGZvdW5kYXRpb24gb2YgdGhlIG1ldGhvZCBvZiBtb21lbnRzIGVzdGltYXRvciAoTU1FKQ0KDQoqIEltcGxlbWVudCBNTUUgaW4gUiwgaW5jb3Jwb3JhdGluZyBudW1lcmljYWwgYXBwcm94aW1hdGlvbiBtZXRob2RzDQoNClwNCg0KKipVc2Ugb2YgQUkgVG9vbHMqKg0KDQoqKlBvbGljeSBvbiBBSSBUb29sIFVzZSoqOiBTdHVkZW50cyBtdXN0IGFkaGVyZSB0byB0aGUgQUkgdG9vbCBwb2xpY3kgc3BlY2lmaWVkIGluIHRoZSBjb3Vyc2Ugc3lsbGFidXMuIFRoZSBkaXJlY3QgY29weWluZyBvZiBBSS1nZW5lcmF0ZWQgY29udGVudCBpcyBzdHJpY3RseSBwcm9oaWJpdGVkLiBBbGwgc3VibWl0dGVkIHdvcmsgbXVzdCByZWZsZWN0IHlvdXIgb3duIHVuZGVyc3RhbmRpbmc7IHdoZXJlIGV4dGVybmFsIHRvb2xzIGFyZSBjb25zdWx0ZWQsIGNvbnRlbnQgbXVzdCBiZSB0aG9yb3VnaGx5IHJlcGhyYXNlZCBhbmQgc3ludGhlc2l6ZWQgaW4geW91ciBvd24gd29yZHMuDQoNCioqQ29kZSBJbmNsdXNpb24gUmVxdWlyZW1lbnQqKjogQW55IGNvZGUgaW5jbHVkZWQgaW4geW91ciBlc3NheSBtdXN0IGJlIHByb3Blcmx5IGNvbW1lbnRlZCB0byBleHBsYWluIHRoZSBwdXJwb3NlIGFuZC9vciBleHBlY3RlZCBvdXRwdXQgb2Yga2V5IGNvZGUgbGluZXMuIFN1Ym1pdHRpbmcgQUktZ2VuZXJhdGVkIGNvZGUgd2l0aG91dCBtZWFuaW5nZnVsLCBzdHVkZW50LWFkZGVkIGNvbW1lbnRzIHdpbGwgbm90IGJlIGFjY2VwdGVkLg0KDQpcDQoNCioqTG9nLWxvZ2lzdGljIERpc3RyaWJ1dGlvbioqDQoNClRoZSBsb2ctbG9naXN0aWMgZGlzdHJpYnV0aW9uIChhbHNvIGtub3duIGFzIHRoZSBGaXNrIGRpc3RyaWJ1dGlvbikgaXMgYSBjb250aW51b3VzIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbiB0aGF0IGlzIHBhcnRpY3VsYXJseSB1c2VmdWwgaW4gY29udGV4dHMgd2hlcmUgZGF0YSBleGhpYml0IG5vbi1uZWdhdGl2ZSwgc2tld2VkIGJlaGF2aW9yIGFuZCB3aGVyZSB0aGUgaGF6YXJkIHJhdGUgaXMgdW5pbW9kYWwgKGluY3JlYXNlcyB0byBhIHBlYWsgYW5kIHRoZW4gZGVjcmVhc2VzKS4gSXQgaGFzIGJlZW4gd2lkZWx5IHVzZWQgaW4gdGhlIGFyZWFzIHN1Y2ggYXMgc3Vydml2YWwgYW5hbHlzaXMgYW5kIHJlbGlhYmlsaXR5IGVuZ2luZWVyaW5nLCBlbnZpcm9ubWVudGFsIHNjaWVuY2UsIGVjb25vbWljcywgcGhhcm1hY29sb2d5LCBmaW5hbmNlIGFuZCByaXNrIG1hbmFnZW1lbnQsIGV0Yy4gDQoNCkZvciBnaXZlbiBzaGFwZSBwYXJhbWV0ZXIgJFxiZXRhJCBhbmQgc2NhbGUgcGFyYW1ldGVyICRcYWxwaGEkLCB0aGUgY3VtdWxhdGl2ZSBkaXN0cmlidXRpb24gZnVuY3Rpb24NCg0KJCQNCkYoeCkgPSBcZnJhY3sxfXsxKyh4L1xhbHBoYSleey1cYmV0YX19DQokJA0KDQpBcyBhbiBleGVyY2lzZSwgeW91IGNhbiBkZXJpdmUgdGhlIGRlbnNpdHkgaW4gdGhlIGZvbGxvd2luZyBmb3JtDQoNCiQkDQpmKHgpID0gXGZyYWN7KFxiZXRhL1xhbHBoYSkoeC9cYWxwaGEpXntcYmV0YS0xfX17WzErKHgvXGFscGhhKV5cYmV0YV1eMn0sIFwgXCBcdGV4dHsgZm9yIH0gXCBcIHggPiAwLg0KJCQNCg0KQWZ0ZXIgc29tZSBhbGdlYnJhLCB3ZSBjYW4gZmluZCB0aGUgJGskdGggbW9tZW50DQoNCiQkDQpcbXVfayA9IEVbWF5rXSA9IFxhbHBoYV5rIEJcbGVmdCgxK1xmcmFje2t9e1xiZXRhfSwgMSAtIFxmcmFje2t9e1xiZXRhfSBccmlnaHQpLg0KJCQNCg0KVGhpcyBhc3NpZ25tZW50IHdpbGwgZm9jdXMgb24gZmluZGluZyBNTUUgb2YgcGFyYW1ldGVycyAkXGFscGhhJCBhbmQgJFxiZXRhJCBiYXNlZCBvbiBhIHJlYWwtd29ybGQgYXBwbGljYXRpb24gZGF0YSBzZXQuDQoNCg0KXA0KDQojIyAqKlF1ZXN0aW9uIDE6IERlcml2ZSB0aGUgbG9nLWxvZ2lzdGljIGRlbnNpdHkgZnVuY3Rpb24gKioNCg0KR2l2ZW4gdGhlIENERiBvZiB0aGUgdHdvLXBhcmFtZXRlciBsb2ctbG9naXN0aWMgZGlzdHJpYnV0aW9uDQoNCiQkDQpGKHgpID0gXGZyYWN7MX17MSsoeC9cYWxwaGEpXnstXGJldGF9fS4NCiQkDQoNCg0KVGhlIHByb2JhYmlsaXR5IGRlbnNpdHkgZnVuY3Rpb24gaXMgdGhlIGRlcml2YXRpdmUgb2YgdGhlIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uIG9mIHRoZSBsb2ctbG9naXN0aWMgZnVuY3Rpb24uIA0KDQpgYGB7cn0NCg0KY2RmID0gZXhwcmVzc2lvbigoMSkgLygxICsgKHgvYWxwaGEpKV4oLWJldGEpKSAjd3JpdGUgdGhlIENERiBmb3JtdWxhIGFzIGFuIGV4cHJlc3Npb24gDQpwZGYgPSBEKGNkZiwgIngiKSAjdGFrZSB0aGUgZGVyaXZhdGl2ZSBvZiB0aGUgY2RmDQoNCnByaW50KHBkZikNCg0KYGBgDQoNCg0KXA0KDQojIyAqKlF1ZXN0aW9uIDI6IERpc3RyaWJ1dGlvbiBvZiBSZWNvdmVyeSBUaW1lIGZyb20gQSBTdXJnZXJ5KioNCg0KVGltZSB0byByZWNvdmVyeSAoaW4gZGF5cykgYWZ0ZXIgYSBzcGVjaWZpYyBrbmVlIHN1cmdlcnkgcHJvY2VkdXJlLiBUaGlzIGZvbGxvd3MgYSB0eXBpY2FsICoqbG9nLWxvZ2lzdGljIHBhdHRlcm4qKiBpbiBtZWRpY2FsIHN1cnZpdmFsL3JlY292ZXJ5IGFuYWx5c2lzOg0KDQpgYGANCjguMjMsIDEyLjc0LCAxNC44MywgMTYuNjEsIDE4LjE2LCAxOS41NSwgMjAuODAsIDIxLjk0LCAyMy4wMCwgMjMuOTgsIDI0Ljg5LCAyNS43NSwgMjYuNTYsIA0KMjcuMzQsIDI4LjA4LCAyOC43OSwgMjkuNDgsIDMwLjE1LCAzMC44MSwgMzEuNDUsIDMyLjA4LCAzMi43MCwgMzMuMzEsIDMzLjkyLCAzNC41MywgMzUuMTMsIA0KMzUuNzMsIDM2LjMzLCAzNi45MywgMzcuNTMsIDM4LjE0LCAzOC43NSwgMzkuMzcsIDQwLjAwLCA0MC42NCwgNDEuMjksIDQxLjk1LCA0Mi42MywgNDMuMzMsIA0KNDQuMDUsIDQ0Ljc5LCA0NS41NiwgNDYuMzYsIDQ3LjIwLCA0OC4wOCwgNDkuMDIsIDUwLjAzLCA1MS4xMiwgNTIuMzIsIDUzLjY1DQpgYGANCkJhc2VkIG9uIHRoZSBhYm92ZSBkYXRhIHRvIHBlcmZvcm0gdGhlIGZvbGxvd2luZyBhbmFseXNpcy4NCg0KYSkgVXNpbmcgbWV0aG9kIG9mIG1vbWVudCBlc3RpbWF0aW9uIHRvIGVzdGltYXRlICRcYWxwaGEkIGFuZCAkXGJldGEkLCBkZW5vdGVkIGJ5ICRcaGF0e1xhbHBoYX0kIGFuZCAkXGhhdHtcYmV0YX0kLCByZXNwZWN0aXZlbHkuIA0KDQoNCg0KYGBge3J9DQpyZWNvdmVyeSA9IGMoOC4yMywgMTIuNzQsIDE0LjgzLCAxNi42MSwgMTguMTYsIDE5LjU1LCAyMC44MCwgMjEuOTQsIDIzLjAwLCAyMy45OCwgMjQuODksIDI1Ljc1LCAyNi41NiwgDQoyNy4zNCwgMjguMDgsIDI4Ljc5LCAyOS40OCwgMzAuMTUsIDMwLjgxLCAzMS40NSwgMzIuMDgsIDMyLjcwLCAzMy4zMSwgMzMuOTIsIDM0LjUzLCAzNS4xMywgDQozNS43MywgMzYuMzMsIDM2LjkzLCAzNy41MywgMzguMTQsIDM4Ljc1LCAzOS4zNywgNDAuMDAsIDQwLjY0LCA0MS4yOSwgNDEuOTUsIDQyLjYzLCA0My4zMywgDQo0NC4wNSwgNDQuNzksIDQ1LjU2LCA0Ni4zNiwgNDcuMjAsIDQ4LjA4LCA0OS4wMiwgNTAuMDMsIDUxLjEyLCA1Mi4zMiwgNTMuNjUpDQoNCmhpc3QocmVjb3ZlcnkpDQoNCnMucmVjb3Zlcnk9IHNvcnQocmVjb3ZlcnkpDQojYQ0KDQpsZW5ndGgocmVjb3ZlcnkpICNuID0gNTANCm0xID0gbWVhbihyZWNvdmVyeSkgI3NhbXBsZSBtZWFuIHhfYmFyPTM0LjE5MjINCm0yID1tZWFuKHJlY292ZXJ5XjIpICNzZWNvbmQgbW9tZW50ICMxMjg4DQoNCm1vbV9iZXRhIDwtIGZ1bmN0aW9uKGJldGEsIG0xLCBtMikNCnsNCiAgdGVybTEgPC0gKCAyICogcGkvIGJldGEpIC9zaW4oMiAqIHBpL2JldGEpICAjc2Vjb25kIG1vbWVudA0KICB0ZXJtMiA8LSAoKHBpIC8gYmV0YSkgL3NpbiAocGkgL2JldGEpKV4yICAjc3F1YXJlIG9mIG1lYW4gZGl2aWRlZCBieSBhbHBoYSBzcXVhcmVkDQogIA0KICByZXR1cm4odGVybTEgLyB0ZXJtMiAtIChtMiAvIG0xXjIpKQ0KfQ0KI2luZm8gZm91bmQ6IDovL2VmYWlkbmJtbm5uaWJwY2FqcGNnbGNsZWZpbmRta2FqL2h0dHBzOi8vd3d3Lm1hdGgud20uZWR1L35sZWVtaXMvY2hhcnQvVURSL1BERnMvTG9nbG9naXN0aWMucGRmDQoNCiNub25saW5lYXIgZnVuY3Rpb24gbXVzdCBzb2x2ZSBmb3IgYmV0YQ0KICAgIHNvbF9iZXRhIDwtIHVuaXJvb3QobW9tX2JldGEsIGludGVydmFsID0gYygyLjEsIDIwKSwgbTEgPSBtMSwgbTIgPSBtMikkcm9vdA0KI3N1YnNpdHV0ZSBiZXRhIHRvIGZpbmQgYWxwaGENCiAgICBzb2xfYWxwaGEgPC0gbTEgLyAoKHBpIC8gc29sX2JldGEpIC8gc2luKHBpIC8gc29sX2JldGEpKQ0KICAgIA0KIyBQcmludCBSZXN1bHRzDQpjYXQoIkVzdGltYXRlZCBBbHBoYSAoU2NhbGUvTWVkaWFuKToiLCBzb2xfYWxwaGEsICJcbiIpICNFc3RpbWF0ZWQgQWxwaGEgKFNjYWxlL01lZGlhbik6IDMyLjY1NDMgDQpjYXQoIkVzdGltYXRlZCBCZXRhIChTaGFwZS9XaWR0aCk6Iiwgc29sX2JldGEsICJcbiIpICAjRXN0aW1hdGVkIEJldGEgKFNoYXBlL1dpZHRoKTogNi4wMDYyMzIgDQoNCg0KDQoNCg0KYGBgDQpFc3RpbWF0ZWQgQWxwaGEgKFNjYWxlL01lZGlhbik6IDMyLjY1NDMgDQpFc3RpbWF0ZWQgQmV0YSAoU2hhcGUvV2lkdGgpOiA2LjAwNjIzMg0KDQpUaGUgbWVkaWFuIHJlY292ZXJ5IHRpbWUgZm9yIGEgcGF0aWVudCBpcyAzMi42NSBkYXlzLiBBcyBhIGxvd2VyIGJldGEgdmFsdWUgYXQgNiB3ZSBrbm93IHRoYXQgcmVjb3ZlcnkgdGltZSBvdmVyIGFsbCBpbiBvdXIgc2FtcGxlIGhhdmUgc2ltaWxhciB0aW1lcy4gSW4gb3RoZXIgd29yZHMgdGhlIHNoYXBlIG9mIG91ciBkaXN0cmlidXRpb24gaXMgbm90IHZlcnkgd2lkZSwgc3VnZ2VzdGluZyB0aGVyZSBpcyBsYXJnZSB2YXJpZXR5IG9mIHRpbWUgZGlmZmVyZW5jZXMgaW4gdGhlIGRhdGE7IHRoaXMgZG9lcyBub3Qgb2NjdXIuDQoNCmIpIFNpbmNlIHRoZSBtb21lbnQgZXN0aW1hdGVzICRcaGF0e1xhbHBoYX0kIGFuZCAkXGhhdHtcYmV0YX0kIGFyZSByYW5kb20sIGNvbnN0cnVjdCBib290c3RyYXAgc2FtcGxpbmcgZGlzdHJpYnV0aW9ucyBmb3IgZWFjaC4gVG8gdmlzdWFsaXplIHRoZXNlIGRpc3RyaWJ1dGlvbnMsIHBsb3Qgc2VwYXJhdGUgYm9vdHN0cmFwIGhpc3RvZ3JhbXMgZm9yICRcaGF0e1xhbHBoYX0kIGFuZCAkXGhhdHtcYmV0YX0kLiAgaGVuLCBvdmVybGF5IGEgc21vb3RoIGRlbnNpdHkgY3VydmUgb24gZWFjaCBoaXN0b2dyYW0gdXNpbmcgR2F1c3NpYW4ga2VybmVsIGRlbnNpdHkgZXN0aW1hdGlvbi4gRmluYWxseSwgZGVzY3JpYmUgdGhlIHBhdHRlcm5zIG9mIHRoZXNlIGRlbnNpdHkgY3VydmVzLg0KDQpgYGB7cn0NCnNldC5zZWVkKDMyNSkNCg0KYm9vdF9hbHBoYSA9IE5VTEwNCmJvb3RfYmV0YSA9IE5VTEwNCg0KZm9yKGkgaW4gMToxMDAwKQ0Kew0KICBzYW1wbGVfaSA9IHNhbXBsZShyZWNvdmVyeSwgc2l6ZT01MCwgcmVwbGFjZSA9IFRSVUUpICNyYW5kb20gc2FtcGxlIGZyb20gdGhlIHNhbXBsZSByZWNvdmVyeQ0KICANCiAgI2NhbGN1bGF0ZSBtb21lbnRzIGZyb20gdGhlIHNwZWNpZmljIHNhbXBsZXMNCiAgDQptMV9pID0gbWVhbihzYW1wbGVfaSkgICNmaXJzdCBtb21lbnQNCm0yX2kgPSBtZWFuKHNhbXBsZV9pXjIpICNzZWNvbmQgbW9tZW50DQogIA0KICBib290X2JldGFbaV0gPSB1bmlyb290KG1vbV9iZXRhLCBpbnRlcnZhbCA9IGMoMi4xLCAyMCksIG0xID0gbTFfaSwgbTIgPSBtMl9pKSRyb290DQojc3Vic2l0dXRlIGJldGEgdG8gZmluZCBhbHBoYQ0KICBib290X2FscGhhW2ldID0gbTFfaSAvICgocGkgL2Jvb3RfYmV0YVtpXSkgLyBzaW4ocGkgLyBib290X2JldGFbaV0pKQ0KDQoNCn0NCg0KDQoNCiMgQ3JlYXRlIGRhdGEgZnJhbWUgZm9yIHBsb3R0aW5nDQpib290X3Jlc3VsdHMgPC0gZGF0YS5mcmFtZShhbHBoYSA9IGJvb3RfYWxwaGEsIGJldGEgPSBib290X2JldGEpDQogDQoNCmBgYA0KYGBge3J9DQojIFBsb3R0aW5nIHRoZSBib290IHN0cmFwcyBvZiBhbHBoYSBhbmQgYmV0YSBwYXJhbWV0ZXJzIChib290X3Jlc3VsdHMgZGF0YSBmcmFtZSkNCmJvb3RzZ2dwIDwtIGdncGxvdChib290X3Jlc3VsdHMpICsNCiAgI0dyYXBoIHRoZSBBbHBoYSBkZW5zaXR5DQogIGdlb21fZGVuc2l0eShhZXMoeCA9IGFscGhhLCBjb2xvciA9ICJhbHBoYSIpLCBzaXplID0gMSkgKw0KICAjIEdyYXBoIHRoZSBCZXRhIGRlbnNpdHkNCiAgZ2VvbV9kZW5zaXR5KGFlcyh4ID0gYmV0YSwgY29sb3IgPSAiYmV0YSIpLCBzaXplID0gMSkgKw0KICANCiAgbGFicyh0aXRsZSA9ICJCb290c3RyYXAgRGlzdHJpYnV0aW9ucyBmb3IgQWxwaGEgKFJlY292ZXJ5IHRpbWUpIGFuZCBCZXRhIExvZy1Mb2dpc3RpYyBQYXJhbWV0ZXJzIiwNCiAgICAgICB4ID0gIkVzdGltYXRlIFZhbHVlIiwgDQogICAgICAgeSA9ICJEZW5zaXR5IikgKw0KICBzY2FsZV9jb2xvcl9tYW51YWwobmFtZSA9ICJQYXJhbWV0ZXJzIiwgDQogICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKCJhbHBoYSIgPSAicmVkIiwgImJldGEiID0gImJsdWUiKSkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkNCg0KIyBJbnRlcmFjdGl2ZSBncmFwaA0KZ2dwbG90bHkoYm9vdHNnZ3ApDQpgYGANCg0KVGhpcyBncmFwaCBwbGFjZXMgdGhlIGRpc3RyaWJ1dGlvbnMgb2YgYm90aCB0aGUgYWxwaGEgZGlzdHJpYnV0aW9uIGFuZCB0aGUgYmV0YSBkaXN0cmlidXRpb24gb24gdGhlIHNhbWUgcGxhY2UuIFdlIHNlZSB0aGUgZXN0aW1hdGVkIGJvb3RzdHJhcCB2YWx1ZSBvZiB0aGUgYmV0YSAoJFxiZXRhJCA9IDUuODM3OTY1KSBpcyBmYXIgbG93ZXIgdGhhbiB0aGUgZXN0aW1hdGVkIGJvb3RzdHJhcCBhbHBoYSAoJFxhbHBoYSQgPSAzMC44OTYwNikuIEFkZGl0aW9uYWxseSB0aGUgYWxwaGEgdGFrZSBvbiBhIHdpZGVyIHJhbmdlIG9mIHZhbHVlcyB0aGFuIHRoZSBiZXRhIGRpc3RyaWJ1dGlvbiwgc3VnZ2VzdGluZyB0aGUgYmV0YSB2YWx1ZSBoYXMgbW9yZSBwcmVjaXNpb24gaW4gb3VyIGRpc3RyaWJ1dGlvbi4gSW4gb3RoZXIgd29yZHMsIHRoZSBzaGFwZSBvZiBvdXIgZGF0YSBzZXQsIG9yIGhvdyBzaW1pbGFyIG91ciBkYXRhIHNldCB0byBsaWtlIHJlY292ZXJ5IHRpbWVzIGlzIGxpa2VseSBtb3JlIGNvbnNpc3RlbnQgdGhhbiB0aGUgc3ByZWFkIG9mIG91ciBkYXRhLCB0aGUgZGlzdGFuY2UgYmV0d2VlbiB0aGUgZW5kcyBvZiBvdXIgZGF0YS4NCg0KQWRkaXRpb25hbGx5LCBvdXIgYm9vdHN0cmFwIGVzdGltYXRlZCBhbHBoYSB2YWx1ZXMgYXJlIHNpbWlsYXIgdG8gdGhlIG1vbWVudCBvZiBlc3RpbWF0aW9uIHZhbHVlIG9mICBgciBzb2xfYWxwaGFgIGFzIHdlbGwgYXMgdGhlIGJldGEgYm9vdHN0cmFwIGFuZCBtb21lbnQgb2YgZXN0aW1hdGlvbiBhdCBgciBzb2xfYmV0YWAsIHN1Z2dlc3RpbmcgYm90aCB0aGUgbW9tZW50IG9mIGVzdGltYXRpb25zIGhvbGQgbGl0dGxlIGJpYXMuDQoNCg0KDQpUaGUgQm9vdHN0cmFwIFBhcmFtZXRlcidzIEFscGhhIGFuZCBCZXRhIGdyYXBoZWQgc2VwYXJhdGVseSB3aXRoIHRoZWlyIHJlc3BlY3RpdmUga2VybmVscyBhcmUgYmVsb3cuDQoNCmBgYHtyfQ0KI1RvIHZpc3VhbGl6ZSB0aGVzZSBkaXN0cmlidXRpb25zLCBwbG90IHNlcGFyYXRlIGJvb3RzdHJhcCBoaXN0b2dyYW1zIGZvciAkXGhhdHtcYWxwaGF9JCBhbmQgJFxoYXR7XGJldGF9JC4gIGhlbiwgb3ZlcmxheSBhIHNtb290aCBkZW5zaXR5IGN1cnZlIG9uIGVhY2ggaGlzdG9ncmFtIHVzaW5nIEdhdXNzaWFuIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRpb24uIEZpbmFsbHksIGRlc2NyaWJlIHRoZSBwYXR0ZXJucyBvZiB0aGVzZSBkZW5zaXR5IGN1cnZlcy4NCg0KI2dyYXBoaW5nIHRoZSBCb290c3RyYXAgUGFyYW1ldGVyJ3Mgc2VwYXJhdGVseSB3aXRoIHRoZWlyIHJlc3BlY3RpdmUga2VybmVscw0KDQojIFBsb3R0aW5nIFBhcmFtZXRlciBBbHBoYSAoU2NhbGUpDQpwX2FscGhhIDwtIGdncGxvdChib290X3Jlc3VsdHMsIGFlcyh4ID0gYWxwaGEpKSArDQogICMgVGhlIHJhdyBkYXRhIChIaXN0b2dyYW0pDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gLi5kZW5zaXR5Li4pLCBiaW5zID0gMzAsIGZpbGwgPSAiZ3JheTgwIiwgY29sb3IgPSAid2hpdGUiKSArDQogICMgVGhlIFNtb290aGluZyBMaW5lIChHYXVzc2lhbiBLZXJuZWwpDQogIGdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiLCBzaXplID0gMSwga2VybmVsID0gImdhdXNzaWFuIikgKw0KICBsYWJzKHRpdGxlID0gIkJvb3RzdHJhcCBEaXN0cmlidXRpb24gZm9yIEFscGhhIC0gUmVjb3ZlcnkgVGltZSIsDQogICAgICAgc3VidGl0bGUgPSAiUmVkIGxpbmUgPSBHYXVzc2lhbiBLZXJuZWwgU21vb3RoaW5nIiwNCiAgICAgICB4ID0gIkFscGhhIChEYXlzKSIsIHkgPSAiRGVuc2l0eSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgU2VwYXJhdGUgcGxvdCBmb3IgUGFyYW1ldGVyIEJldGEgKFNoYXBlKQ0KcF9iZXRhIDwtIGdncGxvdChib290X3Jlc3VsdHMsIGFlcyh4ID0gYmV0YSkpICsNCiAgIyBUaGUgcmF3IGRhdGEgKEhpc3RvZ3JhbSkNCiAgZ2VvbV9oaXN0b2dyYW0oYWVzKHkgPSAuLmRlbnNpdHkuLiksIGJpbnMgPSAzMCwgZmlsbCA9ICJncmF5ODAiLCBjb2xvciA9ICJ3aGl0ZSIpICsNCiAgIyBUaGUgU21vb3RoaW5nIExpbmUgKEdhdXNzaWFuIEtlcm5lbCkNCiAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImJsdWUiLCBzaXplID0gMSwga2VybmVsID0gImdhdXNzaWFuIikgKw0KICBsYWJzKHRpdGxlID0gIkJvb3RzdHJhcCBEaXN0cmlidXRpb24gZm9yIEJldGEiLA0KICAgICAgIHN1YnRpdGxlID0gIkJsdWUgbGluZSA9IEdhdXNzaWFuIEtlcm5lbCBTbW9vdGhpbmciLA0KICAgICAgIHggPSAiQmV0YSAoU2hhcGUgUGFyYW1ldGVyKSIsIHkgPSAiRGVuc2l0eSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiNQcmludCBpbnRlcmFjdGl2ZSBncmFwaHMNCmdncGxvdGx5KHBfYWxwaGEpIA0KZ2dwbG90bHkocF9iZXRhKQ0KIA0KYGBgDQoNClRoZSBhbHBoYSBwYXJhbWV0ZXIsIHRoZSBwYXJhbWV0ZXIgcHJvdmlkaW5nIHNjYWxlIGZvciB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiB3aXRoIGl0cyBnYXVzc2lhbiBrZXJuZWwgbG9va3MgYXBwcm94aW1hdGVseSBub3JtYWwsIG1lZXRpbmcgdGhlIGFzc3VtcHRpb24gb2YgbWVhbiBvZiBhIGJvb3RzdHJhcCBkaXN0cmlidXRpb24uIEluIG90aGVyIHdvcmRzLCB0aGUgYm9vdHN0cmFwIGRpc3RyaWJ1dGlvbiBsb29rcyBhcyBleHBlY3RlZC4NCg0KDQpUaGUgYmV0YSBwYXJhbWV0ZXIgYWxzbyBsb29rcyB0byB0YWtlIGEgZ2VuZXJhbGx5IG5vcm1hbCBkaXN0cmlidXRpb24sIGFsdGhvdWdoIG1heSBoYXZlIHNsaWdodCBza2V3LiBNYXkgc3VnZ2VzdCBvdXIgbm9ybWFsIGJhc2VkIGFwcHJveGltYXRpb24gbWF5IGhhdmUgc29tZSBub2lzZSBpbiB0aGUgZGF0YSwgbWF5IG5vdCBiZSB0aGUgYmVzdCBlc3RpbWF0aW9uIHBvc3NpYmxlLiBBbiBhZGRpdGlvbmFsIHJlY29tbWVuZGF0aW9uIGNvdWxkIGJlIHRvIGFsdGVyIHRoZSBiYW5kd2lkdGggb2YgdGhlIHNtb290aGluZyBvZiB0aGUgR2F1c3NpYW4ga2VybmVsLCBhbHRob3VnaCB0aGUga2VybmVsIGxvb2tzIGdlbmVyYWxseSBzbW9vdGguIA0KDQpJbiByZXNwZWN0IHRvIHRoZSByZWNvdmVyeSB0aW1lIGRhdGEgc2V0LCBrbmVlIHN1cmdlcnkgcmVjb3ZlcnkgdGltZSwgYWxwaGEsIGlzIGFib3V0IDMxIGRheXMsIGFuZCB0aHJvdWdoIHRoZSBiZXRhIHZhbHVlLCB0aGlzIGlzIGEgY29uc2lzdGVudCBudW1iZXIgYWNyb3NzIG1vc3QgcGF0aWVudHMu