List of R colors:

http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf

The normal distribution

Example 1

  • The standard normal distribution is the one where \(\mu=0\) and \(\sigma=1\), and is shown in the graph below
X<-seq(-5,5,len=201) #Create the x-axis between -5 and +5
P<-dnorm(X,mean=0,sd=1) # Evaluate the Normal Distribution function over the x-axis
plot(X,P,type='l',lwd=2,col='steelblue') # Plot the Probability along th x-axis

  • The lines of this cell have the following functions:
  1. X<-seq(-5,5,len=200) This creates a sequence of \(x\)-values, which will form the horizontal axis. These values start at -5, and stop at +5, and the sequence has 200 points altogether.
X  
  [1] -5.00 -4.95 -4.90 -4.85 -4.80 -4.75 -4.70 -4.65 -4.60 -4.55 -4.50 -4.45 -4.40 -4.35 -4.30 -4.25 -4.20 -4.15 -4.10 -4.05 -4.00 -3.95 -3.90 -3.85 -3.80 -3.75 -3.70
 [28] -3.65 -3.60 -3.55 -3.50 -3.45 -3.40 -3.35 -3.30 -3.25 -3.20 -3.15 -3.10 -3.05 -3.00 -2.95 -2.90 -2.85 -2.80 -2.75 -2.70 -2.65 -2.60 -2.55 -2.50 -2.45 -2.40 -2.35
 [55] -2.30 -2.25 -2.20 -2.15 -2.10 -2.05 -2.00 -1.95 -1.90 -1.85 -1.80 -1.75 -1.70 -1.65 -1.60 -1.55 -1.50 -1.45 -1.40 -1.35 -1.30 -1.25 -1.20 -1.15 -1.10 -1.05 -1.00
 [82] -0.95 -0.90 -0.85 -0.80 -0.75 -0.70 -0.65 -0.60 -0.55 -0.50 -0.45 -0.40 -0.35 -0.30 -0.25 -0.20 -0.15 -0.10 -0.05  0.00  0.05  0.10  0.15  0.20  0.25  0.30  0.35
[109]  0.40  0.45  0.50  0.55  0.60  0.65  0.70  0.75  0.80  0.85  0.90  0.95  1.00  1.05  1.10  1.15  1.20  1.25  1.30  1.35  1.40  1.45  1.50  1.55  1.60  1.65  1.70
[136]  1.75  1.80  1.85  1.90  1.95  2.00  2.05  2.10  2.15  2.20  2.25  2.30  2.35  2.40  2.45  2.50  2.55  2.60  2.65  2.70  2.75  2.80  2.85  2.90  2.95  3.00  3.05
[163]  3.10  3.15  3.20  3.25  3.30  3.35  3.40  3.45  3.50  3.55  3.60  3.65  3.70  3.75  3.80  3.85  3.90  3.95  4.00  4.05  4.10  4.15  4.20  4.25  4.30  4.35  4.40
[190]  4.45  4.50  4.55  4.60  4.65  4.70  4.75  4.80  4.85  4.90  4.95  5.00
  1. P<-dnorm(X,mean=0,sd=1) This evaluates the normal distribution with mean=0 and standard deviation = 1. With mean=0 this means the peak of the curve is at \(x=0\). The \(sd=1\) command determines how spread out the graph is, the larger sd the more spread out the graph.

  2. The last line instruct R to plot X on the horizontal axis and P on the vertical axis. The argument type=‘l’ instructs R to plot the curve as a line, lwd=2 indicates a linewidth of 2 and col=‘steelblue’ indicates the colour to plot the curve.

Exercise 1

Plot the normal disribution with \(\mu=4\) and \(\sigma=2.15\). Note that you will have to re-define an appropriate X-interval for this plot also. A convient way to do this so that your plot looks symmetric is to set \[\mathbf{X=\text{seq}(\mu-5*\sigma,\mu+5*\sigma)}\] and do not forget to include * when you want to denote multiplication.

Interpretation of the normal curve

Example 2

Illustrate the probability for \(x\) in the intervavl \(-2\leq x\leq 1\) in the normal distribution with \(\mu=0\) and \(\sigma=1\). Calculate this proability.

# Part 1. Plot the normal curve again - See Example 1
X<-seq(-5,5,len=201)
P<-dnorm(X,mean=0,sd=1)
plot(X,P,type='l',lwd=2,col='steelblue')

# Part 2. Shade the required area.
X1=seq(-2,1,length=201) # The interval -5<x<5
P1=dnorm(X1,mean=0,sd=1)
polygon(c(-2,X1,1),c(0,P1,0),col=adjustcolor("cornflowerblue",alpha.f=0.3),border=NA)

  • The code in the cell above has the following meaning:
  1. Part 1 This code has alredy been explained in Example 1

  2. Part 2 We create a new x1 axis between -5 and -1. We create the corresponding y-values using the dnorm() funciton applied to the intrval x1. polygon(c(-5,x_1,-1),c(0,y1,0)) indicates that the area between -5__ and -1 on the x-axis and between 0 and the corresponging values of y1 should be filled in.

  3. col=adjustcolor(“cornflowerblue”,alpha.f=0.3) indicates the fill color and the transparencey alpha of the filling. The smaller the value of alpha the more transparent the filling, where alpha should always be between 0 and 1.

Probabilities

dnorm(-1,mean=0,sd=1)
[1] 0.2419707
dnorm(2,mean=0,sd=1)
[1] 0.05399097
dnorm(2,mean=0,sd=1)-dnorm(-1,mean=0,sd=1)
[1] -0.1879798

Confidence Intervals

Given a population, a Confidence Interval (CI) is a means of estimating a population statistic from the corresponding sample staistic with a certain level of confidence. For example, we may take survey data on a collection of people to estimate the average mothly salary of the people in the survey. Then based on this sample average we can estimate a range for the average slalary of all people in the population, to a certain confidence level. The range of possible values for the population average is called a confidence interval.

Example 3:

  • Suppose we wish to determine the mean salary of the population of a country with a certain degree of confidence.

  • In practice it would be difficult, if not impossible, to collect data on the salary of everybody from the population.

  • Instead, we may collect salary data from numerous samples of people from the population, and then get the mean salary for each of these samples.

  • For each sample, the sample mean would be spread with a normal distribution, whose standard deviation and mean would be close to the mean of the overall population.

  • We let \(\bar{x}\) denote the mean salary from one of these samples, and the standard deviation of the sample be \(\sigma\) (this measures how much the means are spread about the true mean).

  • We can now say that the true population mean lies in the interval \[\bar{x}\pm z_{\frac{\alpha}{2}}\frac{\sigma}{\sqrt{n}},\] where \(n\) is the size of the sample for which the mean \(\bar{x}\) was calculated.

  • The parameter \(\alpha\) is called the confidence parameter associated with the confidence level, and the number \(z_{\frac{\alpha}{2}}\) is the z-score associated with the parameter \(\frac{\alpha}{2}\).

  • From a sample of 100 people, we find that the lowest salary from the sample is EUR 15000 and the highest is EUR 55000, with a mean salary of EUR 35000 and a standard deviation of EUR 2500.

  • We can plot the normal distribution for this data as follows:

    1. We create a sample size between 15000 and 55000 (the sample range), with step size 50. We call this sample data Sample1

    2. We use the dnorm() function to indicate that the data in Sample1 is normally distributed about the mean where the mean is 35000 and the standard deviation is 2500.

    3. We plot the distribution using the usual plot() function, with Sample1 on the x-axis and Data1 on the y-axis.

Sample1<-seq(15000,55000, by=50)
Data1 <- dnorm(Sample1,mean=35000, sd=2500)
plot(Sample1,Data1,ylab="Rel. Freq.",xlab="Salaries (EUR)",type="l",lwd=2,col="red")

A 90% Confidence Interval

  • Suppose we wish to determine the average salary value at a confidence level of 90%.

  • This would correspond to the salary interval which gives 90% of the area beneath the normal distribution curve above.

  • This number can be calculated using a normal distribution table, and finding the \(z_{\alpha}\)-score corresponding to \(\alpha=1-0.90=0.1\).

# Part 1. Plot the normal curve again - See Example 1
Z0<-seq(-5,5,len=200)
H0<-dnorm(Z0,mean=0,sd=1)
plot(Z0,H0,type='l',lwd=2,col='steelblue',main='The 90% confidence interval')

# Part 2. Shade the required area.
x1=seq(-qnorm(0.95),qnorm(0.95),length=200)
y1=dnorm(x1,mean=0,sd=1)
polygon(c(-qnorm(0.95),x1,qnorm(0.95)),c(0,y1,0),col=adjustcolor("cornflowerblue",alpha.f=0.3),border=NA)

  • When we look for a confidence interval of 90% we are looking for the values of \(z\) such that 90% of the area beneath the curve, between \(-z_{\frac{\alpha}{2}}\) and \(z_{\frac{\alpha}{2}}\).

  • It also means we are looking for the \(z\)-values which will exclude 5% of the area in each tail, that is we are looking for the \(z\)-values for each of the dashed line in the plot below:

Standard<-seq(-4,4,by=0.001)
StandardData<-dnorm(Standard,mean=0,sd=1)
plot(Standard,StandardData,ylab="Rel. Freq.", xlab="z", type="l", lwd=2,col="red")
segments(-qnorm(0.9),0,-qnorm(0.9),dnorm(-qnorm(0.9),mean=0,sd=1),lwd=2.5,lty=2)
segments(qnorm(0.9),0,qnorm(0.9),dnorm(qnorm(0.9),mean=0,sd=1),lwd=2.5,lty=2)

  • 90% of the area beneath the curve is contained between the two dashed lines.

  • 5% of the area is in each tail to the left and right.

  • It also means that the area beneath the curve containing the left tail and the middle portion is 95%

  • To find the \(z\)-value corresponding to this 95 % in R we can use the qnorm() function as follows:

