Chapter 4 - Main Concepts

Linear Regression Analogy to the Geocentric Model

The Ptolemaic geocentric model using the additive combination of circles and epicycles was able to predict the movement of the planets with some accuracy. Despite its inaccuracies, the model worked within certain boundaries and had its uses.

Similarly, Linear regression is like the geocentric model of the solar system in many ways:

  • Simple Yet Powerful: uses an additive combination of measurements (like variables) to predict an outcome. It’s a straightforward tool that can describe a wide variety of phenomena.

  • Descriptive but Limited: can accurately describe relationships between variables but may not capture the full complexity of the real-world processes if taken too literally.

  • Useful Approximation: helps in making predictions and understanding data, even though it might not always capture every nuance.

Example to Illustrate

Imagine you’re a farmer trying to predict the yield of your crop based on the amount of rainfall and fertilizer used. You gather data over several years and use linear regression to create a model:

\[ \text{Crop Yield} = \beta_0 + \beta_1 \times \text{Rainfall} + \beta_2 \times \text{Fertilizer} \]

Epicycles in Farming: Just like epicycles were circles on circles to predict planet positions, you’re using rainfall and fertilizer (variables) to predict crop yield.

Approximation: Your linear regression model gives a good approximation of crop yield based on the data you have, similar to how the geocentric model approximated planetary positions.

Limits: If you tried to predict crop yield in a completely different climate with different soil, the model might fail, just as the geocentric model would fail to plot a Mars probe.

Bayesian Linear Regression

The chapter introduces linear regression as a Bayesian procedure, which means using probability distributions to describe uncertainty. Instead of just finding the best-fitting line, Bayesian regression provides a distribution of possible lines, giving a more nuanced understanding of the uncertainty in predictions.


Call:
lm(formula = scores ~ hours, data = data)

Residuals:
      1       2       3       4       5 
-3.5366  1.0061  5.0915 -0.8232 -1.7378 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)  47.6220     3.8381  12.408  0.00113 **
hours         5.4573     0.6621   8.242  0.00374 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.792 on 3 degrees of freedom
Multiple R-squared:  0.9577,    Adjusted R-squared:  0.9436 
F-statistic: 67.93 on 1 and 3 DF,  p-value: 0.00374

                2.5 %    97.5 %
(Intercept) 35.407486 59.836417
hours        3.350122  7.564513
`geom_smooth()` using formula = 'y ~ x'
`geom_smooth()` using formula = 'y ~ x'

Side-by-Side Comparison

  • Frequentist Plot:

    • Shows a single best-fit line with a shaded area representing the confidence interval.
    • The confidence interval provides an estimate of the uncertainty around the best-fit line.
  • Bayesian Plot:

    • Shows multiple lines sampled from the posterior distribution, indicating a range of plausible models.
    • The spread of these lines gives a visual representation of the uncertainty in the parameter estimates.

Why normal distributions are normal

The familiar “bell” curve of the Gaussian distribution is emerging from the randomness. Where does it come from? Why is it so common?

Normality by addition When you add together many random values from the same distribution, the result tends to form a bell curve, or normal distribution. Here’s an easy way to understand why this happens:

  1. Average and Fluctuations:
  • Think of the average value of the distribution as the center point.
  • Each random value you pick is like a fluctuation or deviation from this average. Some values will be above the average, and some will be below.
  1. Adding Fluctuations:
  • When you start adding these random values, the deviations tend to balance out. A value above the average can be offset by a value below the average.
  • For example, if one value is higher than the average by a certain amount, another value might be lower by about the same amount, canceling each other out.
  1. More Values, More Cancellation:
  • The more values you add together, the more they cancel each other out. This is because there are more opportunities for positive deviations to be balanced by negative deviations.
  1. Resulting Sum:
  • After adding many values, the most likely outcome is one where these fluctuations have balanced out, leading to a sum that is close to zero relative to the average.
  • This balancing act creates a bell curve because there are many ways to achieve sums near the average (due to many combinations of small positive and negative deviations) and fewer ways to achieve extreme sums.

Visual Example

Imagine rolling a die:

  • Each roll gives you a number between 1 and 6.
  • The average (mean) roll is 3.5.
  • If you roll the die many times and add the results, the sum of these rolls will form a bell curve around the mean value because the high and low rolls balance out over many rolls.

Why Use the Gaussian Distribution in Hypotheses?

In the context of statistical modeling, the Gaussian (or normal) distribution is often used as a foundation for building hypotheses. The justifications for this choice fall into two broad categories: ontological and epistemological.

1. Ontological Justification The ontological reason for using the Gaussian distribution is that it appears frequently in nature. While we might never encounter a perfect Gaussian distribution, we often observe patterns that approximate it across various domains and scales. Some examples include:

  • Measurement Errors: Errors in measurements tend to follow a normal distribution.
  • Biological Variations: Growth rates and other biological measures often exhibit Gaussian patterns.
  • Physical Phenomena: The velocities of molecules in a gas, for instance, are normally distributed.

The underlying reason for this prevalence is that many natural processes involve the addition of small, random fluctuations. When these fluctuations are added together repeatedly, the result tends to be a Gaussian distribution. This is because the process of summing these fluctuations sheds all detailed information about the individual contributions, leaving only the mean and spread (variance).

However, it’s important to note that the Gaussian distribution is not the only pattern in nature. There are other significant distributions, like exponential, gamma, and Poisson, which also arise from natural processes. The Gaussian is part of the broader exponential family of distributions, all of which are fundamental in the natural world.

2. Epistemological Justification The epistemological justification for using the Gaussian distribution is based on the concept of maximum entropy and information theory. When we only know or are willing to assume the mean and variance of a distribution, the Gaussian distribution is the most reasonable choice. This is because:

  • State of Ignorance: The Gaussian distribution represents a state of minimal assumptions beyond knowing the mean and variance. It does not introduce any additional assumptions about the data.
  • Maximum Entropy: Given the constraints of finite variance, the Gaussian distribution is the shape that can be realized in the largest number of ways. It is the least surprising and least informative assumption, making it the most consistent with our limited knowledge. In essence, if we don’t have specific information suggesting a different distribution, the Gaussian distribution is the safest, most neutral assumption to make. It aligns with the idea of making the least informative assumption that still fits our known constraints.

Practical Implications Using the Gaussian distribution as a starting point for building models doesn’t mean we are committing to it as the only or best model. It is a practical tool that helps us begin modeling continuous measurements. As we gather more information or develop specific knowledge about the data, we can refine our models and possibly choose other distributions that better fit our data’s characteristics.

In summary, the Gaussian distribution is a powerful tool in statistical modeling due to its natural occurrence in many processes and its role as a default assumption when we have limited information. It provides a solid foundation for building and refining our understanding of data.

Simple Explanation with Examples

Main Idea When we don’t have much information about a set of data, but we do know its average (mean) and how spread out the values are (variance), the Gaussian distribution is the most neutral choice. It’s like saying, “Given what little we know, this is the safest bet.”

Example 1: Heights of Students Imagine you’re a school principal, and you want to understand the heights of students in your school. You don’t have detailed data about every student’s height, but you do know the average height (mean) and the general variability in heights (variance).

Known Information:

  • Average height (mean): 150 cm
  • Variability in heights (variance): 25 cm²

Given just this information, you choose to assume that the heights follow a Gaussian distribution because it is the least biased choice. It doesn’t make any extra assumptions about the specific shape of the data beyond what you know.

Ontological Justification

  • Normal Distribution:
    • You assume the heights follow a normal distribution with the given mean and variance. This is reasonable because it implies that most people have heights around the average, with fewer people being much taller or shorter. This aligns well with how human heights are typically distributed.
  • Uniform Distribution:
    • Alternatively, if you assume the heights follow a uniform distribution, you imply that any height within a certain range is equally likely. This assumption doesn’t match the natural clustering of human heights around an average value and can be considered less realistic and more informative than necessary.

Epistemological Justification

  • Normal Distribution:
    • The normal distribution is the most unbiased choice when you only know the mean and variance of the data. It is the least informative assumption you can make about the data beyond these two parameters.
  • Uniform Distribution:
    • Assumes all outcomes in the interval [a, b] are equally likely, which is a strong assumption compared to knowing just the mean and variance. This makes it a less neutral choice when you have limited information.

Framework for Describing Models

Step 1: Recognize a Set of Variables

Observable Variable (Data): - Heights of individuals (let’s denote it as \(y\)).

Unobservable Variables (Parameters): - Mean height (\(\mu\)). - Standard deviation of heights (\(\sigma\)).

Step 2: Define Each Variable

Heights (\(y\)): The heights are distributed according to a normal (Gaussian) distribution with mean \(\mu\) and standard deviation \(\sigma\).

\[ y_i \sim \text{Normal}(\mu, \sigma) \]

Mean Height (\(\mu\)): This parameter can be modeled with a prior distribution if we have some prior knowledge. Let’s assume a normal prior with mean 178 cm and standard deviation 20 cm.

\[ \mu \sim \text{Normal}(178, 20) \]

Standard Deviation (\(\sigma\)): This parameter can also be modeled with a prior distribution. Let’s assume a uniform prior from 0 to 50 cm, indicating we believe the standard deviation could reasonably be anywhere in this range.

\[ \sigma \sim \text{Uniform}(0, 50) \]

Step 3: Joint Generative Model

Combining these variables and their probability distributions, we define a joint generative model. This model allows us to simulate hypothetical observations and analyze real data.

  1. Specify priors: \[ \mu \sim \text{Normal}(178, 20) \] \[ \sigma \sim \text{Uniform}(0, 50) \]

  2. Specify likelihood: \[ y_i \sim \text{Normal}(\mu, \sigma) \]

This model describes how the observed data (heights) are generated from the underlying parameters (mean and standard deviation).

Step 4: Compute the Posterior

To compute the posterior distribution, we apply Bayes’ theorem:

\[ P(\mu, \sigma \mid y) \propto P(y \mid \mu, \sigma) P(\mu) P(\sigma) \]

where:

  • \(P(\mu, \sigma \mid y)\) is the posterior distribution.
  • \(P(y \mid \mu, \sigma)\) is the likelihood of the observed data.
  • \(P(\mu)\) and \(P(\sigma)\) are the priors.

Prior Choices

Computing the posterior distribution

The chapter investigates two ways of computing the posterior: grid approximation and Quadratic approximation.

  • Grid approximation:
    • Pros: Simple, intuitive, and easy to understand.
    • Cons: Computationally expensive and may not scale well to high-dimensional problems.
  • Quadratic approximation:
    • Pros: Fast and efficient for high-dimensional problems.
    • Cons: Requires more advanced mathematical techniques and may be less intuitive.

Questions to discuss

