Simulations in R
Carrying out simulations in R is actually quite straightforward.
We will walk through the steps involved one at a time.
Suppose that we are interested in the random variable \(X\), which follows the standard normal distribution - in other words, \(X \sim N(0, 1)\).
We can generate a sample of 100 observations from this distribution using the following R code:
set.seed(1)
n <- 100
x <- rnorm(n)
Run this code now.
Note: The default mean and standard deviation values used by rnorm
are 0 and 1 respectively, so we don’t need to specify these.
We can plot our generated data using the hist
function, as shown below.
hist(x, freq = FALSE, col = "chartreuse3", xlim = c(-3, 3),
main = paste("Histogram of random sample \n from standard Normal distribution, n = ", n))
# Overlay standard normal curve
curve(dnorm(x), add = TRUE, col = "blue", lwd = 2)
# Add line denoting sample mean
abline(v = round(mean(x), 3), col = "red", lwd = 2, lty = 2)

Note that we have also used the curve
and dnorm
functions here to overlay the standard normal distribution probability density curve.
As expected, the 100 sample observations appear to fit the standard normal distribution probability density curve well.
Our main interest here is not the variability of the sample values however, but rather the sample mean.
If we check the sample mean of x
, we find that this is equal to approximately 0.109 (shown by the red dashed line in the plot above). Since this is the sample mean for just one sample, we can’t be too confident in using this estimate as an accurate estimate of the population mean (which we know was specified to be 0
).
Rather than relying on just one sample, we will now simulate a number of random samples from \(X\), in order to obtain a more accurate estimate of the sample mean \(\bar{X}\).
To begin, suppose we sample 5 observations of \(X\), and then compute the sample mean of these observations.
Using the code in 2.1, it follows that this process is quite straightforward:
set.seed(1)
n <- 5 # Specify sample size
x <- rnorm(n) # Randomly generate ns samples from the normal distribution
norm_mean <- mean(x) # Compute the mean of the samples, and store it in a new object
Since our underlying data is generated from a normal distribution, it follows that the distribution of the sample mean will also be normal (we can think of this result as a precursor to the Central Limit Theorem).
To accurately visualise the distribution of the sample mean, we will need to repeat the process outlined in 2.4 many times. This is where our simulations can really shine.
Suppose, rather than conducting the process outlined in 2.4 once, we instead conduct it 10000 times.
It would take a while to write this code out line by line in R (over 9000 lines potentially!).
Instead, to save time, we will use a loop
.
Specifically, we will use what is known as a for loop
. A for loop
is a function that will repeat a specified set of operations a specified number of times.
The Code
chunk below provides a simple example of the R syntax for a for loop
.
for(i in 1:10){
x <- rnorm(i)
mean(x)
}
How do we interpret this code?
Well,we have specified that for some input i
, where i
can take the integer values 1 up to 10, the for loop
will simulate i
random values from the standard Normal distribution, store them in the object x
, and then compute the mean of x
.
Thus, our for loop
runs like this:
- The
for loop
starts with the first specified value, 1, and simulates 1 random value from the standard Normal distribution.
- The mean of
x
is now computed. This is the last operation in the for loop
.
- Since the specified operations inside the loop have been finished for that value of
i
, the loop starts again, with i=2
now.
- This process continues, until the final specified value of
i
, namely i=10
, has been used.
- At this point, the
for loop
is complete.
Note: We do not have to use the letter i
here, it is simply convention. You can use a different letter, but remember, make sure you have not used your chosen letter as a name for a previous object in which you have stored data.
The Code
chunk below expands upon the for loop
example discussed above in 2.5. Take a look at this code, read the comments carefully, and make sure you understand what the code does (note some values are missing, as denoted by the ...
).
#Specify sample size
ns <- ...
# Specify number of times to conduct process
trials <- ...
# create object in which to store sample means once they are generated
norm.means <- rep(0, trials) # Note length is equal to the number of trials
# Run for loop
for(i in 1:trials){
# Randomly generate ns samples from the normal distribution
x <- rnorm(ns)
# Compute mean of samples, and store it in the norm.means object, in ith position
norm.means[i] <- mean(x)
}
Once you feel confident in your understanding of this code, replace the ...
missing details for ns
and trials
, using the following details:
- You want to take 10000 samples of randomly generated values from the standard Normal distribution.
- Each sample should have a sample size of 5.
Once you have filled in the details, run your code.
Hint: If you have given this a decent shot, but are stuck, you can check the Code
chunk below:
#Specify sample size
ns <- 5
# Specify number of times to conduct process
trials <- 10000
# create object in which to store sample means once they are generated
norm.means <- rep(0, trials) # Note length is equal to the number of trials
# Run for loop
for(i in 1:trials){
# Randomly generate ns samples from the normal distribution
x <- rnorm(ns)
# Compute mean of samples, and store it in the norm.means object, in ith position
norm.means[i] <- mean(x)
}
To visualise our results, we can use the following code:
hist(norm.means, freq = FALSE, breaks = 20, col = "red",
xlim = c(-3, 3),
xlab = expression(bar(x)),
main = paste("Histogram of means, n = ", ns))
We can also overlay a normal density curve, that, since our underlying data is normal,
will reflect the distribution of the sample mean.
curve(dnorm(x,
mean = 0, sd = 1/sqrt(ns)),
add = TRUE, col = "blue", lwd = 2)
Run these code chunks now, and check your results. Are our simulated sample means close to the population mean of 0?
Repeat steps 2.6 and 2.7, using a sample of 30 instead of 5. What do you notice about the distribution of the simulated sample means?
Finally, repeat steps 2.6 and 2.7, using a sample of 60. What do you notice about the distribution of the simulated sample means now?
CLT Simulation - Exponential Distribution
To demonstrate the magic of the Central Limit Theorem, let’s carry out some simulations involving data generated from distributions other than the normal distribution.
For example, let’s now consider the Exponential distribution.
The Exponential distribution is known to be highly skewed (i.e. asymmetric). Clearly, we cannot fit a normal curve well to data generated from an Exponential distribution. However, as we work through this question, we will find that when we model the distribution of sample means of data generated from an Exponential distribution, this distribution of sample means can be fitted well by a normal curve, especially as our sample size increases. This (somewhat unintuitive) result is due to the Central Limit Theorem!
Recall that the Exponential distribution is defined by one parameter, known as the rate parameter (in contrast for example to the Normal distribution, which is defined by two parameters, namely the mean and the variance).
Suppose now that our random variable \(X\) follows an exponential distribution with rate parameter \(\lambda = 10\). In other words, \(X \sim Exp(10)\).
We can generate a sample of 100 observations from this distribution using the following R code:
set.seed(1)
n <- 100
rate = 10
x <- rexp(n, rate = rate)
Note that we use rexp
to randomly generate values from the exponential distribution, instead of using rnorm
(which is for the normal distribution).
Run this code now.
Our generated data is highly skewed, and clearly different to data generated from the symmetric normal distribution. If we try (somewhat optimistically) to overlay a normal distribution probability density curve (similar to in 2.2), with appropriate mean and variance values, (shown in blue), our result is unhelpful.

Instead of considering the individual data points generated from the Exponential distribution, let’s shift our focus to the sample mean of these data points.
If we check the sample mean of x
, we find that this is equal to 0.1030676. In theory, we know that the population mean \(\mu = 1/\lambda = 0.1\), so this sample mean is quite a good estimate.
Let us now conduct the simulation process used in 2.6, for our exponentially distributed data.
Using the code in 2.6 as a guide, simulate 10000 sample means of \(X\), using samples of size 5.
Plot your results, using the code in 2.7 as a guide.
Note: You will have to change the x-axis range for the histogram (via the xlim
argument). Try using a range of 0 to 0.4.
Note 2: Use the code in the Code
chunk below to overlay the appropriate Normal distribution probability density curve:
curve(dnorm(x, mean = 1/rate, sd = 1/rate/sqrt(ns)), add = TRUE,
col = "blue", lwd = 2)
What do you notice about your resultant plot?
Repeats 3.4 for \(X \sim Exp(10)\), using a sample of 30 instead of 5. What do you notice about the distribution of the simulated sample means?
Finally, repeat 3.4 for \(X \sim Exp(10)\), using a sample of 60. What do you notice about the distribution of the simulated sample means now?
CLT Simulation - Bernoulli Distribution
As discussed in Section 3.3 of Topic 4, the Central Limit Theorem even applies to discrete random variables.
Suppose that our random variable \(X\) now follows a Bernoulli distribution with success parameter \(p = 0.3\). In other words, \(X \sim BERN(0.3)\).
If we generate a sample of 100 observations from this distribution (see the R code below) and then visualise our generated data, we see a roughly 70/30 split of observations between \(x=0\) and \(x=1\). Clearly, (just as in the Exponential distribution case), the normal distribution probability density curve, with appropriate parameter specifications, (shown in blue), is an extremely poor fit for this data.
set.seed(1)
n <- 100
p = 0.3
x <- rbinom(n, 1, p)
Note that we use rbinom
to randomly generate values from the Bernoulli distribution, instead of using rnorm
(which is for the normal distribution).

