1 Question 1: Derive the Gradient of the Likelihood function

We assume that \(x_1, x_2, \dots, x_n\) are i.i.d. from a Gamma distribution with shape parameter \(\alpha > 0\) and scale parameter \(\beta > 0\).

The density function is:

\[ f(x \mid \alpha, \beta) = \frac{1}{\Gamma(\alpha)\beta^\alpha} x^{\alpha-1} e^{-x/\beta}, \quad x > 0. \]


1.1 (a) Full Log-Likelihood Function

First, we write the likelihood function by multiplying the density across all observations:

\[ L(\alpha, \beta) = \prod_{i=1}^{n} \frac{1}{\Gamma(\alpha)\beta^\alpha} x_i^{\alpha-1} e^{-x_i/\beta}. \]

Now we take the natural logarithm to simplify the product into a sum.

Using log rules: - \(\log(ab) = \log a + \log b\) - \(\log(a^b) = b \log a\)

We obtain the full log-likelihood:

\[ \ell(\alpha, \beta) = -n \log \Gamma(\alpha) - n\alpha \log \beta + (\alpha - 1)\sum_{i=1}^{n} \log x_i - \frac{1}{\beta}\sum_{i=1}^{n} x_i. \]

This function measures how plausible \((\alpha, \beta)\) are given the observed data.


1.2 (b) Derivation of the Score Functions

The score functions are the first partial derivatives of the log-likelihood with respect to \(\alpha\) and \(\beta\).


1.2.1 Derivative with Respect to \(\beta\)

We differentiate \(\ell(\alpha, \beta)\) with respect to \(\beta\).

Only the terms involving \(\beta\) are:

\[ - n\alpha \log \beta - \frac{1}{\beta}\sum_{i=1}^{n} x_i. \]

Taking derivatives term-by-term:

  • \(\frac{d}{d\beta}(-n\alpha \log \beta) = -\frac{n\alpha}{\beta}\)

  • \(\frac{d}{d\beta}\left(-\frac{1}{\beta}\sum x_i\right) = \frac{1}{\beta^2}\sum x_i\)

Therefore, the score function for \(\beta\) is:

\[ \frac{\partial \ell}{\partial \beta} = -\frac{n\alpha}{\beta} + \frac{1}{\beta^2} \sum_{i=1}^{n} x_i. \]


1.2.2 Derivative with Respect to \(\alpha\)

Now differentiate with respect to \(\alpha\).

The terms involving \(\alpha\) are:

\[ - n \log \Gamma(\alpha) - n\alpha \log \beta + (\alpha - 1)\sum_{i=1}^{n} \log x_i. \]

We use the identity:

\[ \frac{d}{d\alpha}\log \Gamma(\alpha) = \psi(\alpha), \]

where \(\psi(\alpha)\) is the digamma function.

Taking derivatives:

  • \(\frac{d}{d\alpha}(-n \log \Gamma(\alpha)) = -n\psi(\alpha)\)

  • \(\frac{d}{d\alpha}(-n\alpha \log \beta) = -n\log \beta\)

  • \(\frac{d}{d\alpha}((\alpha - 1)\sum \log x_i) = \sum \log x_i\)

Combining these results:

\[ \frac{\partial \ell}{\partial \alpha} = - n\psi(\alpha) - n\log \beta + \sum_{i=1}^{n} \log x_i. \]


2 Question 2

2.1 (a) :MLE using Gradient-Based Optimization

# -----------------------------
# Step 1: Enter the Birth Data
# -----------------------------

# observed delivery times 
birth_data <- c(
2.1, 3.4, 4.25, 5.6, 6.4, 7.3, 8.5, 8.75, 8.9, 9.5, 9.75, 10, 10.4, 10.4, 16, 19,
4, 4.1, 5, 5.5, 5.7, 6.5, 7.25, 7.3, 7.5, 8.2, 8.5, 9.75, 11, 11.2, 15, 16.5, 2.6,
3.6, 3.6, 6.4, 6.8, 7.5, 7.5, 8.25, 8.5, 10.4, 10.75, 14.25, 14.5, 1.5, 4.7, 4.7,
7.2, 7.25, 8.1, 8.5, 9.2, 9.5, 10.7, 11.5, 2.5, 2.5, 3.4, 4.2, 5.9, 6.25, 7.3, 7.5,
7.8, 8.3, 8.3, 10.25, 12.9, 14.3, 4, 4, 5.25, 6.1, 6.5, 6.9, 7, 8.45, 9.25, 10.1,
10.2, 12.75, 14.6, 2, 2.7, 2.75, 3.4, 4.2, 4.3, 4.9, 6.25, 7, 9, 9.25, 10.7
)

n <- length(birth_data)   # sample size


# -----------------------------------
# Step 2: Log-Likelihood Function
# -----------------------------------

# This function returns the *negative* log-likelihood.
# We use negative because optim() performs minimization by default.

gamma_loglik <- function(params, data) {
  
  alpha <- params[1]   
  beta  <- params[2]
  
  # Enforce positivity constraint (Gamma parameters must be > 0)
  if(alpha <= 0 || beta <= 0) return(Inf)
  
  n <- length(data)
  
  loglik <- -n * log(gamma(alpha)) -
            n * alpha * log(beta) +
            (alpha - 1) * sum(log(data)) -
            (1 / beta) * sum(data)
  
  return(-loglik)  # negative for minimization
}


# -----------------------------------
# Step 3: Gradient 
# -----------------------------------

# This function returns the gradient as a numeric vector.
# It contains the two partial derivatives derived in Question 1.