1. Normal Distribution Justification:

  • Why is the Gaussian distribution often used as the skeleton for hypotheses in Bayesian regression? Discuss the ontological and epistemological justifications presented in the notebook.

2. Priors and Their Influence:

  • How do the choices of priors (Normal vs. Uniform) influence the results of Bayesian regression?

3. Visualizing Posterior Distributions:

  • The notebook includes plots of posterior distributions for 𝜇 and 𝜎 using both grid and quadratic approximations. What insights can you draw from these plots about the behavior of the posterior distributions?

4. Computational Challenges:

  • Bayesian methods, especially those involving complex models, can be computationally intensive. How do address these challenges?
LS0tDQp0aXRsZTogIlN0YXRpc3RpY2FsIFJldGhpbmtpbmcgd2l0aCBSIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KIyBJbXBvcnQgdGhlIG5lY2Vzc2FyeSBsaWJyYXJpZXMgZm9yIHRoZSBhbmFseXNpcy4NCg0KIyBJbnN0YWxsIG5lY2Vzc2FyeSBwYWNrYWdlcyBpZiBub3QgYWxyZWFkeSBpbnN0YWxsZWQNCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZ2dhbmltYXRlIiwgcXVpZXRseSA9IFRSVUUpKSBpbnN0YWxsLnBhY2thZ2VzKCJnZ2FuaW1hdGUiKQ0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJnZ3Bsb3QyIiwgcXVpZXRseSA9IFRSVUUpKSBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZHBseXIiLCBxdWlldGx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMoImRwbHlyIikNCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZ2lmc2tpIiwgcXVpZXRseSA9IFRSVUUpKSBpbnN0YWxsLnBhY2thZ2VzKCJnaWZza2kiKQ0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJhdiIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygiYXYiKQ0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJiYXNlNjRlbmMiLCBxdWlldGx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMoImJhc2U2NGVuYyIpDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIm1hZ2ljayIsIHF1aWV0bHkgPSBUUlVFKSkgaW5zdGFsbC5wYWNrYWdlcygibWFnaWNrIikNCg0KIyBMb2FkIG5lY2Vzc2FyeSBsaWJyYXJpZXMNCmxpYnJhcnkocmV0aGlua2luZykNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZ3JpZEV4dHJhKQ0KDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdnYW5pbWF0ZSkNCmxpYnJhcnkoZHBseXIpDQoNCmxpYnJhcnkobWFnaWNrKQ0KbGlicmFyeShodG1sdG9vbHMpDQpsaWJyYXJ5KGJhc2U2NGVuYykNCg0KDQoNCmBgYA0KDQojIENoYXB0ZXIgNCAtIE1haW4gQ29uY2VwdHMNCg0KIyMgTGluZWFyIFJlZ3Jlc3Npb24gQW5hbG9neSB0byB0aGUgR2VvY2VudHJpYyBNb2RlbA0KDQpUaGUgUHRvbGVtYWljIGdlb2NlbnRyaWMgbW9kZWwgdXNpbmcgdGhlIGFkZGl0aXZlIGNvbWJpbmF0aW9uIG9mIGNpcmNsZXMNCmFuZCBlcGljeWNsZXMgd2FzIGFibGUgdG8gcHJlZGljdCB0aGUgbW92ZW1lbnQgb2YgdGhlIHBsYW5ldHMgd2l0aCBzb21lDQphY2N1cmFjeS4gRGVzcGl0ZSBpdHMgaW5hY2N1cmFjaWVzLCB0aGUgbW9kZWwgd29ya2VkIHdpdGhpbiBjZXJ0YWluDQpib3VuZGFyaWVzIGFuZCBoYWQgaXRzIHVzZXMuDQoNClNpbWlsYXJseSwgTGluZWFyIHJlZ3Jlc3Npb24gaXMgbGlrZSB0aGUgZ2VvY2VudHJpYyBtb2RlbCBvZiB0aGUgc29sYXINCnN5c3RlbSBpbiBtYW55IHdheXM6DQoNCi0gICAqKlNpbXBsZSBZZXQgUG93ZXJmdWwqKjogdXNlcyBhbiBhZGRpdGl2ZSBjb21iaW5hdGlvbiBvZg0KICAgIG1lYXN1cmVtZW50cyAobGlrZSB2YXJpYWJsZXMpIHRvIHByZWRpY3QgYW4gb3V0Y29tZS4gSXQncyBhDQogICAgc3RyYWlnaHRmb3J3YXJkIHRvb2wgdGhhdCBjYW4gZGVzY3JpYmUgYSB3aWRlIHZhcmlldHkgb2YgcGhlbm9tZW5hLg0KDQotICAgKipEZXNjcmlwdGl2ZSBidXQgTGltaXRlZCoqOiBjYW4gYWNjdXJhdGVseSBkZXNjcmliZSByZWxhdGlvbnNoaXBzDQogICAgYmV0d2VlbiB2YXJpYWJsZXMgYnV0IG1heSBub3QgY2FwdHVyZSB0aGUgZnVsbCBjb21wbGV4aXR5IG9mIHRoZQ0KICAgIHJlYWwtd29ybGQgcHJvY2Vzc2VzIGlmIHRha2VuIHRvbyBsaXRlcmFsbHkuDQoNCi0gICAqKlVzZWZ1bCBBcHByb3hpbWF0aW9uKio6IGhlbHBzIGluIG1ha2luZyBwcmVkaWN0aW9ucyBhbmQNCiAgICB1bmRlcnN0YW5kaW5nIGRhdGEsIGV2ZW4gdGhvdWdoIGl0IG1pZ2h0IG5vdCBhbHdheXMgY2FwdHVyZSBldmVyeQ0KICAgIG51YW5jZS4NCg0KIyMjIEV4YW1wbGUgdG8gSWxsdXN0cmF0ZQ0KDQpJbWFnaW5lIHlvdeKAmXJlIGEgZmFybWVyIHRyeWluZyB0byBwcmVkaWN0IHRoZSB5aWVsZCBvZiB5b3VyIGNyb3AgYmFzZWQNCm9uIHRoZSBhbW91bnQgb2YgcmFpbmZhbGwgYW5kIGZlcnRpbGl6ZXIgdXNlZC4gWW91IGdhdGhlciBkYXRhIG92ZXINCnNldmVyYWwgeWVhcnMgYW5kIHVzZSBsaW5lYXIgcmVncmVzc2lvbiB0byBjcmVhdGUgYSBtb2RlbDoNCg0KJCQgXHRleHR7Q3JvcCBZaWVsZH0gPSBcYmV0YV8wICsgXGJldGFfMSBcdGltZXMgXHRleHR7UmFpbmZhbGx9ICsgXGJldGFfMiBcdGltZXMgXHRleHR7RmVydGlsaXplcn0gJCQNCg0KKipFcGljeWNsZXMgaW4gRmFybWluZyoqOiBKdXN0IGxpa2UgZXBpY3ljbGVzIHdlcmUgY2lyY2xlcyBvbiBjaXJjbGVzIHRvDQpwcmVkaWN0IHBsYW5ldCBwb3NpdGlvbnMsIHlvdeKAmXJlIHVzaW5nIHJhaW5mYWxsIGFuZCBmZXJ0aWxpemVyDQoodmFyaWFibGVzKSB0byBwcmVkaWN0IGNyb3AgeWllbGQuDQoNCioqQXBwcm94aW1hdGlvbioqOiBZb3VyIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsIGdpdmVzIGEgZ29vZA0KYXBwcm94aW1hdGlvbiBvZiBjcm9wIHlpZWxkIGJhc2VkIG9uIHRoZSBkYXRhIHlvdSBoYXZlLCBzaW1pbGFyIHRvIGhvdw0KdGhlIGdlb2NlbnRyaWMgbW9kZWwgYXBwcm94aW1hdGVkIHBsYW5ldGFyeSBwb3NpdGlvbnMuDQoNCioqTGltaXRzKio6IElmIHlvdSB0cmllZCB0byBwcmVkaWN0IGNyb3AgeWllbGQgaW4gYSBjb21wbGV0ZWx5IGRpZmZlcmVudA0KY2xpbWF0ZSB3aXRoIGRpZmZlcmVudCBzb2lsLCB0aGUgbW9kZWwgbWlnaHQgZmFpbCwganVzdCBhcyB0aGUNCmdlb2NlbnRyaWMgbW9kZWwgd291bGQgZmFpbCB0byBwbG90IGEgTWFycyBwcm9iZS4NCg0KIyMjIEJheWVzaWFuIExpbmVhciBSZWdyZXNzaW9uDQoNClRoZSBjaGFwdGVyIGludHJvZHVjZXMgbGluZWFyIHJlZ3Jlc3Npb24gYXMgYSBCYXllc2lhbiBwcm9jZWR1cmUsIHdoaWNoDQptZWFucyB1c2luZyBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb25zIHRvIGRlc2NyaWJlIHVuY2VydGFpbnR5LiBJbnN0ZWFkDQpvZiBqdXN0IGZpbmRpbmcgdGhlIGJlc3QtZml0dGluZyBsaW5lLCBCYXllc2lhbiByZWdyZXNzaW9uIHByb3ZpZGVzIGENCmRpc3RyaWJ1dGlvbiBvZiBwb3NzaWJsZSBsaW5lcywgZ2l2aW5nIGEgbW9yZSBudWFuY2VkIHVuZGVyc3RhbmRpbmcgb2YNCnRoZSB1bmNlcnRhaW50eSBpbiBwcmVkaWN0aW9ucy4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQojIEV4YW1wbGUgZGF0YQ0KZGF0YSA8LSBkYXRhLmZyYW1lKGhvdXJzID0gYygyLCAzLCA1LCA3LCA5KSwgc2NvcmVzID0gYyg1NSwgNjUsIDgwLCA4NSwgOTUpKQ0KDQojIEZyZXF1ZW50aXN0IHJlZ3Jlc3Npb24NCiMgRml0IGEgZnJlcXVlbnRpc3QgbGluZWFyIG1vZGVsDQpmcmVxX21vZGVsIDwtIGxtKHNjb3JlcyB+IGhvdXJzLCBkYXRhID0gZGF0YSkNCg0KIyBTdW1tYXJ5IG9mIHRoZSBmcmVxdWVudGlzdCBtb2RlbA0Kc3VtbWFyeShmcmVxX21vZGVsKQ0KDQojIFByZWRpY3RlZCB2YWx1ZXMgZnJvbSB0aGUgZnJlcXVlbnRpc3QgbW9kZWwNCmRhdGEkZnJlcV9wcmVkIDwtIHByZWRpY3QoZnJlcV9tb2RlbCkNCg0KIyBDb25maWRlbmNlIGludGVydmFscyBmb3IgdGhlIGZyZXF1ZW50aXN0IG1vZGVsDQpjb25maW50KGZyZXFfbW9kZWwpDQoNCg0KIyBCYXllc2lhbiByZWdyZXNzaW9uDQojIERlZmluZSB0aGUgQmF5ZXNpYW4gbW9kZWwgdXNpbmcgdGhlIG1hcCBmdW5jdGlvbg0KYmF5ZXNfbW9kZWwgPC0gbWFwKA0KICBhbGlzdCgNCiAgICBzY29yZXMgfiBkbm9ybShtdSwgc2lnbWEpLCAgICAgICAgICAjIExpa2VsaWhvb2Q6IGV4YW0gc2NvcmVzIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZA0KICAgIG11IDwtIGEgKyBiICogaG91cnMsICAgICAgICAgICAgICAgICMgTGluZWFyIG1vZGVsOiBtZWFuIG9mIHNjb3JlcyBkZXBlbmRzIG9uIGhvdXJzIHN0dWRpZWQNCiAgICBhIH4gZG5vcm0oNTAsIDEwKSwgICAgICAgICAgICAgICAgICAjIFByaW9yIGZvciB0aGUgaW50ZXJjZXB0DQogICAgYiB+IGRub3JtKDAsIDEwKSwgICAgICAgICAgICAgICAgICAgIyBQcmlvciBmb3IgdGhlIHNsb3BlDQogICAgc2lnbWEgfiBkdW5pZigwLCAxMCkgICAgICAgICAgICAgICAgIyBQcmlvciBmb3IgdGhlIHN0YW5kYXJkIGRldmlhdGlvbg0KICApLA0KICBkYXRhID0gZGF0YQ0KKQ0KDQojIFN1bW1hcml6ZSB0aGUgQmF5ZXNpYW4gbW9kZWwNCnByZWNpcyhiYXllc19tb2RlbCkNCg0KIyBFeHRyYWN0IHBvc3RlcmlvciBzYW1wbGVzDQpwb3N0IDwtIGV4dHJhY3Quc2FtcGxlcyhiYXllc19tb2RlbCwgbiA9IDEwMDApDQoNCg0KIyBDcmVhdGUgY29tYmluZWQgcGxvdA0KIyBDcmVhdGUgdGhlIGZyZXF1ZW50aXN0IHBsb3QNCmZyZXFfcGxvdCA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHggPSBob3VycywgeSA9IHNjb3JlcykpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBUUlVFLCBjb2xvciA9ICJibHVlIiwgZmlsbCA9ICJsaWdodGJsdWUiKSArDQogIGxhYnModGl0bGUgPSAiRnJlcXVlbnRpc3QgTGluZWFyIFJlZ3Jlc3Npb24iLCB4ID0gIkhvdXJzIFN0dWRpZWQiLCB5ID0gIkV4YW0gU2NvcmUiKQ0KDQojIENyZWF0ZSB0aGUgQmF5ZXNpYW4gcGxvdA0KYmF5ZXNfcGxvdCA8LSBnZ3Bsb3QoZGF0YSwgYWVzKHggPSBob3VycywgeSA9IHNjb3JlcykpICsNCiAgZ2VvbV9wb2ludCgpICsNCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sID0gImxpZ2h0Z3JleSIpICsNCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gbWVhbihwb3N0JGEpLCBzbG9wZSA9IG1lYW4ocG9zdCRiKSwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSAxLjIpICsNCiAgbGFicyh0aXRsZSA9ICJCYXllc2lhbiBMaW5lYXIgUmVncmVzc2lvbiIsIHggPSAiSG91cnMgU3R1ZGllZCIsIHkgPSAiRXhhbSBTY29yZSIpDQoNCiMgQWRkIG11bHRpcGxlIHBvc3RlcmlvciBsaW5lcyB0byB0aGUgQmF5ZXNpYW4gcGxvdA0KZm9yIChpIGluIDE6MTAwKSB7DQogIGJheWVzX3Bsb3QgPC0gYmF5ZXNfcGxvdCArDQogICAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gcG9zdCRhW2ldLCBzbG9wZSA9IHBvc3QkYltpXSwgY29sb3IgPSBhbHBoYSgiYmx1ZSIsIDAuMSkpDQp9DQoNCiMgQ29tYmluZSB0aGUgdHdvIHBsb3RzIHNpZGUgYnkgc2lkZQ0KZ3JpZC5hcnJhbmdlKGZyZXFfcGxvdCwgYmF5ZXNfcGxvdCwgbmNvbCA9IDIpDQoNCg0KYGBgDQoNCiMjIyBTaWRlLWJ5LVNpZGUgQ29tcGFyaXNvbg0KDQotICAgKipGcmVxdWVudGlzdCBQbG90Kio6DQoNCiAgICAtICAgU2hvd3MgYSBzaW5nbGUgYmVzdC1maXQgbGluZSB3aXRoIGEgc2hhZGVkIGFyZWEgcmVwcmVzZW50aW5nIHRoZQ0KICAgICAgICBjb25maWRlbmNlIGludGVydmFsLg0KICAgIC0gICBUaGUgY29uZmlkZW5jZSBpbnRlcnZhbCBwcm92aWRlcyBhbiBlc3RpbWF0ZSBvZiB0aGUgdW5jZXJ0YWludHkNCiAgICAgICAgYXJvdW5kIHRoZSBiZXN0LWZpdCBsaW5lLg0KDQotICAgKipCYXllc2lhbiBQbG90Kio6DQoNCiAgICAtICAgU2hvd3MgbXVsdGlwbGUgbGluZXMgc2FtcGxlZCBmcm9tIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uLA0KICAgICAgICBpbmRpY2F0aW5nIGEgcmFuZ2Ugb2YgcGxhdXNpYmxlIG1vZGVscy4NCiAgICAtICAgVGhlIHNwcmVhZCBvZiB0aGVzZSBsaW5lcyBnaXZlcyBhIHZpc3VhbCByZXByZXNlbnRhdGlvbiBvZiB0aGUNCiAgICAgICAgdW5jZXJ0YWludHkgaW4gdGhlIHBhcmFtZXRlciBlc3RpbWF0ZXMuDQoNCiMjIFdoeSBub3JtYWwgZGlzdHJpYnV0aW9ucyBhcmUgbm9ybWFsDQoNClRoZSBmYW1pbGlhciDigJxiZWxs4oCdIGN1cnZlIG9mIHRoZSBHYXVzc2lhbiBkaXN0cmlidXRpb24gaXMgZW1lcmdpbmcgZnJvbQ0KdGhlIHJhbmRvbW5lc3MuIFdoZXJlIGRvZXMgaXQgY29tZSBmcm9tPyBXaHkgaXMgaXQgc28gY29tbW9uPw0KDQoqKk5vcm1hbGl0eSBieSBhZGRpdGlvbioqIFdoZW4geW91IGFkZCB0b2dldGhlciBtYW55IHJhbmRvbSB2YWx1ZXMgZnJvbQ0KdGhlIHNhbWUgZGlzdHJpYnV0aW9uLCB0aGUgcmVzdWx0IHRlbmRzIHRvIGZvcm0gYSBiZWxsIGN1cnZlLCBvciBub3JtYWwNCmRpc3RyaWJ1dGlvbi4gSGVyZeKAmXMgYW4gZWFzeSB3YXkgdG8gdW5kZXJzdGFuZCB3aHkgdGhpcyBoYXBwZW5zOg0KDQoxLiAgKipBdmVyYWdlIGFuZCBGbHVjdHVhdGlvbnMqKjoNCg0KLSAgIFRoaW5rIG9mIHRoZSBhdmVyYWdlIHZhbHVlIG9mIHRoZSBkaXN0cmlidXRpb24gYXMgdGhlIGNlbnRlciBwb2ludC4NCi0gICBFYWNoIHJhbmRvbSB2YWx1ZSB5b3UgcGljayBpcyBsaWtlIGEgZmx1Y3R1YXRpb24gb3IgZGV2aWF0aW9uIGZyb20NCiAgICB0aGlzIGF2ZXJhZ2UuIFNvbWUgdmFsdWVzIHdpbGwgYmUgYWJvdmUgdGhlIGF2ZXJhZ2UsIGFuZCBzb21lIHdpbGwNCiAgICBiZSBiZWxvdy4NCg0KMi4gICoqQWRkaW5nIEZsdWN0dWF0aW9ucyoqOg0KDQotICAgV2hlbiB5b3Ugc3RhcnQgYWRkaW5nIHRoZXNlIHJhbmRvbSB2YWx1ZXMsIHRoZSBkZXZpYXRpb25zIHRlbmQgdG8NCiAgICBiYWxhbmNlIG91dC4gQSB2YWx1ZSBhYm92ZSB0aGUgYXZlcmFnZSBjYW4gYmUgb2Zmc2V0IGJ5IGEgdmFsdWUNCiAgICBiZWxvdyB0aGUgYXZlcmFnZS4NCi0gICBGb3IgZXhhbXBsZSwgaWYgb25lIHZhbHVlIGlzIGhpZ2hlciB0aGFuIHRoZSBhdmVyYWdlIGJ5IGEgY2VydGFpbg0KICAgIGFtb3VudCwgYW5vdGhlciB2YWx1ZSBtaWdodCBiZSBsb3dlciBieSBhYm91dCB0aGUgc2FtZSBhbW91bnQsDQogICAgY2FuY2VsaW5nIGVhY2ggb3RoZXIgb3V0Lg0KDQozLiAgKipNb3JlIFZhbHVlcywgTW9yZSBDYW5jZWxsYXRpb24qKjoNCg0KLSAgIFRoZSBtb3JlIHZhbHVlcyB5b3UgYWRkIHRvZ2V0aGVyLCB0aGUgbW9yZSB0aGV5IGNhbmNlbCBlYWNoIG90aGVyDQogICAgb3V0LiBUaGlzIGlzIGJlY2F1c2UgdGhlcmUgYXJlIG1vcmUgb3Bwb3J0dW5pdGllcyBmb3IgcG9zaXRpdmUNCiAgICBkZXZpYXRpb25zIHRvIGJlIGJhbGFuY2VkIGJ5IG5lZ2F0aXZlIGRldmlhdGlvbnMuDQoNCjQuICAqKlJlc3VsdGluZyBTdW0qKjoNCg0KLSAgIEFmdGVyIGFkZGluZyBtYW55IHZhbHVlcywgdGhlIG1vc3QgbGlrZWx5IG91dGNvbWUgaXMgb25lIHdoZXJlIHRoZXNlDQogICAgZmx1Y3R1YXRpb25zIGhhdmUgYmFsYW5jZWQgb3V0LCBsZWFkaW5nIHRvIGEgc3VtIHRoYXQgaXMgY2xvc2UgdG8NCiAgICB6ZXJvIHJlbGF0aXZlIHRvIHRoZSBhdmVyYWdlLg0KLSAgIFRoaXMgYmFsYW5jaW5nIGFjdCBjcmVhdGVzIGEgYmVsbCBjdXJ2ZSBiZWNhdXNlIHRoZXJlIGFyZSBtYW55IHdheXMNCiAgICB0byBhY2hpZXZlIHN1bXMgbmVhciB0aGUgYXZlcmFnZSAoZHVlIHRvIG1hbnkgY29tYmluYXRpb25zIG9mIHNtYWxsDQogICAgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIGRldmlhdGlvbnMpIGFuZCBmZXdlciB3YXlzIHRvIGFjaGlldmUgZXh0cmVtZQ0KICAgIHN1bXMuDQoNCioqVmlzdWFsIEV4YW1wbGUqKg0KDQpJbWFnaW5lIHJvbGxpbmcgYSBkaWU6DQoNCi0gICBFYWNoIHJvbGwgZ2l2ZXMgeW91IGEgbnVtYmVyIGJldHdlZW4gMSBhbmQgNi4NCi0gICBUaGUgYXZlcmFnZSAobWVhbikgcm9sbCBpcyAzLjUuDQotICAgSWYgeW91IHJvbGwgdGhlIGRpZSBtYW55IHRpbWVzIGFuZCBhZGQgdGhlIHJlc3VsdHMsIHRoZSBzdW0gb2YgdGhlc2UNCiAgICByb2xscyB3aWxsIGZvcm0gYSBiZWxsIGN1cnZlIGFyb3VuZCB0aGUgbWVhbiB2YWx1ZSBiZWNhdXNlIHRoZSBoaWdoDQogICAgYW5kIGxvdyByb2xscyBiYWxhbmNlIG91dCBvdmVyIG1hbnkgcm9sbHMuDQoNCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvPUZBTFNFfQ0KDQoNCiMgU2V0IHNlZWQgZm9yIHJlcHJvZHVjaWJpbGl0eQ0Kc2V0LnNlZWQoMTIzKQ0KDQojIFBhcmFtZXRlcnMNCm51bV9zaW11bGF0aW9ucyA8LSAxMDAwDQpudW1fcm9sbHMgPC0gMzANCg0KIyBGdW5jdGlvbiB0byBzaW11bGF0ZSBkaWNlIHJvbGxzIGFuZCBjYWxjdWxhdGUgc3Vtcw0Kc2ltdWxhdGVfcm9sbHMgPC0gZnVuY3Rpb24obnVtX3NpbXVsYXRpb25zLCBudW1fcm9sbHMpIHsNCiAgZGF0YSA8LSBkYXRhLmZyYW1lKCkNCiAgZm9yIChpIGluIDE6bnVtX3NpbXVsYXRpb25zKSB7DQogICAgcm9sbHMgPC0gc2FtcGxlKDE6NiwgbnVtX3JvbGxzLCByZXBsYWNlID0gVFJVRSkNCiAgICBzdW1fcm9sbHMgPC0gY3Vtc3VtKHJvbGxzKQ0KICAgIHRlbXAgPC0gZGF0YS5mcmFtZShyb2xsX251bWJlciA9IDE6bnVtX3JvbGxzLCBzdW0gPSBzdW1fcm9sbHMsIHNpbXVsYXRpb24gPSBpKQ0KICAgIGRhdGEgPC0gcmJpbmQoZGF0YSwgdGVtcCkNCiAgfQ0KICByZXR1cm4oZGF0YSkNCn0NCg0KIyBTaW11bGF0ZSB0aGUgZGljZSByb2xscw0KZGF0YSA8LSBzaW11bGF0ZV9yb2xscyhudW1fc2ltdWxhdGlvbnMsIG51bV9yb2xscykNCg0KIyBDYWxjdWxhdGUgbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGZvciBub3JtYWxpemF0aW9uDQpkYXRhIDwtIGRhdGEgJT4lDQogIGdyb3VwX2J5KHJvbGxfbnVtYmVyKSAlPiUNCiAgbXV0YXRlKG1lYW5fc3VtID0gbWVhbihzdW0pLCBzZF9zdW0gPSBzZChzdW0pKSAlPiUNCiAgdW5ncm91cCgpDQoNCiMgQ3JlYXRlIGFuaW1hdGVkIHBsb3QNCnAgPC0gZ2dwbG90KGRhdGEsIGFlcyh4ID0gc3VtKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IC4uZGVuc2l0eS4uKSwgYmlucyA9IDMwLCBmaWxsID0gImJsdWUiLCBhbHBoYSA9IDAuNSkgKw0KICBnZW9tX2RlbnNpdHkoY29sb3IgPSAicmVkIiwgc2l6ZSA9IDEpICsNCiAgbGFicyh0aXRsZSA9ICdEaXN0cmlidXRpb24gb2YgU3VtcyBvZiBEaWNlIFJvbGxzOiBSb2xsIHtjbG9zZXN0X3N0YXRlfScsDQogICAgICAgeCA9ICdTdW0gb2YgRGljZSBSb2xscycsIHkgPSAnRGVuc2l0eScpICsNCiAgdGhlbWVfbWluaW1hbCgpICsNCiAgdHJhbnNpdGlvbl9zdGF0ZXMocm9sbF9udW1iZXIsIHRyYW5zaXRpb25fbGVuZ3RoID0gMiwgc3RhdGVfbGVuZ3RoID0gMSkgKw0KICBlYXNlX2Flcygnc2luZS1pbi1vdXQnKQ0KDQojIFNhdmUgdGhlIGFuaW1hdGlvbg0KYW5pbV9zYXZlKCJkaWNlX3JvbGxzX2FuaW1hdGlvbi5naWYiLCBwLCByZW5kZXJlciA9IGdpZnNraV9yZW5kZXJlcigpKQ0KDQoNCmBgYA0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCiMgRGlzcGxheSB0aGUgc2F2ZWQgR0lGIGlubGluZQ0KZ2lmX3BhdGggPC0gImRpY2Vfcm9sbHNfYW5pbWF0aW9uLmdpZiINCmdpZl9kYXRhIDwtIGJhc2U2NGVuYzo6ZGF0YVVSSShmaWxlID0gZ2lmX3BhdGgsIG1pbWUgPSAiaW1hZ2UvZ2lmIikNCg0KIyBVc2UgaHRtbHRvb2xzIHRvIGVtYmVkIHRoZSBHSUYgaW4gdGhlIG5vdGVib29rDQpodG1sdG9vbHM6OnRhZ3MkaW1nKHNyYyA9IGdpZl9kYXRhKQ0KDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0V9DQoNCiMgTnVtYmVyIG9mIHNpbXVsYXRpb25zDQpudW1fc2ltdWxhdGlvbnMgPC0gMTAwMDANCg0KIyBOdW1iZXIgb2YgZGljZSByb2xscyBpbiBlYWNoIHNpbXVsYXRpb24NCm51bV9yb2xscyA8LSAzMA0KDQojIFNpbXVsYXRlIHRoZSBzdW1zIG9mIGRpY2Ugcm9sbHMNCnN1bXMgPC0gcmVwbGljYXRlKG51bV9zaW11bGF0aW9ucywgc3VtKHNhbXBsZSgxOjYsIG51bV9yb2xscywgcmVwbGFjZSA9IFRSVUUpKSkNCg0KIyBQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHN1bXMNCmdncGxvdChkYXRhLmZyYW1lKHN1bXMgPSBzdW1zKSwgYWVzKHggPSBzdW1zKSkgKw0KICBnZW9tX2hpc3RvZ3JhbShhZXMoeSA9IGFmdGVyX3N0YXQoZGVuc2l0eSkpLCBiaW5zID0gMzAsIGZpbGwgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArDQogIGdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFN1bXMgb2YgMzAgRGljZSBSb2xscyIsDQogICAgICAgeCA9ICJTdW0gb2YgRGljZSBSb2xscyIsDQogICAgICAgeSA9ICJEZW5zaXR5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KIyBTaW11bGF0ZSB0aGUgc3VtcyBvZiByYW5kb20gdmFsdWVzIGZyb20gYSB1bmlmb3JtIGRpc3RyaWJ1dGlvbg0Kc3Vtc191bmlmb3JtIDwtIHJlcGxpY2F0ZShudW1fc2ltdWxhdGlvbnMsIHN1bShydW5pZihudW1fcm9sbHMsIDAsIDEpKSkNCg0KIyBQbG90IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHN1bXMNCmdncGxvdChkYXRhLmZyYW1lKHN1bXMgPSBzdW1zX3VuaWZvcm0pLCBhZXMoeCA9IHN1bXMpKSArDQogIGdlb21faGlzdG9ncmFtKGFlcyh5ID0gYWZ0ZXJfc3RhdChkZW5zaXR5KSksIGJpbnMgPSAzMCwgZmlsbCA9ICJncmVlbiIsIGFscGhhID0gMC41KSArDQogIGdlb21fZGVuc2l0eShjb2xvciA9ICJyZWQiKSArDQogIGxhYnModGl0bGUgPSAiRGlzdHJpYnV0aW9uIG9mIFN1bXMgb2YgMzAgVW5pZm9ybSBSYW5kb20gVmFsdWVzIiwNCiAgICAgICB4ID0gIlN1bSBvZiBVbmlmb3JtIFZhbHVlcyIsDQogICAgICAgeSA9ICJEZW5zaXR5IikgKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQojIyMgV2h5IFVzZSB0aGUgR2F1c3NpYW4gRGlzdHJpYnV0aW9uIGluIEh5cG90aGVzZXM/DQpJbiB0aGUgY29udGV4dCBvZiBzdGF0aXN0aWNhbCBtb2RlbGluZywgdGhlIEdhdXNzaWFuIChvciBub3JtYWwpIGRpc3RyaWJ1dGlvbiBpcyBvZnRlbiB1c2VkIGFzIGEgZm91bmRhdGlvbiBmb3IgYnVpbGRpbmcgaHlwb3RoZXNlcy4gVGhlIGp1c3RpZmljYXRpb25zIGZvciB0aGlzIGNob2ljZSBmYWxsIGludG8gdHdvIGJyb2FkIGNhdGVnb3JpZXM6IG9udG9sb2dpY2FsIGFuZCBlcGlzdGVtb2xvZ2ljYWwuDQoNCioqMS4gT250b2xvZ2ljYWwgSnVzdGlmaWNhdGlvbioqDQpUaGUgb250b2xvZ2ljYWwgcmVhc29uIGZvciB1c2luZyB0aGUgR2F1c3NpYW4gZGlzdHJpYnV0aW9uIGlzIHRoYXQgaXQgYXBwZWFycyBmcmVxdWVudGx5IGluIG5hdHVyZS4gV2hpbGUgd2UgbWlnaHQgbmV2ZXIgZW5jb3VudGVyIGEgcGVyZmVjdCBHYXVzc2lhbiBkaXN0cmlidXRpb24sIHdlIG9mdGVuIG9ic2VydmUgcGF0dGVybnMgdGhhdCBhcHByb3hpbWF0ZSBpdCBhY3Jvc3MgdmFyaW91cyBkb21haW5zIGFuZCBzY2FsZXMuIFNvbWUgZXhhbXBsZXMgaW5jbHVkZToNCg0KLSAqKk1lYXN1cmVtZW50IEVycm9ycyoqOiBFcnJvcnMgaW4gbWVhc3VyZW1lbnRzIHRlbmQgdG8gZm9sbG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCi0gKipCaW9sb2dpY2FsIFZhcmlhdGlvbnMqKjogR3Jvd3RoIHJhdGVzIGFuZCBvdGhlciBiaW9sb2dpY2FsIG1lYXN1cmVzIG9mdGVuIGV4aGliaXQgR2F1c3NpYW4gcGF0dGVybnMuDQotICoqUGh5c2ljYWwgUGhlbm9tZW5hKio6IFRoZSB2ZWxvY2l0aWVzIG9mIG1vbGVjdWxlcyBpbiBhIGdhcywgZm9yIGluc3RhbmNlLCBhcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQoNClRoZSB1bmRlcmx5aW5nIHJlYXNvbiBmb3IgdGhpcyBwcmV2YWxlbmNlIGlzIHRoYXQgbWFueSBuYXR1cmFsIHByb2Nlc3NlcyBpbnZvbHZlIHRoZSBhZGRpdGlvbiBvZiBzbWFsbCwgcmFuZG9tIGZsdWN0dWF0aW9ucy4gV2hlbiB0aGVzZSBmbHVjdHVhdGlvbnMgYXJlIGFkZGVkIHRvZ2V0aGVyIHJlcGVhdGVkbHksIHRoZSByZXN1bHQgdGVuZHMgdG8gYmUgYSBHYXVzc2lhbiBkaXN0cmlidXRpb24uIFRoaXMgaXMgYmVjYXVzZSB0aGUgcHJvY2VzcyBvZiBzdW1taW5nIHRoZXNlIGZsdWN0dWF0aW9ucyBzaGVkcyBhbGwgZGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGluZGl2aWR1YWwgY29udHJpYnV0aW9ucywgbGVhdmluZyBvbmx5IHRoZSBtZWFuIGFuZCBzcHJlYWQgKHZhcmlhbmNlKS4NCg0KSG93ZXZlciwgaXQncyBpbXBvcnRhbnQgdG8gbm90ZSB0aGF0IHRoZSBHYXVzc2lhbiBkaXN0cmlidXRpb24gaXMgbm90IHRoZSBvbmx5IHBhdHRlcm4gaW4gbmF0dXJlLiBUaGVyZSBhcmUgb3RoZXIgc2lnbmlmaWNhbnQgZGlzdHJpYnV0aW9ucywgbGlrZSBleHBvbmVudGlhbCwgZ2FtbWEsIGFuZCBQb2lzc29uLCB3aGljaCBhbHNvIGFyaXNlIGZyb20gbmF0dXJhbCBwcm9jZXNzZXMuIFRoZSBHYXVzc2lhbiBpcyBwYXJ0IG9mIHRoZSBicm9hZGVyIGV4cG9uZW50aWFsIGZhbWlseSBvZiBkaXN0cmlidXRpb25zLCBhbGwgb2Ygd2hpY2ggYXJlIGZ1bmRhbWVudGFsIGluIHRoZSBuYXR1cmFsIHdvcmxkLg0KDQoqKjIuIEVwaXN0ZW1vbG9naWNhbCBKdXN0aWZpY2F0aW9uKioNClRoZSBlcGlzdGVtb2xvZ2ljYWwganVzdGlmaWNhdGlvbiBmb3IgdXNpbmcgdGhlIEdhdXNzaWFuIGRpc3RyaWJ1dGlvbiBpcyBiYXNlZCBvbiB0aGUgY29uY2VwdCBvZiBtYXhpbXVtIGVudHJvcHkgYW5kIGluZm9ybWF0aW9uIHRoZW9yeS4gV2hlbiB3ZSBvbmx5IGtub3cgb3IgYXJlIHdpbGxpbmcgdG8gYXNzdW1lIHRoZSBtZWFuIGFuZCB2YXJpYW5jZSBvZiBhIGRpc3RyaWJ1dGlvbiwgdGhlIEdhdXNzaWFuIGRpc3RyaWJ1dGlvbiBpcyB0aGUgbW9zdCByZWFzb25hYmxlIGNob2ljZS4gVGhpcyBpcyBiZWNhdXNlOg0KDQotICoqU3RhdGUgb2YgSWdub3JhbmNlKio6IFRoZSBHYXVzc2lhbiBkaXN0cmlidXRpb24gcmVwcmVzZW50cyBhIHN0YXRlIG9mIG1pbmltYWwgYXNzdW1wdGlvbnMgYmV5b25kIGtub3dpbmcgdGhlIG1lYW4gYW5kIHZhcmlhbmNlLiBJdCBkb2VzIG5vdCBpbnRyb2R1Y2UgYW55IGFkZGl0aW9uYWwgYXNzdW1wdGlvbnMgYWJvdXQgdGhlIGRhdGEuDQotICoqTWF4aW11bSBFbnRyb3B5Kio6IEdpdmVuIHRoZSBjb25zdHJhaW50cyBvZiBmaW5pdGUgdmFyaWFuY2UsIHRoZSBHYXVzc2lhbiBkaXN0cmlidXRpb24gaXMgdGhlIHNoYXBlIHRoYXQgY2FuIGJlIHJlYWxpemVkIGluIHRoZSBsYXJnZXN0IG51bWJlciBvZiB3YXlzLiBJdCBpcyB0aGUgbGVhc3Qgc3VycHJpc2luZyBhbmQgbGVhc3QgaW5mb3JtYXRpdmUgYXNzdW1wdGlvbiwgbWFraW5nIGl0IHRoZSBtb3N0IGNvbnNpc3RlbnQgd2l0aCBvdXIgbGltaXRlZCBrbm93bGVkZ2UuDQpJbiBlc3NlbmNlLCBpZiB3ZSBkb24ndCBoYXZlIHNwZWNpZmljIGluZm9ybWF0aW9uIHN1Z2dlc3RpbmcgYSBkaWZmZXJlbnQgZGlzdHJpYnV0aW9uLCB0aGUgR2F1c3NpYW4gZGlzdHJpYnV0aW9uIGlzIHRoZSBzYWZlc3QsIG1vc3QgbmV1dHJhbCBhc3N1bXB0aW9uIHRvIG1ha2UuIEl0IGFsaWducyB3aXRoIHRoZSBpZGVhIG9mIG1ha2luZyB0aGUgbGVhc3QgaW5mb3JtYXRpdmUgYXNzdW1wdGlvbiB0aGF0IHN0aWxsIGZpdHMgb3VyIGtub3duIGNvbnN0cmFpbnRzLg0KDQoqKlByYWN0aWNhbCBJbXBsaWNhdGlvbnMqKg0KVXNpbmcgdGhlIEdhdXNzaWFuIGRpc3RyaWJ1dGlvbiBhcyBhIHN0YXJ0aW5nIHBvaW50IGZvciBidWlsZGluZyBtb2RlbHMgZG9lc24ndCBtZWFuIHdlIGFyZSBjb21taXR0aW5nIHRvIGl0IGFzIHRoZSBvbmx5IG9yIGJlc3QgbW9kZWwuIEl0IGlzIGEgcHJhY3RpY2FsIHRvb2wgdGhhdCBoZWxwcyB1cyBiZWdpbiBtb2RlbGluZyBjb250aW51b3VzIG1lYXN1cmVtZW50cy4gQXMgd2UgZ2F0aGVyIG1vcmUgaW5mb3JtYXRpb24gb3IgZGV2ZWxvcCBzcGVjaWZpYyBrbm93bGVkZ2UgYWJvdXQgdGhlIGRhdGEsIHdlIGNhbiByZWZpbmUgb3VyIG1vZGVscyBhbmQgcG9zc2libHkgY2hvb3NlIG90aGVyIGRpc3RyaWJ1dGlvbnMgdGhhdCBiZXR0ZXIgZml0IG91ciBkYXRhJ3MgY2hhcmFjdGVyaXN0aWNzLg0KDQpJbiBzdW1tYXJ5LCB0aGUgR2F1c3NpYW4gZGlzdHJpYnV0aW9uIGlzIGEgcG93ZXJmdWwgdG9vbCBpbiBzdGF0aXN0aWNhbCBtb2RlbGluZyBkdWUgdG8gaXRzIG5hdHVyYWwgb2NjdXJyZW5jZSBpbiBtYW55IHByb2Nlc3NlcyBhbmQgaXRzIHJvbGUgYXMgYSBkZWZhdWx0IGFzc3VtcHRpb24gd2hlbiB3ZSBoYXZlIGxpbWl0ZWQgaW5mb3JtYXRpb24uIEl0IHByb3ZpZGVzIGEgc29saWQgZm91bmRhdGlvbiBmb3IgYnVpbGRpbmcgYW5kIHJlZmluaW5nIG91ciB1bmRlcnN0YW5kaW5nIG9mIGRhdGEuDQoNCg0KKipTaW1wbGUgRXhwbGFuYXRpb24gd2l0aCBFeGFtcGxlcyoqDQoNCioqTWFpbiBJZGVhKioNCldoZW4gd2UgZG9uJ3QgaGF2ZSBtdWNoIGluZm9ybWF0aW9uIGFib3V0IGEgc2V0IG9mIGRhdGEsIGJ1dCB3ZSBkbyBrbm93IGl0cyBhdmVyYWdlIChtZWFuKSBhbmQgaG93IHNwcmVhZCBvdXQgdGhlIHZhbHVlcyBhcmUgKHZhcmlhbmNlKSwgdGhlIEdhdXNzaWFuIGRpc3RyaWJ1dGlvbiBpcyB0aGUgbW9zdCBuZXV0cmFsIGNob2ljZS4gSXQncyBsaWtlIHNheWluZywgIkdpdmVuIHdoYXQgbGl0dGxlIHdlIGtub3csIHRoaXMgaXMgdGhlIHNhZmVzdCBiZXQuIg0KDQoqKkV4YW1wbGUgMTogSGVpZ2h0cyBvZiBTdHVkZW50cyoqDQpJbWFnaW5lIHlvdSdyZSBhIHNjaG9vbCBwcmluY2lwYWwsIGFuZCB5b3Ugd2FudCB0byB1bmRlcnN0YW5kIHRoZSBoZWlnaHRzIG9mIHN0dWRlbnRzIGluIHlvdXIgc2Nob29sLiBZb3UgZG9uJ3QgaGF2ZSBkZXRhaWxlZCBkYXRhIGFib3V0IGV2ZXJ5IHN0dWRlbnQncyBoZWlnaHQsIGJ1dCB5b3UgZG8ga25vdyB0aGUgYXZlcmFnZSBoZWlnaHQgKG1lYW4pIGFuZCB0aGUgZ2VuZXJhbCB2YXJpYWJpbGl0eSBpbiBoZWlnaHRzICh2YXJpYW5jZSkuDQoNCioqS25vd24gSW5mb3JtYXRpb246KioNCg0KLSBBdmVyYWdlIGhlaWdodCAobWVhbik6IDE1MCBjbQ0KLSBWYXJpYWJpbGl0eSBpbiBoZWlnaHRzICh2YXJpYW5jZSk6IDI1IGNtwrINCg0KR2l2ZW4ganVzdCB0aGlzIGluZm9ybWF0aW9uLCB5b3UgY2hvb3NlIHRvIGFzc3VtZSB0aGF0IHRoZSBoZWlnaHRzIGZvbGxvdyBhIEdhdXNzaWFuIGRpc3RyaWJ1dGlvbiBiZWNhdXNlIGl0IGlzIHRoZSBsZWFzdCBiaWFzZWQgY2hvaWNlLiBJdCBkb2Vzbid0IG1ha2UgYW55IGV4dHJhIGFzc3VtcHRpb25zIGFib3V0IHRoZSBzcGVjaWZpYyBzaGFwZSBvZiB0aGUgZGF0YSBiZXlvbmQgd2hhdCB5b3Uga25vdy4NCg0KDQoqKk9udG9sb2dpY2FsIEp1c3RpZmljYXRpb24qKg0KDQotIE5vcm1hbCBEaXN0cmlidXRpb246DQogIC0gWW91IGFzc3VtZSB0aGUgaGVpZ2h0cyBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uIHdpdGggdGhlIGdpdmVuIG1lYW4gYW5kIHZhcmlhbmNlLiBUaGlzIGlzIHJlYXNvbmFibGUgYmVjYXVzZSBpdCBpbXBsaWVzIHRoYXQgbW9zdCBwZW9wbGUgaGF2ZSBoZWlnaHRzIGFyb3VuZCB0aGUgYXZlcmFnZSwgd2l0aCBmZXdlciBwZW9wbGUgYmVpbmcgbXVjaCB0YWxsZXIgb3Igc2hvcnRlci4gVGhpcyBhbGlnbnMgd2VsbCB3aXRoIGhvdyBodW1hbiBoZWlnaHRzIGFyZSB0eXBpY2FsbHkgZGlzdHJpYnV0ZWQuDQogIA0KLSBVbmlmb3JtIERpc3RyaWJ1dGlvbjoNCiAgLSBBbHRlcm5hdGl2ZWx5LCBpZiB5b3UgYXNzdW1lIHRoZSBoZWlnaHRzIGZvbGxvdyBhIHVuaWZvcm0gZGlzdHJpYnV0aW9uLCB5b3UgaW1wbHkgdGhhdCBhbnkgaGVpZ2h0IHdpdGhpbiBhIGNlcnRhaW4gcmFuZ2UgaXMgZXF1YWxseSBsaWtlbHkuIFRoaXMgYXNzdW1wdGlvbiBkb2Vzbid0IG1hdGNoIHRoZSBuYXR1cmFsIGNsdXN0ZXJpbmcgb2YgaHVtYW4gaGVpZ2h0cyBhcm91bmQgYW4gYXZlcmFnZSB2YWx1ZSBhbmQgY2FuIGJlIGNvbnNpZGVyZWQgbGVzcyByZWFsaXN0aWMgYW5kIG1vcmUgaW5mb3JtYXRpdmUgdGhhbiBuZWNlc3NhcnkuDQogIA0KKipFcGlzdGVtb2xvZ2ljYWwgSnVzdGlmaWNhdGlvbioqDQoNCi0gTm9ybWFsIERpc3RyaWJ1dGlvbjoNCiAgLSBUaGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBpcyB0aGUgbW9zdCB1bmJpYXNlZCBjaG9pY2Ugd2hlbiB5b3Ugb25seSBrbm93IHRoZSBtZWFuIGFuZCB2YXJpYW5jZSBvZiB0aGUgZGF0YS4gSXQgaXMgdGhlIGxlYXN0IGluZm9ybWF0aXZlIGFzc3VtcHRpb24geW91IGNhbiBtYWtlIGFib3V0IHRoZSBkYXRhIGJleW9uZCB0aGVzZSB0d28gcGFyYW1ldGVycy4NCiAgDQotIFVuaWZvcm0gRGlzdHJpYnV0aW9uOg0KICAtIEFzc3VtZXMgYWxsIG91dGNvbWVzIGluIHRoZSBpbnRlcnZhbCBbYSwgYl0gYXJlIGVxdWFsbHkgbGlrZWx5LCB3aGljaCBpcyBhIHN0cm9uZyBhc3N1bXB0aW9uIGNvbXBhcmVkIHRvIGtub3dpbmcganVzdCB0aGUgbWVhbiBhbmQgdmFyaWFuY2UuIFRoaXMgbWFrZXMgaXQgYSBsZXNzIG5ldXRyYWwgY2hvaWNlIHdoZW4geW91IGhhdmUgbGltaXRlZCBpbmZvcm1hdGlvbi4NCiAgDQojIyMgRnJhbWV3b3JrIGZvciBEZXNjcmliaW5nIE1vZGVscw0KDQojIyMjIFN0ZXAgMTogUmVjb2duaXplIGEgU2V0IG9mIFZhcmlhYmxlcw0KDQoqKk9ic2VydmFibGUgVmFyaWFibGUgKERhdGEpKio6DQotIEhlaWdodHMgb2YgaW5kaXZpZHVhbHMgKGxldCdzIGRlbm90ZSBpdCBhcyBcKCB5IFwpKS4NCg0KKipVbm9ic2VydmFibGUgVmFyaWFibGVzIChQYXJhbWV0ZXJzKSoqOg0KLSBNZWFuIGhlaWdodCAoXCggXG11IFwpKS4NCi0gU3RhbmRhcmQgZGV2aWF0aW9uIG9mIGhlaWdodHMgKFwoIFxzaWdtYSBcKSkuDQoNCiMjIyMgU3RlcCAyOiBEZWZpbmUgRWFjaCBWYXJpYWJsZQ0KDQoqKkhlaWdodHMgKFwoIHkgXCkpKio6IFRoZSBoZWlnaHRzIGFyZSBkaXN0cmlidXRlZCBhY2NvcmRpbmcgdG8gYSBub3JtYWwgKEdhdXNzaWFuKSBkaXN0cmlidXRpb24gd2l0aCBtZWFuIFwoIFxtdSBcKSBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIFwoIFxzaWdtYSBcKS4NCg0KXFsNCnlfaSBcc2ltIFx0ZXh0e05vcm1hbH0oXG11LCBcc2lnbWEpDQpcXQ0KDQoqKk1lYW4gSGVpZ2h0IChcKCBcbXUgXCkpKio6IFRoaXMgcGFyYW1ldGVyIGNhbiBiZSBtb2RlbGVkIHdpdGggYSBwcmlvciBkaXN0cmlidXRpb24gaWYgd2UgaGF2ZSBzb21lIHByaW9yIGtub3dsZWRnZS4gTGV0J3MgYXNzdW1lIGEgbm9ybWFsIHByaW9yIHdpdGggbWVhbiAxNzggY20gYW5kIHN0YW5kYXJkIGRldmlhdGlvbiAyMCBjbS4NCg0KXFsNClxtdSBcc2ltIFx0ZXh0e05vcm1hbH0oMTc4LCAyMCkNClxdDQoNCioqU3RhbmRhcmQgRGV2aWF0aW9uIChcKCBcc2lnbWEgXCkpKio6IFRoaXMgcGFyYW1ldGVyIGNhbiBhbHNvIGJlIG1vZGVsZWQgd2l0aCBhIHByaW9yIGRpc3RyaWJ1dGlvbi4gTGV0J3MgYXNzdW1lIGEgdW5pZm9ybSBwcmlvciBmcm9tIDAgdG8gNTAgY20sIGluZGljYXRpbmcgd2UgYmVsaWV2ZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIGNvdWxkIHJlYXNvbmFibHkgYmUgYW55d2hlcmUgaW4gdGhpcyByYW5nZS4NCg0KXFsNClxzaWdtYSBcc2ltIFx0ZXh0e1VuaWZvcm19KDAsIDUwKQ0KXF0NCg0KIyMjIyBTdGVwIDM6IEpvaW50IEdlbmVyYXRpdmUgTW9kZWwNCg0KQ29tYmluaW5nIHRoZXNlIHZhcmlhYmxlcyBhbmQgdGhlaXIgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9ucywgd2UgZGVmaW5lIGEgam9pbnQgZ2VuZXJhdGl2ZSBtb2RlbC4gVGhpcyBtb2RlbCBhbGxvd3MgdXMgdG8gc2ltdWxhdGUgaHlwb3RoZXRpY2FsIG9ic2VydmF0aW9ucyBhbmQgYW5hbHl6ZSByZWFsIGRhdGEuDQoNCjEuICoqU3BlY2lmeSBwcmlvcnMqKjoNCiAgIFxbDQogICBcbXUgXHNpbSBcdGV4dHtOb3JtYWx9KDE3OCwgMjApDQogICBcXQ0KICAgXFsNCiAgIFxzaWdtYSBcc2ltIFx0ZXh0e1VuaWZvcm19KDAsIDUwKQ0KICAgXF0NCg0KMi4gKipTcGVjaWZ5IGxpa2VsaWhvb2QqKjoNCiAgIFxbDQogICB5X2kgXHNpbSBcdGV4dHtOb3JtYWx9KFxtdSwgXHNpZ21hKQ0KICAgXF0NCg0KVGhpcyBtb2RlbCBkZXNjcmliZXMgaG93IHRoZSBvYnNlcnZlZCBkYXRhIChoZWlnaHRzKSBhcmUgZ2VuZXJhdGVkIGZyb20gdGhlIHVuZGVybHlpbmcgcGFyYW1ldGVycyAobWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uKS4NCg0KIyMjIFN0ZXAgNDogQ29tcHV0ZSB0aGUgUG9zdGVyaW9yDQoNClRvIGNvbXB1dGUgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24sIHdlIGFwcGx5IEJheWVzJyB0aGVvcmVtOg0KDQpcWw0KUChcbXUsIFxzaWdtYSBcbWlkIHkpIFxwcm9wdG8gUCh5IFxtaWQgXG11LCBcc2lnbWEpIFAoXG11KSBQKFxzaWdtYSkNClxdDQoNCndoZXJlOg0KDQotIFwoIFAoXG11LCBcc2lnbWEgXG1pZCB5KSBcKSBpcyB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbi4NCi0gXCggUCh5IFxtaWQgXG11LCBcc2lnbWEpIFwpIGlzIHRoZSBsaWtlbGlob29kIG9mIHRoZSBvYnNlcnZlZCBkYXRhLg0KLSBcKCBQKFxtdSkgXCkgYW5kIFwoIFAoXHNpZ21hKSBcKSBhcmUgdGhlIHByaW9ycy4NCg0KDQoqKlByaW9yIENob2ljZXMqKg0KDQpgYGB7ciwgZWNobz1GYWxzZX0NCg0KDQojIFNldCB1cCB0aGUgcGxvdHRpbmcgYXJlYSB0byBoYXZlIDEgcm93IGFuZCAyIGNvbHVtbnMNCnBhcihtZnJvdz1jKDEsMikpDQoNCiMgUGxvdCBkZW5zaXR5IGN1cnZlcyBmb3IgcHJpb3IgbWVhbnMNCnBsb3QoTlVMTCwgeGxpbT1jKDAsIDM1MCksIHlsaW09YygwLCAwLjAyNSksIHhsYWI9IngiLCB5bGFiPSJEZW5zaXR5IiwgbWFpbj0iUHJpb3IgTWVhbiIpDQpjdXJ2ZShkbm9ybSh4LCAxNzgsIDIwKSwgZnJvbT0wLCB0bz0zNTAsIGNvbD0iYmx1ZSIsIGFkZD1UUlVFKQ0KY3VydmUoZG5vcm0oeCwgMTc4LCA1MCksIGZyb209MCwgdG89MzUwLCBjb2w9InJlZCIsIGFkZD1UUlVFKQ0KbGVnZW5kKCJ0b3ByaWdodCIsIGxlZ2VuZD1jKCJOb3JtYWwoMTc4LCAyMCkiLCAiTm9ybWFsKDE3OCwgNTApIiksIGNvbD1jKCJibHVlIiwgInJlZCIpLCBsdHk9MSkNCg0KIyBQbG90IGRlbnNpdHkgY3VydmVzIGZvciBwcmlvciBzdGFuZGFyZCBkZXZpYXRpb25zDQpwbG90KE5VTEwsIHhsaW09YygwLCAxMDApLCB5bGltPWMoMCwgMC4wNSksIHhsYWI9IngiLCB5bGFiPSJEZW5zaXR5IiwgbWFpbj0iUHJpb3IgU3RhbmRhcmQgRGV2aWF0aW9uIikNCmN1cnZlKGR1bmlmKHgsIDAsIDUwKSwgZnJvbT0wLCB0bz01MCwgY29sPSJibHVlIiwgYWRkPVRSVUUpDQpjdXJ2ZShkdW5pZih4LCAwLCAxMDApLCBmcm9tPTAsIHRvPTEwMCwgY29sPSJyZWQiLCBhZGQ9VFJVRSkNCmxlZ2VuZCgidG9wcmlnaHQiLCBsZWdlbmQ9YygiVW5pZm9ybSgwLCA1MCkiLCAiVW5pZm9ybSgwLCAxMDApIiksIGNvbD1jKCJibHVlIiwgInJlZCIpLCBsdHk9MSkNCg0KDQpgYGANCmBgYHtyLCBlY2hvPUZBTFNFfQ0KDQoNCiMgSW5zdGFsbCBuZWNlc3NhcnkgcGFja2FnZXMgaWYgbm90IGFscmVhZHkgaW5zdGFsbGVkDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImdncGxvdDIiLCBxdWlldGx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJncmlkRXh0cmEiLCBxdWlldGx5ID0gVFJVRSkpIGluc3RhbGwucGFja2FnZXMoImdyaWRFeHRyYSIpDQoNCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KGdyaWRFeHRyYSkNCg0KIyBTZXQgc2VlZCBmb3IgcmVwcm9kdWNpYmlsaXR5DQpzZXQuc2VlZCgxMjMpDQoNCiMgRGVmaW5lIHByaW9yIHBhcmFtZXRlcnMNCnByaW9yX21lYW5zIDwtIGMoMTc4LCAxNzgpDQpwcmlvcl9zZHMgPC0gYygyMCwgNTApDQpwcmlvcl9zaWdtYV9yYW5nZXMgPC0gbGlzdChjKDAsIDUwKSwgYygwLCAxMDApKQ0KDQojIEZ1bmN0aW9uIHRvIGNvbXB1dGUgcHJlZGljdGl2ZSBwcmlvcnMNCmNvbXB1dGVfcHJlZGljdGl2ZV9wcmlvciA8LSBmdW5jdGlvbihtZWFuLCBzZCwgc2lnbWFfcmFuZ2UpIHsNCiAgc2FtcGxlX211IDwtIHJub3JtKDFlNCwgbWVhbiwgc2QpDQogIHNhbXBsZV9zaWdtYSA8LSBydW5pZigxZTQsIHNpZ21hX3JhbmdlWzFdLCBzaWdtYV9yYW5nZVsyXSkNCiAgcHJpb3JfaCA8LSBybm9ybSgxZTQsIHNhbXBsZV9tdSwgc2FtcGxlX3NpZ21hKQ0KICByZXR1cm4ocHJpb3JfaCkNCn0NCg0KIyBDb21wdXRlIHByZWRpY3RpdmUgcHJpb3JzIGZvciBlYWNoIGNvbWJpbmF0aW9uDQpwcmlvcl9oXzEgPC0gY29tcHV0ZV9wcmVkaWN0aXZlX3ByaW9yKDE3OCwgMjAsIGMoMCwgNTApKQ0KcHJpb3JfaF8yIDwtIGNvbXB1dGVfcHJlZGljdGl2ZV9wcmlvcigxNzgsIDIwLCBjKDAsIDEwMCkpDQpwcmlvcl9oXzMgPC0gY29tcHV0ZV9wcmVkaWN0aXZlX3ByaW9yKDE3OCwgNTAsIGMoMCwgNTApKQ0KcHJpb3JfaF80IDwtIGNvbXB1dGVfcHJlZGljdGl2ZV9wcmlvcigxNzgsIDUwLCBjKDAsIDEwMCkpDQoNCiMgQ3JlYXRlIHBsb3RzIGZvciBlYWNoIGNvbWJpbmF0aW9uIHdpdGggcmVkdWNlZCB0aXRsZSBmb250IHNpemUNCnBsb3QxIDwtIGdncGxvdChkYXRhLmZyYW1lKHByaW9yX2hfMSksIGFlcyh4ID0gcHJpb3JfaF8xKSkgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJibHVlIiwgYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJOb3JtYWwoMTc4LCAyMCkgJiBVbmlmb3JtKDAsIDUwKSIsIHggPSAiSGVpZ2h0IiwgeSA9ICJEZW5zaXR5IikgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMzUwKSkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpDQoNCnBsb3QyIDwtIGdncGxvdChkYXRhLmZyYW1lKHByaW9yX2hfMiksIGFlcyh4ID0gcHJpb3JfaF8yKSkgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJyZWQiLCBhbHBoYSA9IDAuNSkgKw0KICBsYWJzKHRpdGxlID0gIk5vcm1hbCgxNzgsIDIwKSAmIFVuaWZvcm0oMCwgMTAwKSIsIHggPSAiSGVpZ2h0IiwgeSA9ICJEZW5zaXR5IikgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMCwgMzUwKSkgKw0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMCkpDQoNCnBsb3QzIDwtIGdncGxvdChkYXRhLmZyYW1lKHByaW9yX2hfMyksIGFlcyh4ID0gcHJpb3JfaF8zKSkgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJncmVlbiIsIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiTm9ybWFsKDE3OCwgNTApICYgVW5pZm9ybSgwLCA1MCkiLCB4ID0gIkhlaWdodCIsIHkgPSAiRGVuc2l0eSIpICsNCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDM1MCkpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQ0KDQpwbG90NCA8LSBnZ3Bsb3QoZGF0YS5mcmFtZShwcmlvcl9oXzQpLCBhZXMoeCA9IHByaW9yX2hfNCkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAicHVycGxlIiwgYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJOb3JtYWwoMTc4LCA1MCkgJiBVbmlmb3JtKDAsIDEwMCkiLCB4ID0gIkhlaWdodCIsIHkgPSAiRGVuc2l0eSIpICsNCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsIDM1MCkpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTApKQ0KDQojIEFycmFuZ2UgcGxvdHMgaW4gYSAyeDIgZ3JpZA0KZ3JpZC5hcnJhbmdlKHBsb3QxLCBwbG90MiwgcGxvdDMsIHBsb3Q0LCBuY29sID0gMikNCg0KYGBgDQoNCiMjIyBDb21wdXRpbmcgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24NCg0KVGhlIGNoYXB0ZXIgaW52ZXN0aWdhdGVzIHR3byB3YXlzIG9mIGNvbXB1dGluZyB0aGUgcG9zdGVyaW9yOiBncmlkIGFwcHJveGltYXRpb24gYW5kIFF1YWRyYXRpYyBhcHByb3hpbWF0aW9uLg0KDQotIEdyaWQgYXBwcm94aW1hdGlvbjoNCiAgLSBQcm9zOiBTaW1wbGUsIGludHVpdGl2ZSwgYW5kIGVhc3kgdG8gdW5kZXJzdGFuZC4NCiAgLSBDb25zOiBDb21wdXRhdGlvbmFsbHkgZXhwZW5zaXZlIGFuZCBtYXkgbm90IHNjYWxlIHdlbGwgdG8gaGlnaC1kaW1lbnNpb25hbCBwcm9ibGVtcy4NCg0KLSBRdWFkcmF0aWMgYXBwcm94aW1hdGlvbjoNCiAgLSBQcm9zOiBGYXN0IGFuZCBlZmZpY2llbnQgZm9yIGhpZ2gtZGltZW5zaW9uYWwgcHJvYmxlbXMuDQogIC0gQ29uczogUmVxdWlyZXMgbW9yZSBhZHZhbmNlZCBtYXRoZW1hdGljYWwgdGVjaG5pcXVlcyBhbmQgbWF5IGJlIGxlc3MgaW50dWl0aXZlLg0KIA0KDQoNCmBgYHtyLCBlY2hvPUZBTFNFfQ0KDQojIExvYWQgZGF0YQ0KZGF0YShIb3dlbGwxKQ0KZCA8LSBIb3dlbGwxDQpkMiA8LSBkW2QkYWdlID49IDE4LCBdDQoNCiMgR3JpZCBhcHByb3hpbWF0aW9uDQptdS5saXN0IDwtIHNlcShmcm9tID0gMTUwLCB0byA9IDE2MCwgbGVuZ3RoLm91dCA9IDUwMCkNCnNpZ21hLmxpc3QgPC0gc2VxKGZyb20gPSA3LCB0byA9IDksIGxlbmd0aC5vdXQgPSA1MDApDQpwb3N0IDwtIGV4cGFuZC5ncmlkKG11ID0gbXUubGlzdCwgc2lnbWEgPSBzaWdtYS5saXN0KQ0KcG9zdCRMTCA8LSBzYXBwbHkoMTpucm93KHBvc3QpLCBmdW5jdGlvbihpKSBzdW0oZG5vcm0oZDIkaGVpZ2h0LCBwb3N0JG11W2ldLCBwb3N0JHNpZ21hW2ldLCBsb2cgPSBUUlVFKSkpDQpwb3N0JHByb2QgPC0gcG9zdCRMTCArIGRub3JtKHBvc3QkbXUsIDE3OCwgMjAsIFRSVUUpICsgZHVuaWYocG9zdCRzaWdtYSwgMCwgNTAsIFRSVUUpDQpwb3N0JHByb2IgPC0gZXhwKHBvc3QkcHJvZCAtIG1heChwb3N0JHByb2QpKQ0KDQojIFNhbXBsaW5nIGZyb20gdGhlIHBvc3RlcmlvciBmb3IgZ3JpZCBhcHByb3hpbWF0aW9uDQpzYW1wbGUucm93cyA8LSBzYW1wbGUoMTpucm93KHBvc3QpLCBzaXplID0gMWU0LCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IHBvc3QkcHJvYikNCnNhbXBsZS5tdSA8LSBwb3N0JG11W3NhbXBsZS5yb3dzXQ0Kc2FtcGxlLnNpZ21hIDwtIHBvc3Qkc2lnbWFbc2FtcGxlLnJvd3NdDQoNCiMgUXVhZHJhdGljIGFwcHJveGltYXRpb24NCmZsaXN0IDwtIGFsaXN0KA0KICBoZWlnaHQgfiBkbm9ybShtdSwgc2lnbWEpLA0KICBtdSB+IGRub3JtKDE3OCwgMjApLA0KICBzaWdtYSB+IGR1bmlmKDAsIDUwKQ0KKQ0KbTQuMSA8LSBxdWFwKGZsaXN0LCBkYXRhID0gZDIpDQpwb3N0X3F1YXAgPC0gZXh0cmFjdC5zYW1wbGVzKG00LjEsIG4gPSAxZTQpDQoNCiMgQ3JlYXRlIGRlbnNpdHkgcGxvdHMgZm9yIG11IGFuZCBzaWdtYSBmb3IgYm90aCBtZXRob2RzDQpkZW5zX211X2dyaWQgPC0gZ2dwbG90KGRhdGEuZnJhbWUobXUgPSBzYW1wbGUubXUpLCBhZXMoeCA9IG11KSkgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJibHVlIiwgYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJQb3N0ZXJpb3Igb2YgTXUgKEdyaWQgQXBwcm94KSIsIHggPSBleHByZXNzaW9uKG11KSwgeSA9ICJEZW5zaXR5IikNCg0KZGVuc19zaWdtYV9ncmlkIDwtIGdncGxvdChkYXRhLmZyYW1lKHNpZ21hID0gc2FtcGxlLnNpZ21hKSwgYWVzKHggPSBzaWdtYSkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAiYmx1ZSIsIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiUG9zdGVyaW9yIG9mIFNpZ21hIChHcmlkIEFwcHJveCkiLCB4ID0gZXhwcmVzc2lvbihzaWdtYSksIHkgPSAiRGVuc2l0eSIpDQoNCmRlbnNfbXVfcXVhcCA8LSBnZ3Bsb3QoZGF0YS5mcmFtZShtdSA9IHBvc3RfcXVhcCRtdSksIGFlcyh4ID0gbXUpKSArDQogIGdlb21fZGVuc2l0eShmaWxsID0gInJlZCIsIGFscGhhID0gMC41KSArDQogIGxhYnModGl0bGUgPSAiUG9zdGVyaW9yIG9mIE11IChRdWFkcmF0aWMgQXBwcm94KSIsIHggPSBleHByZXNzaW9uKG11KSwgeSA9ICJEZW5zaXR5IikNCg0KZGVuc19zaWdtYV9xdWFwIDwtIGdncGxvdChkYXRhLmZyYW1lKHNpZ21hID0gcG9zdF9xdWFwJHNpZ21hKSwgYWVzKHggPSBzaWdtYSkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAicmVkIiwgYWxwaGEgPSAwLjUpICsNCiAgbGFicyh0aXRsZSA9ICJQb3N0ZXJpb3Igb2YgU2lnbWEgKFF1YWRyYXRpYyBBcHByb3gpIiwgeCA9IGV4cHJlc3Npb24oc2lnbWEpLCB5ID0gIkRlbnNpdHkiKQ0KDQojIEFycmFuZ2UgcGxvdHMgaW4gYSAyeDIgZ3JpZA0KZ3JpZC5hcnJhbmdlKGRlbnNfbXVfZ3JpZCwgZGVuc19tdV9xdWFwLCBkZW5zX3NpZ21hX2dyaWQsIGRlbnNfc2lnbWFfcXVhcCwgbmNvbCA9IDIpDQoNCiMgQ29tcHV0ZSA5NSUgY3JlZGlibGUgaW50ZXJ2YWxzIGZvciBib3RoIG1ldGhvZHMNCmNpX211X2dyaWQgPC0gUEkoc2FtcGxlLm11LCBwcm9iID0gMC45NSkNCmNpX3NpZ21hX2dyaWQgPC0gUEkoc2FtcGxlLnNpZ21hLCBwcm9iID0gMC45NSkNCg0KY2lfbXVfcXVhcCA8LSBQSShwb3N0X3F1YXAkbXUsIHByb2IgPSAwLjk1KQ0KY2lfc2lnbWFfcXVhcCA8LSBQSShwb3N0X3F1YXAkc2lnbWEsIHByb2IgPSAwLjk1KQ0KDQojIFJvdW5kIHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMgdG8gdHdvIGRlY2ltYWwgcGxhY2VzDQpjaV9tdV9ncmlkIDwtIHJvdW5kKGNpX211X2dyaWQsIDIpDQpjaV9zaWdtYV9ncmlkIDwtIHJvdW5kKGNpX3NpZ21hX2dyaWQsIDIpDQpjaV9tdV9xdWFwIDwtIHJvdW5kKGNpX211X3F1YXAsIDIpDQpjaV9zaWdtYV9xdWFwIDwtIHJvdW5kKGNpX3NpZ21hX3F1YXAsIDIpDQoNCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSB0byBjb21wYXJlIHRoZSBjcmVkaWJsZSBpbnRlcnZhbHMNCmNvbXBhcmlzb25fdGFibGUgPC0gZGF0YS5mcmFtZSgNCiAgUGFyYW1ldGVyID0gYygiTXUiLCAiU2lnbWEiKSwNCiAgTWV0aG9kID0gYygiR3JpZCBBcHByb3hpbWF0aW9uIiwgIkdyaWQgQXBwcm94aW1hdGlvbiIsICJRdWFkcmF0aWMgQXBwcm94aW1hdGlvbiIsICJRdWFkcmF0aWMgQXBwcm94aW1hdGlvbiIpLA0KICBMb3dlciA9IGMoY2lfbXVfZ3JpZFsxXSwgY2lfc2lnbWFfZ3JpZFsxXSwgY2lfbXVfcXVhcFsxXSwgY2lfc2lnbWFfcXVhcFsxXSksDQogIFVwcGVyID0gYyhjaV9tdV9ncmlkWzJdLCBjaV9zaWdtYV9ncmlkWzJdLCBjaV9tdV9xdWFwWzJdLCBjaV9zaWdtYV9xdWFwWzJdKQ0KKQ0KDQojIERpc3BsYXkgdGhlIGNvbXBhcmlzb24gdGFibGUNCnByaW50KGNvbXBhcmlzb25fdGFibGUpDQoNCg0KYGBgDQoNCiMjIFF1ZXN0aW9ucyB0byBkaXNjdXNzDQoNCioqMS4gTm9ybWFsIERpc3RyaWJ1dGlvbiBKdXN0aWZpY2F0aW9uKio6DQoNCiAgLSBXaHkgaXMgdGhlIEdhdXNzaWFuIGRpc3RyaWJ1dGlvbiBvZnRlbiB1c2VkIGFzIHRoZSBza2VsZXRvbiBmb3IgaHlwb3RoZXNlcyBpbiBCYXllc2lhbiByZWdyZXNzaW9uPyBEaXNjdXNzIHRoZSBvbnRvbG9naWNhbCBhbmQgZXBpc3RlbW9sb2dpY2FsIGp1c3RpZmljYXRpb25zIHByZXNlbnRlZCBpbiB0aGUgbm90ZWJvb2suDQoNCioqMi4gUHJpb3JzIGFuZCBUaGVpciBJbmZsdWVuY2UqKjoNCg0KICAtIEhvdyBkbyB0aGUgY2hvaWNlcyBvZiBwcmlvcnMgKE5vcm1hbCB2cy4gVW5pZm9ybSkgaW5mbHVlbmNlIHRoZSByZXN1bHRzIG9mIEJheWVzaWFuIHJlZ3Jlc3Npb24/IA0KDQoqKjMuIFZpc3VhbGl6aW5nIFBvc3RlcmlvciBEaXN0cmlidXRpb25zKio6DQoNCiAgLSBUaGUgbm90ZWJvb2sgaW5jbHVkZXMgcGxvdHMgb2YgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbnMgZm9yIPCdnIcgYW5kIPCdnI4gdXNpbmcgYm90aCBncmlkIGFuZCBxdWFkcmF0aWMgYXBwcm94aW1hdGlvbnMuIFdoYXQgaW5zaWdodHMgY2FuIHlvdSBkcmF3IGZyb20gdGhlc2UgcGxvdHMgYWJvdXQgdGhlIGJlaGF2aW9yIG9mIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9ucz8NCg0KKio0LiBDb21wdXRhdGlvbmFsIENoYWxsZW5nZXMqKjoNCg0KICAtIEJheWVzaWFuIG1ldGhvZHMsIGVzcGVjaWFsbHkgdGhvc2UgaW52b2x2aW5nIGNvbXBsZXggbW9kZWxzLCBjYW4gYmUgY29tcHV0YXRpb25hbGx5IGludGVuc2l2ZS4gSG93IGRvIGFkZHJlc3MgdGhlc2UgY2hhbGxlbmdlcz8NCg0KDQoNCg0KDQo=