z90=qnorm(0.95)
z90
[1] 1.644854
  • In the plot above this means that 95% of the are beneath the curve is between \(z=-\infty\) and \(1.64485\).

  • It also means that 90% of the area lies, from \(z=-1.644854\) to \(z=-1.644854\).

  • For the purposes of our salary survey above, it also means \[z_{\frac{\alpha}{2}}=1.644845\]

  • In terms of our survey we are also 90% certain that the mean population salry lies in the range

lower_bound=35000-z90*2500/sqrt(100)
upper_bound=35000+z90*2500/sqrt(100)
lower_bound
[1] 34588.79
upper_bound
[1] 35411.21

We are 90% confident that the avareage salary of the overall population lies in the range €34,588.79 to €35,411.21.

In terms of our normal distribution plot this means, we are 90% certain the mean population salary lies between the two dashed blue lines.

Sample1<-seq(15000,55000, by=50)
Data1 <- dnorm(Sample1,mean=35000, sd=2500)
plot(Sample1,Data1,ylab="Rel. Freq.",xlab="Salaries (EUR)",type="l",lwd=2,col="red")
abline(v=lower_bound,lwd=2,lty=2,col="blue")
abline(v=upper_bound,lwd=2,lty=2,col="blue")

Exercise 2

A company wishes to determine the cost associated with providing health insurance for all of its employees. The company asked a sample of 35 employees how much they currently pay annually for health insurance. The data obtained revealed a sample mean premium of EUR635 with a standard deviation of EUR67. Using this data answer the following

  1. Find the 90%, 95%, 96% and 99% confidence intervals for the average amount spent by all customers.
  2. Plot a normal distribution for this data set showing the confidence intervals obtained.

Exercise 3

The mean number of emails received by employees at a company was measured on a ample of 58 employees. The sample mean was found to be 21 emails per day with a standard deviation of 9. Using this data answer the following

  1. Find the 90%, 94%, 96% and 99% confidence intervals for the average amount spent by all customers.
  2. Plot a normal distribution for this data set showing the confidence intervals obtained.

Samples, Means and Standard Deviations

The Mean

Given a data set we can calculate the mean and the standard deviation of the data-set using the functions mean() and sd().

Given a data set of size \(n\), with data values \(x_1,x_2,\ldots,x_n\), the mean of the data set is given by \[ \bar{x}=\frac{\displaystyle{\sum_{i=1}^{n}}x_{i}}{N}. \] This can be evaluated in R using the function mean():

Example 2

Suppose the data from a survey is given by the data set \[ 1.3,-4.2,1.55,6.78,4.5,3.21, 5.89,7.34,-6.88,-7.9 \] Create a data structure in R to represent this data set. Use the mean() function to evaluate the mean of the data set.

dataset2<-c(1.3,-4.2,1.55,6.78,4.5,3.21, 5.89,7.34,-6.88,-7.9)
mean(dataset2)
[1] 1.159
  • Hence the mean is \[\bar{x}=1.159\]

The Standard Deviation

Given a data set we can calculate the mean and the standard deviation of the data-set using the functions mean() and sd().

Given a data set of size \(n\), with data values \(x_1,x_2,\ldots,x_n\), the mean of the data set is given by \[ s=\frac{\displaystyle{\sum_{i=1}^{n}}(x_{i}-\bar{x})^2}{N-1}. \] This can be evaluated in R using the function mean():

Example 4

Evaluate the standard deviation of the data set in Example 2 using the sd() function.

sd(dataset2)
[1] 5.608865
  • Hence the standard deviation is \[ s= 5.608865 \]

Example 5

The inflation rate in Ireland between the years 1992 and 2016 is given in the data file IrelandInflation.csv(Source: World Bank). We will import this into R using the usual command read.csv(file.choose()) as a data structure. Using this data structure we want to answer the following:

  1. Find the mean inflation rate between the years 1992 and 2016
  2. Find the standard deviation of this data set
  3. Find the number of data points in this data set
  4. Using these three values, find the range of possible values for the average inflation rate in Ireland over all years with 95% confidence
  5. Plot the inflation data as a normal distribution.

Importing the Data

InflationData<-read.csv("IrelandInflation.csv")
InflationData

Creating the Data Structure

Inflation<-InflationData$Inflation.Rate..
Inflation
 [1]  3.119790e+00  1.408776e+00  2.345707e+00  2.514464e+00  1.693076e+00  1.437211e+00  2.426878e+00  1.640271e+00  5.564830e+00  4.872355e+00  4.651952e+00
[12]  3.479883e+00  2.194873e+00  2.431541e+00  3.938895e+00  4.879925e+00  4.053506e+00 -4.479938e+00 -9.461664e-01  2.578870e+00  1.692785e+00  5.026782e-01
[23]  1.967858e-01 -2.945990e-01  3.120000e-13

Part 1 - The Mean Inflation

xbar=mean(Inflation)
xbar
[1] 2.076174
  • The mean inflation rate between 1992 and 2016 in Ireland was \(\bar{x}=2.076174%\)

Part 2 - The Standard Deviation

s=sd(Inflation)
s
[1] 2.189926
  • The standard deviation in the rate of inflation between 1992 and 2016 is \(\sigma=2.189926\)

Part - The Number of Data Points

We use the length() function to determine the number of data-points in Inflation

n=length(Inflation)
n
[1] 25
  • There are \(n=25\) data points in the data set Inflation

Part 4 - The 90% Confidence Interval

  • The confidence parameter \(\alpha\) is given by \[\alpha = 1-0.95=0.05\Rightarrow \frac{\alpha}{2}=0.025\]

  • We now wish to find the \(z_{\frac{\alpha}{2}}\) which gives an area of \(0.95+0.025=0.975\) under the curve of the normal distribution. We find this \(z\)-score using qnorm()

z0=qnorm(0.975)
z0
[1] 1.959964
  • For the 95% confidence interval, we have \(z_{\frac{\alpha}{2}}=1.959964\). Hence the upper and lower bound for the 95% confidence interval for the data set are
xlower=xbar-z0*s/sqrt(n)
xupper=xbar+z0*s/sqrt(n)

xlower
[1] 1.217739
xupper
[1] 2.934609

We are 95% certain that the mean inflation rate for Ireland lies in the interval 1.217739% to 2.934609%.

Part 5 - The Normal Distribution Plot

We now plot StandardInflation to give the normal distribution plot:

  1. First we create an interval appropriate for creating a normal distribution form the data-set Inflation: For this plot, we will make the plot range start at \(\bar{x}-5\sigma\) and end at \(\bar{x}+5\sigma\), with a step-size 0.0001:
Interval1=seq(xbar-5*s,xbar+5*s,by=0.0001)
  1. Next we create a normal distribution from this data with mean and standard deviation evaluated earlier:
NormalDistInflation=dnorm(Interval1, mean=xbar, sd=s)

3 Now we plot NormalDistInflation on the y-axis and Interval1 on the x-axis:

plot(Interval1,NormalDistInflation,ylab="Rel. Freq.",xlab="Inflation Rate %",type="l",lwd=2,col="red")
abline(v=xlower,lwd=2,lty=2,col="blue")
abline(v=xupper,lwd=2,lty=2,col="blue")

Exercise 4:

  • The data file IrelandEmissions.csv contains the CO2 emissions, in metric tons per capital, of Ireland between 1992 and 2016. (Source: World Bank)

  • Using the data in this file, create a data structure to capture the numerical data over those 25 years.

  • Using this data structure answer the following:

  1. Find the mean inflation rate between the years 1992 and 2016
  2. Find the standard deviation of this data set
  3. Find the number of data points in this data set
  4. Using these three values, find the 90% and 99% confidence intervals for the average CO2 emissions of Ireland over all years.
  5. Plot the inflation data as a normal distribution, and indicate the confidence intervals on these plots.

Interpretation of Confidence Intervals

X=c(0.34,0.77,0.98,1.03,1.45,1.87,1.99,2.11,2.23,2.24,2.87,2.89,2.97,3.04,3.45,3.56,3.77,3.79,3.81,3.97,4.12,4.34,4.88,5.01,5.16)
mean(X)
[1] 2.9056

Sampling the population

  • In many cases of practical interest, this mean is not available to us, and the best we can do is form a confidence interval for this mean.

  • To form these confidence intervals, we take samples of the population data.

  • This is implemented in R as follows:

n=4 # sample size
N=10 # number of samples
Sample<-replicate(N,sample(X,n))
  • We have taken 10 Samples with each sample having 4 data values
Sample
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 3.45 2.24 1.99 1.03 0.77 0.98 3.56 3.97 5.01  1.87
[2,] 3.77 5.16 4.12 0.34 2.24 3.45 5.16 3.56 2.89  3.97
[3,] 2.23 2.89 2.23 2.23 2.97 2.97 1.45 0.34 3.45  1.03
[4,] 1.99 1.03 2.87 5.16 3.97 3.04 2.97 4.88 3.77  4.88
  • Now we wish to take the mean of each sample, which we do as follows:
M <- numeric(length = length(1:N))
for (i in 1:N) {
  M[i] <- mean(Sample[,i])
}
M
 [1] 2.8600 2.8300 2.8025 2.1900 2.4875 2.6100 3.2850 3.1875 3.7800 2.9375
  • Clearly, the mean of each sample does not match the mean of the population.

Confidence Intervals from the Samples

  • We now form the 60% Confidence Interval associated with each sample mean, and to do so we need the z score corresponding to the 80th percentile:
z<-qnorm(0.80,mean=0,sd=1)
z
[1] 0.8416212
  • Next we form the standard error associated with the population and the samples:
  1. The standard deviation of the population is
sigma<-sqrt(sum((X-mean(X))^2)/length(X))
sigma
[1] 1.343143

We do this because the function sd() uses the formula for sample standard deviation.

  1. The standard error is
SE<-sigma/sqrt(n)
SE
[1] 0.6715714

i.e. the population standard deviation divided by the sample size.

  1. The lower boundaries of the confidence intervals are now:
