Discrete Univariate Distributions
4.2.1 Discrete Uniform Distribution
The random variable X is said to follow a discrete
uniform distribution with parameter n (where \(n ∈ ℕ)\) if the probability X
takes on the value x is the same for all
x, where \(x = x_1, x_2, …,
x_n\).
For Discrete Uniform Distribution one has:
- \[P(X=x_i|n)= \frac{1}{n}\] for
\(i=1,2,...,n\)
- \[E[X]=\frac{1}{n} \sum_{i=1}^n
x_i\]
- \[Var[X]=\frac{1}{n} \sum_{i=1}^n
(x_i-E[X])^2\]
Exercise: When \(x_i =
i\) for \(i = 1, …, n\), it can
be shown that \(E[X] = \frac{n+1}{2}\)
and that \(Var[X] = \frac{n^2−1}{12}\),
respectively.
Example 4.1
One light bulb is randomly selected from a box that contains a
40-watt light bulb, a 60-watt light bulb, a 75-watt light bulb, a
100-watt light bulb, and a 120-watt light bulb. Write the probability
function for the random variable that represents the wattage of the
randomly selected light bulb, and determine the mean and variance of
that random variable.
Solution: The random variable X can
assume the set of values \(Ω = {40, 60, 75,
100, 120}\). The probability density function for the random
variable X is
\(P(X=x|n=5)=\frac{1}{5}\) for \(x=40, 60, 75, 100, 120\)
Try the code
Watts <- c(40, 60, 75, 100, 120)
n <- length(Watts)
meanWatts <- (1/n)*sum(Watts)
varWatts<- (1/n)*sum((Watts - meanWatts)^2)
ans <- c(meanWatts, varWatts)
ans
4.2.2 Bernoulli and Binomial Distributions
A Bernoulli trial is a random experiment with only
two possible outcomes. The outcomes are
mutually exclusive and exhaustive;e.g., success or
failure, true or false, alive or dead, male or female, etc. A Bernoulli
random variable, X, can take on two values, where
X(success) = 1 and X(failure) = 0. The probability that X
is a success is \(\pi\), and the
probability that X is a failure is \(1-\pi\).
For Bernoulli distribution pdf,
mean, and variance of a Bernoulli random variable are:
\[X \sim Bernoulli(\pi)\]
- \[P(X=x|\pi)= \pi^x(1-\pi)^{1-x}\]
for \(x=0,1\)
- \[E[X]=\pi\]
- \[Var[X]=\pi(1-\pi)\]
When a sequence of Bernoulli trials conforms to the following list of
requirements, it is called a binomial experiment:
- The experiment consists of a fixed number (
n) of
Bernoulli trials.
- The probability of success for each trial, denoted by \(\pi\), is constant from trial to trial. The
probability of failure is \(\rho =
1-\pi\)
- The trials are independent.
- The random variable of interest, X, is the number of observed
successes during the n trials.
For Binomial distribution pdf,
mean, and variance of a binomial random variable are:
\[X \sim Bin(n, \pi) \]
- \[P(X=x|n, \pi)= {n \choose x}
\pi^x(1-\pi)^{n-x}\] for \(x=0,1, ...,
n\)
- \[E[X]=n \pi\]
- \[Var[X]=n \pi(1-\pi)\]
Exercise (optional): Prove 1,2 and 3 above.
Code below is used to create graphs that represent the probability
density function and the cumulative distribution function for a Bin(8,
0.3) random variable:
Try it!
opar <- par(no.readonly = TRUE)
par(mfrow=c(1, 2), pty = "s")
x <- 0:8
px <- dbinom(x = x, size = 8,prob = 0.3)
# plot probability vs corresponding x-values
plot(x, px, type = "h", xlab = "x", ylab="P(X = x)",
main = "PDF of X~Bin(8, 0.3)")
xs <- rep(0:8, round(dbinom(0:8, 8, .3)*100000, 0)) # creates vector of 0s, 1s, ...8s, according to the expected number of each one out of 10,000 trials
# plot the empirical cdf
plot(ecdf(xs), main = "CDF of X~Bin(8, 0.3)",
ylab = expression(P(X<=x)), xlab = "x")
par(opar)
Q: Change the probability, \(\pi\) parameter to value close to zero.
What do you observe? How does it skew the distribution. Now, increase
`n’ to bigger value, even bigger. Do you notice correction of the
skewness?
Exercise: Graph the pdf and
cdf for \(X \sim
Bin(10,\frac{1}{2})\) (# of heads of tossing a fair coin 10 times
experiment) it is part of the weekly programming exercises Rmd file.
R functions for Binomial Distribution Calculations
Description
Density, distribution function, quantile function and random
generation for the binomial distribution with parameters size and
prob.
This is conventionally interpreted as the number of ‘successes’ in
size trials.
Usage
dbinom(x, size, prob, log = FALSE) this computes the
pdf values
pbinom(q, size, prob, lower.tail = TRUE, log.p = FALSE)
this gives \(P(X \le x)\) the
pdf values
qbinom(p, size, prob, lower.tail = TRUE, log.p = FALSE)
this gives the quantiles \(P(X \le k) \ge
p\)
rbinom(n, size, prob)
Arguments
x, q - vector of quantiles. p - vector of
probabilities. n - number of observations.
size - number of trials (zero or more). prob -
probability of success on each trial.
Example: Using the function rbinom(),
one can generate 1000 samples of a \(Bin(n =
5, \pi = 0.5)\) as shown below:
set.seed(123)
x <- rbinom(1000, 5, .5)
table(x)/1000 # The empirical distribution
Example 4.3
Binomial Calculation Consider the problem of
calculating the probability of obtaining 6 or more heads in
10 tosses of a weighted coin (not fair),
where the probability of obtaining a head in any given trial is
0.33.
# adding probabilities
sum(dbinom(x = 6:10, size = 10, prob = 0.33)) # P(X >= 6)=P(6)+P(7)+P(8)+P(9)+P(10)
# or
1 - pbinom(5, 10, 0.33) # 1 - P(X <= 5)
#or
pbinom(5, 10, 0.33, lower = FALSE) # P(X >= 6)
# or
1 - sum(dbinom(5:0, 10, 0.33)) # 1 - P(X <= 5)
4.2.3 Poisson Distribution
The Poisson distribution is very popular for modeling the number of
times particular events occur in given times or on defined spaces, or in
general unit interval of time (units of time may
vary).
E.g.
number of phone calls to 911 between 1 a.m. and 2 a.m.
number of accidents at a busy street corner during a 24-hour
period
number of typographical errors on a single page of this
book
See definition of Poisson Process in the text, page
256.
Suppose there is an experiment that satisfies the three criteria for
an approximate Poisson process with parameter \(\lambda\), \(\lambda\) mean number of occurrences on a
unit interval of time.
Let X represent the number of outcomes in an interval of
length 1 (t = 1).
Then one has:
Poisson Distribution mean, and variance of a
binomial random variable are:
\[X \sim Pois(\lambda)\]
- \[P(X=x|\lambda)=\frac{\lambda^xe^{-\lambda}}{x!}\]
for \(x=0,1,2,...\)
- \[E[X]=\lambda\]
- \[Var[X]=\lambda\]
Review the code to see how to represent a
pdf and cdf for a
Pois(λ = 1) random variable. Although the values
x can take on with the Poisson distribution are $0, 1, 2,…,
$ the probability a Poisson random variable has a value of eight or
greater when λ = 1 is extremely small (< 0). Consequently, the pdf,
and cdf do not extend beyond eight.
opar <- par(no.readonly = TRUE)
par(mfrow=c(1, 2), pty = "s")
x <- 0:8
px <- dpois(x,lambda = 1) # computes the pdf at the points x
# plot probability vs x-values
plot(x, px, type = "h", xlab = "x", ylab="P(X = x)",
main = "PDF of X ~ Pois(1)")
xs <- rep(0:8, round(dpois(0:8, 1)*100000, 0)) # create vector of 100,000 values according to the expected number of occurrences of 0s,1s, 2s, ...and we cut at 8s other values can be ignored
# plot the empirical cdf
plot(ecdf(xs), main = "CDF of X ~ Pois(1)",
ylab = expression(P(X <=x)), xlab = "x")
par(opar)
Note: The Poisson distribution is particularly
appropriate for modeling “rare” phenomena or outcomes
where the probability of success is small.
Given n independent Poisson random
variables \(X_1, X_2,…, X_n\) with
parameters \(λ_1, λ_2,…, λ_n\)
respectively, \(Y= \sum_{i=1}^n X_i \sim
Pois(\sum_{i=1}^n \lambda_i=\lambda)\)
Example 4.6 More accidents are registered in auto
body repair shops during the months of May and June than in the rest of
the year. Suppose a particular auto body repair shop has an average of
four accidents per month. What is the probability there will be more
than seven accidents in this auto body shop during the month of May?
What is the probability no more than three accidents will occur during
the months of May and June?
Solution: Assuming accidents in the auto body shop
follow an approximate Poisson process, the probability of x
accidents in one month is
\[P(X=x|4)=\frac{4^xe^{-4}}{x!}\]
for \(x=0,1,2,...\)
Using R:
# lower parameter TRUE - computes probabilities up to the point, FALSE to the right of the point
1 - ppois(q = 7, lambda = 4, lower = TRUE) # P(X > 7|4) = 1 - P(X<=7|4)
ppois(q = 7, lambda = 4, lower = FALSE) # P(X > 7|4) notice lower = FALSE
ppois(q = 3, lambda = 8) # P(X <= 3|8)
R functions for the Poisson Distribution Calculations
Description
Density, distribution function, quantile function and random
generation for the Poisson distribution with parameter lambda.
Usage
dpois(x, lambda, log = FALSE)
ppois(q, lambda, lower.tail = TRUE, log.p = FALSE)
qpois(p, lambda, lower.tail = TRUE, log.p = FALSE)
rpois(n, lambda)
Arguments
x - vector of (non-negative integer) quantiles.
q - vector of quantiles. p - vector of
probabilities. n - number of random values to return.
lambda - vector of (non-negative) means.
4.2.4 Geometric Distribution
A random variable X that counts the number of Bernoulli
trials that result in failure before the first success is called a
geometric random variable. Clearly, the probability of
a success after r failures is \(π
× (1 − π)^r\), which leads to the geometric probability
distribution function where \(\rho = 1 −
π\) is the probability of failure.
The pdf, mean, and variance for a geometric random
variable are shown below:
\[X \sim Geo(\pi)\] \[P(X=x|\pi)=\pi\rho^x\] for \(x=0,1,2 ...\)
\[E[X]=\frac{\rho}{\pi}\] \[Var[X]=\frac{\rho}{\pi^2}\]
The code below can be used to create graphs that represent the
probability density function and the cumulative distribution function
for a \(Geo(π = 0.3)\) random
variable.
opar <- par(no.readonly = TRUE)
par(mfrow=c(1, 2), pty = "s")
x <- 0:15
px <- dgeom(x = x, prob = .3)
plot(x, px, type = "h", xlab = "x", ylab="P(X = x)",
main = "PDF of X ~ Geom(0.3)")
xs <- rep(0:15, round(dgeom(0:15, 0.3)*100000, 0))
plot(ecdf(xs), main = "CDF of X ~ Geom(0.3)",
ylab = expression(P(X <=x)), xlab = "x")
par(opar)
Pr. 18 / page 308 in text Suppose the percentage of
drinks sold from a vending machine are 80% and 20% for soft drinks and
bottled water, respectively.
- What is the probability that on a randomly selected day, the first
soft drink is the fourth drink sold?
- Find the probability that exactly 1 out of 10 drinks sold is a soft
drink.
Solution: Let X = number of waters
(failures) purchased before the first soft drink is purchased. Then,
\(X \sim Geo(0.80)\).
dgeom(x = 3, prob = 0.80) # P(X = 3)
- Let
X = number of soft drinks sold. Then, \(X \sim Bin(10, 0.80)\) and \(P(X = 1) = 0\) since one has:
pbinom(q = 1, size = 10, prob = 0.8) # P(X = 1)
Optional to review: 4.2.5 Negative Binomial
Distribution & 4.2.6 Hypergeometric Distribution
4.3 Continuous Univariate Distributions
4.3.2 Exponential Distribution
If W is the waiting time until the first outcome of a
Poisson process with mean \(\lambda > 0\) (# occurrences over unit
interval), then the pdf, mean, and variance for
W are shown below:
- \[f(x| \lambda)=\lambda e^{-\lambda
x}\] for \(x \ge 0\), and 0
otherwise
- \[E[X]=\frac{1}{\lambda}\]
- \[Var[X]=\frac{1}{\lambda^2}\]
Consequently, when \(w > 0\), the
pdf of W is \(F'(w) = f(w) = λe^{−λw}\).
The exponential distribution is characterized by a lack of memory
property and is often used to model lifetimes of electronic components
as well as waiting times for Poisson processes.
A random variable is said to be memoryless if
\[P(X > t_2 + t_1 |X > t_1) = P(X
> t_2)\] for all \(t_1,
t_2\)
Exercise: Try to show that above is equivalent
to
\[P(X > t_2 + t_1)=P(X > t_1) P(X
> t_2)\] for all \(t_1,
t_2\)
R functions for the Exponential Distribution
Description
Density, distribution function, quantile function and random
generation for the exponential distribution with rate rate (i.e., mean
1/rate).
Usage
dexp(x, rate = 1, log = FALSE)
pexp(q, rate = 1, lower.tail = TRUE, log.p = FALSE)
qexp(p, rate = 1, lower.tail = TRUE, log.p = FALSE)
rexp(n, rate = 1)
Arguments
x, q - vector of quantiles. p - vector of
probabilities. n- number of observations. If length(n) >
1, the length is taken to be the number required. rate -
vector of rates. log, log.p - logical; if TRUE,
probabilities p are given as log(p). lower.tail - logical;
if TRUE (default), probabilities are P[X ≤ x], otherwise, P[X >
x].
Example 4.17, page 279 in text
Exponential Distribution: Light Bulbs If the life of
a certain type of light bulb has an exponential distribution with a mean
of 8 months, find
- The probability that a randomly selected light bulb lasts between 3
and 12 months.
- The 95th percentile of the distribution.
- The probability that a light bulb that has lasted for 10 months will
last more than 25 months.
Solution:
YOUR CODE HERE:
# uncomment the code below to see solution - explain why
pexp(q = 12, rate = 1/8) - pexp(q = 3, rate = 1/8)
f1 <- function(x){(1/8) * exp(-x/8)} # define f1
(integrate(f1, lower = 3, upper = 12)$value) # integrate f1
# the 95 quantile/percentile
qexp(0.95, 1/8)
pexp(25, 1/8, lower = FALSE)/pexp(10, 1/8, lower = FALSE)
# or
1 - pexp(15, 1/8)
# or
pexp(15, 1/8, lower = FALSE)
4.3.7 Normal (Gaussian) Distribution
most important distribution in statistical applications
many numerical populations have distributions that can be
approximated with the normal distribution.
The pdf, mean, and variance for a normal random
variable X with mean μ and variance \(\sigma^2\) are provided: \[X \sim N(\mu, \sigma^2)\] \[ f(x|\mu,\sigma) = \frac{1}{\sqrt{2\pi\sigma^2}}
e^{-\frac{(x-\mu)^2}{2\sigma^2}}\] for \(-\infty < x <\infty\)
\[E[X]=\mu\]
\[Var[X]=\sigma^2\]
R functions for the Normal Distribution
Description
Density, distribution function, quantile function and random
generation for the normal distribution with mean equal to mean and
standard deviation equal to sd.
Usage
dnorm(x, mean = 0, sd = 1, log = FALSE)
pnorm(q, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
qnorm(p, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
rnorm(n, mean = 0, sd = 1)
Arguments
x, q - vector of quantiles. p - vector of
probabilities. n - number of observations. If length(n)
> 1, the length is taken to be the number required. mean
- vector of means. sd - vector of standard deviations.
Example 4.25
Scores on a particular standardized test follow a normal distribution
with a mean of 100 and standard deviation of 10.
- What is the probability that a randomly selected individual will
score between 90 and 115?
- What score does one need to be in the top 10%?
- Find the constant c such that \(P(105 \le
X \le c) = 0.10\).
# (a)
pnorm(q = 115,mean = 100, sd = 10) - pnorm(q = 90, mean = 100, sd = 10) # see why
# (b)
qnorm(p = .90, mean = 100, sd = 10) # check why
# (c)
qnorm(0.10 + pnorm(105, 100, 10), 100, 10) # see the text page 299.
Motivational Problem (Pr. 20 / page 309 in text)
The weekly production of a banana plantation can be modeled with a
normal random variable that has a mean of 5 tons and a standard
deviation of 2 tons.
- Find the probability that, in at most 1 out of the 8 randomly chosen
weeks, the production has been less than 3 tons.
- Find the probability that at least 3 weeks are needed to obtain a
production greater than 10 tons.
Solution:
- Let X = number of weeks where production is less than 3 tons. Then,
\(X \sim Bin(8, 0.1587)\). Let W =
production, \(W \sim N(5, 2)\) and
\(P(W \le 3) = 0.1587\). So, P(X ) =
0.6298. Check the code below!
p <- pnorm(3, 5, 2) # P(W < 3)
pbinom(1, 8, p)
- Let \(X_n\) = number of weeks where
production is less than 10 tons before the first week with production
over 10 tons. \(X_n \sim Geo(\pi = P(W \ge 10)
= 0.0062)\), and \(P(X_n \ge 2) = 1 −
P(Xn \le 1) = 0.9876\).
PI <- 1 - pnorm(q = 10,mean = 5, sd = 2) # P(W >= 10)
PI
1 - pgeom(1, PI)
0.9876192
Quantile-Quantile Plots for Normal Distributions (Q-Q Plots)
Many of the techniques and testing assume the underlying distribution
is normal.
One of the more useful graphical procedures for assessing
distributions is the quantile-quantile plot. (Recall from Section 2.7.3
that this graph is also called a Q-Q plot.)
R function qqnorm() helps determine whether the
underlying distribution is normal.
** Example** Consider the values stored in the variable scores of the
data frame SCORE (in the PASWR2 package) and
shown below which are the scores a random sample of 20 college freshmen
received on a standardized test.
119 107 96 107 97 103 94 106 87 112 99 99 90 106 110 99 105 100 100
94
To compute the pairs of values plotted in an
R quantile-quantile plot for the variable scores of the
data frame SCORE inspect the code below:
n <- length(SCORE$scores) # number of observations
X <- (1:n - 1/2)/n # 100% split into n=20 equal intervals
Xs <- qnorm(X) # quantiles of X
Ys <- sort(SCORE$scores) # sorted scores
plot(Xs, Ys) # plot Ys vs Xs
quantile(Xs, c(0.25, 0.75))
quantile(Ys, c(0.25, 0.75))
qqnorm(SCORE$scores) #using qqnorm
qqline(SCORE$scores) #adding line through 1st and 3rd quantile
You can do this using ggplot2 much nicer:
ggplot(data = SCORE, aes(sample = scores)) + stat_qq()
REMINDER: DO NOT MISS TO REVIEW THE PROGRAMMING EXERCISES
before you attempt the quiz for the week!
LS0tCnRpdGxlOiBXZWVrIDUgLSBVbml2YXJpYXRlIFByb2JhYmlsaXR5IERpc3RyaWJ1dGlvbnMKZGF0ZTogJ2ByIFN5cy5EYXRlKClgJwpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKZWRpdG9yX29wdGlvbnM6IAogIG1hcmtkb3duOiAKICAgIHdyYXA6IHNlbnRlbmNlCi0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkKYGBgCgpgYGB7ciBwYWNrYWdlcywgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gIEZBTFNFfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoTUFTUykKbGlicmFyeShQQVNXUjIpCgpgYGAKCiMjIE9iamVjdGl2ZXMKCi0gICBDb21wdXRlIHByb2JhYmlsaXRpZXMgcmVsYXRlZCB0byBkaXNjcmV0ZSBhbmQgY29udGludW91cyByYW5kb20gdmFyaWFibGVzCi0gICBVc2UgZXhwZXJpbWVudGFsIGFuZCB0aGVvcmV0aWNhbCBwcm9iYWJpbGl0aWVzIHRvIGZvcm11bGF0ZSBhbmQgc29sdmUgYXBwbGllZCBwcm9ibGVtcwoKPiBNb3RpdmF0aW9uOgoKRGlzY3JldGUgZGlzdHJpYnV0aW9ucyBjYW4gYmUgdXNlZCB0byBtb2RlbCB0aGUgbnVtYmVyIG9mIGZhaWx1cmVzIHVudGlsIGEgc3VjY2Vzc2Z1bCByb2NrZXQgbGF1bmNoLCB0aGUgbnVtYmVyIG9mIHBhc3Npbmcgc3R1ZGVudHMgaW4gYSBjbGFzcywgb3IgdGhlIG51bWJlciBvZiB0YXhpcyB0aGF0IHBhc3MgYSBzdHJlZXQgY29ybmVyLCBhcyB3ZWxsIGFzIG1hbnkgb3RoZXIgcGhlbm9tZW5hIHdpdGggY291bnRhYmxlIG91dGNvbWVzLgpDb250aW51b3VzIGRpc3RyaWJ1dGlvbnMgYXJlIHVzZWQgdG8gbW9kZWwgbWVhc3VyZW1lbnQgdmFyaWFibGVzIHN1Y2ggYXMgd2VpZ2h0LCBoZWlnaHQsIGFuZCB0aW1lLgoKPiAqKk1vdGl2YXRpb25hbCBQcm9ibGVtIChQci4gMjAgLyBwYWdlIDMwOSBpbiB0ZXh0KSoqCgpUaGUgd2Vla2x5IHByb2R1Y3Rpb24gb2YgYSBiYW5hbmEgcGxhbnRhdGlvbiBjYW4gYmUgbW9kZWxlZCB3aXRoIGEgbm9ybWFsIHJhbmRvbSB2YXJpYWJsZSB0aGF0IGhhcyBhIG1lYW4gb2YgNSB0b25zIGFuZCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAyIHRvbnMuCgooYSkgRmluZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCwgaW4gYXQgbW9zdCAxIG91dCBvZiB0aGUgOCByYW5kb21seSBjaG9zZW4gd2Vla3MsIHRoZSBwcm9kdWN0aW9uIGhhcyBiZWVuIGxlc3MgdGhhbiAzIHRvbnMuCihiKSBGaW5kIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGF0IGxlYXN0IDMgd2Vla3MgYXJlIG5lZWRlZCB0byBvYnRhaW4gYSBwcm9kdWN0aW9uIGdyZWF0ZXIgdGhhbiAxMCB0b25zLgoKLSAgIFNvbHV0aW9uIHRvd2FyZHMgdGhlIGVuZCBvZiB0aGUgbm90ZXMhCgojIyBEaXNjcmV0ZSBVbml2YXJpYXRlIERpc3RyaWJ1dGlvbnMKCiMjIyA0LjIuMSBEaXNjcmV0ZSBVbmlmb3JtIERpc3RyaWJ1dGlvbgoKVGhlIHJhbmRvbSB2YXJpYWJsZSBgWGAgaXMgc2FpZCB0byBmb2xsb3cgYSBkaXNjcmV0ZSB1bmlmb3JtIGRpc3RyaWJ1dGlvbiB3aXRoIHBhcmFtZXRlciBgbmAgKHdoZXJlICRuIOKIiCDihJUpJCBpZiB0aGUgcHJvYmFiaWxpdHkgYFhgIHRha2VzIG9uIHRoZSB2YWx1ZSBgeGAgaXMgdGhlICoqc2FtZSoqIGZvciBhbGwgYHhgLCB3aGVyZSAkeCA9IHhfMSwgeF8yLCDigKYsIHhfbiQuCgpGb3IgKipEaXNjcmV0ZSBVbmlmb3JtIERpc3RyaWJ1dGlvbioqIG9uZSBoYXM6Cgo+IDEuICAkJFAoWD14X2l8bik9IFxmcmFjezF9e259JCQgZm9yICRpPTEsMiwuLi4sbiQKCj4gMi4gICQkRVtYXT1cZnJhY3sxfXtufSBcc3VtX3tpPTF9Xm4geF9pJCQKCj4gMy4gICQkVmFyW1hdPVxmcmFjezF9e259IFxzdW1fe2k9MX1ebiAoeF9pLUVbWF0pXjIkJAoKKipFeGVyY2lzZToqKiBXaGVuICR4X2kgPSBpJCBmb3IgJGkgPSAxLCDigKYsIG4kLCBpdCBjYW4gYmUgc2hvd24gdGhhdCAkRVtYXSA9IFxmcmFje24rMX17Mn0kIGFuZCB0aGF0ICRWYXJbWF0gPSBcZnJhY3tuXjLiiJIxfXsxMn0kLCByZXNwZWN0aXZlbHkuCgoqKkV4YW1wbGUgNC4xKioKCk9uZSBsaWdodCBidWxiIGlzIHJhbmRvbWx5IHNlbGVjdGVkIGZyb20gYSBib3ggdGhhdCBjb250YWlucyBhIDQwLXdhdHQgbGlnaHQgYnVsYiwgYSA2MC13YXR0IGxpZ2h0IGJ1bGIsIGEgNzUtd2F0dCBsaWdodCBidWxiLCBhIDEwMC13YXR0IGxpZ2h0IGJ1bGIsIGFuZCBhIDEyMC13YXR0IGxpZ2h0IGJ1bGIuCldyaXRlIHRoZSBwcm9iYWJpbGl0eSBmdW5jdGlvbiBmb3IgdGhlIHJhbmRvbSB2YXJpYWJsZSB0aGF0IHJlcHJlc2VudHMgdGhlIHdhdHRhZ2Ugb2YgdGhlIHJhbmRvbWx5IHNlbGVjdGVkIGxpZ2h0IGJ1bGIsIGFuZCBkZXRlcm1pbmUgdGhlIG1lYW4gYW5kIHZhcmlhbmNlIG9mIHRoYXQgcmFuZG9tIHZhcmlhYmxlLgoKKipTb2x1dGlvbjoqKiBUaGUgcmFuZG9tIHZhcmlhYmxlIGBYYCBjYW4gYXNzdW1lIHRoZSBzZXQgb2YgdmFsdWVzICTOqSA9IHs0MCwgNjAsIDc1LCAxMDAsIDEyMH0kLgpUaGUgcHJvYmFiaWxpdHkgZGVuc2l0eSBmdW5jdGlvbiBmb3IgdGhlIHJhbmRvbSB2YXJpYWJsZSBgWGAgaXMKCiRQKFg9eHxuPTUpPVxmcmFjezF9ezV9JCBmb3IgJHg9NDAsIDYwLCA3NSwgMTAwLCAxMjAkCgpUcnkgdGhlIGNvZGUKCmBgYHtyIGV4LiA0LjF9CgpXYXR0cyA8LSBjKDQwLCA2MCwgNzUsIDEwMCwgMTIwKQpuIDwtIGxlbmd0aChXYXR0cykKbWVhbldhdHRzIDwtICgxL24pKnN1bShXYXR0cykKdmFyV2F0dHM8LSAoMS9uKSpzdW0oKFdhdHRzIC0gbWVhbldhdHRzKV4yKQphbnMgPC0gYyhtZWFuV2F0dHMsIHZhcldhdHRzKQphbnMKYGBgCgojIyMgNC4yLjIgQmVybm91bGxpIGFuZCBCaW5vbWlhbCBEaXN0cmlidXRpb25zCgpBICoqQmVybm91bGxpIHRyaWFsKiogaXMgYSByYW5kb20gZXhwZXJpbWVudCB3aXRoIG9ubHkgKip0d28gcG9zc2libGUgb3V0Y29tZXMqKi4KVGhlIG91dGNvbWVzIGFyZSAqKm11dHVhbGx5IGV4Y2x1c2l2ZSBhbmQgZXhoYXVzdGl2ZSoqO2UuZy4sIHN1Y2Nlc3Mgb3IgZmFpbHVyZSwgdHJ1ZSBvciBmYWxzZSwgYWxpdmUgb3IgZGVhZCwgbWFsZSBvciBmZW1hbGUsIGV0Yy4KQSBCZXJub3VsbGkgcmFuZG9tIHZhcmlhYmxlLCBgWGAsIGNhbiB0YWtlIG9uIHR3byB2YWx1ZXMsIHdoZXJlIFgoc3VjY2VzcykgPSAxIGFuZCBYKGZhaWx1cmUpID0gMC4KVGhlIHByb2JhYmlsaXR5IHRoYXQgYFhgIGlzIGEgc3VjY2VzcyBpcyAkXHBpJCwgYW5kIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGBYYCBpcyBhIGZhaWx1cmUgaXMgJDEtXHBpJC4KCkZvciAqKkJlcm5vdWxsaSBkaXN0cmlidXRpb24qKiAqKnBkZioqLCBtZWFuLCBhbmQgdmFyaWFuY2Ugb2YgYSBCZXJub3VsbGkgcmFuZG9tIHZhcmlhYmxlIGFyZToKCiQkWCBcc2ltIEJlcm5vdWxsaShccGkpJCQKCj4gMS4gICQkUChYPXh8XHBpKT0gXHBpXngoMS1ccGkpXnsxLXh9JCQgZm9yICR4PTAsMSQKCj4gMi4gICQkRVtYXT1ccGkkJAoKPiAzLiAgJCRWYXJbWF09XHBpKDEtXHBpKSQkCgpXaGVuIGEgc2VxdWVuY2Ugb2YgQmVybm91bGxpIHRyaWFscyBjb25mb3JtcyB0byB0aGUgZm9sbG93aW5nIGxpc3Qgb2YgcmVxdWlyZW1lbnRzLCBpdCBpcyBjYWxsZWQgYSAqKmJpbm9taWFsIGV4cGVyaW1lbnQqKjoKCj4gMS4gIFRoZSBleHBlcmltZW50IGNvbnNpc3RzIG9mIGEgZml4ZWQgbnVtYmVyIChgbmApIG9mIEJlcm5vdWxsaSB0cmlhbHMuCj4gMi4gIFRoZSBwcm9iYWJpbGl0eSBvZiBzdWNjZXNzIGZvciBlYWNoIHRyaWFsLCBkZW5vdGVkIGJ5ICRccGkkLCBpcyBjb25zdGFudCBmcm9tIHRyaWFsIHRvIHRyaWFsLiBUaGUgcHJvYmFiaWxpdHkgb2YgZmFpbHVyZSBpcyAkXHJobyA9IDEtXHBpJAo+IDMuICBUaGUgdHJpYWxzIGFyZSBpbmRlcGVuZGVudC4KPiA0LiAgVGhlIHJhbmRvbSB2YXJpYWJsZSBvZiBpbnRlcmVzdCwgWCwgaXMgdGhlIG51bWJlciBvZiBvYnNlcnZlZCBzdWNjZXNzZXMgZHVyaW5nIHRoZSBuIHRyaWFscy4KCkZvciAqKkJpbm9taWFsIGRpc3RyaWJ1dGlvbioqICoqcGRmKiosIG1lYW4sIGFuZCB2YXJpYW5jZSBvZiBhIGJpbm9taWFsIHJhbmRvbSB2YXJpYWJsZSBhcmU6CgokJFggXHNpbSBCaW4obiwgXHBpKSAkJAoKPiAxLiAgJCRQKFg9eHxuLCBccGkpPSB7biBcY2hvb3NlIHh9IFxwaV54KDEtXHBpKV57bi14fSQkIGZvciAkeD0wLDEsIC4uLiwgbiQKCj4gMi4gICQkRVtYXT1uIFxwaSQkCgo+IDMuICAkJFZhcltYXT1uIFxwaSgxLVxwaSkkJAoKKipFeGVyY2lzZSAob3B0aW9uYWwpKio6IFByb3ZlIDEsMiBhbmQgMyBhYm92ZS4KCkNvZGUgYmVsb3cgaXMgdXNlZCB0byBjcmVhdGUgZ3JhcGhzIHRoYXQgcmVwcmVzZW50IHRoZSBwcm9iYWJpbGl0eSBkZW5zaXR5IGZ1bmN0aW9uIGFuZCB0aGUgY3VtdWxhdGl2ZSBkaXN0cmlidXRpb24gZnVuY3Rpb24gZm9yIGEgQmluKDgsIDAuMykgcmFuZG9tIHZhcmlhYmxlOgoKVHJ5IGl0IQoKYGBge3IgQmlufQpvcGFyIDwtIHBhcihuby5yZWFkb25seSA9IFRSVUUpCnBhcihtZnJvdz1jKDEsIDIpLCBwdHkgPSAicyIpCnggPC0gMDo4CnB4IDwtIGRiaW5vbSh4ID0geCwgc2l6ZSA9IDgscHJvYiA9ICAwLjMpCgojIHBsb3QgcHJvYmFiaWxpdHkgdnMgY29ycmVzcG9uZGluZyB4LXZhbHVlcwpwbG90KHgsIHB4LCB0eXBlID0gImgiLCB4bGFiID0gIngiLCB5bGFiPSJQKFggPSB4KSIsCiAgICBtYWluID0gIlBERiBvZiBYfkJpbig4LCAwLjMpIikKeHMgPC0gcmVwKDA6OCwgcm91bmQoZGJpbm9tKDA6OCwgOCwgLjMpKjEwMDAwMCwgMCkpICMgY3JlYXRlcyB2ZWN0b3Igb2YgMHMsIDFzLCAuLi44cywgYWNjb3JkaW5nIHRvIHRoZSBleHBlY3RlZCBudW1iZXIgb2YgZWFjaCBvbmUgb3V0IG9mIDEwLDAwMCB0cmlhbHMKCiMgcGxvdCB0aGUgZW1waXJpY2FsIGNkZgpwbG90KGVjZGYoeHMpLCBtYWluID0gIkNERiBvZiBYfkJpbig4LCAwLjMpIiwKICAgIHlsYWIgPSBleHByZXNzaW9uKFAoWDw9eCkpLCB4bGFiID0gIngiKQpwYXIob3BhcikKYGBgCgoqKlE6KiogQ2hhbmdlIHRoZSBwcm9iYWJpbGl0eSwgJFxwaSQgcGFyYW1ldGVyIHRvIHZhbHVlIGNsb3NlIHRvIHplcm8uCldoYXQgZG8geW91IG9ic2VydmU/CkhvdyBkb2VzIGl0IHNrZXcgdGhlIGRpc3RyaWJ1dGlvbi4KTm93LCBpbmNyZWFzZSBcYG4nIHRvIGJpZ2dlciB2YWx1ZSwgZXZlbiBiaWdnZXIuCkRvIHlvdSBub3RpY2UgY29ycmVjdGlvbiBvZiB0aGUgc2tld25lc3M/CgoqKkV4ZXJjaXNlOioqIEdyYXBoIHRoZSAqKnBkZioqIGFuZCAqKmNkZioqIGZvciAkWCBcc2ltIEJpbigxMCxcZnJhY3sxfXsyfSkkIChcIyBvZiBoZWFkcyBvZiB0b3NzaW5nIGEgZmFpciBjb2luIDEwIHRpbWVzIGV4cGVyaW1lbnQpIGl0IGlzIHBhcnQgb2YgdGhlIHdlZWtseSBwcm9ncmFtbWluZyBleGVyY2lzZXMgUm1kIGZpbGUuCgojIyMjIFIgZnVuY3Rpb25zIGZvciBCaW5vbWlhbCBEaXN0cmlidXRpb24gQ2FsY3VsYXRpb25zCgoqKkRlc2NyaXB0aW9uKioKCkRlbnNpdHksIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiwgcXVhbnRpbGUgZnVuY3Rpb24gYW5kIHJhbmRvbSBnZW5lcmF0aW9uIGZvciB0aGUgYmlub21pYWwgZGlzdHJpYnV0aW9uIHdpdGggcGFyYW1ldGVycyBzaXplIGFuZCBwcm9iLgoKVGhpcyBpcyBjb252ZW50aW9uYWxseSBpbnRlcnByZXRlZCBhcyB0aGUgbnVtYmVyIG9mICdzdWNjZXNzZXMnIGluIHNpemUgdHJpYWxzLgoKVXNhZ2UKCmBkYmlub20oeCwgc2l6ZSwgcHJvYiwgbG9nID0gRkFMU0UpYCB0aGlzIGNvbXB1dGVzIHRoZSAqKnBkZioqIHZhbHVlcwoKYHBiaW5vbShxLCBzaXplLCBwcm9iLCBsb3dlci50YWlsID0gVFJVRSwgbG9nLnAgPSBGQUxTRSlgIHRoaXMgZ2l2ZXMgJFAoWCBcbGUgeCkkIHRoZSAqKnBkZioqIHZhbHVlcwoKYHFiaW5vbShwLCBzaXplLCBwcm9iLCBsb3dlci50YWlsID0gVFJVRSwgbG9nLnAgPSBGQUxTRSlgIHRoaXMgZ2l2ZXMgdGhlIHF1YW50aWxlcyAkUChYIFxsZSBrKSBcZ2UgcCQKCmByYmlub20obiwgc2l6ZSwgcHJvYilgCgpBcmd1bWVudHMKCmB4LCBxYCAtIHZlY3RvciBvZiBxdWFudGlsZXMuCmBwYCAtIHZlY3RvciBvZiBwcm9iYWJpbGl0aWVzLgpgbmAgLSBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zLgpgc2l6ZWAgLSBudW1iZXIgb2YgdHJpYWxzICh6ZXJvIG9yIG1vcmUpLgpgcHJvYmAgLSBwcm9iYWJpbGl0eSBvZiBzdWNjZXNzIG9uIGVhY2ggdHJpYWwuCgoqKkV4YW1wbGU6KiogVXNpbmcgdGhlIGZ1bmN0aW9uIGByYmlub20oKWAsIG9uZSBjYW4gZ2VuZXJhdGUgMTAwMCBzYW1wbGVzIG9mIGEgJEJpbihuID0gNSwgXHBpID0gMC41KSQgYXMgc2hvd24gYmVsb3c6CgpgYGB7ciByYmlub219CgpzZXQuc2VlZCgxMjMpCnggPC0gcmJpbm9tKDEwMDAsIDUsIC41KQp0YWJsZSh4KS8xMDAwICMgVGhlIGVtcGlyaWNhbCBkaXN0cmlidXRpb24KCmBgYAoKKipFeGFtcGxlIDQuMyoqCgoqKkJpbm9taWFsIENhbGN1bGF0aW9uKiogQ29uc2lkZXIgdGhlIHByb2JsZW0gb2YgY2FsY3VsYXRpbmcgdGhlIHByb2JhYmlsaXR5IG9mIG9idGFpbmluZyBgNmAgb3IgbW9yZSBoZWFkcyBpbiBgMTBgIHRvc3NlcyBvZiBhICoqd2VpZ2h0ZWQqKiBjb2luIChub3QgZmFpciksIHdoZXJlIHRoZSBwcm9iYWJpbGl0eSBvZiBvYnRhaW5pbmcgYSBoZWFkIGluIGFueSBnaXZlbiB0cmlhbCBpcyBgMC4zM2AuCgpgYGB7cn0KIyBhZGRpbmcgcHJvYmFiaWxpdGllcyAKc3VtKGRiaW5vbSh4ID0gNjoxMCwgc2l6ZSA9IDEwLCBwcm9iID0gMC4zMykpICAgICAgICAgICMgUChYID49IDYpPVAoNikrUCg3KStQKDgpK1AoOSkrUCgxMCkKCiMgb3IKMSAtIHBiaW5vbSg1LCAxMCwgMC4zMykgICAgICAgICAgICAgICMgMSAtIFAoWCA8PSA1KQojb3IgCnBiaW5vbSg1LCAxMCwgMC4zMywgbG93ZXIgPSBGQUxTRSkgICAjIFAoWCA+PSA2KQojIG9yIAoxIC0gc3VtKGRiaW5vbSg1OjAsIDEwLCAwLjMzKSkgIyAxIC0gUChYIDw9IDUpCgpgYGAKCiMjIyA0LjIuMyBQb2lzc29uIERpc3RyaWJ1dGlvbgoKVGhlIFBvaXNzb24gZGlzdHJpYnV0aW9uIGlzIHZlcnkgcG9wdWxhciBmb3IgbW9kZWxpbmcgdGhlIG51bWJlciBvZiB0aW1lcyBwYXJ0aWN1bGFyIGV2ZW50cyBvY2N1ciBpbiBnaXZlbiB0aW1lcyBvciBvbiBkZWZpbmVkIHNwYWNlcywgb3IgaW4gZ2VuZXJhbCAqKnVuaXQqKiBpbnRlcnZhbCBvZiB0aW1lICh1bml0cyBvZiB0aW1lIG1heSB2YXJ5KS4KCkUuZy4KCi0gICBudW1iZXIgb2YgcGhvbmUgY2FsbHMgdG8gOTExIGJldHdlZW4gMSBhLm0uCiAgICBhbmQgMiBhLm0uCgotICAgbnVtYmVyIG9mIGFjY2lkZW50cyBhdCBhIGJ1c3kgc3RyZWV0IGNvcm5lciBkdXJpbmcgYSAyNC1ob3VyIHBlcmlvZAoKLSAgIG51bWJlciBvZiB0eXBvZ3JhcGhpY2FsIGVycm9ycyBvbiBhIHNpbmdsZSBwYWdlIG9mIHRoaXMgYm9vawoKU2VlIGRlZmluaXRpb24gb2YgKipQb2lzc29uIFByb2Nlc3MqKiBpbiB0aGUgdGV4dCwgcGFnZSAyNTYuCgpTdXBwb3NlIHRoZXJlIGlzIGFuIGV4cGVyaW1lbnQgdGhhdCBzYXRpc2ZpZXMgdGhlIHRocmVlIGNyaXRlcmlhIGZvciBhbiBhcHByb3hpbWF0ZSBQb2lzc29uIHByb2Nlc3Mgd2l0aCBwYXJhbWV0ZXIgJFxsYW1iZGEkLCAkXGxhbWJkYSQgbWVhbiBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgb24gYSB1bml0IGludGVydmFsIG9mIHRpbWUuCgpMZXQgYFhgIHJlcHJlc2VudCB0aGUgbnVtYmVyIG9mIG91dGNvbWVzIGluIGFuIGludGVydmFsIG9mIGxlbmd0aCAxICh0ID0gMSkuCgpUaGVuIG9uZSBoYXM6CgoqKlBvaXNzb24gRGlzdHJpYnV0aW9uKiogbWVhbiwgYW5kIHZhcmlhbmNlIG9mIGEgYmlub21pYWwgcmFuZG9tIHZhcmlhYmxlIGFyZToKCiQkWCBcc2ltIFBvaXMoXGxhbWJkYSkkJAoKPiAxLiAgJCRQKFg9eHxcbGFtYmRhKT1cZnJhY3tcbGFtYmRhXnhlXnstXGxhbWJkYX19e3ghfSQkIGZvciAkeD0wLDEsMiwuLi4kCgo+IDIuICAkJEVbWF09XGxhbWJkYSQkCgo+IDMuICAkJFZhcltYXT1cbGFtYmRhJCQKCioqUmV2aWV3IHRoZSBjb2RlKiogdG8gc2VlIGhvdyB0byByZXByZXNlbnQgYSAqKnBkZioqIGFuZCAqKmNkZioqIGZvciBhIGBQb2lzKM67ID0gMSlgIHJhbmRvbSB2YXJpYWJsZS4KQWx0aG91Z2ggdGhlIHZhbHVlcyBgeGAgY2FuIHRha2Ugb24gd2l0aCB0aGUgUG9pc3NvbiBkaXN0cmlidXRpb24gYXJlIFwkMCwgMSwgMiwuLi4sIFwkIHRoZSBwcm9iYWJpbGl0eSBhIFBvaXNzb24gcmFuZG9tIHZhcmlhYmxlIGhhcyBhIHZhbHVlIG9mIGVpZ2h0IG9yIGdyZWF0ZXIgd2hlbiDOuyA9IDEgaXMgZXh0cmVtZWx5IHNtYWxsIChcPCAwKS4KQ29uc2VxdWVudGx5LCB0aGUgcGRmLCBhbmQgY2RmIGRvIG5vdCBleHRlbmQgYmV5b25kIGVpZ2h0LgoKYGBge3IgcGRmIGFuZCBjZGYgUG9pc30Kb3BhciA8LSBwYXIobm8ucmVhZG9ubHkgPSBUUlVFKQpwYXIobWZyb3c9YygxLCAyKSwgcHR5ID0gInMiKQoKeCA8LSAwOjgKcHggPC0gZHBvaXMoeCxsYW1iZGEgPSAxKSAjIGNvbXB1dGVzIHRoZSBwZGYgYXQgdGhlIHBvaW50cyB4CgojIHBsb3QgcHJvYmFiaWxpdHkgdnMgeC12YWx1ZXMKcGxvdCh4LCBweCwgdHlwZSA9ICJoIiwgeGxhYiA9ICJ4IiwgeWxhYj0iUChYID0geCkiLAogICAgbWFpbiA9ICJQREYgb2YgWCB+IFBvaXMoMSkiKQoKeHMgPC0gcmVwKDA6OCwgcm91bmQoZHBvaXMoMDo4LCAxKSoxMDAwMDAsIDApKSAjIGNyZWF0ZSB2ZWN0b3Igb2YgMTAwLDAwMCB2YWx1ZXMgYWNjb3JkaW5nIHRvIHRoZSBleHBlY3RlZCBudW1iZXIgb2Ygb2NjdXJyZW5jZXMgb2YgMHMsMXMsIDJzLCAuLi5hbmQgd2UgY3V0IGF0IDhzIG90aGVyIHZhbHVlcyBjYW4gYmUgaWdub3JlZAojIHBsb3QgdGhlIGVtcGlyaWNhbCBjZGYKcGxvdChlY2RmKHhzKSwgbWFpbiA9ICJDREYgb2YgWCB+IFBvaXMoMSkiLAogICAgeWxhYiA9IGV4cHJlc3Npb24oUChYIDw9eCkpLCB4bGFiID0gIngiKQoKcGFyKG9wYXIpCgpgYGAKCioqTm90ZToqKiBUaGUgUG9pc3NvbiBkaXN0cmlidXRpb24gaXMgcGFydGljdWxhcmx5IGFwcHJvcHJpYXRlIGZvciBtb2RlbGluZyAqKiJyYXJlIioqIHBoZW5vbWVuYSBvciBvdXRjb21lcyB3aGVyZSB0aGUgcHJvYmFiaWxpdHkgb2Ygc3VjY2VzcyBpcyBzbWFsbC4KCkdpdmVuIGBuYCAqKmluZGVwZW5kZW50KiogUG9pc3NvbiByYW5kb20gdmFyaWFibGVzICRYXzEsIFhfMizigKYsIFhfbiQgd2l0aCBwYXJhbWV0ZXJzICTOu18xLCDOu18yLOKApiwgzrtfbiQgcmVzcGVjdGl2ZWx5LCAkWT0gXHN1bV97aT0xfV5uIFhfaSBcc2ltIFBvaXMoXHN1bV97aT0xfV5uIFxsYW1iZGFfaT1cbGFtYmRhKSQKCioqRXhhbXBsZSA0LjYqKiBNb3JlIGFjY2lkZW50cyBhcmUgcmVnaXN0ZXJlZCBpbiBhdXRvIGJvZHkgcmVwYWlyIHNob3BzIGR1cmluZyB0aGUgbW9udGhzIG9mIE1heSBhbmQgSnVuZSB0aGFuIGluIHRoZSByZXN0IG9mIHRoZSB5ZWFyLgpTdXBwb3NlIGEgcGFydGljdWxhciBhdXRvIGJvZHkgcmVwYWlyIHNob3AgaGFzIGFuIGF2ZXJhZ2Ugb2YgZm91ciBhY2NpZGVudHMgcGVyIG1vbnRoLgpXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSB0aGVyZSB3aWxsIGJlIG1vcmUgdGhhbiBzZXZlbiBhY2NpZGVudHMgaW4gdGhpcyBhdXRvIGJvZHkgc2hvcCBkdXJpbmcgdGhlIG1vbnRoIG9mIE1heT8KV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgbm8gbW9yZSB0aGFuIHRocmVlIGFjY2lkZW50cyB3aWxsIG9jY3VyIGR1cmluZyB0aGUgbW9udGhzIG9mIE1heSBhbmQgSnVuZT8KCioqU29sdXRpb246KiogQXNzdW1pbmcgYWNjaWRlbnRzIGluIHRoZSBhdXRvIGJvZHkgc2hvcCBmb2xsb3cgYW4gYXBwcm94aW1hdGUgUG9pc3NvbiBwcm9jZXNzLCB0aGUgcHJvYmFiaWxpdHkgb2YgYHhgIGFjY2lkZW50cyBpbiBvbmUgbW9udGggaXMKCiQkUChYPXh8NCk9XGZyYWN7NF54ZV57LTR9fXt4IX0kJCBmb3IgJHg9MCwxLDIsLi4uJAoKVXNpbmcgYFJgOgoKYGBge3J9CiMgbG93ZXIgcGFyYW1ldGVyIFRSVUUgLSBjb21wdXRlcyBwcm9iYWJpbGl0aWVzIHVwIHRvIHRoZSBwb2ludCwgRkFMU0UgdG8gdGhlIHJpZ2h0IG9mIHRoZSBwb2ludAoxIC0gcHBvaXMocSA9IDcsIGxhbWJkYSA9IDQsIGxvd2VyID0gVFJVRSkgICAgICAgICAgICAgICAjIFAoWCA+IDd8NCkgPSAxIC0gUChYPD03fDQpCgpwcG9pcyhxID0gNywgbGFtYmRhID0gNCwgbG93ZXIgPSBGQUxTRSkgICAgIyBQKFggPiA3fDQpIG5vdGljZSBsb3dlciA9IEZBTFNFCgpwcG9pcyhxID0gMywgbGFtYmRhID0gOCkgIyBQKFggPD0gM3w4KQoKYGBgCgojIyMjIFIgZnVuY3Rpb25zIGZvciB0aGUgUG9pc3NvbiBEaXN0cmlidXRpb24gQ2FsY3VsYXRpb25zCgoqKkRlc2NyaXB0aW9uKioKCkRlbnNpdHksIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiwgcXVhbnRpbGUgZnVuY3Rpb24gYW5kIHJhbmRvbSBnZW5lcmF0aW9uIGZvciB0aGUgUG9pc3NvbiBkaXN0cmlidXRpb24gd2l0aCBwYXJhbWV0ZXIgbGFtYmRhLgoKVXNhZ2UKCmBkcG9pcyh4LCBsYW1iZGEsIGxvZyA9IEZBTFNFKWAKCmBwcG9pcyhxLCBsYW1iZGEsIGxvd2VyLnRhaWwgPSBUUlVFLCBsb2cucCA9IEZBTFNFKWAKCmBxcG9pcyhwLCBsYW1iZGEsIGxvd2VyLnRhaWwgPSBUUlVFLCBsb2cucCA9IEZBTFNFKWAKCmBycG9pcyhuLCBsYW1iZGEpYAoKQXJndW1lbnRzCgpgeGAgLSB2ZWN0b3Igb2YgKG5vbi1uZWdhdGl2ZSBpbnRlZ2VyKSBxdWFudGlsZXMuCmBxYCAtIHZlY3RvciBvZiBxdWFudGlsZXMuCmBwYCAtIHZlY3RvciBvZiBwcm9iYWJpbGl0aWVzLgpgbmAgLSBudW1iZXIgb2YgcmFuZG9tIHZhbHVlcyB0byByZXR1cm4uCmBsYW1iZGFgIC0gdmVjdG9yIG9mIChub24tbmVnYXRpdmUpIG1lYW5zLgoKIyMjIDQuMi40IEdlb21ldHJpYyBEaXN0cmlidXRpb24KCkEgcmFuZG9tIHZhcmlhYmxlIGBYYCB0aGF0IGNvdW50cyB0aGUgbnVtYmVyIG9mIEJlcm5vdWxsaSB0cmlhbHMgdGhhdCByZXN1bHQgaW4gZmFpbHVyZSBiZWZvcmUgdGhlIGZpcnN0IHN1Y2Nlc3MgaXMgY2FsbGVkIGEgKipnZW9tZXRyaWMqKiByYW5kb20gdmFyaWFibGUuCkNsZWFybHksIHRoZSBwcm9iYWJpbGl0eSBvZiBhIHN1Y2Nlc3MgYWZ0ZXIgYHJgIGZhaWx1cmVzIGlzICTPgCDDlyAoMSDiiJIgz4ApXnIkLCB3aGljaCBsZWFkcyB0byB0aGUgZ2VvbWV0cmljIHByb2JhYmlsaXR5IGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiB3aGVyZSAkXHJobyA9IDEg4oiSIM+AJCBpcyB0aGUgcHJvYmFiaWxpdHkgb2YgZmFpbHVyZS4KClRoZSAqKnBkZioqLCBtZWFuLCBhbmQgdmFyaWFuY2UgZm9yIGEgZ2VvbWV0cmljIHJhbmRvbSB2YXJpYWJsZSBhcmUgc2hvd24gYmVsb3c6CgokJFggXHNpbSBHZW8oXHBpKSQkICQkUChYPXh8XHBpKT1ccGlccmhvXngkJCBmb3IgJHg9MCwxLDIgLi4uJAoKJCRFW1hdPVxmcmFje1xyaG99e1xwaX0kJCAkJFZhcltYXT1cZnJhY3tccmhvfXtccGleMn0kJAoKVGhlIGNvZGUgYmVsb3cgY2FuIGJlIHVzZWQgdG8gY3JlYXRlIGdyYXBocyB0aGF0IHJlcHJlc2VudCB0aGUgcHJvYmFiaWxpdHkgZGVuc2l0eSBmdW5jdGlvbiBhbmQgdGhlIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uIGZvciBhICRHZW8oz4AgPSAwLjMpJCByYW5kb20gdmFyaWFibGUuCgpgYGB7ciBHZW99CgpvcGFyIDwtIHBhcihuby5yZWFkb25seSA9IFRSVUUpCnBhcihtZnJvdz1jKDEsIDIpLCBwdHkgPSAicyIpCnggPC0gMDoxNQpweCA8LSBkZ2VvbSh4ID0geCwgcHJvYiA9IC4zKQoKcGxvdCh4LCBweCwgdHlwZSA9ICJoIiwgeGxhYiA9ICJ4IiwgeWxhYj0iUChYID0geCkiLAogICAgIG1haW4gPSAiUERGIG9mIFggfiBHZW9tKDAuMykiKQp4cyA8LSByZXAoMDoxNSwgcm91bmQoZGdlb20oMDoxNSwgMC4zKSoxMDAwMDAsIDApKQpwbG90KGVjZGYoeHMpLCBtYWluID0gIkNERiBvZiBYIH4gR2VvbSgwLjMpIiwKICAgICB5bGFiID0gZXhwcmVzc2lvbihQKFggPD14KSksIHhsYWIgPSAieCIpCnBhcihvcGFyKQpgYGAKCioqUHIuIDE4IC8gcGFnZSAzMDggaW4gdGV4dCoqIFN1cHBvc2UgdGhlIHBlcmNlbnRhZ2Ugb2YgZHJpbmtzIHNvbGQgZnJvbSBhIHZlbmRpbmcgbWFjaGluZSBhcmUgODAlIGFuZCAyMCUgZm9yIHNvZnQgZHJpbmtzIGFuZCBib3R0bGVkIHdhdGVyLCByZXNwZWN0aXZlbHkuCgooYSkgV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCBvbiBhIHJhbmRvbWx5IHNlbGVjdGVkIGRheSwgdGhlIGZpcnN0IHNvZnQgZHJpbmsgaXMgdGhlIGZvdXJ0aCBkcmluayBzb2xkPwooYikgRmluZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCBleGFjdGx5IDEgb3V0IG9mIDEwIGRyaW5rcyBzb2xkIGlzIGEgc29mdCBkcmluay4KCioqU29sdXRpb246KiogTGV0IGBYYCA9IG51bWJlciBvZiB3YXRlcnMgKGZhaWx1cmVzKSBwdXJjaGFzZWQgYmVmb3JlIHRoZSBmaXJzdCBzb2Z0IGRyaW5rIGlzIHB1cmNoYXNlZC4KVGhlbiwgJFggXHNpbSBHZW8oMC44MCkkLgoKKGEpIAoKYGBge3IgcHIuIDE4YX0KCmRnZW9tKHggPSAzLCBwcm9iID0gMC44MCkgIyBQKFggPSAzKQoKYGBgCgooYikgTGV0IGBYYCA9IG51bWJlciBvZiBzb2Z0IGRyaW5rcyBzb2xkLiBUaGVuLCAkWCBcc2ltIEJpbigxMCwgMC44MCkkIGFuZCAkUChYID0gMSkgPSAwJCBzaW5jZSBvbmUgaGFzOgoKYGBge3IgcHIuIDE4Yn0KcGJpbm9tKHEgPSAxLCBzaXplID0gMTAsIHByb2IgPSAwLjgpICMgUChYID0gMSkKYGBgCgoqKk9wdGlvbmFsIHRvIHJldmlldzoqKiA0LjIuNSBOZWdhdGl2ZSBCaW5vbWlhbCBEaXN0cmlidXRpb24gJiA0LjIuNiBIeXBlcmdlb21ldHJpYyBEaXN0cmlidXRpb24KCiMjIDQuMyBDb250aW51b3VzIFVuaXZhcmlhdGUgRGlzdHJpYnV0aW9ucwoKIyMjIDQuMy4xIFVuaWZvcm0gRGlzdHJpYnV0aW9uIChDb250aW51b3VzKQoKPiBUaGUgY29udGludW91cyB1bmlmb3JtIGRpc3RyaWJ1dGlvbiBoYXMgYSAqKnBkZioqIHRoYXQgaXMgY29uc3RhbnQgb3ZlciBhIGNsb3NlZCBpbnRlcnZhbC4KCj4gQW4gaW1wb3J0YW50IGFwcGxpY2F0aW9uIG9mIHRoZSB1bmlmb3JtIGRpc3RyaWJ1dGlvbiBpbmNsdWRlcyByYW5kb20gbnVtYmVyIGdlbmVyYXRpb24uCgoqKlVuaWZvcm0gRGlzdHJpYnV0aW9uKioKCiQkWCBcc2ltIFVuaWYoYSxiKSQkCgo+IDEuICAkJGYoeHxhLGIpPVxmcmFjezF9e2ItYX0kJCBmb3IgJGEgXGxlIHggXGxlIGIkCgo+IDIuICAkJEVbWF09XGZyYWN7YithfXsyfSQkCgo+IDMuICAkJFZhcltYXT1cZnJhY3soYi1hKV4yfXsxMn0kJAoKR2VuZXJhdGluZyBQc2V1ZG8gUmFuZG9tIE51bWJlcnMgdXNpbmcgYFJgIGNvbW1hbmQgKnJkaXN0KiB3aGVyZSAqZGlzdCogaXMgZGlzdHJpYnV0aW9uIG5hbWUuClVzZSBgcnVuaWZgIGZvciB0aGUgbmV4dCBleGFtcGxlLgoKKipFeGFtcGxlOioqCgpGb3IgJFggXHNpbSBVbmlmKDIsNikkIG9uZSBoYXMgJEVbWF09NCQgYW5kICRWYXJbWF09XGZyYWN7MTZ9ezEyfT1cZnJhY3s0fXszfSQKCkVzdGltYXRlICRFW1hdJCBhbmQgJFZhcltYXSQgYnkgdXNpbmcgYSBsYXJnZSBudW1iZXIgb2YgdmFsdWVzIGRyYXduIGF0IHJhbmRvbSBmcm9tIGEgYFVuaWYoMiwgNilgLgoKYGBge3J9CnNldC5zZWVkKDEzKQpUTSA8LSA0ICMgdHJ1ZSBtZWFuClRWIDwtIDQvMyAjIHRydWUgdmFyaWFuY2UKCnggPC0gcnVuaWYobiA9IDEwMDAwLG1pbiA9IDIsbWF4ID0gNikKRXggPC0gbWVhbih4KQpFeAoKVnggPC0gbWVhbigoeC1FeCleMikKVngKClBFIDwtIGMoUGVyY2VudEVycm9yTWVhbiAgPSBhYnMoRXggLSBUTSkvVE0qMTAwLCAKICAgICAgICBQZXJjZW50RXJyb3JWYXJpYW5jZSA9IGFicyhWeCAtIFRWKS9UVioxMDApICMgcGVyY2VudCBlcnJvciBvZiB0aGUgZXN0aW1hdGUgZnJvbSB0aGUgdHJ1ZSBtZWFuIGFuZCB2YXIKQU5TIDwtIGMoU2ltTWVhbiA9IEV4LCBUaGVNZWFuID0gVE0sIFNpbVZhciA9IFZ4LCBUaGVWYXIgPSBUVikKQU5TCmBgYAoKIyMjIDQuMy4yIEV4cG9uZW50aWFsIERpc3RyaWJ1dGlvbgoKSWYgYFdgIGlzIHRoZSB3YWl0aW5nIHRpbWUgdW50aWwgdGhlIGZpcnN0IG91dGNvbWUgb2YgYSBgUG9pc3NvbmAgcHJvY2VzcyB3aXRoIG1lYW4gJFxsYW1iZGEgPiAwJCAoXCMgb2NjdXJyZW5jZXMgb3ZlciB1bml0IGludGVydmFsKSwgdGhlbiB0aGUgKipwZGYqKiwgbWVhbiwgYW5kIHZhcmlhbmNlIGZvciBgV2AgYXJlIHNob3duIGJlbG93OgoKPiAxLiAgJCRmKHh8IFxsYW1iZGEpPVxsYW1iZGEgZV57LVxsYW1iZGEgeH0kJCBmb3IgJHggXGdlIDAkLCBhbmQgMCBvdGhlcndpc2UKCj4gMi4gICQkRVtYXT1cZnJhY3sxfXtcbGFtYmRhfSQkCgo+IDMuICAkJFZhcltYXT1cZnJhY3sxfXtcbGFtYmRhXjJ9JCQKCkNvbnNlcXVlbnRseSwgd2hlbiAkdyA+IDAkLCB0aGUgKipwZGYqKiBvZiBgV2AgaXMgJEYnKHcpID0gZih3KSA9IM67ZV574oiSzrt3fSQuCgpUaGUgZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIGlzIGNoYXJhY3Rlcml6ZWQgYnkgYSBsYWNrIG9mIG1lbW9yeSBwcm9wZXJ0eSBhbmQgaXMgb2Z0ZW4gdXNlZCB0byBtb2RlbCBsaWZldGltZXMgb2YgZWxlY3Ryb25pYyBjb21wb25lbnRzIGFzIHdlbGwgYXMgd2FpdGluZyB0aW1lcyBmb3IgUG9pc3NvbiBwcm9jZXNzZXMuCgpBIHJhbmRvbSB2YXJpYWJsZSBpcyBzYWlkIHRvIGJlICoqbWVtb3J5bGVzcyoqIGlmCgokJFAoWCA+IHRfMiArIHRfMSB8WCA+IHRfMSkgPSBQKFggPiB0XzIpJCQgZm9yIGFsbCAkdF8xLCB0XzIkCgoqKkV4ZXJjaXNlOioqIFRyeSB0byBzaG93IHRoYXQgYWJvdmUgaXMgZXF1aXZhbGVudCB0bwoKJCRQKFggPiB0XzIgKyB0XzEpPVAoWCA+IHRfMSkgUChYID4gdF8yKSQkIGZvciBhbGwgJHRfMSwgdF8yJAoKIyMjIyBSIGZ1bmN0aW9ucyBmb3IgdGhlIEV4cG9uZW50aWFsIERpc3RyaWJ1dGlvbgoKKipEZXNjcmlwdGlvbioqCgpEZW5zaXR5LCBkaXN0cmlidXRpb24gZnVuY3Rpb24sIHF1YW50aWxlIGZ1bmN0aW9uIGFuZCByYW5kb20gZ2VuZXJhdGlvbiBmb3IgdGhlIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiB3aXRoIHJhdGUgcmF0ZSAoaS5lLiwgbWVhbiAxL3JhdGUpLgoKVXNhZ2UKCmBkZXhwKHgsIHJhdGUgPSAxLCBsb2cgPSBGQUxTRSlgCgpgcGV4cChxLCByYXRlID0gMSwgbG93ZXIudGFpbCA9IFRSVUUsIGxvZy5wID0gRkFMU0UpYAoKYHFleHAocCwgcmF0ZSA9IDEsIGxvd2VyLnRhaWwgPSBUUlVFLCBsb2cucCA9IEZBTFNFKWAKCmByZXhwKG4sIHJhdGUgPSAxKWAKCkFyZ3VtZW50cwoKYHgsIHFgIC0gdmVjdG9yIG9mIHF1YW50aWxlcy4KYHBgIC0gdmVjdG9yIG9mIHByb2JhYmlsaXRpZXMuCmBuYC0gbnVtYmVyIG9mIG9ic2VydmF0aW9ucy4KSWYgbGVuZ3RoKG4pIFw+IDEsIHRoZSBsZW5ndGggaXMgdGFrZW4gdG8gYmUgdGhlIG51bWJlciByZXF1aXJlZC4KYHJhdGVgIC0gdmVjdG9yIG9mIHJhdGVzLgpgbG9nLCBsb2cucGAgLSBsb2dpY2FsOyBpZiBUUlVFLCBwcm9iYWJpbGl0aWVzIHAgYXJlIGdpdmVuIGFzIGxvZyhwKS4KYGxvd2VyLnRhaWxgIC0gbG9naWNhbDsgaWYgVFJVRSAoZGVmYXVsdCksIHByb2JhYmlsaXRpZXMgYXJlIFBbWCDiiaQgeF0sIG90aGVyd2lzZSwgUFtYIFw+IHhdLgoKKipFeGFtcGxlIDQuMTcsIHBhZ2UgMjc5IGluIHRleHQqKgoKKipFeHBvbmVudGlhbCBEaXN0cmlidXRpb246IExpZ2h0IEJ1bGJzKiogSWYgdGhlIGxpZmUgb2YgYSBjZXJ0YWluIHR5cGUgb2YgbGlnaHQgYnVsYiBoYXMgYW4gZXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIHdpdGggYSBtZWFuIG9mIDggbW9udGhzLCBmaW5kCgooYSkgVGhlIHByb2JhYmlsaXR5IHRoYXQgYSByYW5kb21seSBzZWxlY3RlZCBsaWdodCBidWxiIGxhc3RzIGJldHdlZW4gMyBhbmQgMTIgbW9udGhzLgooYikgVGhlIDk1dGggcGVyY2VudGlsZSBvZiB0aGUgZGlzdHJpYnV0aW9uLgooYykgVGhlIHByb2JhYmlsaXR5IHRoYXQgYSBsaWdodCBidWxiIHRoYXQgaGFzIGxhc3RlZCBmb3IgMTAgbW9udGhzIHdpbGwgbGFzdCBtb3JlIHRoYW4gMjUgbW9udGhzLgoKKipTb2x1dGlvbjoqKgoKWU9VUiBDT0RFIEhFUkU6CgpgYGB7ciBFeC4gNC4xN30KIyB1bmNvbW1lbnQgdGhlIGNvZGUgYmVsb3cgdG8gc2VlIHNvbHV0aW9uIC0gZXhwbGFpbiB3aHkKcGV4cChxID0gMTIsIHJhdGUgPSAxLzgpIC0gcGV4cChxID0gMywgcmF0ZSA9IDEvOCkKCmYxIDwtIGZ1bmN0aW9uKHgpeygxLzgpICogZXhwKC14LzgpfSAgICAgICAgIyBkZWZpbmUgZjEKKGludGVncmF0ZShmMSwgbG93ZXIgPSAzLCB1cHBlciA9IDEyKSR2YWx1ZSkgICAjIGludGVncmF0ZSBmMQoKIyB0aGUgOTUgcXVhbnRpbGUvcGVyY2VudGlsZQpxZXhwKDAuOTUsIDEvOCkgCgpwZXhwKDI1LCAxLzgsIGxvd2VyID0gRkFMU0UpL3BleHAoMTAsIDEvOCwgbG93ZXIgPSBGQUxTRSkKIyBvcgoxIC0gcGV4cCgxNSwgMS84KQojIG9yCnBleHAoMTUsIDEvOCwgbG93ZXIgPSBGQUxTRSkKCmBgYAoKIyMjIDQuMy43IE5vcm1hbCAoR2F1c3NpYW4pIERpc3RyaWJ1dGlvbgoKPiBtb3N0IGltcG9ydGFudCBkaXN0cmlidXRpb24gaW4gc3RhdGlzdGljYWwgYXBwbGljYXRpb25zCgo+IG1hbnkgbnVtZXJpY2FsIHBvcHVsYXRpb25zIGhhdmUgZGlzdHJpYnV0aW9ucyB0aGF0IGNhbiBiZSBhcHByb3hpbWF0ZWQgd2l0aCB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KClRoZSAqKnBkZioqLCBtZWFuLCBhbmQgdmFyaWFuY2UgZm9yIGEgbm9ybWFsIHJhbmRvbSB2YXJpYWJsZSBYIHdpdGggbWVhbiDOvCBhbmQgdmFyaWFuY2UgJFxzaWdtYV4yJCBhcmUgcHJvdmlkZWQ6ICQkWCBcc2ltIE4oXG11LCBcc2lnbWFeMikkJCAkJCBmKHh8XG11LFxzaWdtYSkgPSBcZnJhY3sxfXtcc3FydHsyXHBpXHNpZ21hXjJ9fSBlXnstXGZyYWN7KHgtXG11KV4yfXsyXHNpZ21hXjJ9fSQkIGZvciAkLVxpbmZ0eSA8IHggPFxpbmZ0eSQKCiQkRVtYXT1cbXUkJAoKJCRWYXJbWF09XHNpZ21hXjIkJAoKIyMjIyBSIGZ1bmN0aW9ucyBmb3IgdGhlIE5vcm1hbCBEaXN0cmlidXRpb24KCioqRGVzY3JpcHRpb24qKgoKRGVuc2l0eSwgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uLCBxdWFudGlsZSBmdW5jdGlvbiBhbmQgcmFuZG9tIGdlbmVyYXRpb24gZm9yIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uIHdpdGggbWVhbiBlcXVhbCB0byBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gZXF1YWwgdG8gc2QuCgpVc2FnZQoKYGRub3JtKHgsIG1lYW4gPSAwLCBzZCA9IDEsIGxvZyA9IEZBTFNFKWAKCmBwbm9ybShxLCBtZWFuID0gMCwgc2QgPSAxLCBsb3dlci50YWlsID0gVFJVRSwgbG9nLnAgPSBGQUxTRSlgCgpgcW5vcm0ocCwgbWVhbiA9IDAsIHNkID0gMSwgbG93ZXIudGFpbCA9IFRSVUUsIGxvZy5wID0gRkFMU0UpYAoKYHJub3JtKG4sIG1lYW4gPSAwLCBzZCA9IDEpYAoKQXJndW1lbnRzCgpgeCwgcWAgLSB2ZWN0b3Igb2YgcXVhbnRpbGVzLgpgcGAgLSB2ZWN0b3Igb2YgcHJvYmFiaWxpdGllcy4KYG5gIC0gbnVtYmVyIG9mIG9ic2VydmF0aW9ucy4KSWYgbGVuZ3RoKG4pIFw+IDEsIHRoZSBsZW5ndGggaXMgdGFrZW4gdG8gYmUgdGhlIG51bWJlciByZXF1aXJlZC4KYG1lYW5gIC0gdmVjdG9yIG9mIG1lYW5zLgpgc2RgIC0gdmVjdG9yIG9mIHN0YW5kYXJkIGRldmlhdGlvbnMuCgoqKkV4YW1wbGUgNC4yNSoqCgpTY29yZXMgb24gYSBwYXJ0aWN1bGFyIHN0YW5kYXJkaXplZCB0ZXN0IGZvbGxvdyBhIG5vcm1hbCBkaXN0cmlidXRpb24gd2l0aCBhIG1lYW4gb2YgMTAwIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gb2YgMTAuCgooYSkgV2hhdCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhIHJhbmRvbWx5IHNlbGVjdGVkIGluZGl2aWR1YWwgd2lsbCBzY29yZSBiZXR3ZWVuIDkwIGFuZCAxMTU/CihiKSBXaGF0IHNjb3JlIGRvZXMgb25lIG5lZWQgdG8gYmUgaW4gdGhlIHRvcCAxMCU/CihjKSBGaW5kIHRoZSBjb25zdGFudCBjIHN1Y2ggdGhhdCAkUCgxMDUgXGxlIFggXGxlIGMpID0gMC4xMCQuCgpgYGB7ciBub3JtfQoKIyAoYSkKcG5vcm0ocSA9IDExNSxtZWFuID0gIDEwMCwgc2QgPSAxMCkgLSBwbm9ybShxID0gOTAsIG1lYW4gPSAxMDAsIHNkID0gMTApICMgc2VlIHdoeQojIChiKSAKcW5vcm0ocCA9IC45MCwgbWVhbiA9IDEwMCwgc2QgPSAxMCkgIyBjaGVjayB3aHkKIyAoYykgCnFub3JtKDAuMTAgKyBwbm9ybSgxMDUsIDEwMCwgMTApLCAxMDAsIDEwKSAjIHNlZSB0aGUgdGV4dCBwYWdlIDI5OS4KYGBgCgoqKk1vdGl2YXRpb25hbCBQcm9ibGVtIChQci4gMjAgLyBwYWdlIDMwOSBpbiB0ZXh0KSoqCgpUaGUgd2Vla2x5IHByb2R1Y3Rpb24gb2YgYSBiYW5hbmEgcGxhbnRhdGlvbiBjYW4gYmUgbW9kZWxlZCB3aXRoIGEgbm9ybWFsIHJhbmRvbSB2YXJpYWJsZSB0aGF0IGhhcyBhIG1lYW4gb2YgNSB0b25zIGFuZCBhIHN0YW5kYXJkIGRldmlhdGlvbiBvZiAyIHRvbnMuCgooYSkgRmluZCB0aGUgcHJvYmFiaWxpdHkgdGhhdCwgaW4gYXQgbW9zdCAxIG91dCBvZiB0aGUgOCByYW5kb21seSBjaG9zZW4gd2Vla3MsIHRoZSBwcm9kdWN0aW9uIGhhcyBiZWVuIGxlc3MgdGhhbiAzIHRvbnMuCihiKSBGaW5kIHRoZSBwcm9iYWJpbGl0eSB0aGF0IGF0IGxlYXN0IDMgd2Vla3MgYXJlIG5lZWRlZCB0byBvYnRhaW4gYSBwcm9kdWN0aW9uIGdyZWF0ZXIgdGhhbiAxMCB0b25zLgoKKipTb2x1dGlvbjoqKgoKPiAoYSkgTGV0IFggPSBudW1iZXIgb2Ygd2Vla3Mgd2hlcmUgcHJvZHVjdGlvbiBpcyBsZXNzIHRoYW4gMyB0b25zLiBUaGVuLCAkWCBcc2ltIEJpbig4LCAwLjE1ODcpJC4gTGV0IFcgPSBwcm9kdWN0aW9uLCAkVyBcc2ltIE4oNSwgMikkIGFuZCAkUChXIFxsZSAzKSA9IDAuMTU4NyQuIFNvLCBQKFggXGxlIDEpID0gMC42Mjk4LiBDaGVjayB0aGUgY29kZSBiZWxvdyEKCmBgYHtyfQoKcCA8LSBwbm9ybSgzLCA1LCAyKSAjIFAoVyA8IDMpCnBiaW5vbSgxLCA4LCBwKQoKYGBgCgooYikgTGV0ICRYX24kID0gbnVtYmVyIG9mIHdlZWtzIHdoZXJlIHByb2R1Y3Rpb24gaXMgbGVzcyB0aGFuIDEwIHRvbnMgYmVmb3JlIHRoZSBmaXJzdCB3ZWVrIHdpdGggcHJvZHVjdGlvbiBvdmVyIDEwIHRvbnMuICRYX24gXHNpbSBHZW8oXHBpID0gUChXIFxnZSAxMCkgPSAwLjAwNjIpJCwgYW5kICRQKFhfbiBcZ2UgMikgPSAxIOKIkiBQKFhuIFxsZSAxKSA9IDAuOTg3NiQuCgpgYGB7cn0KUEkgPC0gMSAtIHBub3JtKHEgPSAxMCxtZWFuID0gIDUsIHNkID0gMikgIyBQKFcgPj0gMTApClBJCgoxIC0gcGdlb20oMSwgUEkpCjAuOTg3NjE5MgoKYGBgCgojIyMjIFF1YW50aWxlLVF1YW50aWxlIFBsb3RzIGZvciBOb3JtYWwgRGlzdHJpYnV0aW9ucyAoUS1RIFBsb3RzKQoKPiBNYW55IG9mIHRoZSB0ZWNobmlxdWVzIGFuZCB0ZXN0aW5nIGFzc3VtZSB0aGUgdW5kZXJseWluZyBkaXN0cmlidXRpb24gaXMgbm9ybWFsLgoKPiBPbmUgb2YgdGhlIG1vcmUgdXNlZnVsIGdyYXBoaWNhbCBwcm9jZWR1cmVzIGZvciBhc3Nlc3NpbmcgZGlzdHJpYnV0aW9ucyBpcyB0aGUgcXVhbnRpbGUtcXVhbnRpbGUgcGxvdC4KPiAoUmVjYWxsIGZyb20gU2VjdGlvbiAyLjcuMyB0aGF0IHRoaXMgZ3JhcGggaXMgYWxzbyBjYWxsZWQgYSBRLVEgcGxvdC4pCgo+IFIgZnVuY3Rpb24gYHFxbm9ybSgpYCBoZWxwcyBkZXRlcm1pbmUgd2hldGhlciB0aGUgdW5kZXJseWluZyBkaXN0cmlidXRpb24gaXMgbm9ybWFsLgoKXCpcKiBFeGFtcGxlXCpcKiBDb25zaWRlciB0aGUgdmFsdWVzIHN0b3JlZCBpbiB0aGUgdmFyaWFibGUgc2NvcmVzIG9mIHRoZSBkYXRhIGZyYW1lIGBTQ09SRWAgKGluIHRoZSBgUEFTV1IyYCBwYWNrYWdlKSBhbmQgc2hvd24gYmVsb3cgd2hpY2ggYXJlIHRoZSBzY29yZXMgYSByYW5kb20gc2FtcGxlIG9mIDIwIGNvbGxlZ2UgZnJlc2htZW4gcmVjZWl2ZWQgb24gYSBzdGFuZGFyZGl6ZWQgdGVzdC4KCj4gMTE5IDEwNyA5NiAxMDcgOTcgMTAzIDk0IDEwNiA4NyAxMTIgOTkgOTkgOTAgMTA2IDExMCA5OSAxMDUgMTAwIDEwMCA5NAoKVG8gY29tcHV0ZSB0aGUgcGFpcnMgb2YgdmFsdWVzIHBsb3R0ZWQgaW4gYW4gYFIgcXVhbnRpbGUtcXVhbnRpbGUgcGxvdGAgZm9yIHRoZSB2YXJpYWJsZSBzY29yZXMgb2YgdGhlIGRhdGEgZnJhbWUgU0NPUkUgaW5zcGVjdCB0aGUgY29kZSBiZWxvdzoKCmBgYHtyfQpuIDwtIGxlbmd0aChTQ09SRSRzY29yZXMpICMgbnVtYmVyIG9mIG9ic2VydmF0aW9ucwoKWCA8LSAoMTpuIC0gMS8yKS9uICMgMTAwJSBzcGxpdCBpbnRvIG49MjAgZXF1YWwgaW50ZXJ2YWxzClhzIDwtIHFub3JtKFgpICMgcXVhbnRpbGVzIG9mIFgKWXMgPC0gc29ydChTQ09SRSRzY29yZXMpICMgc29ydGVkIHNjb3JlcwpwbG90KFhzLCBZcykgIyBwbG90IFlzIHZzIFhzCnF1YW50aWxlKFhzLCBjKDAuMjUsIDAuNzUpKSAKcXVhbnRpbGUoWXMsIGMoMC4yNSwgMC43NSkpCgpxcW5vcm0oU0NPUkUkc2NvcmVzKSAjdXNpbmcgcXFub3JtCnFxbGluZShTQ09SRSRzY29yZXMpICNhZGRpbmcgbGluZSB0aHJvdWdoIDFzdCBhbmQgM3JkIHF1YW50aWxlCmBgYAoKWW91IGNhbiBkbyB0aGlzIHVzaW5nIGBnZ3Bsb3QyYCBtdWNoIG5pY2VyOgoKYGBge3J9CmdncGxvdChkYXRhID0gU0NPUkUsIGFlcyhzYW1wbGUgPSBzY29yZXMpKSArIHN0YXRfcXEoKQpgYGAKCioqUkVNSU5ERVI6IERPIE5PVCBNSVNTIFRPIFJFVklFVyBUSEUgUFJPR1JBTU1JTkcgRVhFUkNJU0VTIGJlZm9yZSB5b3UgYXR0ZW1wdCB0aGUgcXVpeiBmb3IgdGhlIHdlZWshKioK