gamma_score <- function(params, data) {
  
  alpha <- params[1]
  beta  <- params[2]
  
  if(alpha <= 0 || beta <= 0) return(c(Inf, Inf))
  
  n <- length(data)
  
  # Partial derivative with respect to alpha
  grad_alpha <- -n * digamma(alpha) -
                n * log(beta) +
                sum(log(data))
  
  # Partial derivative with respect to beta
  grad_beta <- - (n * alpha) / beta +
               (1 / beta^2) * sum(data)
  
  # Return gradient vector
  return(-c(grad_alpha, grad_beta))
}


# -----------------------------------
# Step 4: Choose Initial Values
# -----------------------------------

# Reasonable starting values based on method of moments intuition
initial_values <- c(alpha = 2, beta = 2)


# -----------------------------------
# Step 5: Run Optimization
# -----------------------------------

mle_result <- optim(
  par = initial_values,
  fn = gamma_loglik,
  gr = gamma_score,
  data = birth_data,
  method = "L-BFGS-B",         # allows bounds
  lower = c(1e-6, 1e-6)        # enforce positivity
)

mle_result$par   # Estimated (alpha_hat, beta_hat)
   alpha     beta 
4.387850 1.760123 

2.2 (b) Method of Moments:

# Compute sample mean
x_bar <- mean(birth_data)

# Compute sample variance 
s2 <- var(birth_data)

# Method of Moments estimator for alpha
alpha_mme <- x_bar^2 / s2

# Method of Moments estimator for beta
beta_mme <- s2 / x_bar

c(alpha_mme = alpha_mme, beta_mme = beta_mme)
alpha_mme  beta_mme 
 4.685073  1.648460 

2.3 2(c) Comparison of Method of Moments and Maximum Likelihood

We compare the Method of Moments (MME) and Maximum Likelihood Estimation (MLE) both theoretically and visually.

# ---------------------------------------
# Plot histogram with fitted densities
# ---------------------------------------

# Create histogram scaled to density
hist(birth_data,
     probability = TRUE,           # scale histogram to density
     breaks = 15,
     col = "lightgray",
     border = "white",
     main = "Gamma Fit: MLE vs MME",
     xlab = "Delivery Time (hours)")

# Create grid of x values for smooth curves
x_grid <- seq(min(birth_data),
              max(birth_data),
              length.out = 500)

# Add MLE fitted density
lines(x_grid,
      dgamma(x_grid,
             shape = mle_result$par[1],
             scale = mle_result$par[2]),
      col = "blue",
      lwd = 2)

# Add MME fitted density
lines(x_grid,
      dgamma(x_grid,
             shape = alpha_mme,
             scale = beta_mme),
      col = "red",
      lwd = 2,
      lty = 2)

# Add legend
legend("topright",
       legend = c("MLE", "MME"),
       col = c("blue", "red"),
       lwd = 2,
       lty = c(1,2))

The Method of Moments (MME) and Maximum Likelihood Estimation (MLE) are two general approaches for estimating unknown parameters in a probability distribution. The Method of Moments determines parameter values by equating sample moments, such as the sample mean and variance, to their corresponding theoretical moments. In contrast, Maximum Likelihood Estimation selects parameter values that maximize the likelihood function, meaning it chooses the values under which the observed data are most probable.

In this application, both methods were used to estimate the parameters of a Gamma model for delivery times. Although the numerical estimates differed slightly, both methods produced very similar fitted curves when overlaid on the histogram. The data display moderate right skewness, and both fitted distributions capture the central concentration of observations as well as the gradual decline in the right tail. The visual difference between the two fitted curves is small, indicating that both methods provide a reasonable description of the data.

The Method of Moments has the advantage of conceptual simplicity. It is straightforward to compute and often leads to algebraically simple solutions. Because it relies only on summary statistics, it is computationally efficient and easy to implement. However, since it uses only selected characteristics of the data rather than the full probability structure, it may be less statistically efficient and may not capture subtle features of the distribution as effectively.

Maximum Likelihood Estimation typically requires more computational effort, especially when closed-form solutions do not exist and numerical optimization is necessary. Despite this, MLE has stronger theoretical properties under standard conditions. It is generally consistent, asymptotically normal, and asymptotically efficient, meaning that in large samples it tends to produce estimates with desirable statistical properties. Because it is based on the full likelihood function, it often provides a slightly better overall fit.

In conclusion, both methods perform similarly for this dataset, as shown by the nearly overlapping fitted curves. However, Maximum Likelihood Estimation is generally preferred in practice due to its stronger theoretical justification and its use of the full distributional information. The Method of Moments remains useful for its simplicity and as a practical starting point for more advanced estimation procedures.