ML<-M-z*SE
ML
 [1] 2.294791 2.264791 2.237291 1.624791 1.922291 2.044791 2.719791 2.622291 3.214791 2.372291

The upper ends of the confidence intervals are:

MU<-M+z*SE
MU
 [1] 3.425209 3.395209 3.367709 2.755209 3.052709 3.175209 3.850209 3.752709 4.345209 3.502709
  • The 60% confidence intervals following from these 10 samples are:
paste(ML,MU,sep=' to ')
 [1] "2.29479124068733 to 3.42520875931267" "2.26479124068733 to 3.39520875931267" "2.23729124068733 to 3.36770875931267" "1.62479124068733 to 2.75520875931267"
 [5] "1.92229124068733 to 3.05270875931267" "2.04479124068733 to 3.17520875931267" "2.71979124068733 to 3.85020875931267" "2.62229124068733 to 3.75270875931267"
 [9] "3.21479124068733 to 4.34520875931267" "2.37229124068733 to 3.50270875931267"

Recall: The actual mean of the pupulation is

mean(X)
[1] 2.9056
  • We deliberitely chose 60% confidence intervals to highlight the point that not all confidence intervals contain the true population mean.

  • This gives us the correct interpretation for the 60% confidence interval:

    • A confidence iterval either does or does not contain the true population mean.

    • As we can see, if we take enough samples, then some of these confidence intervals will contain the mean and some will not.

    • If we take a large enough number of samples, then on average, 60% of the confidence intervals deduced from those samples, at confidence level 60%, will contain the true mean.

Exercise 5:

  1. Using the same data set X, take N=50 samples of sample size n=5.

  2. Find the mean of each sample.

  3. Find the 90% confidence interval associated with these sample averages.

  4. Do all these confidence intervals contain the true population mean?