However, as we will soon see, despite our data being generated from a discrete distribution, we can still use the Central Limit Theorem to obtain an accurate estimate of the population mean!
Let us now conduct the simulation process used in 2.6, for our Bernoulli distributed data.
Using the code in 2.6 as a guide, simulate 10000 sample means of \(X\), using samples of size 5.
Then, plot your results, using the code in 2.7 as a guide.
Note: You will have to change the x-axis range for the histogram (via the xlim
argument).
Note 2: Use the code in the Code
chunk below to overlay the appropriate normal distribution probability density curve:
# Set mu and sigma for the approximating normal distribution
mu <- p
sigma <- sqrt(p*(1 - p))
# Overlay the normal density
curve(dnorm(x, mu, sigma/sqrt(ns)), add = TRUE, col = "blue", lwd = 2)
What do you notice about your resultant plot?
Repeat 3.4 for \(X \sim BERN(0.3)\), using a sample of 30 instead of 5. What do you notice about the distribution of the simulated sample means?
Finally, repeat 3.4 for \(X \sim BERN(0.3)\), using a sample of 60. What do you notice about the distribution of the simulated sample means now?
Extension - Average Diamond Prices
Let’s consider how we can apply the Central Limit Theorem to real data.
For this question, we will consider data on approximately 54,000 round cut diamonds. This data is stored in the diamonds
data set in the ggplot2
R package. We will treat this data as the population data.
Install and load the ggplot2
R package now.
Hint: If you need a refresher on installing and loading packages in R, check the Code
chunk below:
# Note that you will have to change this code to the relevant package
install.packages("palmerpenguins")
library(palmerpenguins)
If we plot the price of round cut diamonds using a histogram, we can see that the data is clearly not normally distributed.
Make sure to run this code before continuing.
hist(diamonds$price, col = "skyblue", xlab = "Diamond Price ($)",
main = "Histogram of Diamond Prices ($)", freq = F)