LS0tDQp0aXRsZTogJ1NUQSA1MDYgSE9NRVdPUksgNScNCmF1dGhvcjogJ0dlcmFyZCBJa2UnDQpkYXRlOiAiMjAyNi0wMy0wMiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogICAgICAgICAgICAgICMgb3V0cHV0IGRvY3VtZW50IGZvcm1hdA0KICAgIHRvYzogeWVzICAgICAgICAgICAgICAgICAgIyBhZGQgdGFibGUgY29udGVudHMNCiAgICB0b2NfZmxvYXQ6IHllcyAgICAgICAgICAgICMgdG9jX3Byb3BlcnR5OiBmbG9hdGluZw0KICAgIHRvY19kZXB0aDogNCAgICAgICAgICAgICAgIyBkZXB0aCBvZiBUT0MgaGVhZGluZ3MNCiAgICBmaWdfd2lkdGg6IDYgICAgICAgICAgICAgICMgZ2xvYmFsIGZpZ3VyZSB3aWR0aA0KICAgIGZpZ19oZWlnaHQ6IDQgICAgICAgICAgICAgIyBnbG9iYWwgZmlndXJlIGhlaWdodA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMgICAgICAgICAgIyBhZGQgZmlndXJlIGNhcHRpb24NCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcyAgICAgICMgbnVtYmVyaW5nIHNlY3Rpb24gaGVhZGluZ3MNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMgICAgICAgICMgVE9DIHN1YmhlYWRpbmcgY2xhcHNpbmcNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUgICAgICAgICMgZm9sZGluZy9zaG93aW5nIGNvZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMgICAgICAgICMgYWxsb3cgdG8gZG93bmxvYWQgY29tcGxldGUgUk1hcmtkb3duIHNvdXJjZSBjb2RlDQogICAgc21vb3RoX3Njcm9sbDogeWVzICAgICAgICAjIHNjcm9sbGluZyB0ZXh0IG9mIHRoZSBkb2N1bWVudA0KICAgIHRoZW1lOiBsdW1lbiAgICAgICAgICAgICAgIyB2aXN1YWwgdGhlbWUgZm9yIEhUTUwgZG9jdW1lbnQgb25seQ0KICAgIGhpZ2hsaWdodDogdGFuZ28gICAgICAgICAgIyBjb2RlIHN5bnRheCBoaWdobGlnaHRpbmcgc3R5bGVzDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICB3b3JkX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAnNCcNCi0tLQ0KDQpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9DQpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovDQogICAgbGlzdC1zdHlsZTp1cHBlci1yb21hbjsNCiAgICBiYWNrZ3JvdW5kLWltYWdlOm5vbmU7DQogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsNCiAgICBiYWNrZ3JvdW5kLXBvc2l0aW9uOjA7DQp9DQoNCmgxLnRpdGxlIHsgICAgLyogbGV2ZWwgMSBoZWFkZXIgb2YgdGl0bGUgICovDQogIGZvbnQtc2l6ZTogMjRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQoNCmg0LmF1dGhvciB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogIGZvbnQtc2l6ZTogMThweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICBjb2xvcjogRGFya1JlZDsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KDQpoMSB7IC8qIEhlYWRlciAxIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAyMHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGNlbnRlcjsNCn0NCg0KaDIgeyAvKiBIZWFkZXIgMiAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogbmF2eTsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KDQpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxNnB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmg0IHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBkYXJrcmVkOw0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCi8qIEFkZCBkb3RzIGFmdGVyIG51bWJlcmVkIGhlYWRlcnMgKi8NCi5oZWFkZXItc2VjdGlvbi1udW1iZXI6OmFmdGVyIHsNCiAgY29udGVudDogIi4iOw0KfQ0KYGBgDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0KIyBjb2RlIGNodW5rIHNwZWNpZmllcyB3aGV0aGVyIHRoZSBSIGNvZGUsIHdhcm5pbmdzLCBhbmQgb3V0cHV0IA0KIyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBvdXRwdXQgZmlsZXMuDQoNCmlmICghcmVxdWlyZSgia25pdHIiKSkgeyAgICAgICAgICAgICAgICAgICAgICAjIHVzZSBjb25kaXRpb25hbCBzdGF0ZW1lbnQgdG8gZGV0ZWN0DQogICBpbnN0YWxsLnBhY2thZ2VzKCJrbml0ciIpICAgICAgICAgICAgICAgICAgIyB3aGV0aGVyIGEgcGFja2FnZSB3YXMgaW5zdGFsbGVkIGluDQogICBsaWJyYXJ5KGtuaXRyKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3VyIG1hY2hpbmUuIElmIG5vdCwgaW5zdGFsbCBpdCBhbmQNCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGxvYWQgaXQgdG8gdGhlIHdvcmtpbmcgZGlyZWN0b3J5Lg0KIw0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAgICAgICMgaW5jbHVkZSBjb2RlIGNodW5rIGluIHRoZSBvdXRwdXQgZmlsZQ0KICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICAgICAgICMgc29tZXRpbWVzLCB5b3UgY29kZSBtYXkgcHJvZHVjZSB3YXJuaW5nIG1lc3NhZ2VzLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgeW91IGNhbiBjaG9vc2UgdG8gaW5jbHVkZSB0aGUgd2FybmluZyBtZXNzYWdlcyBpbg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdGhlIG91dHB1dCBmaWxlLiANCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwgICAgICAgICAjIHlvdSBjYW4gYWxzbyBkZWNpZGUgd2hldGhlciB0byBpbmNsdWRlIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGluIHRoZSBvdXRwdXQgZmlsZS4NCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsICAgICAgICAjIHN1cHByZXNzIG1lc3NhZ2VzIA0KICAgICAgICAgICAgICAgICAgICAgIGNvbW1lbnQgPSBOQSAgICAgICAgICAgICMgcmVtb3ZlIHRoZSBkZWZhdWx0IGxlYWRpbmcgaGFzaCB0YWdzIGluIHRoZSBvdXRwdXQNCiAgICAgICAgICAgICAgICAgICAgICApICAgDQpgYGANCg0KIyBRdWVzdGlvbiAxOiBEZXJpdmUgdGhlIEdyYWRpZW50IG9mIHRoZSBMaWtlbGlob29kIGZ1bmN0aW9uDQoNCldlIGFzc3VtZSB0aGF0ICR4XzEsIHhfMiwgXGRvdHMsIHhfbiQgYXJlIGkuaS5kLiBmcm9tIGEgR2FtbWEgZGlzdHJpYnV0aW9uIHdpdGggc2hhcGUgcGFyYW1ldGVyICRcYWxwaGEgPiAwJCBhbmQgc2NhbGUgcGFyYW1ldGVyICRcYmV0YSA+IDAkLg0KDQpUaGUgZGVuc2l0eSBmdW5jdGlvbiBpczoNCg0KJCQNCmYoeCBcbWlkIFxhbHBoYSwgXGJldGEpDQo9DQpcZnJhY3sxfXtcR2FtbWEoXGFscGhhKVxiZXRhXlxhbHBoYX0NCnhee1xhbHBoYS0xfSBlXnsteC9cYmV0YX0sDQpccXVhZCB4ID4gMC4NCiQkDQoNCi0tLQ0KDQojIyAoYSkgRnVsbCBMb2ctTGlrZWxpaG9vZCBGdW5jdGlvbg0KDQpGaXJzdCwgd2Ugd3JpdGUgdGhlIGxpa2VsaWhvb2QgZnVuY3Rpb24gYnkgbXVsdGlwbHlpbmcgdGhlIGRlbnNpdHkgYWNyb3NzIGFsbCBvYnNlcnZhdGlvbnM6DQoNCiQkDQpMKFxhbHBoYSwgXGJldGEpDQo9DQpccHJvZF97aT0xfV57bn0NClxmcmFjezF9e1xHYW1tYShcYWxwaGEpXGJldGFeXGFscGhhfQ0KeF9pXntcYWxwaGEtMX0NCmVeey14X2kvXGJldGF9Lg0KJCQNCg0KTm93IHdlIHRha2UgdGhlIG5hdHVyYWwgbG9nYXJpdGhtIHRvIHNpbXBsaWZ5IHRoZSBwcm9kdWN0IGludG8gYSBzdW0uDQoNClVzaW5nIGxvZyBydWxlczoNCi0gJFxsb2coYWIpID0gXGxvZyBhICsgXGxvZyBiJA0KLSAkXGxvZyhhXmIpID0gYiBcbG9nIGEkDQoNCldlIG9idGFpbiB0aGUgZnVsbCBsb2ctbGlrZWxpaG9vZDoNCg0KJCQNClxlbGwoXGFscGhhLCBcYmV0YSkNCj0NCi1uIFxsb2cgXEdhbW1hKFxhbHBoYSkNCi0gblxhbHBoYSBcbG9nIFxiZXRhDQorIChcYWxwaGEgLSAxKVxzdW1fe2k9MX1ee259IFxsb2cgeF9pDQotIFxmcmFjezF9e1xiZXRhfVxzdW1fe2k9MX1ee259IHhfaS4NCiQkDQoNClRoaXMgZnVuY3Rpb24gbWVhc3VyZXMgaG93IHBsYXVzaWJsZSAkKFxhbHBoYSwgXGJldGEpJCBhcmUgZ2l2ZW4gdGhlIG9ic2VydmVkIGRhdGEuDQoNCi0tLQ0KDQojIyAoYikgRGVyaXZhdGlvbiBvZiB0aGUgU2NvcmUgRnVuY3Rpb25zIA0KDQpUaGUgc2NvcmUgZnVuY3Rpb25zIGFyZSB0aGUgZmlyc3QgcGFydGlhbCBkZXJpdmF0aXZlcyBvZiB0aGUgbG9nLWxpa2VsaWhvb2Qgd2l0aCByZXNwZWN0IHRvICRcYWxwaGEkIGFuZCAkXGJldGEkLg0KDQoNCi0tLQ0KDQojIyMgRGVyaXZhdGl2ZSB3aXRoIFJlc3BlY3QgdG8gJFxiZXRhJA0KDQpXZSBkaWZmZXJlbnRpYXRlICRcZWxsKFxhbHBoYSwgXGJldGEpJCB3aXRoIHJlc3BlY3QgdG8gJFxiZXRhJC4NCg0KT25seSB0aGUgdGVybXMgaW52b2x2aW5nICRcYmV0YSQgYXJlOg0KDQokJA0KLSBuXGFscGhhIFxsb2cgXGJldGENCi0gXGZyYWN7MX17XGJldGF9XHN1bV97aT0xfV57bn0geF9pLg0KJCQNCg0KVGFraW5nIGRlcml2YXRpdmVzIHRlcm0tYnktdGVybToNCg0KLSAkXGZyYWN7ZH17ZFxiZXRhfSgtblxhbHBoYSBcbG9nIFxiZXRhKSA9IC1cZnJhY3tuXGFscGhhfXtcYmV0YX0kDQoNCi0gJFxmcmFje2R9e2RcYmV0YX1cbGVmdCgtXGZyYWN7MX17XGJldGF9XHN1bSB4X2lccmlnaHQpDQo9DQpcZnJhY3sxfXtcYmV0YV4yfVxzdW0geF9pJA0KDQpUaGVyZWZvcmUsIHRoZSBzY29yZSBmdW5jdGlvbiBmb3IgJFxiZXRhJCBpczoNCg0KJCQNClxmcmFje1xwYXJ0aWFsIFxlbGx9e1xwYXJ0aWFsIFxiZXRhfQ0KPQ0KLVxmcmFje25cYWxwaGF9e1xiZXRhfQ0KKw0KXGZyYWN7MX17XGJldGFeMn0NClxzdW1fe2k9MX1ee259IHhfaS4NCiQkDQoNCi0tLQ0KDQojIyMgRGVyaXZhdGl2ZSB3aXRoIFJlc3BlY3QgdG8gJFxhbHBoYSQNCg0KTm93IGRpZmZlcmVudGlhdGUgd2l0aCByZXNwZWN0IHRvICRcYWxwaGEkLg0KDQpUaGUgdGVybXMgaW52b2x2aW5nICRcYWxwaGEkIGFyZToNCg0KJCQNCi0gbiBcbG9nIFxHYW1tYShcYWxwaGEpDQotIG5cYWxwaGEgXGxvZyBcYmV0YQ0KKyAoXGFscGhhIC0gMSlcc3VtX3tpPTF9XntufSBcbG9nIHhfaS4NCiQkDQoNCldlIHVzZSB0aGUgaWRlbnRpdHk6DQoNCiQkDQpcZnJhY3tkfXtkXGFscGhhfVxsb2cgXEdhbW1hKFxhbHBoYSkNCj0NClxwc2koXGFscGhhKSwNCiQkDQoNCndoZXJlICRccHNpKFxhbHBoYSkkIGlzIHRoZSBkaWdhbW1hIGZ1bmN0aW9uLg0KDQpUYWtpbmcgZGVyaXZhdGl2ZXM6DQoNCi0gJFxmcmFje2R9e2RcYWxwaGF9KC1uIFxsb2cgXEdhbW1hKFxhbHBoYSkpID0gLW5ccHNpKFxhbHBoYSkkDQoNCi0gJFxmcmFje2R9e2RcYWxwaGF9KC1uXGFscGhhIFxsb2cgXGJldGEpID0gLW5cbG9nIFxiZXRhJA0KDQotICRcZnJhY3tkfXtkXGFscGhhfSgoXGFscGhhIC0gMSlcc3VtIFxsb2cgeF9pKQ0KPQ0KXHN1bSBcbG9nIHhfaSQNCg0KQ29tYmluaW5nIHRoZXNlIHJlc3VsdHM6DQoNCiQkDQpcZnJhY3tccGFydGlhbCBcZWxsfXtccGFydGlhbCBcYWxwaGF9DQo9DQotIG5ccHNpKFxhbHBoYSkNCi0gblxsb2cgXGJldGENCisgXHN1bV97aT0xfV57bn0gXGxvZyB4X2kuDQokJA0KDQotLS0NCg0KIyBRdWVzdGlvbiAyDQojIyAoYSkgOk1MRSB1c2luZyBHcmFkaWVudC1CYXNlZCBPcHRpbWl6YXRpb24NCmBgYHtyfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBTdGVwIDE6IEVudGVyIHRoZSBCaXJ0aCBEYXRhDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgb2JzZXJ2ZWQgZGVsaXZlcnkgdGltZXMgDQpiaXJ0aF9kYXRhIDwtIGMoDQoyLjEsIDMuNCwgNC4yNSwgNS42LCA2LjQsIDcuMywgOC41LCA4Ljc1LCA4LjksIDkuNSwgOS43NSwgMTAsIDEwLjQsIDEwLjQsIDE2LCAxOSwNCjQsIDQuMSwgNSwgNS41LCA1LjcsIDYuNSwgNy4yNSwgNy4zLCA3LjUsIDguMiwgOC41LCA5Ljc1LCAxMSwgMTEuMiwgMTUsIDE2LjUsIDIuNiwNCjMuNiwgMy42LCA2LjQsIDYuOCwgNy41LCA3LjUsIDguMjUsIDguNSwgMTAuNCwgMTAuNzUsIDE0LjI1LCAxNC41LCAxLjUsIDQuNywgNC43LA0KNy4yLCA3LjI1LCA4LjEsIDguNSwgOS4yLCA5LjUsIDEwLjcsIDExLjUsIDIuNSwgMi41LCAzLjQsIDQuMiwgNS45LCA2LjI1LCA3LjMsIDcuNSwNCjcuOCwgOC4zLCA4LjMsIDEwLjI1LCAxMi45LCAxNC4zLCA0LCA0LCA1LjI1LCA2LjEsIDYuNSwgNi45LCA3LCA4LjQ1LCA5LjI1LCAxMC4xLA0KMTAuMiwgMTIuNzUsIDE0LjYsIDIsIDIuNywgMi43NSwgMy40LCA0LjIsIDQuMywgNC45LCA2LjI1LCA3LCA5LCA5LjI1LCAxMC43DQopDQoNCm4gPC0gbGVuZ3RoKGJpcnRoX2RhdGEpICAgIyBzYW1wbGUgc2l6ZQ0KDQoNCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgU3RlcCAyOiBMb2ctTGlrZWxpaG9vZCBGdW5jdGlvbg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIFRoaXMgZnVuY3Rpb24gcmV0dXJucyB0aGUgKm5lZ2F0aXZlKiBsb2ctbGlrZWxpaG9vZC4NCiMgV2UgdXNlIG5lZ2F0aXZlIGJlY2F1c2Ugb3B0aW0oKSBwZXJmb3JtcyBtaW5pbWl6YXRpb24gYnkgZGVmYXVsdC4NCg0KZ2FtbWFfbG9nbGlrIDwtIGZ1bmN0aW9uKHBhcmFtcywgZGF0YSkgew0KICANCiAgYWxwaGEgPC0gcGFyYW1zWzFdICAgDQogIGJldGEgIDwtIHBhcmFtc1syXQ0KICANCiAgIyBFbmZvcmNlIHBvc2l0aXZpdHkgY29uc3RyYWludCAoR2FtbWEgcGFyYW1ldGVycyBtdXN0IGJlID4gMCkNCiAgaWYoYWxwaGEgPD0gMCB8fCBiZXRhIDw9IDApIHJldHVybihJbmYpDQogIA0KICBuIDwtIGxlbmd0aChkYXRhKQ0KICANCiAgbG9nbGlrIDwtIC1uICogbG9nKGdhbW1hKGFscGhhKSkgLQ0KICAgICAgICAgICAgbiAqIGFscGhhICogbG9nKGJldGEpICsNCiAgICAgICAgICAgIChhbHBoYSAtIDEpICogc3VtKGxvZyhkYXRhKSkgLQ0KICAgICAgICAgICAgKDEgLyBiZXRhKSAqIHN1bShkYXRhKQ0KICANCiAgcmV0dXJuKC1sb2dsaWspICAjIG5lZ2F0aXZlIGZvciBtaW5pbWl6YXRpb24NCn0NCg0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFN0ZXAgMzogR3JhZGllbnQgDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgVGhpcyBmdW5jdGlvbiByZXR1cm5zIHRoZSBncmFkaWVudCBhcyBhIG51bWVyaWMgdmVjdG9yLg0KIyBJdCBjb250YWlucyB0aGUgdHdvIHBhcnRpYWwgZGVyaXZhdGl2ZXMgZGVyaXZlZCBpbiBRdWVzdGlvbiAxLg0KDQpnYW1tYV9zY29yZSA8LSBmdW5jdGlvbihwYXJhbXMsIGRhdGEpIHsNCiAgDQogIGFscGhhIDwtIHBhcmFtc1sxXQ0KICBiZXRhICA8LSBwYXJhbXNbMl0NCiAgDQogIGlmKGFscGhhIDw9IDAgfHwgYmV0YSA8PSAwKSByZXR1cm4oYyhJbmYsIEluZikpDQogIA0KICBuIDwtIGxlbmd0aChkYXRhKQ0KICANCiAgIyBQYXJ0aWFsIGRlcml2YXRpdmUgd2l0aCByZXNwZWN0IHRvIGFscGhhDQogIGdyYWRfYWxwaGEgPC0gLW4gKiBkaWdhbW1hKGFscGhhKSAtDQogICAgICAgICAgICAgICAgbiAqIGxvZyhiZXRhKSArDQogICAgICAgICAgICAgICAgc3VtKGxvZyhkYXRhKSkNCiAgDQogICMgUGFydGlhbCBkZXJpdmF0aXZlIHdpdGggcmVzcGVjdCB0byBiZXRhDQogIGdyYWRfYmV0YSA8LSAtIChuICogYWxwaGEpIC8gYmV0YSArDQogICAgICAgICAgICAgICAoMSAvIGJldGFeMikgKiBzdW0oZGF0YSkNCiAgDQogICMgUmV0dXJuIGdyYWRpZW50IHZlY3Rvcg0KICByZXR1cm4oLWMoZ3JhZF9hbHBoYSwgZ3JhZF9iZXRhKSkNCn0NCg0KDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFN0ZXAgNDogQ2hvb3NlIEluaXRpYWwgVmFsdWVzDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMgUmVhc29uYWJsZSBzdGFydGluZyB2YWx1ZXMgYmFzZWQgb24gbWV0aG9kIG9mIG1vbWVudHMgaW50dWl0aW9uDQppbml0aWFsX3ZhbHVlcyA8LSBjKGFscGhhID0gMiwgYmV0YSA9IDIpDQoNCg0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KIyBTdGVwIDU6IFJ1biBPcHRpbWl6YXRpb24NCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KbWxlX3Jlc3VsdCA8LSBvcHRpbSgNCiAgcGFyID0gaW5pdGlhbF92YWx1ZXMsDQogIGZuID0gZ2FtbWFfbG9nbGlrLA0KICBnciA9IGdhbW1hX3Njb3JlLA0KICBkYXRhID0gYmlydGhfZGF0YSwNCiAgbWV0aG9kID0gIkwtQkZHUy1CIiwgICAgICAgICAjIGFsbG93cyBib3VuZHMNCiAgbG93ZXIgPSBjKDFlLTYsIDFlLTYpICAgICAgICAjIGVuZm9yY2UgcG9zaXRpdml0eQ0KKQ0KDQptbGVfcmVzdWx0JHBhciAgICMgRXN0aW1hdGVkIChhbHBoYV9oYXQsIGJldGFfaGF0KQ0KYGBgDQoNCiMjIChiKSBNZXRob2Qgb2YgTW9tZW50czoNCmBgYHtyfQ0KDQojIENvbXB1dGUgc2FtcGxlIG1lYW4NCnhfYmFyIDwtIG1lYW4oYmlydGhfZGF0YSkNCg0KIyBDb21wdXRlIHNhbXBsZSB2YXJpYW5jZSANCnMyIDwtIHZhcihiaXJ0aF9kYXRhKQ0KDQojIE1ldGhvZCBvZiBNb21lbnRzIGVzdGltYXRvciBmb3IgYWxwaGENCmFscGhhX21tZSA8LSB4X2Jhcl4yIC8gczINCg0KIyBNZXRob2Qgb2YgTW9tZW50cyBlc3RpbWF0b3IgZm9yIGJldGENCmJldGFfbW1lIDwtIHMyIC8geF9iYXINCg0KYyhhbHBoYV9tbWUgPSBhbHBoYV9tbWUsIGJldGFfbW1lID0gYmV0YV9tbWUpDQpgYGANCg0KIyMgMihjKSBDb21wYXJpc29uIG9mIE1ldGhvZCBvZiBNb21lbnRzIGFuZCBNYXhpbXVtIExpa2VsaWhvb2QNCg0KV2UgY29tcGFyZSB0aGUgTWV0aG9kIG9mIE1vbWVudHMgKE1NRSkgYW5kIE1heGltdW0gTGlrZWxpaG9vZCBFc3RpbWF0aW9uIChNTEUpIGJvdGggdGhlb3JldGljYWxseSBhbmQgdmlzdWFsbHkuDQoNCmBgYHtyfQ0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCiMgUGxvdCBoaXN0b2dyYW0gd2l0aCBmaXR0ZWQgZGVuc2l0aWVzDQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIENyZWF0ZSBoaXN0b2dyYW0gc2NhbGVkIHRvIGRlbnNpdHkNCmhpc3QoYmlydGhfZGF0YSwNCiAgICAgcHJvYmFiaWxpdHkgPSBUUlVFLCAgICAgICAgICAgIyBzY2FsZSBoaXN0b2dyYW0gdG8gZGVuc2l0eQ0KICAgICBicmVha3MgPSAxNSwNCiAgICAgY29sID0gImxpZ2h0Z3JheSIsDQogICAgIGJvcmRlciA9ICJ3aGl0ZSIsDQogICAgIG1haW4gPSAiR2FtbWEgRml0OiBNTEUgdnMgTU1FIiwNCiAgICAgeGxhYiA9ICJEZWxpdmVyeSBUaW1lIChob3VycykiKQ0KDQojIENyZWF0ZSBncmlkIG9mIHggdmFsdWVzIGZvciBzbW9vdGggY3VydmVzDQp4X2dyaWQgPC0gc2VxKG1pbihiaXJ0aF9kYXRhKSwNCiAgICAgICAgICAgICAgbWF4KGJpcnRoX2RhdGEpLA0KICAgICAgICAgICAgICBsZW5ndGgub3V0ID0gNTAwKQ0KDQojIEFkZCBNTEUgZml0dGVkIGRlbnNpdHkNCmxpbmVzKHhfZ3JpZCwNCiAgICAgIGRnYW1tYSh4X2dyaWQsDQogICAgICAgICAgICAgc2hhcGUgPSBtbGVfcmVzdWx0JHBhclsxXSwNCiAgICAgICAgICAgICBzY2FsZSA9IG1sZV9yZXN1bHQkcGFyWzJdKSwNCiAgICAgIGNvbCA9ICJibHVlIiwNCiAgICAgIGx3ZCA9IDIpDQoNCiMgQWRkIE1NRSBmaXR0ZWQgZGVuc2l0eQ0KbGluZXMoeF9ncmlkLA0KICAgICAgZGdhbW1hKHhfZ3JpZCwNCiAgICAgICAgICAgICBzaGFwZSA9IGFscGhhX21tZSwNCiAgICAgICAgICAgICBzY2FsZSA9IGJldGFfbW1lKSwNCiAgICAgIGNvbCA9ICJyZWQiLA0KICAgICAgbHdkID0gMiwNCiAgICAgIGx0eSA9IDIpDQoNCiMgQWRkIGxlZ2VuZA0KbGVnZW5kKCJ0b3ByaWdodCIsDQogICAgICAgbGVnZW5kID0gYygiTUxFIiwgIk1NRSIpLA0KICAgICAgIGNvbCA9IGMoImJsdWUiLCAicmVkIiksDQogICAgICAgbHdkID0gMiwNCiAgICAgICBsdHkgPSBjKDEsMikpDQpgYGANCg0KDQpUaGUgTWV0aG9kIG9mIE1vbWVudHMgKE1NRSkgYW5kIE1heGltdW0gTGlrZWxpaG9vZCBFc3RpbWF0aW9uIChNTEUpIGFyZSB0d28gZ2VuZXJhbCBhcHByb2FjaGVzIGZvciBlc3RpbWF0aW5nIHVua25vd24gcGFyYW1ldGVycyBpbiBhIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbi4gVGhlIE1ldGhvZCBvZiBNb21lbnRzIGRldGVybWluZXMgcGFyYW1ldGVyIHZhbHVlcyBieSBlcXVhdGluZyBzYW1wbGUgbW9tZW50cywgc3VjaCBhcyB0aGUgc2FtcGxlIG1lYW4gYW5kIHZhcmlhbmNlLCB0byB0aGVpciBjb3JyZXNwb25kaW5nIHRoZW9yZXRpY2FsIG1vbWVudHMuIEluIGNvbnRyYXN0LCBNYXhpbXVtIExpa2VsaWhvb2QgRXN0aW1hdGlvbiBzZWxlY3RzIHBhcmFtZXRlciB2YWx1ZXMgdGhhdCBtYXhpbWl6ZSB0aGUgbGlrZWxpaG9vZCBmdW5jdGlvbiwgbWVhbmluZyBpdCBjaG9vc2VzIHRoZSB2YWx1ZXMgdW5kZXIgd2hpY2ggdGhlIG9ic2VydmVkIGRhdGEgYXJlIG1vc3QgcHJvYmFibGUuDQoNCkluIHRoaXMgYXBwbGljYXRpb24sIGJvdGggbWV0aG9kcyB3ZXJlIHVzZWQgdG8gZXN0aW1hdGUgdGhlIHBhcmFtZXRlcnMgb2YgYSBHYW1tYSBtb2RlbCBmb3IgZGVsaXZlcnkgdGltZXMuIEFsdGhvdWdoIHRoZSBudW1lcmljYWwgZXN0aW1hdGVzIGRpZmZlcmVkIHNsaWdodGx5LCBib3RoIG1ldGhvZHMgcHJvZHVjZWQgdmVyeSBzaW1pbGFyIGZpdHRlZCBjdXJ2ZXMgd2hlbiBvdmVybGFpZCBvbiB0aGUgaGlzdG9ncmFtLiBUaGUgZGF0YSBkaXNwbGF5IG1vZGVyYXRlIHJpZ2h0IHNrZXduZXNzLCBhbmQgYm90aCBmaXR0ZWQgZGlzdHJpYnV0aW9ucyBjYXB0dXJlIHRoZSBjZW50cmFsIGNvbmNlbnRyYXRpb24gb2Ygb2JzZXJ2YXRpb25zIGFzIHdlbGwgYXMgdGhlIGdyYWR1YWwgZGVjbGluZSBpbiB0aGUgcmlnaHQgdGFpbC4gVGhlIHZpc3VhbCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byBmaXR0ZWQgY3VydmVzIGlzIHNtYWxsLCBpbmRpY2F0aW5nIHRoYXQgYm90aCBtZXRob2RzIHByb3ZpZGUgYSByZWFzb25hYmxlIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhLg0KDQpUaGUgTWV0aG9kIG9mIE1vbWVudHMgaGFzIHRoZSBhZHZhbnRhZ2Ugb2YgY29uY2VwdHVhbCBzaW1wbGljaXR5LiBJdCBpcyBzdHJhaWdodGZvcndhcmQgdG8gY29tcHV0ZSBhbmQgb2Z0ZW4gbGVhZHMgdG8gYWxnZWJyYWljYWxseSBzaW1wbGUgc29sdXRpb25zLiBCZWNhdXNlIGl0IHJlbGllcyBvbmx5IG9uIHN1bW1hcnkgc3RhdGlzdGljcywgaXQgaXMgY29tcHV0YXRpb25hbGx5IGVmZmljaWVudCBhbmQgZWFzeSB0byBpbXBsZW1lbnQuIEhvd2V2ZXIsIHNpbmNlIGl0IHVzZXMgb25seSBzZWxlY3RlZCBjaGFyYWN0ZXJpc3RpY3Mgb2YgdGhlIGRhdGEgcmF0aGVyIHRoYW4gdGhlIGZ1bGwgcHJvYmFiaWxpdHkgc3RydWN0dXJlLCBpdCBtYXkgYmUgbGVzcyBzdGF0aXN0aWNhbGx5IGVmZmljaWVudCBhbmQgbWF5IG5vdCBjYXB0dXJlIHN1YnRsZSBmZWF0dXJlcyBvZiB0aGUgZGlzdHJpYnV0aW9uIGFzIGVmZmVjdGl2ZWx5Lg0KDQpNYXhpbXVtIExpa2VsaWhvb2QgRXN0aW1hdGlvbiB0eXBpY2FsbHkgcmVxdWlyZXMgbW9yZSBjb21wdXRhdGlvbmFsIGVmZm9ydCwgZXNwZWNpYWxseSB3aGVuIGNsb3NlZC1mb3JtIHNvbHV0aW9ucyBkbyBub3QgZXhpc3QgYW5kIG51bWVyaWNhbCBvcHRpbWl6YXRpb24gaXMgbmVjZXNzYXJ5LiBEZXNwaXRlIHRoaXMsIE1MRSBoYXMgc3Ryb25nZXIgdGhlb3JldGljYWwgcHJvcGVydGllcyB1bmRlciBzdGFuZGFyZCBjb25kaXRpb25zLiBJdCBpcyBnZW5lcmFsbHkgY29uc2lzdGVudCwgYXN5bXB0b3RpY2FsbHkgbm9ybWFsLCBhbmQgYXN5bXB0b3RpY2FsbHkgZWZmaWNpZW50LCBtZWFuaW5nIHRoYXQgaW4gbGFyZ2Ugc2FtcGxlcyBpdCB0ZW5kcyB0byBwcm9kdWNlIGVzdGltYXRlcyB3aXRoIGRlc2lyYWJsZSBzdGF0aXN0aWNhbCBwcm9wZXJ0aWVzLiBCZWNhdXNlIGl0IGlzIGJhc2VkIG9uIHRoZSBmdWxsIGxpa2VsaWhvb2QgZnVuY3Rpb24sIGl0IG9mdGVuIHByb3ZpZGVzIGEgc2xpZ2h0bHkgYmV0dGVyIG92ZXJhbGwgZml0Lg0KDQpJbiBjb25jbHVzaW9uLCBib3RoIG1ldGhvZHMgcGVyZm9ybSBzaW1pbGFybHkgZm9yIHRoaXMgZGF0YXNldCwgYXMgc2hvd24gYnkgdGhlIG5lYXJseSBvdmVybGFwcGluZyBmaXR0ZWQgY3VydmVzLiBIb3dldmVyLCBNYXhpbXVtIExpa2VsaWhvb2QgRXN0aW1hdGlvbiBpcyBnZW5lcmFsbHkgcHJlZmVycmVkIGluIHByYWN0aWNlIGR1ZSB0byBpdHMgc3Ryb25nZXIgdGhlb3JldGljYWwganVzdGlmaWNhdGlvbiBhbmQgaXRzIHVzZSBvZiB0aGUgZnVsbCBkaXN0cmlidXRpb25hbCBpbmZvcm1hdGlvbi4gVGhlIE1ldGhvZCBvZiBNb21lbnRzIHJlbWFpbnMgdXNlZnVsIGZvciBpdHMgc2ltcGxpY2l0eSBhbmQgYXMgYSBwcmFjdGljYWwgc3RhcnRpbmcgcG9pbnQgZm9yIG1vcmUgYWR2YW5jZWQgZXN0aW1hdGlvbiBwcm9jZWR1cmVzLg==