LS0tCnRpdGxlOiAiRGF0YSBWaXN1YWxpc2F0aW9uIDIwMTkgLSBBc3NpZ25tZW50IDQiCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKCiMjIyBMaXN0IG9mIFIgY29sb3JzOgoKaHR0cDovL3d3dy5zdGF0LmNvbHVtYmlhLmVkdS9+dHpoZW5nL2ZpbGVzL1Jjb2xvci5wZGYKCgoKIyBUaGUgbm9ybWFsIGRpc3RyaWJ1dGlvbgoKKiBUaGUgX19ub3JtYWwgZGlzdHJpYnV0aW9uX18gaXMgdGhlIGdyYXBoIG9mIHRoZSBmdW5jdGlvbgpcWyBmKHgpPVxmcmFjezF9e1xzcXJ0ezJccGkgXHNpZ21hfX1lXnstXGZyYWN7KHgtXG11KV4yfXsyXHNpZ21hfX1cXQp3aGVyZSAkXG11JCAocHJvbm91bmNlZCBhcyAibXUiKSBpcyB0aGUgX19tZWFuX18gYW5kICRcc2lnbWEkIChwcm9ub3VuY2VkIGFzICJzaWdtYSIiKSBpcyB0aGUgX19zdGFuZGFyZCBkZXZpYWl0b25fXyBvZiB0aGUgZGlzdHJpYnV0aW9uLgoKCiMjIEV4YW1wbGUgMQoKKiBUaGUgX19zdGFuZGFyZF9fIG5vcm1hbCBkaXN0cmlidXRpb24gaXMgdGhlIG9uZSB3aGVyZSAkXG11PTAkIGFuZCAkXHNpZ21hPTEkLCBhbmQgaXMgc2hvd24gaW4gdGhlIGdyYXBoIGJlbG93CgpgYGB7cn0KWDwtc2VxKC01LDUsbGVuPTIwMSkgI0NyZWF0ZSB0aGUgeC1heGlzIGJldHdlZW4gLTUgYW5kICs1ClA8LWRub3JtKFgsbWVhbj0wLHNkPTEpICMgRXZhbHVhdGUgdGhlIE5vcm1hbCBEaXN0cmlidXRpb24gZnVuY3Rpb24gb3ZlciB0aGUgeC1heGlzCnBsb3QoWCxQLHR5cGU9J2wnLGx3ZD0yLGNvbD0nc3RlZWxibHVlJykgIyBQbG90IHRoZSBQcm9iYWJpbGl0eSBhbG9uZyB0aCB4LWF4aXMKCmBgYAoqIFRoZSBsaW5lcyBvZiB0aGlzIGNlbGwgaGF2ZSB0aGUgZm9sbG93aW5nIGZ1bmN0aW9uczoKICAgIAoxLiBfX1g8LXNlcSgtNSw1LGxlbj0yMDApX18gVGhpcyBjcmVhdGVzIGEgIHNlcXVlbmNlIG9mICR4JC12YWx1ZXMsIHdoaWNoIHdpbGwgZm9ybSB0aGUgaG9yaXpvbnRhbCBheGlzLiBUaGVzZSB2YWx1ZXMgc3RhcnQgYXQgLTUsIGFuZCBzdG9wIGF0ICs1LCBhbmQgdGhlIHNlcXVlbmNlIGhhcyAyMDAgcG9pbnRzIGFsdG9nZXRoZXIuCiAgICAKYGBge3J9ClggIApgYGAKICAgIAoyLiBfX1A8LWRub3JtKFgsbWVhbj0wLHNkPTEpX18gVGhpcyBldmFsdWF0ZXMgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24gd2l0aCBfX21lYW49MF9fIGFuZCBfX3N0YW5kYXJkIGRldmlhdGlvbiA9IDFfXy4gV2l0aCBfX21lYW49MF9fIHRoaXMgbWVhbnMgdGhlIHBlYWsgb2YgdGhlIGN1cnZlIGlzIGF0ICR4PTAkLiBUaGUgJHNkPTEkIGNvbW1hbmQgZGV0ZXJtaW5lcyBob3cgc3ByZWFkIG91dCB0aGUgZ3JhcGggaXMsIHRoZSBsYXJnZXIgX19zZF9fIHRoZSBtb3JlIHNwcmVhZCBvdXQgdGhlIGdyYXBoLgogICAKMy4gVGhlIGxhc3QgbGluZSBpbnN0cnVjdCBfX1JfXyB0byBwbG90IF9fWF9fIG9uIHRoZSBob3Jpem9udGFsIGF4aXMgYW5kIF9fUF9fIG9uIHRoZSB2ZXJ0aWNhbCBheGlzLiBUaGUgYXJndW1lbnQgX190eXBlPSdsJ19fIGluc3RydWN0cyBfX1JfXyB0byBwbG90IHRoZSBjdXJ2ZSBhcyBhIGxpbmUsIF9fbHdkPTJfXyBpbmRpY2F0ZXMgYSBfX2xpbmV3aWR0aF9fIG9mIDIgYW5kIF9fY29sPSdzdGVlbGJsdWUnX18gIGluZGljYXRlcyB0aGUgX19jb2xvdXJfXyB0byBwbG90IHRoZSBjdXJ2ZS4gCgoKIyMgRXhlcmNpc2UgMQoKUGxvdCB0aGUgbm9ybWFsIGRpc3JpYnV0aW9uIHdpdGggJFxtdT00JCBhbmQgJFxzaWdtYT0yLjE1JC4gTm90ZSB0aGF0IHlvdSB3aWxsIGhhdmUgdG8gcmUtZGVmaW5lIGFuIGFwcHJvcHJpYXRlIF9fWF9fLWludGVydmFsIGZvciB0aGlzIHBsb3QgYWxzby4gQSBjb252aWVudCB3YXkgdG8gZG8gdGhpcyBzbyB0aGF0IHlvdXIgcGxvdCBsb29rcyBzeW1tZXRyaWMgaXMgdG8gc2V0IApcW1xtYXRoYmZ7WD1cdGV4dHtzZXF9KFxtdS01KlxzaWdtYSxcbXUrNSpcc2lnbWEpfVxdCmFuZCBfX2RvIG5vdF9fIGZvcmdldCB0byBpbmNsdWRlICogd2hlbiB5b3Ugd2FudCB0byBkZW5vdGUgbXVsdGlwbGljYXRpb24uCgojIEludGVycHJldGF0aW9uIG9mIHRoZSBub3JtYWwgY3VydmUKKiBXaGVuICR4JCBpcyBfX25vcm1hbGx5IGRpc3RyaWJ1dGVkX18gd2l0aCBtZWFuICRcbXUkIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gJFxzaWdtYSQsIHRoZW4gdGhlIF9fcHJvYWJpbGl0eV9fIHRoYXQgJHgkIGxpZXMgYmV0d2VlbiB0aGUgdmFsdWVzICR4XzEkIGFuZCAkeF8yJCBpcyB0aGUgX19hcmVhX18gdW5kZXIgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24gY3VydmUsIGJldHdlZW4gdGhlc2UgdHdvIHZhbHVlcy4KCiogQW4gaW1wcm90YW50IGZlYXR1cmUgb2YgZXZlcnkgbm9ybWFsIGRpc3RyaWJ1dGlvbiBjdXJ2ZSBpcyB0aGUgdGhlIF9fdG90YWwgYXJlYV9fIGJlbmVhdGggdGhlIGN1cnZlIGlzIGFsd2F5cyBlcXVhbCB0byAxLgoKCiMjIEV4YW1wbGUgMgpJbGx1c3RyYXRlIHRoZSBwcm9iYWJpbGl0eSBmb3IgJHgkIGluIHRoZSBpbnRlcnZhdmwgJC0yXGxlcSB4XGxlcSAxJCBpbiB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aXRoICRcbXU9MCQgYW5kICRcc2lnbWE9MSQuIENhbGN1bGF0ZSB0aGlzIHByb2FiaWxpdHkuCgpgYGB7cn0KIyBQYXJ0IDEuIFBsb3QgdGhlIG5vcm1hbCBjdXJ2ZSBhZ2FpbiAtIFNlZSBFeGFtcGxlIDEKWDwtc2VxKC01LDUsbGVuPTIwMSkKUDwtZG5vcm0oWCxtZWFuPTAsc2Q9MSkKcGxvdChYLFAsdHlwZT0nbCcsbHdkPTIsY29sPSdzdGVlbGJsdWUnKQoKIyBQYXJ0IDIuIFNoYWRlIHRoZSByZXF1aXJlZCBhcmVhLgpYMT1zZXEoLTIsMSxsZW5ndGg9MjAxKSAjIFRoZSBpbnRlcnZhbCAtNTx4PDUKUDE9ZG5vcm0oWDEsbWVhbj0wLHNkPTEpCnBvbHlnb24oYygtMixYMSwxKSxjKDAsUDEsMCksY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsYWxwaGEuZj0wLjMpLGJvcmRlcj1OQSkKYGBgCgoqIFRoZSBjb2RlIGluIHRoZSBjZWxsIGFib3ZlIGhhcyB0aGUgZm9sbG93aW5nIG1lYW5pbmc6CgoxLiBfX1BhcnQgMV9fIFRoaXMgY29kZSBoYXMgYWxyZWR5IGJlZW4gZXhwbGFpbmVkIGluIF9fRXhhbXBsZSAxX18KICAgIAoyLiBfX1BhcnQgMl9fIFdlIGNyZWF0ZSBhIG5ldyBfX3gxX18gYXhpcyBiZXR3ZWVuIF9fLTVfXyBhbmQgX18tMV9fLiBXZSBjcmVhdGUgdGhlIGNvcnJlc3BvbmRpbmcgX195LXZhbHVlc19fIHVzaW5nIHRoZSBfX2Rub3JtKClfXyBmdW5jaXRvbiBhcHBsaWVkIHRvIHRoZSBpbnRydmFsIF9feDFfXy4gX19wb2x5Z29uKGMoLTUseF8xLC0xKSxjKDAseTEsMCkpIGluZGljYXRlcyB0aGF0IHRoZSBhcmVhIGJldHdlZW4gX18tNV9fIGFuZCBfXy0xX18gb24gdGhlIF9feF9fLWF4aXMgYW5kIGJldHdlZW4gX18wX18gYW5kIHRoZSBjb3JyZXNwb25naW5nIHZhbHVlcyBvZiBfX3kxX18gc2hvdWxkIGJlIGZpbGxlZCBpbi4gICAgICAKICAgIAozLiBfX2NvbD1hZGp1c3Rjb2xvcigiY29ybmZsb3dlcmJsdWUiLGFscGhhLmY9MC4zKV9fIGluZGljYXRlcyB0aGUgZmlsbCBjb2xvciBhbmQgdGhlIHRyYW5zcGFyZW5jZXkgX19hbHBoYV9fIG9mIHRoZSBmaWxsaW5nLiBUaGUgc21hbGxlciB0aGUgdmFsdWUgb2YgX19hbHBoYV9fIHRoZSBtb3JlIHRyYW5zcGFyZW50IHRoZSBmaWxsaW5nLCB3aGVyZSBfX2FscGhhX18gc2hvdWxkIGFsd2F5cyBiZSBiZXR3ZWVuIF9fMF9fIGFuZCBfXzFfXy4KCgojIFByb2JhYmlsaXRpZXMKKiBUaGUgcHJvYmFiaWxpdHkgdGhhdCAkeCQgbGllcyBiZXR3ZWVuICQtXGluZnR5JCBhbmQgJC0xJCBpcyBmb3VuZCB1c2luZyB0aGUgZnVuY3Rpb24gX19kbm9ybSgpX18KCmBgYHtyfQpkbm9ybSgtMSxtZWFuPTAsc2Q9MSkKYGBgCgoqIFRoZSBwcm9iYWJpbGl0eSB0aGF0ICR4JCBsaWVzIGJldHdlZW4gJC1caW5mdHkkIGFuZCAkMiQgaXMKCmBgYHtyfQpkbm9ybSgyLG1lYW49MCxzZD0xKQpgYGAKCiogVGhlIHRoZSBwcm9iYWJpbGl0eSB0aGF0IF9feF9fIGxpZXMgYmV0d2VlbiBfXy0xX18gYW5kIF9fMl9fIGlzIApgYGB7cn0KZG5vcm0oMixtZWFuPTAsc2Q9MSktZG5vcm0oLTEsbWVhbj0wLHNkPTEpCmBgYAoKKiBUaGlzIGNvcnJlc3BvbmQgdG8gdGhlIHNoYWRlZCBhcmVhIHNob3duIGFib3ZlLgoKIyBDb25maWRlbmNlIEludGVydmFscwoKR2l2ZW4gYSBwb3B1bGF0aW9uLCBhIF9fQ29uZmlkZW5jZSBJbnRlcnZhbCAoQ0kpX18gaXMgYSBtZWFucyBvZiBlc3RpbWF0aW5nIGEgX19wb3B1bGF0aW9uIHN0YXRpc3RpY19fIGZyb20gdGhlIGNvcnJlc3BvbmRpbmcgX19zYW1wbGUgc3RhaXN0aWNfXyB3aXRoIGEgY2VydGFpbiBsZXZlbCBvZiBjb25maWRlbmNlLiBGb3IgZXhhbXBsZSwgd2UgbWF5IHRha2Ugc3VydmV5IGRhdGEgb24gYSBjb2xsZWN0aW9uIG9mIHBlb3BsZSB0byBlc3RpbWF0ZSB0aGUgYXZlcmFnZSBtb3RobHkgc2FsYXJ5IG9mIHRoZSBwZW9wbGUgaW4gdGhlIHN1cnZleS4gVGhlbiBiYXNlZCBvbiB0aGlzIHNhbXBsZSBhdmVyYWdlIHdlIGNhbiBlc3RpbWF0ZSBhIHJhbmdlIGZvciB0aGUgYXZlcmFnZSBzbGFsYXJ5IG9mIGFsbCBwZW9wbGUgaW4gdGhlIHBvcHVsYXRpb24sIHRvIGEgY2VydGFpbiBjb25maWRlbmNlIGxldmVsLiBUaGUgcmFuZ2Ugb2YgcG9zc2libGUgdmFsdWVzIGZvciB0aGUgcG9wdWxhdGlvbiBhdmVyYWdlIGlzIGNhbGxlZCBhIGNvbmZpZGVuY2UgaW50ZXJ2YWwuCgojIyBFeGFtcGxlIDM6IAoKKiBTdXBwb3NlIHdlIHdpc2ggdG8gZGV0ZXJtaW5lIHRoZSBtZWFuIHNhbGFyeSBvZiB0aGUgcG9wdWxhdGlvbiBvZiBhIGNvdW50cnkgd2l0aCBhIGNlcnRhaW4gZGVncmVlIG9mIGNvbmZpZGVuY2UuCgoqIEluIHByYWN0aWNlIGl0IHdvdWxkIGJlIGRpZmZpY3VsdCwgaWYgbm90IGltcG9zc2libGUsIHRvIGNvbGxlY3QgZGF0YSBvbiB0aGUgc2FsYXJ5IG9mIGV2ZXJ5Ym9keSBmcm9tIHRoZSBwb3B1bGF0aW9uLgoKKiBJbnN0ZWFkLCB3ZSBtYXkgY29sbGVjdCBzYWxhcnkgZGF0YSBmcm9tIG51bWVyb3VzIHNhbXBsZXMgb2YgcGVvcGxlIGZyb20gdGhlIHBvcHVsYXRpb24sIGFuZCB0aGVuIGdldCB0aGUgbWVhbiBzYWxhcnkgZm9yIGVhY2ggb2YgdGhlc2Ugc2FtcGxlcy4KCiogRm9yIGVhY2ggc2FtcGxlLCB0aGUgX19zYW1wbGUgbWVhbl9fIHdvdWxkIGJlIHNwcmVhZCB3aXRoIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiwgd2hvc2Ugc3RhbmRhcmQgZGV2aWF0aW9uIGFuZCBtZWFuIHdvdWxkIGJlIGNsb3NlIHRvIHRoZSBtZWFuIG9mIHRoZSBvdmVyYWxsIHBvcHVsYXRpb24uCgoqIFdlIGxldCAkXGJhcnt4fSQgZGVub3RlIHRoZSBtZWFuIHNhbGFyeSBmcm9tIG9uZSBvZiB0aGVzZSBzYW1wbGVzLCBhbmQgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgc2FtcGxlIGJlICRcc2lnbWEkICh0aGlzIG1lYXN1cmVzIGhvdyBtdWNoIHRoZSBtZWFucyBhcmUgc3ByZWFkIGFib3V0IHRoZSB0cnVlIG1lYW4pLgoKKiBXZSBjYW4gbm93IHNheSB0aGF0IHRoZSB0cnVlIHBvcHVsYXRpb24gbWVhbiBsaWVzIGluIHRoZSBpbnRlcnZhbApcW1xiYXJ7eH1ccG0gel97XGZyYWN7XGFscGhhfXsyfX1cZnJhY3tcc2lnbWF9e1xzcXJ0e259fSxcXQp3aGVyZSAkbiQgaXMgdGhlIHNpemUgb2YgdGhlIHNhbXBsZSBmb3Igd2hpY2ggdGhlIG1lYW4gJFxiYXJ7eH0kIHdhcyBjYWxjdWxhdGVkLgoKKiBUaGUgcGFyYW1ldGVyICRcYWxwaGEkIGlzIGNhbGxlZCB0aGUgX19jb25maWRlbmNlIHBhcmFtZXRlcl9fIGFzc29jaWF0ZWQgd2l0aCB0aGUgY29uZmlkZW5jZSBsZXZlbCwgYW5kIHRoZSBudW1iZXIgJHpfe1xmcmFje1xhbHBoYX17Mn19JCBpcyB0aGUgX196LXNjb3JlX18gYXNzb2NpYXRlZCB3aXRoIHRoZSBwYXJhbWV0ZXIgJFxmcmFje1xhbHBoYX17Mn0kLgoKKiBGcm9tIGEgc2FtcGxlIG9mIDEwMCBwZW9wbGUsIHdlIGZpbmQgdGhhdCB0aGUgbG93ZXN0IHNhbGFyeSBmcm9tIHRoZSBzYW1wbGUgaXMgRVVSIDE1MDAwIGFuZCB0aGUgaGlnaGVzdCBpcyBFVVIgNTUwMDAsIHdpdGggYSBtZWFuIHNhbGFyeSBvZiBFVVIgMzUwMDAgYW5kIGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIEVVUiAyNTAwLgoKKiBXZSBjYW4gcGxvdCB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBmb3IgdGhpcyBkYXRhIGFzIGZvbGxvd3M6CgogIDEuIFdlIGNyZWF0ZSBhIHNhbXBsZSBzaXplIGJldHdlZW4gMTUwMDAgYW5kIDU1MDAwICh0aGUgc2FtcGxlIHJhbmdlKSwgd2l0aCBzdGVwIHNpemUgNTAuIFdlIGNhbGwgdGhpcyBzYW1wbGUgZGF0YSBfX1NhbXBsZTFfXwogIAogIDIuIFdlIHVzZSB0aGUgX19kbm9ybSgpX18gZnVuY3Rpb24gdG8gaW5kaWNhdGUgdGhhdCB0aGUgZGF0YSBpbiBfX1NhbXBsZTFfXyBpcyBfX25vcm1hbGx5IGRpc3RyaWJ1dGVkIGFib3V0IHRoZSBtZWFuX18gd2hlcmUgdGhlIG1lYW4gaXMgMzUwMDAgYW5kIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gaXMgMjUwMC4KICAKICAzLiBXZSBwbG90IHRoZSBkaXN0cmlidXRpb24gdXNpbmcgdGhlIHVzdWFsIF9fcGxvdCgpX18gZnVuY3Rpb24sIHdpdGggX19TYW1wbGUxX18gb24gdGhlIHgtYXhpcyBhbmQgX19EYXRhMV9fIG9uIHRoZSB5LWF4aXMuCiAgCmBgYHtyfQpTYW1wbGUxPC1zZXEoMTUwMDAsNTUwMDAsIGJ5PTUwKQpEYXRhMSA8LSBkbm9ybShTYW1wbGUxLG1lYW49MzUwMDAsIHNkPTI1MDApCnBsb3QoU2FtcGxlMSxEYXRhMSx5bGFiPSJSZWwuIEZyZXEuIix4bGFiPSJTYWxhcmllcyAoRVVSKSIsdHlwZT0ibCIsbHdkPTIsY29sPSJyZWQiKQpgYGAKIyMgQSA5MCUgQ29uZmlkZW5jZSBJbnRlcnZhbAoKKiBTdXBwb3NlIHdlIHdpc2ggdG8gZGV0ZXJtaW5lIHRoZSBfX2F2ZXJhZ2VfXyBzYWxhcnkgdmFsdWUgYXQgYSBjb25maWRlbmNlIGxldmVsIG9mICBfXzkwJV9fLgoKKiBUaGlzIHdvdWxkIGNvcnJlc3BvbmQgdG8gdGhlIHNhbGFyeSBpbnRlcnZhbCB3aGljaCBnaXZlcyA5MCUgb2YgdGhlIGFyZWEgYmVuZWF0aCB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBjdXJ2ZSBhYm92ZS4KCiogVGhpcyBudW1iZXIgY2FuIGJlIGNhbGN1bGF0ZWQgdXNpbmcgYSBub3JtYWwgZGlzdHJpYnV0aW9uIHRhYmxlLCBhbmQgZmluZGluZyB0aGUgJHpfe1xhbHBoYX0kLXNjb3JlIGNvcnJlc3BvbmRpbmcgdG8gJFxhbHBoYT0xLTAuOTA9MC4xJC4KCmBgYHtyfQojIFBhcnQgMS4gUGxvdCB0aGUgbm9ybWFsIGN1cnZlIGFnYWluIC0gU2VlIEV4YW1wbGUgMQpaMDwtc2VxKC01LDUsbGVuPTIwMCkKSDA8LWRub3JtKFowLG1lYW49MCxzZD0xKQpwbG90KFowLEgwLHR5cGU9J2wnLGx3ZD0yLGNvbD0nc3RlZWxibHVlJyxtYWluPSdUaGUgOTAlIGNvbmZpZGVuY2UgaW50ZXJ2YWwnKQoKIyBQYXJ0IDIuIFNoYWRlIHRoZSByZXF1aXJlZCBhcmVhLgp4MT1zZXEoLXFub3JtKDAuOTUpLHFub3JtKDAuOTUpLGxlbmd0aD0yMDApCnkxPWRub3JtKHgxLG1lYW49MCxzZD0xKQpwb2x5Z29uKGMoLXFub3JtKDAuOTUpLHgxLHFub3JtKDAuOTUpKSxjKDAseTEsMCksY29sPWFkanVzdGNvbG9yKCJjb3JuZmxvd2VyYmx1ZSIsYWxwaGEuZj0wLjMpLGJvcmRlcj1OQSkKYGBgCgoqIFdoZW4gd2UgbG9vayBmb3IgYSBjb25maWRlbmNlIGludGVydmFsIG9mIDkwJSB3ZSBhcmUgbG9va2luZyBmb3IgdGhlIHZhbHVlcyBvZiAkeiQgc3VjaCB0aGF0IDkwJSBvZiB0aGUgYXJlYSBiZW5lYXRoIHRoZSBjdXJ2ZSwgYmV0d2VlbiAkLXpfe1xmcmFje1xhbHBoYX17Mn19JCBhbmQgJHpfe1xmcmFje1xhbHBoYX17Mn19JC4KCiogSXQgYWxzbyBtZWFucyB3ZSBhcmUgbG9va2luZyBmb3IgdGhlICR6JC12YWx1ZXMgd2hpY2ggd2lsbCBleGNsdWRlIDUlIG9mIHRoZSBhcmVhIGluIGVhY2ggdGFpbCwgdGhhdCBpcyB3ZSBhcmUgbG9va2luZyBmb3IgdGhlICR6JC12YWx1ZXMgZm9yIGVhY2ggb2YgdGhlIGRhc2hlZCBsaW5lIGluIHRoZSBwbG90IGJlbG93OiAKCgpgYGB7cn0KU3RhbmRhcmQ8LXNlcSgtNCw0LGJ5PTAuMDAxKQpTdGFuZGFyZERhdGE8LWRub3JtKFN0YW5kYXJkLG1lYW49MCxzZD0xKQpwbG90KFN0YW5kYXJkLFN0YW5kYXJkRGF0YSx5bGFiPSJSZWwuIEZyZXEuIiwgeGxhYj0ieiIsIHR5cGU9ImwiLCBsd2Q9Mixjb2w9InJlZCIpCnNlZ21lbnRzKC1xbm9ybSgwLjkpLDAsLXFub3JtKDAuOSksZG5vcm0oLXFub3JtKDAuOSksbWVhbj0wLHNkPTEpLGx3ZD0yLjUsbHR5PTIpCnNlZ21lbnRzKHFub3JtKDAuOSksMCxxbm9ybSgwLjkpLGRub3JtKHFub3JtKDAuOSksbWVhbj0wLHNkPTEpLGx3ZD0yLjUsbHR5PTIpCgpgYGAKKiA5MCUgb2YgdGhlIGFyZWEgYmVuZWF0aCB0aGUgY3VydmUgaXMgY29udGFpbmVkIF9fYmV0d2Vlbl9fIHRoZSB0d28gZGFzaGVkIGxpbmVzLgoKKiA1JSBvZiB0aGUgYXJlYSBpcyBpbiBlYWNoIHRhaWwgdG8gdGhlIGxlZnQgYW5kIHJpZ2h0LgoKKiBJdCBhbHNvIG1lYW5zIHRoYXQgdGhlIGFyZWEgYmVuZWF0aCB0aGUgY3VydmUgY29udGFpbmluZyB0aGUgbGVmdCB0YWlsIGFuZCB0aGUgbWlkZGxlIHBvcnRpb24gaXMgOTUlCgoqIFRvIGZpbmQgdGhlICR6JC12YWx1ZSBjb3JyZXNwb25kaW5nIHRvIHRoaXMgOTUgJSBpbiBfXypSKl9fIHdlIGNhbiB1c2UgdGhlIF9fcW5vcm0oKV9fIGZ1bmN0aW9uIGFzIGZvbGxvd3M6CmBgYHtyfQp6OTA9cW5vcm0oMC45NSkKejkwCmBgYAoKCiogSW4gdGhlIHBsb3QgYWJvdmUgdGhpcyBtZWFucyB0aGF0IDk1JSBvZiB0aGUgYXJlIGJlbmVhdGggdGhlIGN1cnZlIGlzIGJldHdlZW4gJHo9LVxpbmZ0eSQgYW5kICQxLjY0NDg1JC4gCgoqIEl0IGFsc28gbWVhbnMgdGhhdCAgX185MCVfXyBvZiB0aGUgYXJlYSBsaWVzLCBmcm9tICR6PS0xLjY0NDg1NCQgdG8gJHo9LTEuNjQ0ODU0JC4KCiogRm9yIHRoZSBwdXJwb3NlcyBvZiBvdXIgc2FsYXJ5IHN1cnZleSBhYm92ZSwgaXQgYWxzbyBtZWFucyAKXFt6X3tcZnJhY3tcYWxwaGF9ezJ9fT0xLjY0NDg0NVxdCgoqIEluIHRlcm1zIG9mIG91ciBzdXJ2ZXkgd2UgYXJlIGFsc28gOTAlIGNlcnRhaW4gdGhhdCB0aGUgX19tZWFuIHBvcHVsYXRpb24gc2FscnlfXyBsaWVzIGluIHRoZSByYW5nZQoKYGBge3J9Cmxvd2VyX2JvdW5kPTM1MDAwLXo5MCoyNTAwL3NxcnQoMTAwKQp1cHBlcl9ib3VuZD0zNTAwMCt6OTAqMjUwMC9zcXJ0KDEwMCkKbG93ZXJfYm91bmQKdXBwZXJfYm91bmQKYGBgCiMjIyBXZSBhcmUgOTAlIGNvbmZpZGVudCB0aGF0IHRoZSBhdmFyZWFnZSBzYWxhcnkgb2YgdGhlIG92ZXJhbGwgcG9wdWxhdGlvbiBsaWVzIGluIHRoZSByYW5nZSDigqwzNCw1ODguNzkgdG8g4oKsMzUsNDExLjIxLgoKSW4gdGVybXMgb2Ygb3VyIG5vcm1hbCBkaXN0cmlidXRpb24gcGxvdCB0aGlzIG1lYW5zLCB3ZSBhcmUgOTAlIGNlcnRhaW4gdGhlIF9fbWVhbiBwb3B1bGF0aW9uIHNhbGFyeV9fIGxpZXMgYmV0d2VlbiB0aGUgdHdvIGRhc2hlZCBibHVlIGxpbmVzLgpgYGB7cn0KU2FtcGxlMTwtc2VxKDE1MDAwLDU1MDAwLCBieT01MCkKRGF0YTEgPC0gZG5vcm0oU2FtcGxlMSxtZWFuPTM1MDAwLCBzZD0yNTAwKQpwbG90KFNhbXBsZTEsRGF0YTEseWxhYj0iUmVsLiBGcmVxLiIseGxhYj0iU2FsYXJpZXMgKEVVUikiLHR5cGU9ImwiLGx3ZD0yLGNvbD0icmVkIikKYWJsaW5lKHY9bG93ZXJfYm91bmQsbHdkPTIsbHR5PTIsY29sPSJibHVlIikKYWJsaW5lKHY9dXBwZXJfYm91bmQsbHdkPTIsbHR5PTIsY29sPSJibHVlIikKYGBgCgoKIyMgRXhlcmNpc2UgMgoKQSBjb21wYW55IHdpc2hlcyB0byBkZXRlcm1pbmUgdGhlIGNvc3QgYXNzb2NpYXRlZCB3aXRoIHByb3ZpZGluZyBoZWFsdGggaW5zdXJhbmNlIGZvciBhbGwgb2YgaXRzIGVtcGxveWVlcy4gVGhlIGNvbXBhbnkgYXNrZWQgYSBzYW1wbGUgb2YgMzUgZW1wbG95ZWVzIGhvdyBtdWNoIHRoZXkgY3VycmVudGx5IHBheSBhbm51YWxseSBmb3IgaGVhbHRoIGluc3VyYW5jZS4gVGhlIGRhdGEgb2J0YWluZWQgcmV2ZWFsZWQgYSBzYW1wbGUgbWVhbiBwcmVtaXVtIG9mIEVVUjYzNSB3aXRoIGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIEVVUjY3LiBVc2luZyB0aGlzIGRhdGEgYW5zd2VyIHRoZSBmb2xsb3dpbmcKCjEuIEZpbmQgdGhlIDkwJSwgOTUlLCA5NiUgYW5kIDk5JSBjb25maWRlbmNlIGludGVydmFscyBmb3IgdGhlIGF2ZXJhZ2UgYW1vdW50IHNwZW50IGJ5IGFsbCBjdXN0b21lcnMuCjIuIFBsb3QgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGZvciB0aGlzIGRhdGEgc2V0IHNob3dpbmcgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9idGFpbmVkLgoKIyMgRXhlcmNpc2UgMwoKVGhlIG1lYW4gbnVtYmVyIG9mIGVtYWlscyByZWNlaXZlZCBieSBlbXBsb3llZXMgYXQgYSBjb21wYW55IHdhcyBtZWFzdXJlZCBvbiBhIGFtcGxlIG9mIDU4IGVtcGxveWVlcy4gVGhlIHNhbXBsZSBtZWFuIHdhcyBmb3VuZCB0byBiZSAyMSBlbWFpbHMgcGVyIGRheSB3aXRoIGEgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIDkuIFVzaW5nIHRoaXMgZGF0YSBhbnN3ZXIgdGhlIGZvbGxvd2luZwoKMS4gRmluZCB0aGUgOTAlLCA5NCUsIDk2JSBhbmQgOTklIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciB0aGUgYXZlcmFnZSBhbW91bnQgc3BlbnQgYnkgYWxsIGN1c3RvbWVycy4KMi4gUGxvdCBhIG5vcm1hbCBkaXN0cmlidXRpb24gZm9yIHRoaXMgZGF0YSBzZXQgc2hvd2luZyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgb2J0YWluZWQuCgoKIyBTYW1wbGVzLCBNZWFucyBhbmQgU3RhbmRhcmQgRGV2aWF0aW9ucwoKCiMjIFRoZSBNZWFuCgpHaXZlbiBhIGRhdGEgc2V0IHdlIGNhbiBjYWxjdWxhdGUgdGhlIG1lYW4gYW5kIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhlIGRhdGEtc2V0IHVzaW5nIHRoZSBmdW5jdGlvbnMgX19tZWFuKClfXyBhbmQgX19zZCgpX18uIAoKCkdpdmVuIGEgZGF0YSBzZXQgb2Ygc2l6ZSAkbiQsIHdpdGggZGF0YSB2YWx1ZXMgJHhfMSx4XzIsXGxkb3RzLHhfbiQsIHRoZSBtZWFuIG9mIHRoZSBkYXRhIHNldCBpcyBnaXZlbiBieQpcWwpcYmFye3h9PVxmcmFje1xkaXNwbGF5c3R5bGV7XHN1bV97aT0xfV57bn19eF97aX19e059LgpcXQpUaGlzIGNhbiBiZSBldmFsdWF0ZWQgaW4gX19SX18gdXNpbmcgdGhlIGZ1bmN0aW9uIF9fbWVhbigpX186CgojIyBFeGFtcGxlIDIKClN1cHBvc2UgdGhlIGRhdGEgZnJvbSBhIHN1cnZleSBpcyBnaXZlbiBieSB0aGUgZGF0YSBzZXQKXFsKMS4zLC00LjIsMS41NSw2Ljc4LDQuNSwzLjIxLCA1Ljg5LDcuMzQsLTYuODgsLTcuOQpcXQpDcmVhdGUgYSBkYXRhIHN0cnVjdHVyZSBpbiBfX1JfXyB0byByZXByZXNlbnQgdGhpcyBkYXRhIHNldC4gVXNlIHRoZSBfX21lYW4oKV9fIGZ1bmN0aW9uIHRvIGV2YWx1YXRlIHRoZSBtZWFuIG9mIHRoZSBkYXRhIHNldC4KCmBgYHtyfQpkYXRhc2V0MjwtYygxLjMsLTQuMiwxLjU1LDYuNzgsNC41LDMuMjEsIDUuODksNy4zNCwtNi44OCwtNy45KQptZWFuKGRhdGFzZXQyKQpgYGAKKiBIZW5jZSB0aGUgbWVhbiBpcwpcW1xiYXJ7eH09MS4xNTlcXQoKIyMgVGhlIFN0YW5kYXJkIERldmlhdGlvbgoKR2l2ZW4gYSBkYXRhIHNldCB3ZSBjYW4gY2FsY3VsYXRlIHRoZSBtZWFuIGFuZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBkYXRhLXNldCB1c2luZyB0aGUgZnVuY3Rpb25zIF9fbWVhbigpX18gYW5kIF9fc2QoKV9fLgoKR2l2ZW4gYSBkYXRhIHNldCBvZiBzaXplICRuJCwgd2l0aCBkYXRhIHZhbHVlcyAkeF8xLHhfMixcbGRvdHMseF9uJCwgdGhlIG1lYW4gb2YgdGhlIGRhdGEgc2V0IGlzIGdpdmVuIGJ5ClxbCnM9XGZyYWN7XGRpc3BsYXlzdHlsZXtcc3VtX3tpPTF9XntufX0oeF97aX0tXGJhcnt4fSleMn17Ti0xfS4KXF0KVGhpcyBjYW4gYmUgZXZhbHVhdGVkIGluIF9fUl9fIHVzaW5nIHRoZSBmdW5jdGlvbiBfX21lYW4oKV9fOgoKIyMgRXhhbXBsZSA0CgpFdmFsdWF0ZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSBkYXRhIHNldCBpbiBfX0V4YW1wbGUgMl9fIHVzaW5nIHRoZSBfX3NkKClfXyBmdW5jdGlvbi4KYGBge3J9CnNkKGRhdGFzZXQyKQpgYGAKCiogSGVuY2UgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBpcyAKXFsKcz0gNS42MDg4NjUKXF0KCgojIyBFeGFtcGxlIDUKVGhlIGluZmxhdGlvbiByYXRlIGluIElyZWxhbmQgYmV0d2VlbiB0aGUgeWVhcnMgMTk5MiBhbmQgMjAxNiBpcyBnaXZlbiBpbiB0aGUgZGF0YSBmaWxlIF9fSXJlbGFuZEluZmxhdGlvbi5jc3ZfXyhfU291cmNlOl8gW1dvcmxkIEJhbmtdKGh0dHA6Ly9kYXRhYmFuay53b3JsZGJhbmsub3JnL2RhdGEvaG9tZS5hc3B4KSkuICBXZSB3aWxsIGltcG9ydCB0aGlzIGludG8gX19SX18gdXNpbmcgdGhlIHVzdWFsIGNvbW1hbmQgX19yZWFkLmNzdihmaWxlLmNob29zZSgpKV9fIGFzIGEgZGF0YSBzdHJ1Y3R1cmUuIFVzaW5nIHRoaXMgZGF0YSBzdHJ1Y3R1cmUgd2Ugd2FudCB0byBhbnN3ZXIgdGhlIGZvbGxvd2luZzoKCjEuIEZpbmQgdGhlIG1lYW4gaW5mbGF0aW9uIHJhdGUgYmV0d2VlbiB0aGUgeWVhcnMgMTk5MiBhbmQgMjAxNgoyLiBGaW5kIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgdGhpcyBkYXRhIHNldAozLiBGaW5kIHRoZSBudW1iZXIgb2YgZGF0YSBwb2ludHMgaW4gdGhpcyBkYXRhIHNldAo0LiBVc2luZyB0aGVzZSB0aHJlZSB2YWx1ZXMsIGZpbmQgdGhlIHJhbmdlIG9mIHBvc3NpYmxlIHZhbHVlcyBmb3IgdGhlIGF2ZXJhZ2UgaW5mbGF0aW9uIHJhdGUgaW4gSXJlbGFuZCBvdmVyIGFsbCB5ZWFycyB3aXRoIDk1JSBjb25maWRlbmNlCjUuIFBsb3QgdGhlIGluZmxhdGlvbiBkYXRhIGFzIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4KCgojIyMgSW1wb3J0aW5nIHRoZSBEYXRhCgpgYGB7cn0KSW5mbGF0aW9uRGF0YTwtcmVhZC5jc3YoIklyZWxhbmRJbmZsYXRpb24uY3N2IikKSW5mbGF0aW9uRGF0YQpgYGAKIyMjIENyZWF0aW5nIHRoZSBEYXRhIFN0cnVjdHVyZQpgYGB7cn0KSW5mbGF0aW9uPC1JbmZsYXRpb25EYXRhJEluZmxhdGlvbi5SYXRlLi4KSW5mbGF0aW9uCmBgYAojIyMgUGFydCAxIC0gVGhlIE1lYW4gSW5mbGF0aW9uCgpgYGB7cn0KeGJhcj1tZWFuKEluZmxhdGlvbikKeGJhcgpgYGAKCgoqIFRoZSBtZWFuIGluZmxhdGlvbiByYXRlIGJldHdlZW4gMTk5MiBhbmQgMjAxNiBpbiBJcmVsYW5kIHdhcyAkXGJhcnt4fT0yLjA3NjE3NCUkCgoKIyMjIFBhcnQgMiAtIFRoZSBTdGFuZGFyZCBEZXZpYXRpb24gCgpgYGB7cn0Kcz1zZChJbmZsYXRpb24pCnMKYGBgCiogVGhlIHN0YW5kYXJkIGRldmlhdGlvbiAgaW4gdGhlIHJhdGUgb2YgaW5mbGF0aW9uIGJldHdlZW4gMTk5MiBhbmQgMjAxNiBpcyAkXHNpZ21hPTIuMTg5OTI2JAoKIyMjIFBhcnQgLSBUaGUgTnVtYmVyIG9mIERhdGEgUG9pbnRzCgpXZSB1c2UgdGhlIF9fbGVuZ3RoKClfXyBmdW5jdGlvbiB0byBkZXRlcm1pbmUgdGhlIG51bWJlciBvZiBkYXRhLXBvaW50cyBpbiBfX0luZmxhdGlvbl9fCmBgYHtyfQpuPWxlbmd0aChJbmZsYXRpb24pCm4KYGBgCiogVGhlcmUgYXJlICRuPTI1JCBkYXRhIHBvaW50cyBpbiB0aGUgZGF0YSBzZXQgX19JbmZsYXRpb25fXwoKIyMjIFBhcnQgNCAtIFRoZSA5MCUgQ29uZmlkZW5jZSBJbnRlcnZhbAoqIFRoZSBjb25maWRlbmNlIHBhcmFtZXRlciAkXGFscGhhJCBpcyBnaXZlbiBieQpcW1xhbHBoYSA9IDEtMC45NT0wLjA1XFJpZ2h0YXJyb3cgXGZyYWN7XGFscGhhfXsyfT0wLjAyNVxdCgoqIFdlIG5vdyB3aXNoIHRvIGZpbmQgdGhlICR6X3tcZnJhY3tcYWxwaGF9ezJ9fSQgd2hpY2ggZ2l2ZXMgYW4gYXJlYSBvZiAkMC45NSswLjAyNT0wLjk3NSQgdW5kZXIgdGhlIGN1cnZlIG9mIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLiBXZSBmaW5kIHRoaXMgJHokLXNjb3JlIHVzaW5nIF9fcW5vcm0oKV9fCgpgYGB7cn0KejA9cW5vcm0oMC45NzUpCnowCmBgYAoKCiogRm9yIHRoZSA5NSUgY29uZmlkZW5jZSBpbnRlcnZhbCwgd2UgaGF2ZSAkel97XGZyYWN7XGFscGhhfXsyfX09MS45NTk5NjQkLiBIZW5jZSB0aGUgdXBwZXIgYW5kIGxvd2VyIGJvdW5kIGZvciB0aGUgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoZSBkYXRhIHNldCBhcmUKCmBgYHtyfQp4bG93ZXI9eGJhci16MCpzL3NxcnQobikKeHVwcGVyPXhiYXIrejAqcy9zcXJ0KG4pCgp4bG93ZXIKeHVwcGVyCmBgYAoKIyMjIyBXZSBhcmUgOTUlIGNlcnRhaW4gdGhhdCB0aGUgbWVhbiBpbmZsYXRpb24gcmF0ZSBmb3IgSXJlbGFuZCBsaWVzIGluIHRoZSBpbnRlcnZhbCAxLjIxNzczOSUgdG8gMi45MzQ2MDklLgoKCiMjIyBQYXJ0IDUgLSBUaGUgTm9ybWFsIERpc3RyaWJ1dGlvbiBQbG90CgpXZSBub3cgcGxvdCBfX1N0YW5kYXJkSW5mbGF0aW9uX18gdG8gZ2l2ZSB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBwbG90OgogIAogIDEuIEZpcnN0IHdlIGNyZWF0ZSBhbiBpbnRlcnZhbCBhcHByb3ByaWF0ZSAgZm9yIGNyZWF0aW5nIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBmb3JtIHRoZSBkYXRhLXNldCBfX0luZmxhdGlvbl9fOgogICAgRm9yIHRoaXMgcGxvdCwgd2Ugd2lsbCBtYWtlIHRoZSBwbG90IHJhbmdlIHN0YXJ0IGF0ICRcYmFye3h9LTVcc2lnbWEkICBhbmQgZW5kIGF0ICRcYmFye3h9KzVcc2lnbWEkLCB3aXRoIGEgc3RlcC1zaXplICAgICAgMC4wMDAxOiAgCmBgYHtyfQpJbnRlcnZhbDE9c2VxKHhiYXItNSpzLHhiYXIrNSpzLGJ5PTAuMDAwMSkKYGBgCiAgMi4gTmV4dCB3ZSBjcmVhdGUgYSBub3JtYWwgZGlzdHJpYnV0aW9uIGZyb20gdGhpcyBkYXRhIHdpdGggbWVhbiBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIGV2YWx1YXRlZCBlYXJsaWVyOgpgYGB7cn0KTm9ybWFsRGlzdEluZmxhdGlvbj1kbm9ybShJbnRlcnZhbDEsIG1lYW49eGJhciwgc2Q9cykKYGBgIAogIDMgTm93IHdlIHBsb3QgX19Ob3JtYWxEaXN0SW5mbGF0aW9uX18gb24gdGhlIHktYXhpcyBhbmQgX19JbnRlcnZhbDFfXyBvbiB0aGUgeC1heGlzOgpgYGB7cn0KcGxvdChJbnRlcnZhbDEsTm9ybWFsRGlzdEluZmxhdGlvbix5bGFiPSJSZWwuIEZyZXEuIix4bGFiPSJJbmZsYXRpb24gUmF0ZSAlIix0eXBlPSJsIixsd2Q9Mixjb2w9InJlZCIpCmFibGluZSh2PXhsb3dlcixsd2Q9MixsdHk9Mixjb2w9ImJsdWUiKQphYmxpbmUodj14dXBwZXIsbHdkPTIsbHR5PTIsY29sPSJibHVlIikKYGBgCiMjIEV4ZXJjaXNlIDQ6IAoKKiBUaGUgZGF0YSBmaWxlIF9fSXJlbGFuZEVtaXNzaW9ucy5jc3ZfXyBjb250YWlucyB0aGUgQ08yIGVtaXNzaW9ucywgaW4gbWV0cmljIHRvbnMgcGVyIGNhcGl0YWwsIG9mIElyZWxhbmQgYmV0d2VlbiAxOTkyIGFuZCAyMDE2LgooX1NvdXJjZV86IFtXb3JsZCBCYW5rXShodHRwOi8vZGF0YWJhbmsud29ybGRiYW5rLm9yZy9kYXRhL2hvbWUuYXNweCkpCgoqIFVzaW5nIHRoZSBkYXRhIGluIHRoaXMgZmlsZSwgY3JlYXRlIGEgZGF0YSBzdHJ1Y3R1cmUgdG8gY2FwdHVyZSB0aGUgbnVtZXJpY2FsIGRhdGEgb3ZlciB0aG9zZSAyNSB5ZWFycy4gCgoqIFVzaW5nIHRoaXMgZGF0YSBzdHJ1Y3R1cmUgYW5zd2VyIHRoZSBmb2xsb3dpbmc6CgoxLiBGaW5kIHRoZSBtZWFuIGluZmxhdGlvbiByYXRlIGJldHdlZW4gdGhlIHllYXJzIDE5OTIgYW5kIDIwMTYKMi4gRmluZCB0aGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoaXMgZGF0YSBzZXQKMy4gRmluZCB0aGUgbnVtYmVyIG9mIGRhdGEgcG9pbnRzIGluIHRoaXMgZGF0YSBzZXQKNC4gVXNpbmcgdGhlc2UgdGhyZWUgdmFsdWVzLCBmaW5kIHRoZSA5MCUgYW5kIDk5JSBjb25maWRlbmNlIGludGVydmFscyBmb3IgdGhlIGF2ZXJhZ2UgQ08yIGVtaXNzaW9ucyBvZiBJcmVsYW5kIG92ZXIgYWxsIHllYXJzLgo1LiBQbG90IHRoZSBpbmZsYXRpb24gZGF0YSBhcyBhIG5vcm1hbCBkaXN0cmlidXRpb24sIGFuZCBpbmRpY2F0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbHMgb24gdGhlc2UgcGxvdHMuCgoKCiMgSW50ZXJwcmV0YXRpb24gb2YgQ29uZmlkZW5jZSBJbnRlcnZhbHMKKiBXZSByZWNvcmQgc29tZSBkYXRhIGFzc29jaWF0ZWQgd2l0aCBhIF9fKnBvcHVsYXRpb24qX18sIGdpdmVuIGluIHRoZSBkYXRhIHNldCBfX1hfXyBiZWxvdzoKYGBge3J9Clg9YygwLjM0LDAuNzcsMC45OCwxLjAzLDEuNDUsMS44NywxLjk5LDIuMTEsMi4yMywyLjI0LDIuODcsMi44OSwyLjk3LDMuMDQsMy40NSwzLjU2LDMuNzcsMy43OSwzLjgxLDMuOTcsNC4xMiw0LjM0LDQuODgsNS4wMSw1LjE2KQpgYGAKCiogT2J2aW91c2x5LCB0aGUgX19wb3B1bGF0aW9uIG1lYW5fXyBpcyBlYXNpbHkgYXZhaWxhYmxlIHRvIHVzIGluIHRoaXMgY2FzZToKYGBge3J9Cm1lYW4oWCkKYGBgCgojIyBTYW1wbGluZyB0aGUgcG9wdWxhdGlvbgoKKiBJbiBtYW55IGNhc2VzIG9mIHByYWN0aWNhbCBpbnRlcmVzdCwgdGhpcyBtZWFuIGlzIG5vdCBhdmFpbGFibGUgdG8gdXMsIGFuZCB0aGUgYmVzdCB3ZSBjYW4gZG8gaXMgZm9ybSBhIF9fY29uZmlkZW5jZSBpbnRlcnZhbF9fIGZvciB0aGlzIG1lYW4uCgoqIFRvIGZvcm0gdGhlc2UgY29uZmlkZW5jZSBpbnRlcnZhbHMsIHdlIHRha2UgX19zYW1wbGVzX18gb2YgdGhlIHBvcHVsYXRpb24gZGF0YS4KCiogVGhpcyBpcyBpbXBsZW1lbnRlZCBpbiBfX1JfXyBhcyBmb2xsb3dzOgpgYGB7cn0Kbj00ICMgc2FtcGxlIHNpemUKTj0xMCAjIG51bWJlciBvZiBzYW1wbGVzClNhbXBsZTwtcmVwbGljYXRlKE4sc2FtcGxlKFgsbikpCmBgYAoqIFdlIGhhdmUgdGFrZW4gX18xMCBTYW1wbGVzX18gd2l0aCBlYWNoIHNhbXBsZSAgaGF2aW5nIF9fNCBkYXRhIHZhbHVlc19fCgpgYGB7cn0KU2FtcGxlCmBgYAoKKiBOb3cgd2Ugd2lzaCB0byB0YWtlIHRoZSBfX21lYW4gb2YgZWFjaCBzYW1wbGVfXywgd2hpY2ggd2UgZG8gYXMgZm9sbG93czoKYGBge3J9Ck0gPC0gbnVtZXJpYyhsZW5ndGggPSBsZW5ndGgoMTpOKSkKZm9yIChpIGluIDE6TikgewogIE1baV0gPC0gbWVhbihTYW1wbGVbLGldKQp9Ck0KYGBgCgoqIENsZWFybHksIHRoZSBtZWFuIG9mIGVhY2ggc2FtcGxlIGRvZXMgbm90IG1hdGNoIHRoZSBtZWFuIG9mIHRoZSBwb3B1bGF0aW9uLgoKCiMjIENvbmZpZGVuY2UgSW50ZXJ2YWxzIGZyb20gdGhlIFNhbXBsZXMKCiogV2Ugbm93IGZvcm0gdGhlIF9fNjAlIENvbmZpZGVuY2UgSW50ZXJ2YWxfXyBhc3NvY2lhdGVkIHdpdGggZWFjaCBzYW1wbGUgbWVhbiwgYW5kIHRvIGRvIHNvIHdlIG5lZWQgdGhlIF9feiBzY29yZV9fIGNvcnJlc3BvbmRpbmcgdG8gdGhlIDgwdGggcGVyY2VudGlsZToKCmBgYHtyfQp6PC1xbm9ybSgwLjgwLG1lYW49MCxzZD0xKQp6CmBgYAoKKiBOZXh0IHdlIGZvcm0gdGhlIF9fc3RhbmRhcmQgZXJyb3JfXyBhc3NvY2lhdGVkIHdpdGggdGhlIHBvcHVsYXRpb24gYW5kIHRoZSBzYW1wbGVzOgoKMS4gVGhlIF9fc3RhbmRhcmQgZGV2aWF0aW9uX18gb2YgdGhlIHBvcHVsYXRpb24gaXMgCmBgYHtyfQpzaWdtYTwtc3FydChzdW0oKFgtbWVhbihYKSleMikvbGVuZ3RoKFgpKQpzaWdtYQpgYGAKV2UgZG8gdGhpcyBiZWNhdXNlIHRoZSBmdW5jdGlvbiBfX3NkKClfXyB1c2VzIHRoZSBmb3JtdWxhIGZvciBzYW1wbGUgc3RhbmRhcmQgZGV2aWF0aW9uLgoKMi4gVGhlIF9fc3RhbmRhcmQgZXJyb3JfXyBpcyAKYGBge3J9ClNFPC1zaWdtYS9zcXJ0KG4pClNFCmBgYAppLmUuIHRoZSBwb3B1bGF0aW9uIHN0YW5kYXJkIGRldmlhdGlvbiBkaXZpZGVkIGJ5IHRoZSBzYW1wbGUgc2l6ZS4KCgozLiBUaGUgX19sb3dlciBib3VuZGFyaWVzX18gb2YgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFyZSBub3c6CmBgYHtyfQpNTDwtTS16KlNFCk1MCmBgYAoKVGhlIF9fdXBwZXIgZW5kc19fIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFscyBhcmU6CmBgYHtyfQpNVTwtTSt6KlNFCk1VCmBgYAoKKiBUaGUgNjAlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvbGxvd2luZyBmcm9tIHRoZXNlIDEwIHNhbXBsZXMgYXJlOgoKYGBge3J9CnBhc3RlKE1MLE1VLHNlcD0nIHRvICcpCmBgYAoKX19SZWNhbGw6X18gVGhlIGFjdHVhbCBtZWFuIG9mIHRoZSBwdXB1bGF0aW9uIGlzCgpgYGB7cn0KbWVhbihYKQpgYGAKCiogV2UgZGVsaWJlcml0ZWx5IGNob3NlIDYwJSBjb25maWRlbmNlIGludGVydmFscyB0byBoaWdobGlnaHQgdGhlIHBvaW50IHRoYXQgbm90IGFsbCBjb25maWRlbmNlIGludGVydmFscyBjb250YWluIHRoZSB0cnVlIHBvcHVsYXRpb24gbWVhbi4KCiogVGhpcyBnaXZlcyB1cyB0aGUgY29ycmVjdCBpbnRlcnByZXRhdGlvbiBmb3IgdGhlIDYwJSBjb25maWRlbmNlIGludGVydmFsOgogCiAgICAqIEEgY29uZmlkZW5jZSBpdGVydmFsIGVpdGhlciBkb2VzIG9yIGRvZXMgbm90IGNvbnRhaW4gdGhlIHRydWUgcG9wdWxhdGlvbiBtZWFuLgogCiAgICAqIEFzIHdlIGNhbiBzZWUsIGlmIHdlIHRha2UgZW5vdWdoIHNhbXBsZXMsIHRoZW4gc29tZSBvZiB0aGVzZSBjb25maWRlbmNlIGludGVydmFscyB3aWxsIGNvbnRhaW4gdGhlIG1lYW4gYW5kIHNvbWUgd2lsbCBub3QuCiAKICAgICogSWYgd2UgdGFrZSBhIGxhcmdlIGVub3VnaCBudW1iZXIgb2Ygc2FtcGxlcywgdGhlbiBvbiBhdmVyYWdlLCA2MCUgb2YgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGRlZHVjZWQgZnJvbSB0aG9zZSBzYW1wbGVzLCBhdCBjb25maWRlbmNlIGxldmVsIDYwJSwgd2lsbCBjb250YWluIHRoZSB0cnVlIG1lYW4uCiAKIAojIyBFeGVyY2lzZSA1OgoKMS4gVXNpbmcgdGhlIHNhbWUgZGF0YSBzZXQgX19YX18sIHRha2UgX19OPTUwX18gc2FtcGxlcyBvZiBzYW1wbGUgc2l6ZSBfX249NV9fLgoKMi4gRmluZCB0aGUgbWVhbiBvZiBlYWNoIHNhbXBsZS4KCjMuIEZpbmQgdGhlIF9fOTAlX18gY29uZmlkZW5jZSBpbnRlcnZhbCBhc3NvY2lhdGVkIHdpdGggdGhlc2Ugc2FtcGxlIGF2ZXJhZ2VzLgoKNC4gRG8gYWxsIHRoZXNlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGNvbnRhaW4gdGhlIHRydWUgcG9wdWxhdGlvbiBtZWFuPwo=