Suppose that you are interested in estimating the population mean price for round cut diamonds, but do not have access to the full diamonds
data set.
Instead, you can only sample prices for 5 round cut diamonds at a time, represented by the code below:
x <- sample(diamonds$price, 5)
Using this code and the code in 2.6 as a guide, simulate taking 100 samples of 5 random round cut diamond sale prices, and plot a histogram of the resultant sample means. What do you observe?
Repeat 5.2, but this time suppose that you are able to take samples of 30 diamonds at a time, instead of 5. What changes do you observe?
Great job, that’s everything for today!
Hopefully, this computer lab has helped cement your understanding of the Central Limit Theorem.
LS0tDQp0aXRsZTogIlNUTTEwMDE6IENvbXB1dGVyIExhYiA1QiINCm91dHB1dDoNCiAgYm9va2Rvd246Omh0bWxfZG9jdW1lbnQyOiANCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdGhlbWU6IHJlYWRhYmxlDQogICAgY29kZV9mb2xkaW5nOiBzaG93DQpiaWJsaW9ncmFwaHk6IFNUTTEwMDFfRFNfQ0xfcmVmZXJlbmNlcy5iaWIgDQpsaW5rLWNpdGF0aW9uczogeWVzDQotLS0NCg0KPHN0eWxlPg0KI1RPQyB7DQogIGJhY2tncm91bmQ6IHVybCgiaHR0cHM6Ly93d3cubGF0cm9iZS5lZHUuYXUvX21lZGlhL2xhLXRyb2JlLWFwaS92NS9pbWcvbG9nby5zdmciKTsNCiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOw0KICBwYWRkaW5nLXRvcDogODBweCAhaW1wb3J0YW50Ow0KICBiYWNrZ3JvdW5kLXJlcGVhdDogbm8tcmVwZWF0Ow0KfQ0KPC9zdHlsZT4NCg0KIyMjIERhdGEgU2NpZW5jZSBNb2R1bGUgey19DQoNCiMjIyBUb3BpYyA1QjogU2ltdWxhdGlvbnMgaW4gUiB7LX0NCg0KPGJyPg0KDQpXZWxjb21lIHRvIHRoZSBmaWZ0aCBEYXRhIFNjaWVuY2UgY29tcHV0ZXIgbGFiLg0KDQpJbiBbVG9waWMgNF0oaHR0cHM6Ly9ib29rZG93bi5vcmcvY29udGVudC84OGVmOWI3Yy01ODMzLTRhNzAtODRmMi05MzQ3MDk1N2QxZjkvKSwgd2UgaW50cm9kdWNlZCBzYW1wbGluZyBkaXN0cmlidXRpb25zIGFuZCB0aGUgY29uY2VwdCBvZiB0aGUgKkNlbnRyYWwgTGltaXQgVGhlb3JlbSouIA0KDQpJbiB0aGlzIGNvbXB1dGVyIGxhYiB3ZSB3aWxsIGNvdmVyIGhvdyB0byBjb25kdWN0IHRoZSBzaW11bGF0aW9ucyBkaXNjdXNzZWQgaW4gW0NoYXB0ZXIgMyBvZiBUb3BpYyA0XShodHRwczovL2Jvb2tkb3duLm9yZy9jb250ZW50Lzg4ZWY5YjdjLTU4MzMtNGE3MC04NGYyLTkzNDcwOTU3ZDFmOS8zLXRoZS1jZW50cmFsLWxpbWl0LXRoZW9yZW0uaHRtbCkuIA0KKipJdCBtaWdodCBiZSBoZWxwZnVsIHRvIGtlZXAgdGhpcyBjb250ZW50IG9wZW4gaW4gYSBzZXBhcmF0ZSB0YWIgd2hpbGUgeW91IHdvcmsgdGhyb3VnaCB0aGUgbGFiIG1hdGVyaWFsLCBpbiBjYXNlIHlvdSB3b3VsZCBsaWtlIHRvIHF1aWNrbHkgZG91YmxlLWNoZWNrIHlvdXIgdW5kZXJzdGFuZGluZyBvZiBhbnkgY29uY2VwdHMuKioNCg0KQnkgdGhlIGVuZCBvZiB0aGlzIGxhYiwgeW91IHNob3VsZCBiZSBhYmxlIHRvIGNvbmR1Y3Qgc2ltcGxlIHNpbXVsYXRpb25zIGluIFIuIExldCdzIGdldCBzdGFydGVkIQ0KDQojIFNhbXBsaW5nIERpc3RyaWJ1dGlvbnMNCg0KIyMgU2FtcGxpbmcNCg0KUmVjYWxsIHRoYXQgYSAqKnNhbXBsZSoqIGlzIGEgcmFuZG9tIHNlbGVjdGlvbiBvZiB1bml0cyBmcm9tIGEgY2hvc2VuIHBvcHVsYXRpb24gKGUuZy4gYSBzZWxlY3Rpb24gb2YgU1RNMTAwMSBzdHVkZW50cywgZnJvbSB0aGUgZW50aXJlIFNUTTEwMDEgY29ob3J0KS4NCg0KQmVjYXVzZSBpdCBpcyB0eXBpY2FsbHkgdW5mZWFzaWJsZSB0byBjb2xsZWN0IGRhdGEgb24gdGhlIGVudGlyZSBwb3B1bGF0aW9uLCB3ZSBpbnN0ZWFkIGNvbmR1Y3QgYW5hbHlzZXMgdXNpbmcgYSBzYW1wbGUuIFdlIGhvcGUgdGhhdCB0aGUgaW5mZXJlbmNlcyB3ZSBtYWtlIHVzaW5nIHRoZSBzYW1wbGUgZGF0YSBjYW4gYmUgZXh0cmFwb2xhdGVkIHRvIHByb3ZpZGUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHBvcHVsYXRpb24sIGFuZCB3ZSBjYW4gdXNlIHN0YXRpc3RpY2FsIHRlY2huaXF1ZXMgdG8gYXNjZXJ0YWluIHRoZSBhY2N1cmFjeSBvZiB0aGVzZSBpbmZlcmVuY2VzLiANCg0KT25lIHN1Y2ggc3RhdGlzdGljYWwgdGVjaG5pcXVlIHdlIGNhbiB1c2UgaXMgdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbS4NCg0KIyMgVGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSB7I0NMVH0NCg0KUmVjYWxsIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gKENMVCk6DQoNCjxjZW50ZXI+DQpMZXQgJFhfMSwgXGxkb3RzLCBYX24kIGJlIGEgcmFuZG9tIHNhbXBsZSBmcm9tIGEgZGlzdHJpYnV0aW9uIHdpdGggZmluaXRlIG1lYW4gJFxtdSQgYW5kIGZpbml0ZSB2YXJpYW5jZSAkXHNpZ21hXjIkLiANCg0KRm9yICRcb3ZlcmxpbmV7WH0kIGRlbm90aW5nIHRoZSBzYW1wbGUgbWVhbiwgaWYgJG4kIGlzIHN1ZmZpY2llbnRseSBsYXJnZSB0aGVuDQokJFxvdmVybGluZXtYfVxzdGFja3JlbHtcdGlueSBcdGV4dHthcHByb3gufX1cc2ltIE5cbGVmdChcbXUsXGZyYWN7XHNpZ21hXjJ9e259XHJpZ2h0KSAsICQkDQp3aGVyZSAkXHN0YWNrcmVse1x0aW55IFx0ZXh0e2FwcHJveC59fVxzaW0kIGRlbm90ZXMgJ2FwcHJveGltYXRlbHkgZGlzdHJpYnV0ZWQgYXMnLg0KPC9jZW50ZXI+DQo8YnI+DQoNCkJ5IHRoZSBDTFQsIGl0IGZvbGxvd3MgdGhhdCBhcyB3ZSBpbmNyZWFzZSBvdXIgc2FtcGxlIHNpemUsIHRoZSBzYW1wbGUgbWVhbiAkXG92ZXJsaW5le1h9JCB3aWxsIGdldCBpbmNyZWFzaW5nbHkgY2xvc2VyIChpLmUuIGNvbnZlcmdlKSB0byB0aGUgcG9wdWxhdGlvbiBtZWFuICRcbXUkLiBBcyAkbiQgaW5jcmVhc2VzLCB0aGUgdmFyaWFuY2Ugb2YgdGhlIHNhbXBsZSBtZWFuICRcb3ZlcmxpbmV7WH0kIHdpbGwgYWxzbyBkZWNyZWFzZS4NCg0KSW4gb3RoZXIgd29yZHMsIHdoaWxlIHNhbXBsZXMgb2YgaW5kaXZpZHVhbHMgY2FuIGV4aGliaXQgc2lnbmlmaWNhbnQgdmFyaWF0aW9uLCBzYW1wbGVzIG9mIG1lYW5zIHRlbmQgdG8gaGF2ZSBsZXNzIHZhcmlhYmlsaXR5IChhcyBlYWNoIG1lYW4gaXMgY2FsY3VsYXRlZCBmcm9tIGEgc2FtcGxlIG9mIGluZGl2aWR1YWxzLCByZWR1Y2luZyB0aGUgaW1wYWN0IG9mIG91dGxpZXJzKS4NCg0KTGV0J3MgdmlzdWFsaXNlIHRoaXMgcHJvY2VzcyBpbiBSIHVzaW5nIHNvbWUgc2ltdWxhdGlvbnMuDQoNCiMgU2ltdWxhdGlvbnMgaW4gUg0KDQpDYXJyeWluZyBvdXQgc2ltdWxhdGlvbnMgaW4gUiBpcyBhY3R1YWxseSBxdWl0ZSBzdHJhaWdodGZvcndhcmQuIA0KDQpXZSB3aWxsIHdhbGsgdGhyb3VnaCB0aGUgc3RlcHMgaW52b2x2ZWQgb25lIGF0IGEgdGltZS4NCg0KIyMgeyNiYXNlfQ0KDQpTdXBwb3NlIHRoYXQgd2UgYXJlIGludGVyZXN0ZWQgaW4gdGhlIHJhbmRvbSB2YXJpYWJsZSAkWCQsIHdoaWNoIGZvbGxvd3MgdGhlIHN0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb24gLSBpbiBvdGhlciB3b3JkcywgJFggXHNpbSBOKDAsIDEpJC4NCg0KV2UgY2FuIGdlbmVyYXRlIGEgc2FtcGxlIG9mIDEwMCBvYnNlcnZhdGlvbnMgZnJvbSB0aGlzIGRpc3RyaWJ1dGlvbiB1c2luZyB0aGUgZm9sbG93aW5nIFIgY29kZToNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVH0NCnNldC5zZWVkKDEpDQpuIDwtIDEwMA0KDQp4IDwtIHJub3JtKG4pDQpgYGANCg0KUnVuIHRoaXMgY29kZSBub3cuDQoNCipOb3RlOiBUaGUgZGVmYXVsdCBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gdmFsdWVzIHVzZWQgYnkgYHJub3JtYCBhcmUgMCBhbmQgMSByZXNwZWN0aXZlbHksIHNvIHdlIGRvbid0IG5lZWQgdG8gc3BlY2lmeSB0aGVzZS4qDQoNCiMjIHsjYmFzZWhpc3R9DQoNCldlIGNhbiBwbG90IG91ciBnZW5lcmF0ZWQgZGF0YSB1c2luZyB0aGUgYGhpc3RgIGZ1bmN0aW9uLCBhcyBzaG93biBiZWxvdy4NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVH0NCmhpc3QoeCwgZnJlcSA9IEZBTFNFLCBjb2wgPSAiY2hhcnRyZXVzZTMiLCB4bGltID0gYygtMywgMyksDQogICAgIG1haW4gPSBwYXN0ZSgiSGlzdG9ncmFtIG9mIHJhbmRvbSBzYW1wbGUgXG4gZnJvbSBzdGFuZGFyZCBOb3JtYWwgZGlzdHJpYnV0aW9uLCBuID0gIiwgbikpIA0KIyBPdmVybGF5IHN0YW5kYXJkIG5vcm1hbCBjdXJ2ZQ0KY3VydmUoZG5vcm0oeCksIGFkZCA9IFRSVUUsIGNvbCA9ICJibHVlIiwgbHdkID0gMikNCiMgQWRkIGxpbmUgZGVub3Rpbmcgc2FtcGxlIG1lYW4NCmFibGluZSh2ID0gcm91bmQobWVhbih4KSwgMyksIGNvbCA9ICJyZWQiLCBsd2QgPSAyLCBsdHkgPSAyKQ0KYGBgDQoNCipOb3RlIHRoYXQgd2UgaGF2ZSBhbHNvIHVzZWQgdGhlIGBjdXJ2ZWAgYW5kIGBkbm9ybWAgZnVuY3Rpb25zIGhlcmUgdG8gb3ZlcmxheSB0aGUgc3RhbmRhcmQgbm9ybWFsIGRpc3RyaWJ1dGlvbiBwcm9iYWJpbGl0eSBkZW5zaXR5IGN1cnZlLioNCg0KIyMNCg0KQXMgZXhwZWN0ZWQsIHRoZSAxMDAgc2FtcGxlIG9ic2VydmF0aW9ucyBhcHBlYXIgdG8gZml0IHRoZSBzdGFuZGFyZCBub3JtYWwgZGlzdHJpYnV0aW9uIHByb2JhYmlsaXR5IGRlbnNpdHkgY3VydmUgd2VsbC4gDQoNCk91ciBtYWluIGludGVyZXN0IGhlcmUgaXMgbm90IHRoZSB2YXJpYWJpbGl0eSBvZiB0aGUgc2FtcGxlIHZhbHVlcyBob3dldmVyLCBidXQgcmF0aGVyIHRoZSAqc2FtcGxlIG1lYW4qLiANCg0KSWYgd2UgY2hlY2sgdGhlIHNhbXBsZSBtZWFuIG9mIGB4YCwgd2UgZmluZCB0aGF0IHRoaXMgaXMgZXF1YWwgdG8gYXBwcm94aW1hdGVseSBgciByb3VuZChtZWFuKHgpLCAzKWAgKHNob3duIGJ5IHRoZSByZWQgZGFzaGVkIGxpbmUgaW4gdGhlIHBsb3QgYWJvdmUpLiBTaW5jZSB0aGlzIGlzIHRoZSBzYW1wbGUgbWVhbiBmb3IganVzdCBvbmUgc2FtcGxlLCB3ZSBjYW4ndCBiZSB0b28gY29uZmlkZW50IGluIHVzaW5nIHRoaXMgZXN0aW1hdGUgYXMgYW4gYWNjdXJhdGUgZXN0aW1hdGUgb2YgdGhlIHBvcHVsYXRpb24gbWVhbiAod2hpY2ggd2Uga25vdyB3YXMgc3BlY2lmaWVkIHRvIGJlIGAwYCkuDQoNClJhdGhlciB0aGFuIHJlbHlpbmcgb24ganVzdCBvbmUgc2FtcGxlLCB3ZSB3aWxsIG5vdyBzaW11bGF0ZSBhIG51bWJlciBvZiByYW5kb20gc2FtcGxlcyBmcm9tICRYJCwgaW4gb3JkZXIgdG8gb2J0YWluIGEgbW9yZSBhY2N1cmF0ZSBlc3RpbWF0ZSBvZiB0aGUgc2FtcGxlIG1lYW4gJFxiYXJ7WH0kLiANCg0KIyMgeyNzdGFydH0NCg0KVG8gYmVnaW4sIHN1cHBvc2Ugd2Ugc2FtcGxlIDUgb2JzZXJ2YXRpb25zIG9mICRYJCwgYW5kIHRoZW4gY29tcHV0ZSB0aGUgc2FtcGxlIG1lYW4gb2YgdGhlc2Ugb2JzZXJ2YXRpb25zLg0KDQpVc2luZyB0aGUgY29kZSBpbiBcQHJlZihiYXNlKSwgaXQgZm9sbG93cyB0aGF0IHRoaXMgcHJvY2VzcyBpcyBxdWl0ZSBzdHJhaWdodGZvcndhcmQ6DQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFR9DQpzZXQuc2VlZCgxKQ0KbiA8LSA1ICMgU3BlY2lmeSBzYW1wbGUgc2l6ZQ0KeCA8LSBybm9ybShuKSAjIFJhbmRvbWx5IGdlbmVyYXRlIG5zIHNhbXBsZXMgZnJvbSB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbg0Kbm9ybV9tZWFuIDwtIG1lYW4oeCkgIyBDb21wdXRlIHRoZSBtZWFuIG9mIHRoZSBzYW1wbGVzLCBhbmQgc3RvcmUgaXQgaW4gYSBuZXcgb2JqZWN0DQpgYGANCg0KIyMgeyNzaW1zdGFydH0NCg0KU2luY2Ugb3VyIHVuZGVybHlpbmcgZGF0YSBpcyBnZW5lcmF0ZWQgZnJvbSBhIG5vcm1hbCBkaXN0cmlidXRpb24sIGl0IGZvbGxvd3MgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzYW1wbGUgbWVhbiB3aWxsIGFsc28gYmUgbm9ybWFsICh3ZSBjYW4gdGhpbmsgb2YgdGhpcyByZXN1bHQgYXMgYSBwcmVjdXJzb3IgdG8gdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSkuIA0KDQpUbyBhY2N1cmF0ZWx5IHZpc3VhbGlzZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzYW1wbGUgbWVhbiwgd2Ugd2lsbCBuZWVkIHRvIHJlcGVhdCB0aGUgcHJvY2VzcyBvdXRsaW5lZCBpbiBcQHJlZihzdGFydCkgKiptYW55IHRpbWVzKiouIFRoaXMgaXMgd2hlcmUgb3VyIHNpbXVsYXRpb25zIGNhbiByZWFsbHkgc2hpbmUuDQoNClN1cHBvc2UsIHJhdGhlciB0aGFuIGNvbmR1Y3RpbmcgdGhlIHByb2Nlc3Mgb3V0bGluZWQgaW4gXEByZWYoc3RhcnQpIG9uY2UsIHdlIGluc3RlYWQgY29uZHVjdCBpdCAxMDAwMCB0aW1lcy4gDQpJdCB3b3VsZCB0YWtlIGEgd2hpbGUgdG8gd3JpdGUgdGhpcyBjb2RlIG91dCBsaW5lIGJ5IGxpbmUgaW4gUiAob3ZlciA5MDAwIGxpbmVzIHBvdGVudGlhbGx5ISkuDQoNCkluc3RlYWQsIHRvIHNhdmUgdGltZSwgd2Ugd2lsbCB1c2UgYSBgbG9vcGAuDQpTcGVjaWZpY2FsbHksIHdlIHdpbGwgdXNlIHdoYXQgaXMga25vd24gYXMgYSBgZm9yIGxvb3BgLiBBIGBmb3IgbG9vcGAgaXMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgcmVwZWF0IGEgc3BlY2lmaWVkIHNldCBvZiBvcGVyYXRpb25zIGEgc3BlY2lmaWVkIG51bWJlciBvZiB0aW1lcy4NCg0KVGhlIGBDb2RlYCBjaHVuayBiZWxvdyBwcm92aWRlcyBhIHNpbXBsZSBleGFtcGxlIG9mIHRoZSBSIHN5bnRheCBmb3IgYSBgZm9yIGxvb3BgLg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KZm9yKGkgaW4gMToxMCl7DQogIHggPC0gcm5vcm0oaSkNCiAgbWVhbih4KQ0KfQ0KYGBgDQoNCkhvdyBkbyB3ZSBpbnRlcnByZXQgdGhpcyBjb2RlPw0KV2VsbCx3ZSBoYXZlIHNwZWNpZmllZCB0aGF0IGZvciBzb21lIGlucHV0IGBpYCwgd2hlcmUgYGlgIGNhbiB0YWtlIHRoZSBpbnRlZ2VyIHZhbHVlcyAxIHVwIHRvIDEwLCB0aGUgYGZvciBsb29wYCB3aWxsIHNpbXVsYXRlIGBpYCByYW5kb20gdmFsdWVzIGZyb20gdGhlIHN0YW5kYXJkIE5vcm1hbCBkaXN0cmlidXRpb24sIHN0b3JlIHRoZW0gaW4gdGhlIG9iamVjdCBgeGAsIGFuZCB0aGVuIGNvbXB1dGUgdGhlIG1lYW4gb2YgYHhgLiANCg0KVGh1cywgb3VyIGBmb3IgbG9vcGAgcnVucyBsaWtlIHRoaXM6DQoNCiogVGhlIGBmb3IgbG9vcGAgc3RhcnRzIHdpdGggdGhlIGZpcnN0IHNwZWNpZmllZCB2YWx1ZSwgMSwgYW5kIHNpbXVsYXRlcyAxIHJhbmRvbSB2YWx1ZSBmcm9tIHRoZSBzdGFuZGFyZCBOb3JtYWwgZGlzdHJpYnV0aW9uLiANCiogVGhlIG1lYW4gb2YgYHhgIGlzIG5vdyBjb21wdXRlZC4gVGhpcyBpcyB0aGUgbGFzdCBvcGVyYXRpb24gaW4gdGhlIGBmb3IgbG9vcGAuDQoqIFNpbmNlIHRoZSBzcGVjaWZpZWQgb3BlcmF0aW9ucyBpbnNpZGUgdGhlIGxvb3AgaGF2ZSBiZWVuIGZpbmlzaGVkIGZvciB0aGF0IHZhbHVlIG9mIGBpYCwgdGhlIGxvb3Agc3RhcnRzIGFnYWluLCB3aXRoIGBpPTJgIG5vdy4gDQoqIFRoaXMgcHJvY2VzcyBjb250aW51ZXMsIHVudGlsIHRoZSBmaW5hbCBzcGVjaWZpZWQgdmFsdWUgb2YgYGlgLCBuYW1lbHkgYGk9MTBgLCBoYXMgYmVlbiB1c2VkLiANCiogQXQgdGhpcyBwb2ludCwgdGhlIGBmb3IgbG9vcGAgaXMgY29tcGxldGUuDQoNCipOb3RlOiBXZSBkbyBub3QgaGF2ZSB0byB1c2UgdGhlIGxldHRlciBgaWAgaGVyZSwgaXQgaXMgc2ltcGx5IGNvbnZlbnRpb24uIFlvdSBjYW4gdXNlIGEgZGlmZmVyZW50IGxldHRlciwgYnV0IHJlbWVtYmVyLCBtYWtlIHN1cmUgeW91IGhhdmUgbm90IHVzZWQgeW91ciBjaG9zZW4gbGV0dGVyIGFzIGEgbmFtZSBmb3IgYSBwcmV2aW91cyBvYmplY3QgaW4gd2hpY2ggeW91IGhhdmUgc3RvcmVkIGRhdGEuKg0KDQoNCiMjICB7I3NpbX0NCg0KVGhlIGBDb2RlYCBjaHVuayBiZWxvdyBleHBhbmRzIHVwb24gdGhlIGBmb3IgbG9vcGAgZXhhbXBsZSBkaXNjdXNzZWQgYWJvdmUgaW4gXEByZWYoc2ltc3RhcnQpLiBUYWtlIGEgbG9vayBhdCB0aGlzIGNvZGUsIHJlYWQgdGhlIGNvbW1lbnRzIGNhcmVmdWxseSwgYW5kIG1ha2Ugc3VyZSB5b3UgdW5kZXJzdGFuZCB3aGF0IHRoZSBjb2RlIGRvZXMgKG5vdGUgc29tZSB2YWx1ZXMgYXJlIG1pc3NpbmcsIGFzIGRlbm90ZWQgYnkgdGhlIGAuLi5gKS4NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBGLCBlY2hvID0gVH0NCiNTcGVjaWZ5IHNhbXBsZSBzaXplDQpucyA8LSAuLi4NCiAgDQojIFNwZWNpZnkgbnVtYmVyIG9mIHRpbWVzIHRvIGNvbmR1Y3QgcHJvY2VzcyAgDQp0cmlhbHMgPC0gLi4uDQoNCiMgY3JlYXRlIG9iamVjdCBpbiB3aGljaCB0byBzdG9yZSBzYW1wbGUgbWVhbnMgb25jZSB0aGV5IGFyZSBnZW5lcmF0ZWQNCm5vcm0ubWVhbnMgPC0gcmVwKDAsIHRyaWFscykgIyBOb3RlIGxlbmd0aCBpcyBlcXVhbCB0byB0aGUgbnVtYmVyIG9mIHRyaWFscw0KDQojIFJ1biBmb3IgbG9vcCAgDQpmb3IoaSBpbiAxOnRyaWFscyl7DQogICAgIyBSYW5kb21seSBnZW5lcmF0ZSBucyBzYW1wbGVzIGZyb20gdGhlIG5vcm1hbCBkaXN0cmlidXRpb24NCiAgICB4IDwtIHJub3JtKG5zKSANCiAgICAjIENvbXB1dGUgbWVhbiBvZiBzYW1wbGVzLCBhbmQgc3RvcmUgaXQgaW4gdGhlIG5vcm0ubWVhbnMgb2JqZWN0LCBpbiBpdGggcG9zaXRpb24gDQogICAgbm9ybS5tZWFuc1tpXSA8LSBtZWFuKHgpIA0KICAgIH0NCg0KYGBgDQoNCk9uY2UgeW91IGZlZWwgY29uZmlkZW50IGluIHlvdXIgdW5kZXJzdGFuZGluZyBvZiB0aGlzIGNvZGUsIHJlcGxhY2UgdGhlIGAuLi5gIG1pc3NpbmcgZGV0YWlscyBmb3IgYG5zYCBhbmQgYHRyaWFsc2AsIHVzaW5nIHRoZSBmb2xsb3dpbmcgZGV0YWlsczoNCg0KKiBZb3Ugd2FudCB0byB0YWtlIDEwMDAwIHNhbXBsZXMgb2YgcmFuZG9tbHkgZ2VuZXJhdGVkIHZhbHVlcyBmcm9tIHRoZSBzdGFuZGFyZCBOb3JtYWwgZGlzdHJpYnV0aW9uLg0KKiBFYWNoIHNhbXBsZSBzaG91bGQgaGF2ZSBhIHNhbXBsZSBzaXplIG9mIDUuDQoNCk9uY2UgeW91IGhhdmUgZmlsbGVkIGluIHRoZSBkZXRhaWxzLCBydW4geW91ciBjb2RlLg0KDQoqSGludDogSWYgeW91IGhhdmUgZ2l2ZW4gdGhpcyBhIGRlY2VudCBzaG90LCBidXQgYXJlIHN0dWNrLCB5b3UgY2FuIGNoZWNrIHRoZSBgQ29kZWAgY2h1bmsgYmVsb3c6Kg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIiwgZXZhbCA9IFQsIGVjaG8gPSBUfQ0KI1NwZWNpZnkgc2FtcGxlIHNpemUNCm5zIDwtIDUNCiAgDQojIFNwZWNpZnkgbnVtYmVyIG9mIHRpbWVzIHRvIGNvbmR1Y3QgcHJvY2VzcyAgDQp0cmlhbHMgPC0gMTAwMDANCg0KIyBjcmVhdGUgb2JqZWN0IGluIHdoaWNoIHRvIHN0b3JlIHNhbXBsZSBtZWFucyBvbmNlIHRoZXkgYXJlIGdlbmVyYXRlZA0Kbm9ybS5tZWFucyA8LSByZXAoMCwgdHJpYWxzKSAjIE5vdGUgbGVuZ3RoIGlzIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgdHJpYWxzDQoNCiMgUnVuIGZvciBsb29wICANCmZvcihpIGluIDE6dHJpYWxzKXsNCiAgICAjIFJhbmRvbWx5IGdlbmVyYXRlIG5zIHNhbXBsZXMgZnJvbSB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbg0KICAgIHggPC0gcm5vcm0obnMpIA0KICAgICMgQ29tcHV0ZSBtZWFuIG9mIHNhbXBsZXMsIGFuZCBzdG9yZSBpdCBpbiB0aGUgbm9ybS5tZWFucyBvYmplY3QsIGluIGl0aCBwb3NpdGlvbiANCiAgICBub3JtLm1lYW5zW2ldIDwtIG1lYW4oeCkgDQogICAgfQ0KYGBgDQoNCiMjIHsjdml6fQ0KDQpUbyB2aXN1YWxpc2Ugb3VyIHJlc3VsdHMsIHdlIGNhbiB1c2UgdGhlIGZvbGxvd2luZyBjb2RlOg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KaGlzdChub3JtLm1lYW5zLCBmcmVxID0gRkFMU0UsIGJyZWFrcyA9IDIwLCBjb2wgPSAicmVkIiwgDQogICAgIHhsaW0gPSBjKC0zLCAzKSwNCiAgICAgeGxhYiA9IGV4cHJlc3Npb24oYmFyKHgpKSwNCiAgICAgbWFpbiA9IHBhc3RlKCJIaXN0b2dyYW0gb2YgbWVhbnMsIG4gPSAiLCBucykpIA0KYGBgDQoNCldlIGNhbiBhbHNvIG92ZXJsYXkgYSBub3JtYWwgZGVuc2l0eSBjdXJ2ZSwgdGhhdCwgc2luY2Ugb3VyIHVuZGVybHlpbmcgZGF0YSBpcyBub3JtYWwsDQp3aWxsIHJlZmxlY3QgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc2FtcGxlIG1lYW4uIA0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfSAgDQpjdXJ2ZShkbm9ybSh4LCANCiAgICAgIG1lYW4gPSAwLCBzZCA9IDEvc3FydChucykpLCANCiAgICAgIGFkZCA9IFRSVUUsIGNvbCA9ICJibHVlIiwgbHdkID0gMikgDQpgYGANCg0KUnVuIHRoZXNlIGNvZGUgY2h1bmtzIG5vdywgYW5kIGNoZWNrIHlvdXIgcmVzdWx0cy4gQXJlIG91ciBzaW11bGF0ZWQgc2FtcGxlIG1lYW5zIGNsb3NlIHRvIHRoZSBwb3B1bGF0aW9uIG1lYW4gb2YgMD8NCg0KIyMNCg0KUmVwZWF0IHN0ZXBzIFxAcmVmKHNpbSkgYW5kIFxAcmVmKHZpeiksIHVzaW5nIGEgc2FtcGxlIG9mIDMwIGluc3RlYWQgb2YgNS4gV2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHNpbXVsYXRlZCBzYW1wbGUgbWVhbnM/DQoNCiMjDQoNCkZpbmFsbHksIHJlcGVhdCBzdGVwcyBcQHJlZihzaW0pIGFuZCBcQHJlZih2aXopLCB1c2luZyBhIHNhbXBsZSBvZiA2MC4gV2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHNpbXVsYXRlZCBzYW1wbGUgbWVhbnMgbm93Pw0KDQojIENMVCBTaW11bGF0aW9uIC0gRXhwb25lbnRpYWwgRGlzdHJpYnV0aW9uDQoNClRvIGRlbW9uc3RyYXRlIHRoZSBtYWdpYyBvZiB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtLCBsZXQncyBjYXJyeSBvdXQgc29tZSBzaW11bGF0aW9ucyBpbnZvbHZpbmcgZGF0YSBnZW5lcmF0ZWQgZnJvbSBkaXN0cmlidXRpb25zIG90aGVyIHRoYW4gdGhlIG5vcm1hbCBkaXN0cmlidXRpb24uIA0KDQpGb3IgZXhhbXBsZSwgbGV0J3Mgbm93IGNvbnNpZGVyIHRoZSAqKkV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbioqLiANClRoZSBFeHBvbmVudGlhbCBkaXN0cmlidXRpb24gaXMga25vd24gdG8gYmUgaGlnaGx5IHNrZXdlZCAoaS5lLiBhc3ltbWV0cmljKS4gQ2xlYXJseSwgd2UgY2Fubm90IGZpdCBhIG5vcm1hbCBjdXJ2ZSB3ZWxsIHRvIGRhdGEgZ2VuZXJhdGVkIGZyb20gYW4gRXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uLiBIb3dldmVyLCBhcyB3ZSB3b3JrIHRocm91Z2ggdGhpcyBxdWVzdGlvbiwgd2Ugd2lsbCBmaW5kIHRoYXQgd2hlbiB3ZSBtb2RlbCB0aGUgZGlzdHJpYnV0aW9uIG9mIHNhbXBsZSBtZWFucyBvZiBkYXRhIGdlbmVyYXRlZCBmcm9tIGFuIEV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiwgdGhpcyBkaXN0cmlidXRpb24gb2Ygc2FtcGxlIG1lYW5zICoqY2FuKiogYmUgZml0dGVkIHdlbGwgYnkgYSBub3JtYWwgY3VydmUsIGVzcGVjaWFsbHkgYXMgb3VyIHNhbXBsZSBzaXplIGluY3JlYXNlcy4gVGhpcyAoc29tZXdoYXQgdW5pbnR1aXRpdmUpIHJlc3VsdCBpcyBkdWUgdG8gdGhlIENlbnRyYWwgTGltaXQgVGhlb3JlbSENCg0KIyMNCg0KUmVjYWxsIHRoYXQgdGhlIEV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiBpcyBkZWZpbmVkIGJ5IG9uZSBwYXJhbWV0ZXIsIGtub3duIGFzIHRoZSAqcmF0ZSBwYXJhbWV0ZXIqIChpbiBjb250cmFzdCBmb3IgZXhhbXBsZSB0byB0aGUgTm9ybWFsIGRpc3RyaWJ1dGlvbiwgd2hpY2ggaXMgZGVmaW5lZCBieSB0d28gcGFyYW1ldGVycywgbmFtZWx5IHRoZSBtZWFuIGFuZCB0aGUgdmFyaWFuY2UpLiANCg0KU3VwcG9zZSBub3cgdGhhdCBvdXIgcmFuZG9tIHZhcmlhYmxlICRYJCBmb2xsb3dzIGFuIGV4cG9uZW50aWFsIGRpc3RyaWJ1dGlvbiB3aXRoIHJhdGUgcGFyYW1ldGVyICRcbGFtYmRhID0gMTAkLiBJbiBvdGhlciB3b3JkcywgJFggXHNpbSBFeHAoMTApJC4NCg0KV2UgY2FuIGdlbmVyYXRlIGEgc2FtcGxlIG9mIDEwMCBvYnNlcnZhdGlvbnMgZnJvbSB0aGlzIGRpc3RyaWJ1dGlvbiB1c2luZyB0aGUgZm9sbG93aW5nIFIgY29kZToNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVH0NCnNldC5zZWVkKDEpDQpuIDwtIDEwMA0KcmF0ZSA9IDEwDQp4IDwtIHJleHAobiwgcmF0ZSA9IHJhdGUpDQpgYGANCg0KKk5vdGUgdGhhdCB3ZSB1c2UgYHJleHBgIHRvIHJhbmRvbWx5IGdlbmVyYXRlIHZhbHVlcyBmcm9tIHRoZSBleHBvbmVudGlhbCBkaXN0cmlidXRpb24sIGluc3RlYWQgb2YgdXNpbmcgYHJub3JtYCAod2hpY2ggaXMgZm9yIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uKS4qDQoNClJ1biB0aGlzIGNvZGUgbm93Lg0KDQojIw0KDQpPdXIgZ2VuZXJhdGVkIGRhdGEgaXMgaGlnaGx5IHNrZXdlZCwgYW5kIGNsZWFybHkgZGlmZmVyZW50IHRvIGRhdGEgZ2VuZXJhdGVkIGZyb20gdGhlIHN5bW1ldHJpYyBub3JtYWwgZGlzdHJpYnV0aW9uLiBJZiB3ZSB0cnkgKHNvbWV3aGF0IG9wdGltaXN0aWNhbGx5KSB0byBvdmVybGF5IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBwcm9iYWJpbGl0eSBkZW5zaXR5IGN1cnZlIChzaW1pbGFyIHRvIGluIFxAcmVmKGJhc2VoaXN0KSksICB3aXRoIGFwcHJvcHJpYXRlIG1lYW4gYW5kIHZhcmlhbmNlIHZhbHVlcywgKHNob3duIGluIGJsdWUpLCBvdXIgcmVzdWx0IGlzIHVuaGVscGZ1bC4NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gRiwgZmlnLmRpbSA9IGMoNiw2KX0NCmhpc3QoeCwgZnJlcSA9IEZBTFNFLCBjb2wgPSAiY2hhcnRyZXVzZTMiLCB4bGltID0gYygwLCAwLjUpLA0KICAgICBtYWluID0gcGFzdGUoIkhpc3RvZ3JhbSBvZiByYW5kb20gc2FtcGxlIFxuIGZyb20gRXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uLCBuID0gIiwgbikpDQpjdXJ2ZShkbm9ybSh4LCAxL3JhdGUsIDEvcmF0ZSksIGFkZCA9IFRSVUUsIGNvbCA9ICJibHVlIiwgbHdkID0gMikNCmBgYA0KDQojIw0KDQpJbnN0ZWFkIG9mIGNvbnNpZGVyaW5nIHRoZSBpbmRpdmlkdWFsIGRhdGEgcG9pbnRzIGdlbmVyYXRlZCBmcm9tIHRoZSBFeHBvbmVudGlhbCBkaXN0cmlidXRpb24sIGxldCdzIHNoaWZ0IG91ciBmb2N1cyB0byB0aGUgc2FtcGxlIG1lYW4gb2YgdGhlc2UgZGF0YSBwb2ludHMuDQpJZiB3ZSBjaGVjayB0aGUgc2FtcGxlIG1lYW4gb2YgYHhgLCB3ZSBmaW5kIHRoYXQgdGhpcyBpcyBlcXVhbCB0byBgciBtZWFuKHgpYC4gSW4gdGhlb3J5LCB3ZSBrbm93IHRoYXQgdGhlIHBvcHVsYXRpb24gbWVhbiAkXG11ID0gMS9cbGFtYmRhID0gMC4xJCwgc28gdGhpcyBzYW1wbGUgbWVhbiBpcyBxdWl0ZSBhIGdvb2QgZXN0aW1hdGUuDQoNCiMjIHsjZXhwc2ltfQ0KDQpMZXQgdXMgbm93IGNvbmR1Y3QgdGhlIHNpbXVsYXRpb24gcHJvY2VzcyB1c2VkIGluIFxAcmVmKHNpbSksIGZvciBvdXIgZXhwb25lbnRpYWxseSBkaXN0cmlidXRlZCBkYXRhLg0KDQpVc2luZyB0aGUgY29kZSBpbiBcQHJlZihzaW0pIGFzIGEgZ3VpZGUsIHNpbXVsYXRlIDEwMDAwIHNhbXBsZSBtZWFucyBvZiAkWCQsIHVzaW5nIHNhbXBsZXMgb2Ygc2l6ZSA1Lg0KDQpQbG90IHlvdXIgcmVzdWx0cywgdXNpbmcgdGhlIGNvZGUgaW4gXEByZWYodml6KSBhcyBhIGd1aWRlLg0KDQoqTm90ZTogWW91IHdpbGwgaGF2ZSB0byBjaGFuZ2UgdGhlIHgtYXhpcyByYW5nZSBmb3IgdGhlIGhpc3RvZ3JhbSAodmlhIHRoZSBgeGxpbWAgYXJndW1lbnQpLiBUcnkgdXNpbmcgYSByYW5nZSBvZiAwIHRvIDAuNC4qDQoNCipOb3RlIDI6IFVzZSB0aGUgY29kZSBpbiB0aGUgYENvZGVgIGNodW5rIGJlbG93IHRvIG92ZXJsYXkgdGhlIGFwcHJvcHJpYXRlIE5vcm1hbCBkaXN0cmlidXRpb24gcHJvYmFiaWxpdHkgZGVuc2l0eSBjdXJ2ZToqDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gRiwgZWNobyA9IFR9DQpjdXJ2ZShkbm9ybSh4LCBtZWFuID0gMS9yYXRlLCBzZCA9IDEvcmF0ZS9zcXJ0KG5zKSksIGFkZCA9IFRSVUUsDQogICAgICAgIGNvbCA9ICJibHVlIiwgbHdkID0gMikNCmBgYA0KDQojIw0KDQpXaGF0IGRvIHlvdSBub3RpY2UgYWJvdXQgeW91ciByZXN1bHRhbnQgcGxvdD8NCg0KIyMNCg0KUmVwZWF0cyBcQHJlZihleHBzaW0pIGZvciAkWCBcc2ltIEV4cCgxMCkkLCB1c2luZyBhIHNhbXBsZSBvZiAzMCBpbnN0ZWFkIG9mIDUuIFdoYXQgZG8geW91IG5vdGljZSBhYm91dCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzaW11bGF0ZWQgc2FtcGxlIG1lYW5zPw0KDQojIw0KDQpGaW5hbGx5LCByZXBlYXQgXEByZWYoZXhwc2ltKSBmb3IgJFggXHNpbSBFeHAoMTApJCwgdXNpbmcgYSBzYW1wbGUgb2YgNjAuIFdoYXQgZG8geW91IG5vdGljZSBhYm91dCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzaW11bGF0ZWQgc2FtcGxlIG1lYW5zIG5vdz8NCg0KIyBDTFQgU2ltdWxhdGlvbiAtIEJlcm5vdWxsaSBEaXN0cmlidXRpb24NCg0KQXMgZGlzY3Vzc2VkIGluIFtTZWN0aW9uIDMuMyBvZiBUb3BpYyA0XShodHRwczovL2Jvb2tkb3duLm9yZy9jb250ZW50Lzg4ZWY5YjdjLTU4MzMtNGE3MC04NGYyLTkzNDcwOTU3ZDFmOS8zLTMtY2x0LXNpbXVsYXRlZC1leGFtcGxlLXdpdGgtYmVybm91bGxpLWRpc3RyaWJ1dGVkLXBvcHVsYXRpb24uaHRtbCksIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gZXZlbiBhcHBsaWVzIHRvIGRpc2NyZXRlIHJhbmRvbSB2YXJpYWJsZXMuDQoNClN1cHBvc2UgdGhhdCBvdXIgcmFuZG9tIHZhcmlhYmxlICRYJCBub3cgZm9sbG93cyBhIEJlcm5vdWxsaSBkaXN0cmlidXRpb24gd2l0aCBzdWNjZXNzIHBhcmFtZXRlciAkcCA9IDAuMyQuIEluIG90aGVyIHdvcmRzLCAkWCBcc2ltIEJFUk4oMC4zKSQuDQoNCiMjDQoNCklmIHdlIGdlbmVyYXRlIGEgc2FtcGxlIG9mIDEwMCBvYnNlcnZhdGlvbnMgZnJvbSB0aGlzIGRpc3RyaWJ1dGlvbiAoc2VlIHRoZSBSIGNvZGUgYmVsb3cpIGFuZCB0aGVuIHZpc3VhbGlzZSBvdXIgZ2VuZXJhdGVkIGRhdGEsIHdlIHNlZSBhIHJvdWdobHkgNzAvMzAgc3BsaXQgb2Ygb2JzZXJ2YXRpb25zIGJldHdlZW4gJHg9MCQgYW5kICR4PTEkLiBDbGVhcmx5LCAoanVzdCBhcyBpbiB0aGUgRXhwb25lbnRpYWwgZGlzdHJpYnV0aW9uIGNhc2UpLCB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbiBwcm9iYWJpbGl0eSBkZW5zaXR5IGN1cnZlLCB3aXRoIGFwcHJvcHJpYXRlIHBhcmFtZXRlciBzcGVjaWZpY2F0aW9ucywgKHNob3duIGluIGJsdWUpLCBpcyBhbiBleHRyZW1lbHkgcG9vciBmaXQgZm9yIHRoaXMgZGF0YS4NCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gVH0NCnNldC5zZWVkKDEpDQpuIDwtIDEwMA0KcCA9IDAuMw0KeCA8LSByYmlub20obiwgMSwgcCkNCmBgYA0KDQoqTm90ZSB0aGF0IHdlIHVzZSBgcmJpbm9tYCB0byByYW5kb21seSBnZW5lcmF0ZSB2YWx1ZXMgZnJvbSB0aGUgQmVybm91bGxpIGRpc3RyaWJ1dGlvbiwgaW5zdGVhZCBvZiB1c2luZyBgcm5vcm1gICh3aGljaCBpcyBmb3IgdGhlIG5vcm1hbCBkaXN0cmlidXRpb24pLioNCg0KYGBge3IgY2xhc3Muc291cmNlID0gImZvbGQtc2hvdyIsIGV2YWwgPSBULCBlY2hvID0gRn0NCmhpc3QoeCwgZnJlcSA9IEZBTFNFLCBjb2wgPSAiY2hhcnRyZXVzZTMiLCB4bGltID0gYygwLCAxKSwNCiAgICAgbWFpbiA9IHBhc3RlKCJIaXN0b2dyYW0gb2YgcmFuZG9tIHNhbXBsZSBcbiBmcm9tIEJlcm5vdWxsaSBkaXN0cmlidXRpb24sIG4gPSAiLCBuKSkgDQpjdXJ2ZShkbm9ybSh4LCBwLCBzZCA9IHNxcnQocCooMSAtIHApKSksIGFkZCA9IFRSVUUsIGNvbCA9ICJibHVlIiwgbHdkID0gMikNCmBgYA0KDQojIw0KDQpIb3dldmVyLCBhcyB3ZSB3aWxsIHNvb24gc2VlLCBkZXNwaXRlIG91ciBkYXRhIGJlaW5nIGdlbmVyYXRlZCBmcm9tIGEgZGlzY3JldGUgZGlzdHJpYnV0aW9uLCB3ZSBjYW4gc3RpbGwgdXNlIHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gdG8gb2J0YWluIGFuIGFjY3VyYXRlIGVzdGltYXRlIG9mIHRoZSBwb3B1bGF0aW9uIG1lYW4hDQoNCkxldCB1cyBub3cgY29uZHVjdCB0aGUgc2ltdWxhdGlvbiBwcm9jZXNzIHVzZWQgaW4gXEByZWYoc2ltKSwgZm9yIG91ciBCZXJub3VsbGkgZGlzdHJpYnV0ZWQgZGF0YS4NCg0KVXNpbmcgdGhlIGNvZGUgaW4gXEByZWYoc2ltKSBhcyBhIGd1aWRlLCBzaW11bGF0ZSAxMDAwMCBzYW1wbGUgbWVhbnMgb2YgJFgkLCB1c2luZyBzYW1wbGVzIG9mIHNpemUgNS4NClRoZW4sIHBsb3QgeW91ciByZXN1bHRzLCB1c2luZyB0aGUgY29kZSBpbiBcQHJlZih2aXopIGFzIGEgZ3VpZGUuDQoNCipOb3RlOiBZb3Ugd2lsbCBoYXZlIHRvIGNoYW5nZSB0aGUgeC1heGlzIHJhbmdlIGZvciB0aGUgaGlzdG9ncmFtICh2aWEgdGhlIGB4bGltYCBhcmd1bWVudCkuKg0KDQoqTm90ZSAyOiBVc2UgdGhlIGNvZGUgaW4gdGhlIGBDb2RlYCBjaHVuayBiZWxvdyB0byBvdmVybGF5IHRoZSBhcHByb3ByaWF0ZSBub3JtYWwgZGlzdHJpYnV0aW9uIHByb2JhYmlsaXR5IGRlbnNpdHkgY3VydmU6Kg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1zaG93IiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KIyBTZXQgbXUgYW5kIHNpZ21hIGZvciB0aGUgYXBwcm94aW1hdGluZyBub3JtYWwgZGlzdHJpYnV0aW9uDQptdSA8LSBwDQpzaWdtYSA8LSBzcXJ0KHAqKDEgLSBwKSkNCiAgDQojIE92ZXJsYXkgdGhlIG5vcm1hbCBkZW5zaXR5DQpjdXJ2ZShkbm9ybSh4LCBtdSwgc2lnbWEvc3FydChucykpLCBhZGQgPSBUUlVFLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpDQpgYGANCg0KIyMNCg0KV2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHlvdXIgcmVzdWx0YW50IHBsb3Q/DQoNCiMjDQoNClJlcGVhdCBcQHJlZihleHBzaW0pIGZvciAkWCBcc2ltIEJFUk4oMC4zKSQsIHVzaW5nIGEgc2FtcGxlIG9mIDMwIGluc3RlYWQgb2YgNS4gV2hhdCBkbyB5b3Ugbm90aWNlIGFib3V0IHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIHNpbXVsYXRlZCBzYW1wbGUgbWVhbnM/DQoNCiMjDQoNCkZpbmFsbHksIHJlcGVhdCBcQHJlZihleHBzaW0pIGZvciAkWCBcc2ltIEJFUk4oMC4zKSQsIHVzaW5nIGEgc2FtcGxlIG9mIDYwLiBXaGF0IGRvIHlvdSBub3RpY2UgYWJvdXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgc2ltdWxhdGVkIHNhbXBsZSBtZWFucyBub3c/DQoNCiMgRXh0ZW5zaW9uIC0gQXZlcmFnZSBEaWFtb25kIFByaWNlcw0KDQpMZXQncyBjb25zaWRlciBob3cgd2UgY2FuIGFwcGx5IHRoZSBDZW50cmFsIExpbWl0IFRoZW9yZW0gdG8gcmVhbCBkYXRhLg0KDQpGb3IgdGhpcyBxdWVzdGlvbiwgd2Ugd2lsbCBjb25zaWRlciBkYXRhIG9uIGFwcHJveGltYXRlbHkgNTQsMDAwIHJvdW5kIGN1dCBkaWFtb25kcy4gVGhpcyBkYXRhIGlzIHN0b3JlZCBpbiB0aGUgYGRpYW1vbmRzYCBkYXRhIHNldCBpbiB0aGUgYGdncGxvdDJgIFIgcGFja2FnZS4gV2Ugd2lsbCB0cmVhdCB0aGlzIGRhdGEgYXMgdGhlIHBvcHVsYXRpb24gZGF0YS4NCg0KSW5zdGFsbCBhbmQgbG9hZCB0aGUgYGdncGxvdDJgIFIgcGFja2FnZSBub3cuDQoNCipIaW50OiBJZiB5b3UgbmVlZCBhIHJlZnJlc2hlciBvbiBpbnN0YWxsaW5nIGFuZCBsb2FkaW5nIHBhY2thZ2VzIGluIFIsIGNoZWNrIHRoZSBgQ29kZWAgY2h1bmsgYmVsb3c6Kg0KDQpgYGB7ciBjbGFzcy5zb3VyY2UgPSAiZm9sZC1oaWRlIiwgZXZhbCA9IEYsIGVjaG8gPSBUfQ0KIyBOb3RlIHRoYXQgeW91IHdpbGwgaGF2ZSB0byBjaGFuZ2UgdGhpcyBjb2RlIHRvIHRoZSByZWxldmFudCBwYWNrYWdlDQppbnN0YWxsLnBhY2thZ2VzKCJwYWxtZXJwZW5ndWlucyIpDQpsaWJyYXJ5KHBhbG1lcnBlbmd1aW5zKQ0KYGBgDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLWhpZGUiLCBldmFsID0gVCwgaW5jbHVkZSA9IEZ9DQpsaWJyYXJ5KGdncGxvdDIpDQpgYGANCg0KIyMNCg0KSWYgd2UgcGxvdCB0aGUgcHJpY2Ugb2Ygcm91bmQgY3V0IGRpYW1vbmRzIHVzaW5nIGEgaGlzdG9ncmFtLCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGRhdGEgaXMgY2xlYXJseSBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuDQoNCipNYWtlIHN1cmUgdG8gcnVuIHRoaXMgY29kZSBiZWZvcmUgY29udGludWluZy4qDQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFR9DQpoaXN0KGRpYW1vbmRzJHByaWNlLCBjb2wgPSAic2t5Ymx1ZSIsIHhsYWIgPSAiRGlhbW9uZCBQcmljZSAoJCkiLA0KICAgICBtYWluID0gIkhpc3RvZ3JhbSBvZiBEaWFtb25kIFByaWNlcyAoJCkiLCBmcmVxID0gRikNCmBgYA0KDQojIyB7I2RpYW1vbmRzaW19DQoNClN1cHBvc2UgdGhhdCB5b3UgYXJlIGludGVyZXN0ZWQgaW4gZXN0aW1hdGluZyB0aGUgcG9wdWxhdGlvbiBtZWFuIHByaWNlIGZvciByb3VuZCBjdXQgZGlhbW9uZHMsIGJ1dCBkbyBub3QgaGF2ZSBhY2Nlc3MgdG8gdGhlIGZ1bGwgYGRpYW1vbmRzYCBkYXRhIHNldC4NCg0KSW5zdGVhZCwgeW91IGNhbiBvbmx5IHNhbXBsZSBwcmljZXMgZm9yIDUgcm91bmQgY3V0IGRpYW1vbmRzIGF0IGEgdGltZSwgcmVwcmVzZW50ZWQgYnkgdGhlIGNvZGUgYmVsb3c6DQoNCmBgYHtyIGNsYXNzLnNvdXJjZSA9ICJmb2xkLXNob3ciLCBldmFsID0gVCwgZWNobyA9IFR9DQp4IDwtIHNhbXBsZShkaWFtb25kcyRwcmljZSwgNSkNCmBgYA0KDQpVc2luZyB0aGlzIGNvZGUgYW5kIHRoZSBjb2RlIGluIFxAcmVmKHNpbSkgYXMgYSBndWlkZSwgc2ltdWxhdGUgdGFraW5nIDEwMCBzYW1wbGVzIG9mIDUgcmFuZG9tIHJvdW5kIGN1dCBkaWFtb25kIHNhbGUgcHJpY2VzLCBhbmQgcGxvdCBhIGhpc3RvZ3JhbSBvZiB0aGUgcmVzdWx0YW50IHNhbXBsZSBtZWFucy4gV2hhdCBkbyB5b3Ugb2JzZXJ2ZT8NCg0KIyMgeyNkaWFtb25kc2ltbGFyZ2V9DQoNClJlcGVhdCBcQHJlZihkaWFtb25kc2ltKSwgYnV0IHRoaXMgdGltZSBzdXBwb3NlIHRoYXQgeW91IGFyZSBhYmxlIHRvIHRha2Ugc2FtcGxlcyBvZiAzMCBkaWFtb25kcyBhdCBhIHRpbWUsIGluc3RlYWQgb2YgNS4gV2hhdCBjaGFuZ2VzIGRvIHlvdSBvYnNlcnZlPyANCg0KPGJyPg0KDQojIyMjIEdyZWF0IGpvYiwgdGhhdCdzIGV2ZXJ5dGhpbmcgZm9yIHRvZGF5ISAjIyMjIHstfQ0KDQpIb3BlZnVsbHksIHRoaXMgY29tcHV0ZXIgbGFiIGhhcyBoZWxwZWQgY2VtZW50IHlvdXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgQ2VudHJhbCBMaW1pdCBUaGVvcmVtLg0KDQo8YnI+DQoNCiMgUmVmZXJlbmNlcyB7LSAjUmVmfQ0KPGRpdiBpZD0icmVmcyI+PC9kaXY+DQoNCjxicj4NCg0KPGZvbnQgY29sb3IgPSAiZ3JleSI+DQpUaGVzZSBub3RlcyBoYXZlIGJlZW4gcHJlcGFyZWQgYnkgUnVwZXJ0IEt1dmVrZSBhbmQgQW1hbmRhIFNoYWtlci4gVGhlIGNvcHlyaWdodCBmb3IgdGhlIG1hdGVyaWFsIGluIHRoZXNlIG5vdGVzIHJlc2lkZXMgd2l0aCB0aGUgYXV0aG9ycyBuYW1lZCBhYm92ZSwgd2l0aCB0aGUgRGVwYXJ0bWVudCBvZiBNYXRoZW1hdGljYWwgYW5kIFBoeXNpY2FsIFNjaWVuY2VzIGFuZCB3aXRoIExhIFRyb2JlIFVuaXZlcnNpdHkuIENvcHlyaWdodCBpbiB0aGlzIHdvcmsgaXMgdmVzdGVkIGluIExhIFRyb2JlIFVuaXZlcnNpdHkgaW5jbHVkaW5nIGFsbCBMYSBUcm9iZSBVbml2ZXJzaXR5IGJyYW5kaW5nIGFuZCBuYW1pbmcuIFVubGVzcyBvdGhlcndpc2Ugc3RhdGVkLCBtYXRlcmlhbCB3aXRoaW4gdGhpcyB3b3JrIGlzIGxpY2Vuc2VkIHVuZGVyIGEgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob24gQ29tbWVyY2lhbC1Ob24gRGVyaXZhdGl2ZXMgTGljZW5zZSANCjxhIGhyZWYgPSAiaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LW5jLW5kLzQuMC9DQyIgdGFyZ2V0PSJfYmxhbmsiPiBCWS1OQy1ORC4gPC9hPg0KPC9mb250Pg==