1.0 Introduction

The General Social Survey (GSS) is a sociological survey used to collect data on a wide variety of demographic characteristics and attitudes of residents of the United States. The data has been collected since 1972, approximately every 2 years, by the National Opinion Research Center (NORC) at the University of Chicago. The latest data is from the spring of 2016. The data for the each year the survey was carried out can be found here in STATA format, and here in SPSS format. The GSS Codebook, in PDF format, documents the survey data for all years. The R notebook can be found in the project’s Github page.

2.0 Variables of interest

This notebook is about making inferences about the true difference in average self-ranking in society between two populations: Americans who voted for Mitt Romney in the 2012 presidential election, and those who voted for Obama. The survey’s interviewer asked respondents: “In our society there are groups which tend to be towards the top and those that are towards the bottom. Here we have a scale that runs from top to bottom. Where would you put yourself on this scale?”, and coded the response as \(RANK\). The scale was from 1 to 10, where a 1 meant “at the top” and 10 “at the bottom”. A subset of the respondents (those who had previously stated they voted in the 2012 presidential elections and remembered who they had voted for) were also asked: “Did you vote for Obama or Romney?”, and their reponse was coded as \(PRES12\).

3.0 Reading the data

The R library foreign allows R to read in STATA files, among others. We can then get the variables we want as a two-column dataframe.

library(foreign) # Used to read STATA (*.DTA) files
gss2016 <- read.dta("GSS2016.DTA") # read the file
gss2016_voting_ranking <- gss2016[c("rank", "pres12")] # only need two fields
summary(gss2016_voting_ranking)
      rank          pres12     
 Min.   : 1.0   Min.   :1.000  
 1st Qu.: 4.0   1st Qu.:1.000  
 Median : 5.0   Median :1.000  
 Mean   : 4.8   Mean   :1.424  
 3rd Qu.: 6.0   3rd Qu.:2.000  
 Max.   :10.0   Max.   :5.000  
 NA's   :79     NA's   :1137   

Mini data munging

# Remove NA's
gss2016_voting_ranking <- gss2016_voting_ranking[!is.na(gss2016_voting_ranking$rank) & !is.na(gss2016_voting_ranking$pres12),]
# Keep only those who voted for either Obama or Romney
# Obama = 1, Romney = 2
gss2016_voting_ranking <- gss2016_voting_ranking[gss2016_voting_ranking$pres12 == 1 | gss2016_voting_ranking$pres12 == 2,]
# Replace "1" and "2" in the "pres12" variable
gss2016_voting_ranking$pres12[gss2016_voting_ranking$pres12 == 1] <- "Obama"
gss2016_voting_ranking$pres12[gss2016_voting_ranking$pres12 == 2] <- "Romney"
# Convert "pres12" to factor
gss2016_voting_ranking$pres12 <- factor(gss2016_voting_ranking$pres12)
summary(gss2016_voting_ranking)
      rank           pres12    
 Min.   : 1.000   Obama :1054  
 1st Qu.: 3.000   Romney: 571  
 Median : 5.000                
 Mean   : 4.598                
 3rd Qu.: 5.000                
 Max.   :10.000                
# Self-rank of those who voted for Romney
Romney_self_rank <- gss2016_voting_ranking[gss2016_voting_ranking$pres12 == "Romney",]$rank
# Number of respondents who voted for Romney
Romney_num <- length(Romney_self_rank)
# Average self-ranking of Romney voters
Romney_self_rank_mean <- mean(Romney_self_rank)
# Standard deviation of self-ranking of Romney voters
Romney_self_rank_sd <- sd(Romney_self_rank)
# Self-rank of those who voted for Romney
Obama_self_rank <- gss2016_voting_ranking[gss2016_voting_ranking$pres12 == "Obama",]$rank
# Number of respondents who voted for Romney
Obama_num <- length(Obama_self_rank)
# Average self-ranking of Romney voters
Obama_self_rank_mean <- mean(Obama_self_rank)
# Standard deviation of self-ranking of Romney voters
Obama_self_rank_sd <- sd(Obama_self_rank)
# Building the dataframe
Romney_column <- c(Romney_num, Romney_self_rank_mean, Romney_self_rank_sd)
Obama_column <- c(Obama_num, Obama_self_rank_mean, Obama_self_rank_sd)
summary_df <- data.frame(Romney_column, Obama_column)
rownames(summary_df) <- c("Number of observations", "Mean self-ranking", "Standard deviation of self-ranking")
colnames(summary_df) <- c("Romney", "Obama")
summary_df

4.0 \(95\%\) confidence interval of the difference in mean self-ranking

We can compute a \(95\%\) confidence interval for the true difference in mean self-ranking, \(\mu_{diff}\), between Americans who voted for Romney in 2012 and those who voted for Obama, by using the Central Limit Theorem (CLT). The CLT says that the sampling distribution of a statistic, in this case a difference between two independent means, is approximately normal, with the true difference, \(\mu_{diff}=\mu_1-\mu_2\), as its mean, and the standard error of the sample, \(SE=\sqrt{\frac{s^2_1}{n_1} + \frac{s^2_2}{n_2}}\), as its standard deviation, where \(n_1\) and \(n_2\) are the sizes of each set of samples.

\[ (\bar{x}_1-\bar{x}_2)\sim\ N(mean = \mu_{diff}, sd=\sqrt{\frac{\sigma^2_1}{n_1} + \frac{\sigma^2_2}{n_2}}) \]

If we were able to draw many samples from both populations (Americans who voted for Romney and those who voted for Obama), and computed the difference in mean self-ranking between each two-sample set, \((\bar{x}_1-\bar{x}_2)\), the CLT says the distribution of that difference in means is nearly normal.

In reality, we can only draw one sample from the population. We typically don’t know the true difference in mean self-ranking of the two populations, \(\mu_{diff}=\mu_1-\mu_2\), or the true standard deviations of either population, \(\sigma_1\) and \(\sigma_2\). We can use the standard deviations of the two samples, \(s_1\) and \(s_2\), as proxies for \(\sigma_1\) and \(\sigma_2\). We also don’t know where the difference in sample means we have drawn, \((\bar{x}_1-\bar{x}_2)\), falls in the sampling distribution, but from the CLT, we do know that the differences in means of \(95\%\) of the sample pairs drawn will fall within \(1.96\cdot \sqrt{\frac{\sigma^2_1}{n_1} + \frac{\sigma^2_2}{n_2}}=1.96\cdot SE\) of \(\mu_{diff}\). For \(95\%\) of the samples we draw, an interval within \(1.96\cdot \sqrt{\frac{s^2_1}{n_1} + \frac{s^2_2}{n_2}}=1.96\cdot SE_{(\bar{x}_1 - \bar{x}_2)}\) of \((\bar{x}_1-\bar{x}_2)\) will include the true difference in means between the two populations, \(\mu_{diff}\). For any two-sample set whose difference in means estimate \((\bar{x}_1-\bar{x}_2)\) falls within \(1.96\cdot SE\) of \(\mu_{diff}\), which will happen \(95\%\) of the time, we are \(95\%\) confident that an interval centered around \((\bar{x}_1-\bar{x}_2)\) and within \(1.96\cdot SE_{(\bar{x}_1 - \bar{x}_2)}\) of \((\bar{x}_1-\bar{x}_2)\) will contain the true difference in means of the two populations, \(\mu_{diff}\).

\(95\%\) confidence interval of the difference in population proportions of gun ownership:

\[ (\bar{x}_1-\bar{x}_2) \pm 1.96\cdot SE_{(\bar{x}_1 - \bar{x}_2)} = (\bar{x}_1-\bar{x}_2) \pm 1.96\cdot \sqrt{\frac{s^2_1}{n_1} + \frac{s^2_2}{n_2}} \]

4.1 An example

It is much easier to understand with an actual example and a plot. Suppose we have two populations with true means \(\mu_1=16\) and \(\mu_2=12\), true standard deviations \(\sigma_1=8.0\) and \(\sigma_2=6.0\), and so a true difference in means of \(\mu_{diff}=\mu_1-\mu_2=4.0\) between them, and we draw a sample of size \(n_1=n_2=100\) from each population. Per the CLT, the distribution of the difference in sample means taken from those two populations is approximately normal: \((\bar{x}_1-\bar{x}_2)\sim\ N(mean = 4.0, sd=\sqrt{\frac{8.0^2}{100} + \frac{6.0^2}{100}}=1.0)\). Any two-sample set drawn from the two populations whose difference in means estimate \((\bar{x}_1-\bar{x}_2)\) falls within \((4.0-1.96\cdot1.0,\ 4.0+1.96\cdot1.0)=(2.04,\ 5.96)\) will have a \(95\%\) confidence interval that contains the true difference in means, \(\mu_{diff}=4.0\). If we draw a sample from each population and the samples’ means are \(\bar{x}_1=17.25\) and \(\bar{x}_2=11.5\), the \(95\%\) confidence interval centered around \((\bar{x}_1-\bar{x}_2)=5.75\) will contain the true difference in means \(\mu_{diff}=4.0\). Since the person taking the samples typically doesn’t know either \(\sigma_1\) or \(\sigma_2\), she will use her samples’ standard deviations, \(s_1=8.5\) and \(s_2=5.5\), to compute \(SE_{(\bar{x}_1 - \bar{x}_2)}\), for the purposes of computing the \(95\%\) confidence interval. \(SE_{(\bar{x}_1 - \bar{x}_2)}\) will be: \(SE_{(\bar{x}_1 - \bar{x}_2)}=\sqrt{\frac{8.5^2}{100} + \frac{5.5^2}{100}}=\sqrt{0.7225+0.3025}=1.0124\), and the \(95\%\) confidence interval will be: \((5.75-1.96\cdot1.0124,\ 5.75+1.96\cdot1.0124)=(3.7657,\ 7.7343)\), which contains the true mean difference \(\mu_{diff}=4.0\).

If we are unlucky and draw samples whose difference in means \((\bar{x}_1-\bar{x}_2)\) falls in the shaded area, which should only happen \(5\%\) of the time, its \(95\%\) confidence interval will not include the true difference in means \(\mu_{diff}=4.0\). For example, if \(\bar{x}_1=17.5\), \(\sigma_1=8.75\), \(\bar{x}_2=11.0\), and \(\sigma_2=5.5\), and again each sample has \(100\) observations, then \((\bar{x}_1-\bar{x}_2)=6.5\) and \(SE_{(\bar{x}_1 - \bar{x}_2)}=\sqrt{\frac{8.75^2}{100} + \frac{5.5^2}{100}}=\sqrt{0.7656+0.3025}=1.0335\). The \(95\%\) confidence interval will be \((6.5-1.96\cdot1.0335,\ 6.5+1.96\cdot1.0335)=(4.4743,\ 8.5257)\). That confidence interval will not include the true difference in means, \(\mu_{diff}=4.0\).

#http://www.statmethods.net/advgraphs/probability.html
n_1_example <- 100; n_2_example <- 100
mu_1 <- 16.0; mu_2 <- 12.0; mu_diff <- mu_1 - mu_2
sigma_1 <- 8.0; sigma_2 <- 6.0
se <- sqrt(sigma_1 ^ 2 / n_1_example + sigma_2 ^ 2 / n_2_example)
# x = p_diff +/- 5 std_dev's
x <- seq(-5,5,length=1000)*se + mu_diff
hx <- dnorm(x, mu_diff ,se)
# Values used to shade areas under the curve
upper_bound <- mu_diff + 1.96 * se 
lower_bound <- mu_diff - 1.96 * se 
plot(x, hx, type="n", xlab = "", ylab="", main="Sampling distribution of a difference in means", axes=FALSE)
i <- x >= upper_bound & x <= max(x) # indexes of x where x >= upper_bound
lines(x, hx) # plots normal distribution
polygon(c(upper_bound,x[i],max(x)), c(0,hx[i],0), col="grey") # shades area grey where x >= upper_bound
j <- x >= min(x) & x <= lower_bound # indexes of x where x <= than lower_bound
polygon(c(min(x),x[j],lower_bound), c(0,hx[j],0), col="grey") # shades area grey where x <= lower_bound
axis(1, at=seq(0.00, 10.0, 0.5), pos=0) # draws axis
abline(v=mu_diff)
grid()
x_1_hat <- 17.5; x_2_hat <- 11.0; mu_diff_hat_example <- x_1_hat - x_2_hat
s_1 <- 8.75; s_2 <- 5.5
se_mu_diff_hat <- sqrt(s_1 ^ 2 / n_1_example + s_2 ^ 2 / n_2_example)
axis(1, at=c(mu_diff_hat_example - 1.96 * se_mu_diff_hat, mu_diff_hat_example, mu_diff_hat_example + 1.96 * se_mu_diff_hat), pos=-0.1, col = "blue", lwd = 2, lwd.ticks = 1) 
text(x = 0.6, y = 0.37, labels = expression(paste(mu[diff], " = 4.0")))
text(x = 0.8, y = 0.33, labels = expression(paste(n[1], " = ", n[2],  " = 100")))
text(x = 0.65, y = 0.29, labels = expression(paste(SE, " = 1.00")))
text(x = 0.825, y = 0.255, labels = expression(paste(bar(x)[1]-bar(x)[2], " = 6.5")))
text(x = 1.0, y = 0.22, labels = expression(paste(SE[bar(x)[1]-bar(x)[2]], " = 1.0335")))

4.2 Conditions for the confidence interval

The confidence interval of the difference in means is given by

\[ \bar{x}_{diff}\pm z^*\cdot SE \]

where \(\bar{x}_{diff}=\bar{x}_{1}-\bar{x}_{2}\), is this sample pair’s point estimate of the difference in mean self-ranking between Obama and Romney voters, \(z^*\) is the critical value corresponding to the confidence level we want, and the standard error \(SE\) is given by:

\[ SE=\sqrt{\frac{s_1^{2}}{n_1}+\frac{s_2^{2}}{n_2}} \]

where \(s_1\) and \(s_2\) are the standard deviations of the samples, and \(n_1\) and \(n_2\) the number of observations of each sample.

The conditions for the validity of the confidence interval are:

  1. Sampled observations must be independent, both within groups and between groups.

  2. Each sample size is large: \(n_1\geq 30\) and \(n_2\geq 30\)

  3. The distribution of each sample’s observations is not strongly skewed.

Each observation within a sample is independent of the next, i.e., each respondent who voted for Romney is independent of all other respondents who voted for Romney. Also, respondents who voted for Romney are independent of those who voted for Obama. The data is not paired. That takes care of the first condition.

As we saw in the table on section \(3.0\), there were \(571\) Romney voters and \(1054\) Obama voters, so each sample size is much larger than \(30\).

Finally, we can take a look at the sample distributions

par(mfrow = c(1,2))
hist(Romney_self_rank, main = "Self-ranking in society\n of Romney voters", xlab = "Self-ranking in society", ylab = "Fraction of respondents", freq = FALSE)
hist(Obama_self_rank, main = "Self-ranking in society\n of Obama voters", xlab = "Self-ranking in society", ylab = "Fraction of respondents", freq = FALSE)

Although both distributions are a little right-skewed, it’s not too bad.

4.3 Critical value \(z^*\)

The \(z^*\) corresponding to a \(95\%\) confidence interval in the standard normal distribution can be computed using R:

z_star_95 <- qnorm(p = 0.025, mean = 0, sd = 1, lower.tail = FALSE)
cat("z-value corresponding to 95% confidence interval:", z_star_95)
z-value corresponding to 95% confidence interval: 1.959964

4.4 Standard error

Computing the standard error of the sample using the results from section \(3.0\).

se <- sqrt(Obama_self_rank_sd^2 / Obama_num + Romney_self_rank_sd^2 / Romney_num)
cat("Standard error:", se)
Standard error: 0.08857513

4.5 Confidence interval

Computing the confidence interval bounds

diff_in_avg <- Obama_self_rank_mean - Romney_self_rank_mean
conf_int_lb <- diff_in_avg - z_star_95 * se
conf_int_ub <- diff_in_avg + z_star_95 * se
cat("Difference in mean self-ranking:", diff_in_avg, "\nConfidence interval lower bound:", conf_int_lb, "\nConfidence interval upper bound:", conf_int_ub)
Difference in mean self-ranking: 0.1796791 
Confidence interval lower bound: 0.00607504 
Confidence interval upper bound: 0.3532832

Hence, our confidence interval is \[ 0.1797\pm 1.96\cdot 0.0886=(0.0061, 0.3533) \]

We are \(95\%\) confident that the true difference in mean self-ranking between Obama and Romney voters, \(\mu_{diff}\), is between \(0.0061\) and \(0.3533\).

5.0 Hypothesis testing

We can use the CLT and the data collected to construct a hypothesis testing framework. The hypothesis test considers two possible interpretations of our data, a null hypothesis \(H_0\), and an alternative hypothesis \(H_a\). \(H_0\) basically says that the sampled data could have been drawn simply by chance, and so, it is misleading. There is “nothing going on”. \(H_a\) takes the view that the data collected reveals that “something is going on”. We will either reject the null hypothesis in favor of this alternative, or we will fail to reject it and conclude the sampled data could have been drawn simply by chance. Note that even if we fail to reject \(H_0\), that does not mean we accept it as the ground truth, it’s just that the data we have collected does not allows us to discard \(H_0\).

Suppose we want to find out if the \(0.1797\) difference in mean self-ranking is statistically significant. Our null hypothesis \(H_0\) is:

\[ H_0: The\ true\ difference\ in\ mean\ self-ranking\\ between\ Obama\ and\ Romney\ voters\ is\ \mu_{diff}=0 \\ H_a: \mu_{diff}\neq 0 \]

To perform the test, we assume that \(H_0\) is true and ask, given that \(H_0\) is true, how probable it is to observe data as extreme or more as the one we have.

5.1 The p-value

The p-value quantifies the strength of the evidence against the null hypothesis. We compute it by asking ourselves, given that the null hypothesis \(H_0\) is true, what is the probability of observing data as extreme or more as the one we have.

\[ P(observing\ data\ as\ extreme\ or\ more\ |\ H_{0}\ is\ true) \]

That probability is the p-value. Typically, we use a \(5\%\) significance level as the threshold to reject the null. If the p-value is less than \(5\%\), we reject the null in favor of the alternative.

Our hypothesis test is two-sided. The null hypothesis is that \(\mu_{diff}=0\), so by asking what is the probability of \(observing\ data\ as\ extreme\ or\ more\) in a world in which the null hypothesis is true, we are wondering how probable it is to draw a sample with a difference in means of \(0.1797\) or higher like the one we have drawn, or one with a difference in proportions of \(-0.1797\) or lower. Let’s see it graphically.

#http://www.statmethods.net/advgraphs/probability.html
mu_diff <- 0.00
x <- seq(-4,4,length=1000)*se + mu_diff
hx <- dnorm(x, mu_diff, se)
lb <- diff_in_avg; ub <- max(x)
plot(x, hx, type="n", xlab="Difference in mean self-ranking between Obama and Romney voters", ylab="", main="Sampling distribution under null hypothesis", axes=FALSE)
i <- x >= lb & x <= ub # indexes of x where x >=  lb 
lines(x, hx) # plots normal distribution
polygon(c(lb,x[i],ub), c(0,hx[i],0), col="red") # shades area where x >= lb in red
j <- x >= min(x) & x <= -lb # indexes of x where x <= -lb 
polygon(c(min(x),x[j],-lb), c(0,hx[j],0), col="red") # shades area where x <= -lb in red
axis(1, at=seq(-0.4, 0.4, 0.05), pos=0) # draws axis
abline(v=mu_diff)
grid()


Under the null hypothesis, we live in a world in which the sampling distribution of the difference in mean self-ranking between Obama and Romney voters is centered at \(\mu_{diff} = 0.0\) and has a standard distribution of \(sd=0.1797\). In such a world, we have drawn a sample where the difference in means is \(\bar{x}_{diff}=0.1797\). What is the probability of drawing a sample with a difference in means \(\bar{x}_{diff}\) as high or higher, in either direction, in a world in which the null hypothesis is true?

\[ P(drawing\ a\ sample\ where\ the\ difference\ in\ mean\ self-ranking\\ between\ Obama\ and\ Romney\ voters\ is\ as\ large\ or\ larger\ than\ 0.1797 |\ H_{0}\ is\ true) \\ P(\bar{x}_{diff}\ \geq\ 0.1797\ or\ \bar{x}_{diff}\ \leq\ -0.1797 |\ \mu_{diff} = 0) \]

That probability is the area under the sampling distribution shaded in red in the plot. It can be computed using pnorm().

area <- 2 * pnorm(q = diff_in_avg, mean = mu_diff, sd = se, lower.tail = FALSE)
# Multiplied by 2 because the hypothesis test is two-sided.
cat("Our p-value:", area)
Our p-value: 0.04250412

So our p-value, the probability of drawing a sample pair with \(\bar{x}_{diff}=0.1797\) or higher, or one with \(\bar{x}_{diff}=-0.1797\) or lower, under the null hypothesis, is about \(0.043\). At the \(5\%\) significance level, we can (barely) reject the null hypothesis. Looking at the confidence interval, we might have surmised that it was going to be close, since the confidence interval almost includes the null value, \(0\). The lower bound of the confidence interval for \(\bar{x}_{diff}\) is \(0.0061\), and our null value is \(\mu_{diff}=0\).

References

  1. Çetinkaya-Rundel, M. Data Analysis and Statistical Inference. Spring 2014. Coursera.

  2. Diez, D., Barr, C., Çetinkaya-Rundel, M. OpenIntro Statistics, Second Edition. PDF.

  3. Navidi, W. Statistics for engineers and scientists, Third Edition. New York: McGraw Hill, 2011.

  4. UCLA Institute for Digital Reserach and Education, HOW CAN I INCLUDE GREEK LETTERS IN MY PLOT LABELS? | R CODE FRAGMENTS. Retrieved from https://stats.idre.ucla.edu

  5. Kabacoff, R. Probability Plots. Retrieved from http://www.statmethods.net

  6. Carlos Cinelli and Tom, Code chunk font size in Rmarkdown with knitr and latex. Retrieved from https://stackoverflow.com

  7. DrewConway and Christopher DuBois, Getting LaTeX into R Plots. Retrieved from https://stackoverflow.com

LS0tDQp0aXRsZTogIkNvbXBhcmluZyB0d28gcG9wdWxhdGlvbiBtZWFucyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB0cnVlDQogICAgdG9jX2RlcHRoOiA1DQogICAgdG9jX2Zsb2F0OiB0cnVlDQotLS0NCg0KPHN0eWxlIHR5cGU9InRleHQvY3NzIj4NCg0KYm9keSwgdGQgew0KICAgZm9udC1zaXplOiAxOHB4Ow0KfQ0KaDEgew0KICBmb250LXNpemU6IDMycHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KaDIgew0KICBmb250LXNpemU6IDI4cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KaDMgew0KICBmb250LXNpemU6IDI0cHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KaDQgew0KICBmb250LXNpemU6IDIwcHg7DQogIGZvbnQtd2VpZ2h0OiBib2xkOw0KfQ0KY29kZS5yew0KICBmb250LXNpemU6IDE2cHg7DQp9DQpwcmUgew0KICBmb250LXNpemU6IDE2cHgNCn0NCjwvc3R5bGU+DQoNCiMjIDEuMCBJbnRyb2R1Y3Rpb24NCg0KVGhlIFtHZW5lcmFsIFNvY2lhbCBTdXJ2ZXkgKEdTUyldKGh0dHA6Ly9nc3Mubm9yYy5vcmcvKSBpcyBhIHNvY2lvbG9naWNhbCBzdXJ2ZXkgdXNlZCB0byBjb2xsZWN0IGRhdGEgb24gYSB3aWRlIHZhcmlldHkgb2YgZGVtb2dyYXBoaWMgY2hhcmFjdGVyaXN0aWNzIGFuZCBhdHRpdHVkZXMgb2YgcmVzaWRlbnRzIG9mIHRoZSBVbml0ZWQgU3RhdGVzLiBUaGUgZGF0YSBoYXMgYmVlbiBjb2xsZWN0ZWQgc2luY2UgMTk3MiwgYXBwcm94aW1hdGVseSBldmVyeSAyIHllYXJzLCBieSB0aGUgW05hdGlvbmFsIE9waW5pb24gUmVzZWFyY2ggQ2VudGVyIChOT1JDKV0oaHR0cDovL3d3dy5ub3JjLm9yZy9QYWdlcy9kZWZhdWx0LmFzcHgpIGF0IHRoZSBVbml2ZXJzaXR5IG9mIENoaWNhZ28uIFRoZSBsYXRlc3QgZGF0YSBpcyBmcm9tIHRoZSBzcHJpbmcgb2YgMjAxNi4gVGhlIGRhdGEgZm9yIHRoZSBlYWNoIHllYXIgdGhlIHN1cnZleSB3YXMgY2FycmllZCBvdXQgY2FuIGJlIGZvdW5kIFtoZXJlXShodHRwOi8vZ3NzLm5vcmMub3JnL2dldC10aGUtZGF0YS9zdGF0YSkgaW4gU1RBVEEgZm9ybWF0LCBhbmQgW2hlcmVdKGh0dHA6Ly9nc3Mubm9yYy5vcmcvZ2V0LXRoZS1kYXRhL3Nwc3MpIGluIFNQU1MgZm9ybWF0LiBUaGUgW0dTUyBDb2RlYm9va10oaHR0cDovL2dzcy5ub3JjLm9yZy9HZXQtRG9jdW1lbnRhdGlvbiksIGluIFBERiBmb3JtYXQsIGRvY3VtZW50cyB0aGUgc3VydmV5IGRhdGEgZm9yIGFsbCB5ZWFycy4gVGhlIFIgbm90ZWJvb2sgY2FuIGJlIGZvdW5kIGluIHRoZSBwcm9qZWN0J3MgW0dpdGh1YiBwYWdlXShodHRwczovL2dpdGh1Yi5jb20vY2FybG9zcm9yL3N0YXQtaW5mLWNvbXBhcmluZy10d28tbWVhbnMpLg0KDQojIyAyLjAgVmFyaWFibGVzIG9mIGludGVyZXN0DQoNClRoaXMgbm90ZWJvb2sgaXMgYWJvdXQgbWFraW5nIGluZmVyZW5jZXMgYWJvdXQgdGhlIHRydWUgZGlmZmVyZW5jZSBpbiBhdmVyYWdlIHNlbGYtcmFua2luZyBpbiBzb2NpZXR5IGJldHdlZW4gdHdvIHBvcHVsYXRpb25zOiBBbWVyaWNhbnMgd2hvIHZvdGVkIGZvciBNaXR0IFJvbW5leSBpbiB0aGUgMjAxMiBwcmVzaWRlbnRpYWwgZWxlY3Rpb24sIGFuZCB0aG9zZSB3aG8gdm90ZWQgZm9yIE9iYW1hLiBUaGUgc3VydmV5J3MgaW50ZXJ2aWV3ZXIgYXNrZWQgcmVzcG9uZGVudHM6ICoqIkluIG91ciBzb2NpZXR5IHRoZXJlIGFyZSBncm91cHMgd2hpY2ggdGVuZCB0byBiZSB0b3dhcmRzIHRoZSB0b3AgYW5kIHRob3NlIHRoYXQgYXJlIHRvd2FyZHMgdGhlIGJvdHRvbS4gSGVyZSB3ZSBoYXZlIGEgc2NhbGUgdGhhdCBydW5zIGZyb20gdG9wIHRvIGJvdHRvbS4gV2hlcmUgd291bGQgeW91IHB1dCB5b3Vyc2VsZiBvbiB0aGlzIHNjYWxlPyIqKiwgYW5kIGNvZGVkIHRoZSByZXNwb25zZSBhcyAkUkFOSyQuIFRoZSBzY2FsZSB3YXMgZnJvbSAxIHRvIDEwLCB3aGVyZSBhIDEgbWVhbnQgImF0IHRoZSB0b3AiIGFuZCAxMCAiYXQgdGhlIGJvdHRvbSIuIEEgc3Vic2V0IG9mIHRoZSByZXNwb25kZW50cyAodGhvc2Ugd2hvIGhhZCBwcmV2aW91c2x5IHN0YXRlZCB0aGV5IHZvdGVkIGluIHRoZSAyMDEyIHByZXNpZGVudGlhbCBlbGVjdGlvbnMgYW5kIHJlbWVtYmVyZWQgd2hvIHRoZXkgaGFkIHZvdGVkIGZvcikgd2VyZSBhbHNvIGFza2VkOiAqKiJEaWQgeW91IHZvdGUgZm9yIE9iYW1hIG9yIFJvbW5leT8iKiosIGFuZCB0aGVpciByZXBvbnNlIHdhcyBjb2RlZCBhcyAkUFJFUzEyJC4NCg0KIyMgMy4wIFJlYWRpbmcgdGhlIGRhdGENCg0KVGhlIFIgbGlicmFyeSBbKipmb3JlaWduKipdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9mb3JlaWduL2ZvcmVpZ24ucGRmKSBhbGxvd3MgUiB0byByZWFkIGluIFNUQVRBIGZpbGVzLCBhbW9uZyBvdGhlcnMuIFdlIGNhbiB0aGVuIGdldCB0aGUgdmFyaWFibGVzIHdlIHdhbnQgYXMgYSB0d28tY29sdW1uIGRhdGFmcmFtZS4NCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KGZvcmVpZ24pICMgVXNlZCB0byByZWFkIFNUQVRBICgqLkRUQSkgZmlsZXMNCmdzczIwMTYgPC0gcmVhZC5kdGEoIkdTUzIwMTYuRFRBIikgIyByZWFkIHRoZSBmaWxlDQpnc3MyMDE2X3ZvdGluZ19yYW5raW5nIDwtIGdzczIwMTZbYygicmFuayIsICJwcmVzMTIiKV0gIyBvbmx5IG5lZWQgdHdvIGZpZWxkcw0KDQpzdW1tYXJ5KGdzczIwMTZfdm90aW5nX3JhbmtpbmcpDQpgYGANCg0KTWluaSBkYXRhIG11bmdpbmcNCmBgYHtyfQ0KIyBSZW1vdmUgTkEncw0KZ3NzMjAxNl92b3RpbmdfcmFua2luZyA8LSBnc3MyMDE2X3ZvdGluZ19yYW5raW5nWyFpcy5uYShnc3MyMDE2X3ZvdGluZ19yYW5raW5nJHJhbmspICYgIWlzLm5hKGdzczIwMTZfdm90aW5nX3JhbmtpbmckcHJlczEyKSxdDQojIEtlZXAgb25seSB0aG9zZSB3aG8gdm90ZWQgZm9yIGVpdGhlciBPYmFtYSBvciBSb21uZXkNCiMgT2JhbWEgPSAxLCBSb21uZXkgPSAyDQpnc3MyMDE2X3ZvdGluZ19yYW5raW5nIDwtIGdzczIwMTZfdm90aW5nX3JhbmtpbmdbZ3NzMjAxNl92b3RpbmdfcmFua2luZyRwcmVzMTIgPT0gMSB8IGdzczIwMTZfdm90aW5nX3JhbmtpbmckcHJlczEyID09IDIsXQ0KDQojIFJlcGxhY2UgIjEiIGFuZCAiMiIgaW4gdGhlICJwcmVzMTIiIHZhcmlhYmxlDQpnc3MyMDE2X3ZvdGluZ19yYW5raW5nJHByZXMxMltnc3MyMDE2X3ZvdGluZ19yYW5raW5nJHByZXMxMiA9PSAxXSA8LSAiT2JhbWEiDQpnc3MyMDE2X3ZvdGluZ19yYW5raW5nJHByZXMxMltnc3MyMDE2X3ZvdGluZ19yYW5raW5nJHByZXMxMiA9PSAyXSA8LSAiUm9tbmV5Ig0KDQojIENvbnZlcnQgInByZXMxMiIgdG8gZmFjdG9yDQpnc3MyMDE2X3ZvdGluZ19yYW5raW5nJHByZXMxMiA8LSBmYWN0b3IoZ3NzMjAxNl92b3RpbmdfcmFua2luZyRwcmVzMTIpDQoNCnN1bW1hcnkoZ3NzMjAxNl92b3RpbmdfcmFua2luZykNCmBgYA0KDQpgYGB7cn0NCiMgU2VsZi1yYW5rIG9mIHRob3NlIHdobyB2b3RlZCBmb3IgUm9tbmV5DQpSb21uZXlfc2VsZl9yYW5rIDwtIGdzczIwMTZfdm90aW5nX3JhbmtpbmdbZ3NzMjAxNl92b3RpbmdfcmFua2luZyRwcmVzMTIgPT0gIlJvbW5leSIsXSRyYW5rDQojIE51bWJlciBvZiByZXNwb25kZW50cyB3aG8gdm90ZWQgZm9yIFJvbW5leQ0KUm9tbmV5X251bSA8LSBsZW5ndGgoUm9tbmV5X3NlbGZfcmFuaykNCiMgQXZlcmFnZSBzZWxmLXJhbmtpbmcgb2YgUm9tbmV5IHZvdGVycw0KUm9tbmV5X3NlbGZfcmFua19tZWFuIDwtIG1lYW4oUm9tbmV5X3NlbGZfcmFuaykNCiMgU3RhbmRhcmQgZGV2aWF0aW9uIG9mIHNlbGYtcmFua2luZyBvZiBSb21uZXkgdm90ZXJzDQpSb21uZXlfc2VsZl9yYW5rX3NkIDwtIHNkKFJvbW5leV9zZWxmX3JhbmspDQoNCiMgU2VsZi1yYW5rIG9mIHRob3NlIHdobyB2b3RlZCBmb3IgUm9tbmV5DQpPYmFtYV9zZWxmX3JhbmsgPC0gZ3NzMjAxNl92b3RpbmdfcmFua2luZ1tnc3MyMDE2X3ZvdGluZ19yYW5raW5nJHByZXMxMiA9PSAiT2JhbWEiLF0kcmFuaw0KIyBOdW1iZXIgb2YgcmVzcG9uZGVudHMgd2hvIHZvdGVkIGZvciBSb21uZXkNCk9iYW1hX251bSA8LSBsZW5ndGgoT2JhbWFfc2VsZl9yYW5rKQ0KIyBBdmVyYWdlIHNlbGYtcmFua2luZyBvZiBSb21uZXkgdm90ZXJzDQpPYmFtYV9zZWxmX3JhbmtfbWVhbiA8LSBtZWFuKE9iYW1hX3NlbGZfcmFuaykNCiMgU3RhbmRhcmQgZGV2aWF0aW9uIG9mIHNlbGYtcmFua2luZyBvZiBSb21uZXkgdm90ZXJzDQpPYmFtYV9zZWxmX3Jhbmtfc2QgPC0gc2QoT2JhbWFfc2VsZl9yYW5rKQ0KDQojIEJ1aWxkaW5nIHRoZSBkYXRhZnJhbWUNClJvbW5leV9jb2x1bW4gPC0gYyhSb21uZXlfbnVtLCBSb21uZXlfc2VsZl9yYW5rX21lYW4sIFJvbW5leV9zZWxmX3Jhbmtfc2QpDQpPYmFtYV9jb2x1bW4gPC0gYyhPYmFtYV9udW0sIE9iYW1hX3NlbGZfcmFua19tZWFuLCBPYmFtYV9zZWxmX3Jhbmtfc2QpDQoNCnN1bW1hcnlfZGYgPC0gZGF0YS5mcmFtZShSb21uZXlfY29sdW1uLCBPYmFtYV9jb2x1bW4pDQoNCnJvd25hbWVzKHN1bW1hcnlfZGYpIDwtIGMoIk51bWJlciBvZiBvYnNlcnZhdGlvbnMiLCAiTWVhbiBzZWxmLXJhbmtpbmciLCAiU3RhbmRhcmQgZGV2aWF0aW9uIG9mIHNlbGYtcmFua2luZyIpDQoNCmNvbG5hbWVzKHN1bW1hcnlfZGYpIDwtIGMoIlJvbW5leSIsICJPYmFtYSIpDQpzdW1tYXJ5X2RmDQpgYGANCg0KIyMgNC4wICQ5NVwlJCBjb25maWRlbmNlIGludGVydmFsIG9mIHRoZSBkaWZmZXJlbmNlIGluIG1lYW4gc2VsZi1yYW5raW5nDQoNCldlIGNhbiBjb21wdXRlIGEgJDk1XCUkIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIHRoZSB0cnVlIGRpZmZlcmVuY2UgaW4gbWVhbiBzZWxmLXJhbmtpbmcsICRcbXVfe2RpZmZ9JCwgYmV0d2VlbiBBbWVyaWNhbnMgd2hvIHZvdGVkIGZvciBSb21uZXkgaW4gMjAxMiBhbmQgdGhvc2Ugd2hvIHZvdGVkIGZvciBPYmFtYSwgYnkgdXNpbmcgdGhlIFtDZW50cmFsIExpbWl0IFRoZW9yZW0gKENMVCldKGh0dHA6Ly93d3cuc3RhdC53bWljaC5lZHUvczE2MC9ib29rL25vZGU0My5odG1sKS4gVGhlIENMVCBzYXlzIHRoYXQgdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiBvZiBhIHN0YXRpc3RpYywgaW4gdGhpcyBjYXNlIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHR3byBpbmRlcGVuZGVudCBtZWFucywgaXMgYXBwcm94aW1hdGVseSBub3JtYWwsIHdpdGggdGhlIHRydWUgZGlmZmVyZW5jZSwgJFxtdV97ZGlmZn09XG11XzEtXG11XzIkLCBhcyBpdHMgbWVhbiwgYW5kIHRoZSBzdGFuZGFyZCBlcnJvciBvZiB0aGUgc2FtcGxlLCAkU0U9XHNxcnR7XGZyYWN7c14yXzF9e25fMX0gKyBcZnJhY3tzXjJfMn17bl8yfX0kLCBhcyBpdHMgc3RhbmRhcmQgZGV2aWF0aW9uLCB3aGVyZSAkbl8xJCBhbmQgJG5fMiQgYXJlIHRoZSBzaXplcyBvZiBlYWNoIHNldCBvZiBzYW1wbGVzLiANCg0KJCQNCihcYmFye3h9XzEtXGJhcnt4fV8yKVxzaW1cIE4obWVhbiA9IFxtdV97ZGlmZn0sIHNkPVxzcXJ0e1xmcmFje1xzaWdtYV4yXzF9e25fMX0gKyBcZnJhY3tcc2lnbWFeMl8yfXtuXzJ9fSkNCiQkDQoNCklmIHdlIHdlcmUgYWJsZSB0byBkcmF3IG1hbnkgc2FtcGxlcyBmcm9tIGJvdGggcG9wdWxhdGlvbnMgKEFtZXJpY2FucyB3aG8gdm90ZWQgZm9yIFJvbW5leSBhbmQgdGhvc2Ugd2hvIHZvdGVkIGZvciBPYmFtYSksIGFuZCBjb21wdXRlZCB0aGUgZGlmZmVyZW5jZSBpbiBtZWFuIHNlbGYtcmFua2luZyBiZXR3ZWVuIGVhY2ggdHdvLXNhbXBsZSBzZXQsICQoXGJhcnt4fV8xLVxiYXJ7eH1fMikkLCB0aGUgQ0xUIHNheXMgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGF0IGRpZmZlcmVuY2UgaW4gbWVhbnMgaXMgbmVhcmx5IG5vcm1hbC4gDQoNCkluIHJlYWxpdHksIHdlIGNhbiBvbmx5IGRyYXcgb25lIHNhbXBsZSBmcm9tIHRoZSBwb3B1bGF0aW9uLiBXZSB0eXBpY2FsbHkgZG9uJ3Qga25vdyB0aGUgdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW4gc2VsZi1yYW5raW5nIG9mIHRoZSB0d28gcG9wdWxhdGlvbnMsICRcbXVfe2RpZmZ9PVxtdV8xLVxtdV8yJCwgb3IgdGhlIHRydWUgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiBlaXRoZXIgcG9wdWxhdGlvbiwgJFxzaWdtYV8xJCBhbmQgJFxzaWdtYV8yJC4gV2UgY2FuIHVzZSB0aGUgc3RhbmRhcmQgZGV2aWF0aW9ucyBvZiB0aGUgdHdvIHNhbXBsZXMsICRzXzEkIGFuZCAkc18yJCwgYXMgcHJveGllcyBmb3IgJFxzaWdtYV8xJCBhbmQgJFxzaWdtYV8yJC4gV2UgYWxzbyBkb24ndCBrbm93IHdoZXJlIHRoZSBkaWZmZXJlbmNlIGluIHNhbXBsZSBtZWFucyB3ZSBoYXZlIGRyYXduLCAkKFxiYXJ7eH1fMS1cYmFye3h9XzIpJCwgZmFsbHMgaW4gdGhlIHNhbXBsaW5nIGRpc3RyaWJ1dGlvbiwgYnV0IGZyb20gdGhlIENMVCwgd2UgZG8ga25vdyB0aGF0IHRoZSBkaWZmZXJlbmNlcyBpbiBtZWFucyBvZiAkOTVcJSQgb2YgdGhlIHNhbXBsZSBwYWlycyBkcmF3biB3aWxsIGZhbGwgd2l0aGluICQxLjk2XGNkb3QgXHNxcnR7XGZyYWN7XHNpZ21hXjJfMX17bl8xfSArIFxmcmFje1xzaWdtYV4yXzJ9e25fMn19PTEuOTZcY2RvdCBTRSQgb2YgJFxtdV97ZGlmZn0kLiBGb3IgJDk1XCUkIG9mIHRoZSBzYW1wbGVzIHdlIGRyYXcsIGFuIGludGVydmFsIHdpdGhpbiAkMS45NlxjZG90IFxzcXJ0e1xmcmFje3NeMl8xfXtuXzF9ICsgXGZyYWN7c14yXzJ9e25fMn19PTEuOTZcY2RvdCBTRV97KFxiYXJ7eH1fMSAtIFxiYXJ7eH1fMil9JCBvZiAkKFxiYXJ7eH1fMS1cYmFye3h9XzIpJCB3aWxsIGluY2x1ZGUgdGhlIHRydWUgZGlmZmVyZW5jZSBpbiBtZWFucyBiZXR3ZWVuIHRoZSB0d28gcG9wdWxhdGlvbnMsICRcbXVfe2RpZmZ9JC4gRm9yIGFueSB0d28tc2FtcGxlIHNldCB3aG9zZSBkaWZmZXJlbmNlIGluIG1lYW5zIGVzdGltYXRlICQoXGJhcnt4fV8xLVxiYXJ7eH1fMikkIGZhbGxzIHdpdGhpbiAkMS45NlxjZG90IFNFJCBvZiAkXG11X3tkaWZmfSQsIHdoaWNoIHdpbGwgaGFwcGVuICQ5NVwlJCBvZiB0aGUgdGltZSwgd2UgYXJlICQ5NVwlJCBjb25maWRlbnQgdGhhdCBhbiBpbnRlcnZhbCBjZW50ZXJlZCBhcm91bmQgJChcYmFye3h9XzEtXGJhcnt4fV8yKSQgYW5kIHdpdGhpbiAkMS45NlxjZG90IFNFX3soXGJhcnt4fV8xIC0gXGJhcnt4fV8yKX0kIG9mICQoXGJhcnt4fV8xLVxiYXJ7eH1fMikkIHdpbGwgY29udGFpbiB0aGUgdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW5zIG9mIHRoZSB0d28gcG9wdWxhdGlvbnMsICRcbXVfe2RpZmZ9JC4NCg0KKiokOTVcJSQgY29uZmlkZW5jZSBpbnRlcnZhbCBvZiB0aGUgZGlmZmVyZW5jZSBpbiBwb3B1bGF0aW9uIHByb3BvcnRpb25zIG9mIGd1biBvd25lcnNoaXA6KioNCg0KJCQNCihcYmFye3h9XzEtXGJhcnt4fV8yKSBccG0gMS45NlxjZG90IFNFX3soXGJhcnt4fV8xIC0gXGJhcnt4fV8yKX0gPSAoXGJhcnt4fV8xLVxiYXJ7eH1fMikgXHBtIDEuOTZcY2RvdCBcc3FydHtcZnJhY3tzXjJfMX17bl8xfSArIFxmcmFje3NeMl8yfXtuXzJ9fQ0KJCQNCg0KIyMjIDQuMSBBbiBleGFtcGxlDQoNCkl0IGlzIG11Y2ggZWFzaWVyIHRvIHVuZGVyc3RhbmQgd2l0aCBhbiBhY3R1YWwgZXhhbXBsZSBhbmQgYSBwbG90LiBTdXBwb3NlIHdlIGhhdmUgdHdvIHBvcHVsYXRpb25zIHdpdGggdHJ1ZSBtZWFucyAkXG11XzE9MTYkIGFuZCAkXG11XzI9MTIkLCB0cnVlIHN0YW5kYXJkIGRldmlhdGlvbnMgJFxzaWdtYV8xPTguMCQgYW5kICRcc2lnbWFfMj02LjAkLCBhbmQgc28gYSB0cnVlIGRpZmZlcmVuY2UgaW4gbWVhbnMgb2YgJFxtdV97ZGlmZn09XG11XzEtXG11XzI9NC4wJCBiZXR3ZWVuIHRoZW0sIGFuZCB3ZSBkcmF3IGEgc2FtcGxlIG9mIHNpemUgJG5fMT1uXzI9MTAwJCBmcm9tIGVhY2ggcG9wdWxhdGlvbi4gUGVyIHRoZSBDTFQsIHRoZSBkaXN0cmlidXRpb24gb2YgdGhlIGRpZmZlcmVuY2UgaW4gc2FtcGxlIG1lYW5zIHRha2VuIGZyb20gdGhvc2UgdHdvIHBvcHVsYXRpb25zIGlzIGFwcHJveGltYXRlbHkgbm9ybWFsOiAkKFxiYXJ7eH1fMS1cYmFye3h9XzIpXHNpbVwgTihtZWFuID0gNC4wLCBzZD1cc3FydHtcZnJhY3s4LjBeMn17MTAwfSArIFxmcmFjezYuMF4yfXsxMDB9fT0xLjApJC4gQW55IHR3by1zYW1wbGUgc2V0IGRyYXduIGZyb20gdGhlIHR3byBwb3B1bGF0aW9ucyB3aG9zZSBkaWZmZXJlbmNlIGluIG1lYW5zIGVzdGltYXRlICQoXGJhcnt4fV8xLVxiYXJ7eH1fMikkIGZhbGxzIHdpdGhpbiAkKDQuMC0xLjk2XGNkb3QxLjAsXCA0LjArMS45NlxjZG90MS4wKT0oMi4wNCxcIDUuOTYpJCB3aWxsIGhhdmUgYSAkOTVcJSQgY29uZmlkZW5jZSBpbnRlcnZhbCB0aGF0IGNvbnRhaW5zIHRoZSB0cnVlIGRpZmZlcmVuY2UgaW4gbWVhbnMsICRcbXVfe2RpZmZ9PTQuMCQuIElmIHdlIGRyYXcgYSBzYW1wbGUgZnJvbSBlYWNoIHBvcHVsYXRpb24gYW5kIHRoZSBzYW1wbGVzJyBtZWFucyBhcmUgJFxiYXJ7eH1fMT0xNy4yNSQgYW5kICRcYmFye3h9XzI9MTEuNSQsIHRoZSAkOTVcJSQgY29uZmlkZW5jZSBpbnRlcnZhbCBjZW50ZXJlZCBhcm91bmQgJChcYmFye3h9XzEtXGJhcnt4fV8yKT01Ljc1JCB3aWxsIGNvbnRhaW4gdGhlIHRydWUgZGlmZmVyZW5jZSBpbiBtZWFucyAkXG11X3tkaWZmfT00LjAkLiBTaW5jZSB0aGUgcGVyc29uIHRha2luZyB0aGUgc2FtcGxlcyB0eXBpY2FsbHkgZG9lc24ndCBrbm93IGVpdGhlciAkXHNpZ21hXzEkIG9yICRcc2lnbWFfMiQsIHNoZSB3aWxsIHVzZSBoZXIgc2FtcGxlcycgc3RhbmRhcmQgZGV2aWF0aW9ucywgJHNfMT04LjUkIGFuZCAkc18yPTUuNSQsIHRvIGNvbXB1dGUgJFNFX3soXGJhcnt4fV8xIC0gXGJhcnt4fV8yKX0kLCBmb3IgdGhlIHB1cnBvc2VzIG9mIGNvbXB1dGluZyB0aGUgJDk1XCUkIGNvbmZpZGVuY2UgaW50ZXJ2YWwuICRTRV97KFxiYXJ7eH1fMSAtIFxiYXJ7eH1fMil9JCB3aWxsIGJlOiAkU0VfeyhcYmFye3h9XzEgLSBcYmFye3h9XzIpfT1cc3FydHtcZnJhY3s4LjVeMn17MTAwfSArIFxmcmFjezUuNV4yfXsxMDB9fT1cc3FydHswLjcyMjUrMC4zMDI1fT0xLjAxMjQkLCBhbmQgdGhlICQ5NVwlJCBjb25maWRlbmNlIGludGVydmFsIHdpbGwgYmU6ICQoNS43NS0xLjk2XGNkb3QxLjAxMjQsXCA1Ljc1KzEuOTZcY2RvdDEuMDEyNCk9KDMuNzY1NyxcIDcuNzM0MykkLCB3aGljaCBjb250YWlucyB0aGUgdHJ1ZSBtZWFuIGRpZmZlcmVuY2UgJFxtdV97ZGlmZn09NC4wJC4NCg0KYGBge3IsIGVjaG89RkFMU0V9DQojaHR0cDovL3d3dy5zdGF0bWV0aG9kcy5uZXQvYWR2Z3JhcGhzL3Byb2JhYmlsaXR5Lmh0bWwNCg0Kbl8xX2V4YW1wbGUgPC0gMTAwOyBuXzJfZXhhbXBsZSA8LSAxMDANCm11XzEgPC0gMTYuMDsgbXVfMiA8LSAxMi4wOyBtdV9kaWZmIDwtIG11XzEgLSBtdV8yDQpzaWdtYV8xIDwtIDguMDsgc2lnbWFfMiA8LSA2LjANCnNlIDwtIHNxcnQoc2lnbWFfMSBeIDIgLyBuXzFfZXhhbXBsZSArIHNpZ21hXzIgXiAyIC8gbl8yX2V4YW1wbGUpDQoNCiMgeCA9IHBfZGlmZiArLy0gNCBzdGRfZGV2J3MNCnggPC0gc2VxKC00LDQsbGVuZ3RoPTEwMDApKnNlICsgbXVfZGlmZg0KaHggPC0gZG5vcm0oeCwgbXVfZGlmZiAsc2UpDQoNCiMgVmFsdWVzIHVzZWQgdG8gc2hhZGUgYXJlYXMgdW5kZXIgdGhlIGN1cnZlDQp1cHBlcl9ib3VuZCA8LSBtdV9kaWZmICsgMS45NiAqIHNlIA0KbG93ZXJfYm91bmQgPC0gbXVfZGlmZiAtIDEuOTYgKiBzZSANCg0KcGxvdCh4LCBoeCwgdHlwZT0ibiIsIHhsYWIgPSAiIiwgeWxhYj0iIiwgbWFpbj0iU2FtcGxpbmcgZGlzdHJpYnV0aW9uIG9mIGEgZGlmZmVyZW5jZSBpbiBtZWFucyIsIGF4ZXM9RkFMU0UpDQoNCmkgPC0geCA+PSB1cHBlcl9ib3VuZCAmIHggPD0gbWF4KHgpICMgaW5kZXhlcyBvZiB4IHdoZXJlIHggPj0gdXBwZXJfYm91bmQNCmxpbmVzKHgsIGh4KSAjIHBsb3RzIG5vcm1hbCBkaXN0cmlidXRpb24NCnBvbHlnb24oYyh1cHBlcl9ib3VuZCx4W2ldLG1heCh4KSksIGMoMCxoeFtpXSwwKSwgY29sPSJncmV5IikgIyBzaGFkZXMgYXJlYSBncmV5IHdoZXJlIHggPj0gdXBwZXJfYm91bmQNCg0KaiA8LSB4ID49IG1pbih4KSAmIHggPD0gbG93ZXJfYm91bmQgIyBpbmRleGVzIG9mIHggd2hlcmUgeCA8PSB0aGFuIGxvd2VyX2JvdW5kDQpwb2x5Z29uKGMobWluKHgpLHhbal0sbG93ZXJfYm91bmQpLCBjKDAsaHhbal0sMCksIGNvbD0iZ3JleSIpICMgc2hhZGVzIGFyZWEgZ3JleSB3aGVyZSB4IDw9IGxvd2VyX2JvdW5kDQoNCmF4aXMoMSwgYXQ9c2VxKDAuMDAsIDguMCwgMC41KSwgcG9zPTApICMgZHJhd3MgYXhpcw0KYWJsaW5lKHY9bXVfZGlmZikNCmdyaWQoKQ0KDQp4XzFfaGF0IDwtIDE3LjI1OyB4XzJfaGF0IDwtIDExLjU7IG11X2RpZmZfaGF0X2V4YW1wbGUgPC0geF8xX2hhdCAtIHhfMl9oYXQNCnNfMSA8LSA4LjU7IHNfMiA8LSA1LjUNCnNlX211X2RpZmZfaGF0IDwtIHNxcnQoc18xIF4gMiAvIG5fMV9leGFtcGxlICsgc18yIF4gMiAvIG5fMl9leGFtcGxlKQ0KYXhpcygxLCBhdD1jKG11X2RpZmZfaGF0X2V4YW1wbGUgLSAxLjk2ICogc2VfbXVfZGlmZl9oYXQsIG11X2RpZmZfaGF0X2V4YW1wbGUsIG11X2RpZmZfaGF0X2V4YW1wbGUgKyAxLjk2ICogc2VfbXVfZGlmZl9oYXQpLCBwb3M9LTAuMSwgY29sID0gImJsdWUiLCBsd2QgPSAyLCBsd2QudGlja3MgPSAxKSANCg0KdGV4dCh4ID0gMC42LCB5ID0gMC4zNywgbGFiZWxzID0gZXhwcmVzc2lvbihwYXN0ZShtdVtkaWZmXSwgIiA9IDQuMCIpKSkNCnRleHQoeCA9IDAuOCwgeSA9IDAuMzMsIGxhYmVscyA9IGV4cHJlc3Npb24ocGFzdGUoblsxXSwgIiA9ICIsIG5bMl0sICAiID0gMTAwIikpKQ0KdGV4dCh4ID0gMC42NSwgeSA9IDAuMjksIGxhYmVscyA9IGV4cHJlc3Npb24ocGFzdGUoU0UsICIgPSAxLjAwIikpKQ0KdGV4dCh4ID0gMC44MjUsIHkgPSAwLjI1NSwgbGFiZWxzID0gZXhwcmVzc2lvbihwYXN0ZShiYXIoeClbMV0tYmFyKHgpWzJdLCAiID0gNS43NSIpKSkNCnRleHQoeCA9IDEuMCwgeSA9IDAuMjIsIGxhYmVscyA9IGV4cHJlc3Npb24ocGFzdGUoU0VbYmFyKHgpWzFdLWJhcih4KVsyXV0sICIgPSAxLjAxMjQiKSkpDQpgYGANCg0KSWYgd2UgYXJlIHVubHVja3kgYW5kICBkcmF3IHNhbXBsZXMgd2hvc2UgZGlmZmVyZW5jZSBpbiBtZWFucyAkKFxiYXJ7eH1fMS1cYmFye3h9XzIpJCBmYWxscyBpbiB0aGUgc2hhZGVkIGFyZWEsIHdoaWNoIHNob3VsZCBvbmx5IGhhcHBlbiAkNVwlJCBvZiB0aGUgdGltZSwgaXRzICQ5NVwlJCBjb25maWRlbmNlIGludGVydmFsIHdpbGwgbm90IGluY2x1ZGUgdGhlIHRydWUgZGlmZmVyZW5jZSBpbiBtZWFucyAkXG11X3tkaWZmfT00LjAkLiBGb3IgZXhhbXBsZSwgaWYgJFxiYXJ7eH1fMT0xNy41JCwgJFxzaWdtYV8xPTguNzUkLCAkXGJhcnt4fV8yPTExLjAkLCBhbmQgJFxzaWdtYV8yPTUuNSQsIGFuZCBhZ2FpbiBlYWNoIHNhbXBsZSBoYXMgJDEwMCQgb2JzZXJ2YXRpb25zLCB0aGVuICQoXGJhcnt4fV8xLVxiYXJ7eH1fMik9Ni41JCBhbmQgJFNFX3soXGJhcnt4fV8xIC0gXGJhcnt4fV8yKX09XHNxcnR7XGZyYWN7OC43NV4yfXsxMDB9ICsgXGZyYWN7NS41XjJ9ezEwMH19PVxzcXJ0ezAuNzY1NiswLjMwMjV9PTEuMDMzNSQuIFRoZSAkOTVcJSQgY29uZmlkZW5jZSBpbnRlcnZhbCB3aWxsIGJlICQoNi41LTEuOTZcY2RvdDEuMDMzNSxcIDYuNSsxLjk2XGNkb3QxLjAzMzUpPSg0LjQ3NDMsXCA4LjUyNTcpJC4gVGhhdCBjb25maWRlbmNlIGludGVydmFsIHdpbGwgKm5vdCogaW5jbHVkZSB0aGUgdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW5zLCAkXG11X3tkaWZmfT00LjAkLg0KDQpgYGB7cn0NCiNodHRwOi8vd3d3LnN0YXRtZXRob2RzLm5ldC9hZHZncmFwaHMvcHJvYmFiaWxpdHkuaHRtbA0KDQpuXzFfZXhhbXBsZSA8LSAxMDA7IG5fMl9leGFtcGxlIDwtIDEwMA0KbXVfMSA8LSAxNi4wOyBtdV8yIDwtIDEyLjA7IG11X2RpZmYgPC0gbXVfMSAtIG11XzINCnNpZ21hXzEgPC0gOC4wOyBzaWdtYV8yIDwtIDYuMA0Kc2UgPC0gc3FydChzaWdtYV8xIF4gMiAvIG5fMV9leGFtcGxlICsgc2lnbWFfMiBeIDIgLyBuXzJfZXhhbXBsZSkNCg0KIyB4ID0gcF9kaWZmICsvLSA1IHN0ZF9kZXYncw0KeCA8LSBzZXEoLTUsNSxsZW5ndGg9MTAwMCkqc2UgKyBtdV9kaWZmDQpoeCA8LSBkbm9ybSh4LCBtdV9kaWZmICxzZSkNCg0KIyBWYWx1ZXMgdXNlZCB0byBzaGFkZSBhcmVhcyB1bmRlciB0aGUgY3VydmUNCnVwcGVyX2JvdW5kIDwtIG11X2RpZmYgKyAxLjk2ICogc2UgDQpsb3dlcl9ib3VuZCA8LSBtdV9kaWZmIC0gMS45NiAqIHNlIA0KDQpwbG90KHgsIGh4LCB0eXBlPSJuIiwgeGxhYiA9ICIiLCB5bGFiPSIiLCBtYWluPSJTYW1wbGluZyBkaXN0cmlidXRpb24gb2YgYSBkaWZmZXJlbmNlIGluIG1lYW5zIiwgYXhlcz1GQUxTRSkNCg0KaSA8LSB4ID49IHVwcGVyX2JvdW5kICYgeCA8PSBtYXgoeCkgIyBpbmRleGVzIG9mIHggd2hlcmUgeCA+PSB1cHBlcl9ib3VuZA0KbGluZXMoeCwgaHgpICMgcGxvdHMgbm9ybWFsIGRpc3RyaWJ1dGlvbg0KcG9seWdvbihjKHVwcGVyX2JvdW5kLHhbaV0sbWF4KHgpKSwgYygwLGh4W2ldLDApLCBjb2w9ImdyZXkiKSAjIHNoYWRlcyBhcmVhIGdyZXkgd2hlcmUgeCA+PSB1cHBlcl9ib3VuZA0KDQpqIDwtIHggPj0gbWluKHgpICYgeCA8PSBsb3dlcl9ib3VuZCAjIGluZGV4ZXMgb2YgeCB3aGVyZSB4IDw9IHRoYW4gbG93ZXJfYm91bmQNCnBvbHlnb24oYyhtaW4oeCkseFtqXSxsb3dlcl9ib3VuZCksIGMoMCxoeFtqXSwwKSwgY29sPSJncmV5IikgIyBzaGFkZXMgYXJlYSBncmV5IHdoZXJlIHggPD0gbG93ZXJfYm91bmQNCg0KYXhpcygxLCBhdD1zZXEoMC4wMCwgMTAuMCwgMC41KSwgcG9zPTApICMgZHJhd3MgYXhpcw0KYWJsaW5lKHY9bXVfZGlmZikNCmdyaWQoKQ0KDQp4XzFfaGF0IDwtIDE3LjU7IHhfMl9oYXQgPC0gMTEuMDsgbXVfZGlmZl9oYXRfZXhhbXBsZSA8LSB4XzFfaGF0IC0geF8yX2hhdA0Kc18xIDwtIDguNzU7IHNfMiA8LSA1LjUNCnNlX211X2RpZmZfaGF0IDwtIHNxcnQoc18xIF4gMiAvIG5fMV9leGFtcGxlICsgc18yIF4gMiAvIG5fMl9leGFtcGxlKQ0KYXhpcygxLCBhdD1jKG11X2RpZmZfaGF0X2V4YW1wbGUgLSAxLjk2ICogc2VfbXVfZGlmZl9oYXQsIG11X2RpZmZfaGF0X2V4YW1wbGUsIG11X2RpZmZfaGF0X2V4YW1wbGUgKyAxLjk2ICogc2VfbXVfZGlmZl9oYXQpLCBwb3M9LTAuMSwgY29sID0gImJsdWUiLCBsd2QgPSAyLCBsd2QudGlja3MgPSAxKSANCg0KdGV4dCh4ID0gMC42LCB5ID0gMC4zNywgbGFiZWxzID0gZXhwcmVzc2lvbihwYXN0ZShtdVtkaWZmXSwgIiA9IDQuMCIpKSkNCnRleHQoeCA9IDAuOCwgeSA9IDAuMzMsIGxhYmVscyA9IGV4cHJlc3Npb24ocGFzdGUoblsxXSwgIiA9ICIsIG5bMl0sICAiID0gMTAwIikpKQ0KdGV4dCh4ID0gMC42NSwgeSA9IDAuMjksIGxhYmVscyA9IGV4cHJlc3Npb24ocGFzdGUoU0UsICIgPSAxLjAwIikpKQ0KdGV4dCh4ID0gMC44MjUsIHkgPSAwLjI1NSwgbGFiZWxzID0gZXhwcmVzc2lvbihwYXN0ZShiYXIoeClbMV0tYmFyKHgpWzJdLCAiID0gNi41IikpKQ0KdGV4dCh4ID0gMS4wLCB5ID0gMC4yMiwgbGFiZWxzID0gZXhwcmVzc2lvbihwYXN0ZShTRVtiYXIoeClbMV0tYmFyKHgpWzJdXSwgIiA9IDEuMDMzNSIpKSkNCmBgYA0KDQojIyMgNC4yIENvbmRpdGlvbnMgZm9yIHRoZSBjb25maWRlbmNlIGludGVydmFsDQoNClRoZSBjb25maWRlbmNlIGludGVydmFsIG9mIHRoZSBkaWZmZXJlbmNlIGluIG1lYW5zIGlzIGdpdmVuIGJ5DQoNCiQkDQpcYmFye3h9X3tkaWZmfVxwbSB6XipcY2RvdCBTRQ0KJCQNCg0Kd2hlcmUgJFxiYXJ7eH1fe2RpZmZ9PVxiYXJ7eH1fezF9LVxiYXJ7eH1fezJ9JCwgaXMgdGhpcyBzYW1wbGUgcGFpcidzIHBvaW50IGVzdGltYXRlIG9mIHRoZSBkaWZmZXJlbmNlIGluIG1lYW4gc2VsZi1yYW5raW5nIGJldHdlZW4gT2JhbWEgYW5kIFJvbW5leSB2b3RlcnMsICR6XiokIGlzIHRoZSBjcml0aWNhbCB2YWx1ZSBjb3JyZXNwb25kaW5nIHRvIHRoZSBjb25maWRlbmNlIGxldmVsIHdlIHdhbnQsIGFuZCB0aGUgc3RhbmRhcmQgZXJyb3IgJFNFJCBpcyBnaXZlbiBieToNCg0KJCQNClNFPVxzcXJ0e1xmcmFje3NfMV57Mn19e25fMX0rXGZyYWN7c18yXnsyfX17bl8yfX0NCiQkDQoNCndoZXJlICRzXzEkIGFuZCAkc18yJCBhcmUgdGhlIHN0YW5kYXJkIGRldmlhdGlvbnMgb2YgdGhlIHNhbXBsZXMsIGFuZCAkbl8xJCBhbmQgJG5fMiQgdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgb2YgZWFjaCBzYW1wbGUuDQoNClRoZSBjb25kaXRpb25zIGZvciB0aGUgdmFsaWRpdHkgb2YgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgYXJlOg0KDQoxLiBTYW1wbGVkIG9ic2VydmF0aW9ucyBtdXN0IGJlIGluZGVwZW5kZW50LCBib3RoIHdpdGhpbiBncm91cHMgYW5kIGJldHdlZW4gZ3JvdXBzLg0KDQoyLiBFYWNoIHNhbXBsZSBzaXplIGlzIGxhcmdlOiAkbl8xXGdlcSAzMCQgYW5kICRuXzJcZ2VxIDMwJA0KDQozLiBUaGUgZGlzdHJpYnV0aW9uIG9mIGVhY2ggc2FtcGxlJ3Mgb2JzZXJ2YXRpb25zIGlzIG5vdCBzdHJvbmdseSBza2V3ZWQuDQoNCkVhY2ggb2JzZXJ2YXRpb24gd2l0aGluIGEgc2FtcGxlIGlzIGluZGVwZW5kZW50IG9mIHRoZSBuZXh0LCBpLmUuLCBlYWNoIHJlc3BvbmRlbnQgd2hvIHZvdGVkIGZvciBSb21uZXkgaXMgaW5kZXBlbmRlbnQgb2YgYWxsIG90aGVyIHJlc3BvbmRlbnRzIHdobyB2b3RlZCBmb3IgUm9tbmV5LiBBbHNvLCByZXNwb25kZW50cyB3aG8gdm90ZWQgZm9yIFJvbW5leSBhcmUgaW5kZXBlbmRlbnQgb2YgdGhvc2Ugd2hvIHZvdGVkIGZvciBPYmFtYS4gVGhlIGRhdGEgaXMgbm90IHBhaXJlZC4gVGhhdCB0YWtlcyBjYXJlIG9mIHRoZSBmaXJzdCBjb25kaXRpb24uDQoNCkFzIHdlIHNhdyBpbiB0aGUgdGFibGUgb24gc2VjdGlvbiAkMy4wJCwgdGhlcmUgd2VyZSAkNTcxJCBSb21uZXkgdm90ZXJzIGFuZCAkMTA1NCQgT2JhbWEgdm90ZXJzLCBzbyBlYWNoIHNhbXBsZSBzaXplIGlzIG11Y2ggbGFyZ2VyIHRoYW4gJDMwJC4NCg0KRmluYWxseSwgd2UgY2FuIHRha2UgYSBsb29rIGF0IHRoZSBzYW1wbGUgZGlzdHJpYnV0aW9ucw0KDQpgYGB7cn0NCnBhcihtZnJvdyA9IGMoMSwyKSkNCmhpc3QoUm9tbmV5X3NlbGZfcmFuaywgbWFpbiA9ICJTZWxmLXJhbmtpbmcgaW4gc29jaWV0eVxuIG9mIFJvbW5leSB2b3RlcnMiLCB4bGFiID0gIlNlbGYtcmFua2luZyBpbiBzb2NpZXR5IiwgeWxhYiA9ICJGcmFjdGlvbiBvZiByZXNwb25kZW50cyIsIGZyZXEgPSBGQUxTRSkNCmhpc3QoT2JhbWFfc2VsZl9yYW5rLCBtYWluID0gIlNlbGYtcmFua2luZyBpbiBzb2NpZXR5XG4gb2YgT2JhbWEgdm90ZXJzIiwgeGxhYiA9ICJTZWxmLXJhbmtpbmcgaW4gc29jaWV0eSIsIHlsYWIgPSAiRnJhY3Rpb24gb2YgcmVzcG9uZGVudHMiLCBmcmVxID0gRkFMU0UpDQpgYGANCg0KQWx0aG91Z2ggYm90aCBkaXN0cmlidXRpb25zIGFyZSBhIGxpdHRsZSByaWdodC1za2V3ZWQsIGl0J3Mgbm90IHRvbyBiYWQuDQoNCiMjIyA0LjMgQ3JpdGljYWwgdmFsdWUgJHpeKiQNCg0KVGhlICR6XiokIGNvcnJlc3BvbmRpbmcgdG8gYSAkOTVcJSQgY29uZmlkZW5jZSBpbnRlcnZhbCBpbiB0aGUgW3N0YW5kYXJkIG5vcm1hbCBkaXN0cmlidXRpb25dKGh0dHBzOi8vd3d3Lm1hdGhzaXNmdW4uY29tL2RhdGEvc3RhbmRhcmQtbm9ybWFsLWRpc3RyaWJ1dGlvbi10YWJsZS5odG1sKSBjYW4gYmUgY29tcHV0ZWQgdXNpbmcgUjoNCmBgYHtyfQ0Kel9zdGFyXzk1IDwtIHFub3JtKHAgPSAwLjAyNSwgbWVhbiA9IDAsIHNkID0gMSwgbG93ZXIudGFpbCA9IEZBTFNFKQ0KY2F0KCJ6LXZhbHVlIGNvcnJlc3BvbmRpbmcgdG8gOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWw6Iiwgel9zdGFyXzk1KQ0KYGBgDQoNCiMjIyA0LjQgU3RhbmRhcmQgZXJyb3INCg0KQ29tcHV0aW5nIHRoZSBzdGFuZGFyZCBlcnJvciBvZiB0aGUgc2FtcGxlIHVzaW5nIHRoZSByZXN1bHRzIGZyb20gc2VjdGlvbiAkMy4wJC4NCmBgYHtyfQ0Kc2UgPC0gc3FydChPYmFtYV9zZWxmX3Jhbmtfc2ReMiAvIE9iYW1hX251bSArIFJvbW5leV9zZWxmX3Jhbmtfc2ReMiAvIFJvbW5leV9udW0pDQpjYXQoIlN0YW5kYXJkIGVycm9yOiIsIHNlKQ0KYGBgDQoNCiMjIyA0LjUgQ29uZmlkZW5jZSBpbnRlcnZhbA0KDQpDb21wdXRpbmcgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgYm91bmRzDQpgYGB7cn0NCmRpZmZfaW5fYXZnIDwtIE9iYW1hX3NlbGZfcmFua19tZWFuIC0gUm9tbmV5X3NlbGZfcmFua19tZWFuDQpjb25mX2ludF9sYiA8LSBkaWZmX2luX2F2ZyAtIHpfc3Rhcl85NSAqIHNlDQpjb25mX2ludF91YiA8LSBkaWZmX2luX2F2ZyArIHpfc3Rhcl85NSAqIHNlDQpjYXQoIkRpZmZlcmVuY2UgaW4gbWVhbiBzZWxmLXJhbmtpbmc6IiwgZGlmZl9pbl9hdmcsICJcbkNvbmZpZGVuY2UgaW50ZXJ2YWwgbG93ZXIgYm91bmQ6IiwgY29uZl9pbnRfbGIsICJcbkNvbmZpZGVuY2UgaW50ZXJ2YWwgdXBwZXIgYm91bmQ6IiwgY29uZl9pbnRfdWIpDQpgYGANCg0KSGVuY2UsIG91ciBjb25maWRlbmNlIGludGVydmFsIGlzDQokJA0KMC4xNzk3XHBtIDEuOTZcY2RvdCAwLjA4ODY9KDAuMDA2MSwgMC4zNTMzKQ0KJCQNCg0KV2UgYXJlICQ5NVwlJCBjb25maWRlbnQgdGhhdCB0aGUgdHJ1ZSBkaWZmZXJlbmNlIGluIG1lYW4gc2VsZi1yYW5raW5nIGJldHdlZW4gT2JhbWEgYW5kIFJvbW5leSB2b3RlcnMsICRcbXVfe2RpZmZ9JCwgaXMgYmV0d2VlbiAkMC4wMDYxJCBhbmQgJDAuMzUzMyQuDQoNCiMjIDUuMCBIeXBvdGhlc2lzIHRlc3RpbmcNCg0KV2UgY2FuIHVzZSB0aGUgQ0xUIGFuZCB0aGUgZGF0YSBjb2xsZWN0ZWQgdG8gY29uc3RydWN0IGEgaHlwb3RoZXNpcyB0ZXN0aW5nIGZyYW1ld29yay4gVGhlIGh5cG90aGVzaXMgdGVzdCBjb25zaWRlcnMgdHdvIHBvc3NpYmxlIGludGVycHJldGF0aW9ucyBvZiBvdXIgZGF0YSwgYSBudWxsIGh5cG90aGVzaXMgJEhfMCQsIGFuZCBhbiBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzICRIX2EkLiAkSF8wJCBiYXNpY2FsbHkgc2F5cyB0aGF0IHRoZSBzYW1wbGVkIGRhdGEgY291bGQgaGF2ZSBiZWVuIGRyYXduIHNpbXBseSBieSBjaGFuY2UsIGFuZCBzbywgaXQgaXMgbWlzbGVhZGluZy4gVGhlcmUgaXMgIm5vdGhpbmcgZ29pbmcgb24iLiAkSF9hJCB0YWtlcyB0aGUgdmlldyB0aGF0IHRoZSBkYXRhIGNvbGxlY3RlZCByZXZlYWxzIHRoYXQgInNvbWV0aGluZyAqaXMqIGdvaW5nIG9uIi4gV2Ugd2lsbCBlaXRoZXIgcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMgaW4gZmF2b3Igb2YgdGhpcyBhbHRlcm5hdGl2ZSwgb3Igd2Ugd2lsbCBmYWlsIHRvIHJlamVjdCBpdCBhbmQgY29uY2x1ZGUgdGhlIHNhbXBsZWQgZGF0YSBjb3VsZCBoYXZlIGJlZW4gZHJhd24gc2ltcGx5IGJ5IGNoYW5jZS4gTm90ZSB0aGF0IGV2ZW4gaWYgd2UgZmFpbCB0byByZWplY3QgJEhfMCQsIHRoYXQgZG9lcyBub3QgbWVhbiB3ZSBhY2NlcHQgaXQgYXMgdGhlIGdyb3VuZCB0cnV0aCwgaXQncyBqdXN0IHRoYXQgdGhlIGRhdGEgd2UgaGF2ZSBjb2xsZWN0ZWQgZG9lcyBub3QgYWxsb3dzIHVzIHRvIGRpc2NhcmQgJEhfMCQuDQoNClN1cHBvc2Ugd2Ugd2FudCB0byBmaW5kIG91dCBpZiB0aGUgJDAuMTc5NyQgZGlmZmVyZW5jZSBpbiBtZWFuIHNlbGYtcmFua2luZyBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LiBPdXIgbnVsbCBoeXBvdGhlc2lzICRIXzAkIGlzOg0KDQokJA0KSF8wOiBUaGVcIHRydWVcIGRpZmZlcmVuY2VcIGluXCBtZWFuXCBzZWxmLXJhbmtpbmdcXCBiZXR3ZWVuXCBPYmFtYVwgYW5kXCBSb21uZXlcIHZvdGVyc1wgaXNcIFxtdV97ZGlmZn09MA0KXFwNCkhfYTogXG11X3tkaWZmfVxuZXEgMA0KJCQNCg0KVG8gcGVyZm9ybSB0aGUgdGVzdCwgd2UgYXNzdW1lIHRoYXQgJEhfMCQgaXMgdHJ1ZSBhbmQgYXNrLCBnaXZlbiB0aGF0ICRIXzAkIGlzIHRydWUsIGhvdyBwcm9iYWJsZSBpdCBpcyB0byBvYnNlcnZlIGRhdGEgYXMgZXh0cmVtZSBvciBtb3JlIGFzIHRoZSBvbmUgd2UgaGF2ZS4NCg0KIyMjIDUuMSBUaGUgcC12YWx1ZQ0KDQpUaGUgcC12YWx1ZSBxdWFudGlmaWVzIHRoZSBzdHJlbmd0aCBvZiB0aGUgZXZpZGVuY2UgYWdhaW5zdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiBXZSBjb21wdXRlIGl0IGJ5IGFza2luZyBvdXJzZWx2ZXMsIGdpdmVuIHRoYXQgdGhlIG51bGwgaHlwb3RoZXNpcyAkSF8wJCBpcyB0cnVlLCB3aGF0IGlzIHRoZSBwcm9iYWJpbGl0eSBvZiBvYnNlcnZpbmcgZGF0YSBhcyBleHRyZW1lIG9yIG1vcmUgYXMgdGhlIG9uZSB3ZSBoYXZlLg0KDQokJA0KUChvYnNlcnZpbmdcIGRhdGFcIGFzXCBleHRyZW1lXCBvclwgbW9yZVwgfFwgSF97MH1cIGlzXCB0cnVlKQ0KJCQNCg0KVGhhdCBwcm9iYWJpbGl0eSBpcyB0aGUgcC12YWx1ZS4gVHlwaWNhbGx5LCB3ZSB1c2UgYSAkNVwlJCBzaWduaWZpY2FuY2UgbGV2ZWwgYXMgdGhlIHRocmVzaG9sZCB0byByZWplY3QgdGhlIG51bGwuIElmIHRoZSBwLXZhbHVlIGlzIGxlc3MgdGhhbiAkNVwlJCwgd2UgcmVqZWN0IHRoZSBudWxsIGluIGZhdm9yIG9mIHRoZSBhbHRlcm5hdGl2ZS4NCg0KT3VyIGh5cG90aGVzaXMgdGVzdCBpcyB0d28tc2lkZWQuIFRoZSBudWxsIGh5cG90aGVzaXMgaXMgdGhhdCAkXG11X3tkaWZmfT0wJCwgc28gYnkgYXNraW5nIHdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IG9mICRvYnNlcnZpbmdcIGRhdGFcIGFzXCBleHRyZW1lXCBvclwgbW9yZSQgaW4gYSB3b3JsZCBpbiB3aGljaCB0aGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRydWUsIHdlIGFyZSB3b25kZXJpbmcgaG93IHByb2JhYmxlIGl0IGlzIHRvIGRyYXcgYSBzYW1wbGUgd2l0aCBhIGRpZmZlcmVuY2UgaW4gbWVhbnMgb2YgJDAuMTc5NyQgb3IgaGlnaGVyIGxpa2UgdGhlIG9uZSB3ZSBoYXZlIGRyYXduLCBvciBvbmUgd2l0aCBhIGRpZmZlcmVuY2UgaW4gcHJvcG9ydGlvbnMgb2YgJC0wLjE3OTckIG9yIGxvd2VyLiBMZXQncyBzZWUgaXQgZ3JhcGhpY2FsbHkuDQoNCmBgYHtyfQ0KI2h0dHA6Ly93d3cuc3RhdG1ldGhvZHMubmV0L2FkdmdyYXBocy9wcm9iYWJpbGl0eS5odG1sDQoNCm11X2RpZmYgPC0gMC4wMA0KDQp4IDwtIHNlcSgtNCw0LGxlbmd0aD0xMDAwKSpzZSArIG11X2RpZmYNCmh4IDwtIGRub3JtKHgsIG11X2RpZmYsIHNlKQ0KDQpsYiA8LSBkaWZmX2luX2F2ZzsgdWIgPC0gbWF4KHgpDQoNCnBsb3QoeCwgaHgsIHR5cGU9Im4iLCB4bGFiPSJEaWZmZXJlbmNlIGluIG1lYW4gc2VsZi1yYW5raW5nIGJldHdlZW4gT2JhbWEgYW5kIFJvbW5leSB2b3RlcnMiLCB5bGFiPSIiLCBtYWluPSJTYW1wbGluZyBkaXN0cmlidXRpb24gdW5kZXIgbnVsbCBoeXBvdGhlc2lzIiwgYXhlcz1GQUxTRSkNCg0KaSA8LSB4ID49IGxiICYgeCA8PSB1YiAjIGluZGV4ZXMgb2YgeCB3aGVyZSB4ID49ICBsYiANCmxpbmVzKHgsIGh4KSAjIHBsb3RzIG5vcm1hbCBkaXN0cmlidXRpb24NCnBvbHlnb24oYyhsYix4W2ldLHViKSwgYygwLGh4W2ldLDApLCBjb2w9InJlZCIpICMgc2hhZGVzIGFyZWEgd2hlcmUgeCA+PSBsYiBpbiByZWQNCg0KaiA8LSB4ID49IG1pbih4KSAmIHggPD0gLWxiICMgaW5kZXhlcyBvZiB4IHdoZXJlIHggPD0gLWxiIA0KcG9seWdvbihjKG1pbih4KSx4W2pdLC1sYiksIGMoMCxoeFtqXSwwKSwgY29sPSJyZWQiKSAjIHNoYWRlcyBhcmVhIHdoZXJlIHggPD0gLWxiIGluIHJlZA0KDQpheGlzKDEsIGF0PXNlcSgtMC40LCAwLjQsIDAuMDUpLCBwb3M9MCkgIyBkcmF3cyBheGlzDQphYmxpbmUodj1tdV9kaWZmKQ0KZ3JpZCgpDQpgYGANCjxicj4NCg0KVW5kZXIgdGhlIG51bGwgaHlwb3RoZXNpcywgd2UgbGl2ZSBpbiBhIHdvcmxkIGluIHdoaWNoIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgdGhlIGRpZmZlcmVuY2UgaW4gbWVhbiBzZWxmLXJhbmtpbmcgYmV0d2VlbiBPYmFtYSBhbmQgUm9tbmV5IHZvdGVycyBpcyBjZW50ZXJlZCBhdCAkXG11X3tkaWZmfSA9IDAuMCQgYW5kIGhhcyBhIHN0YW5kYXJkIGRpc3RyaWJ1dGlvbiBvZiAkc2Q9MC4xNzk3JC4gSW4gc3VjaCBhIHdvcmxkLCB3ZSBoYXZlIGRyYXduIGEgc2FtcGxlIHdoZXJlIHRoZSBkaWZmZXJlbmNlIGluIG1lYW5zIGlzICRcYmFye3h9X3tkaWZmfT0wLjE3OTckLiBXaGF0IGlzIHRoZSBwcm9iYWJpbGl0eSBvZiBkcmF3aW5nIGEgc2FtcGxlIHdpdGggYSBkaWZmZXJlbmNlIGluIG1lYW5zICRcYmFye3h9X3tkaWZmfSQgYXMgaGlnaCBvciBoaWdoZXIsIGluIGVpdGhlciBkaXJlY3Rpb24sIGluIGEgd29ybGQgaW4gd2hpY2ggdGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0cnVlPw0KDQokJA0KUChkcmF3aW5nXCBhXCBzYW1wbGVcIHdoZXJlXCB0aGVcIGRpZmZlcmVuY2VcIGluXCBtZWFuXCBzZWxmLXJhbmtpbmdcXCBiZXR3ZWVuXCBPYmFtYVwgYW5kXCBSb21uZXlcIHZvdGVyc1wgaXNcIGFzXCBsYXJnZVwgb3JcIGxhcmdlclwgdGhhblwgMC4xNzk3IHxcIEhfezB9XCBpc1wgdHJ1ZSkNClxcDQpQKFxiYXJ7eH1fe2RpZmZ9XCBcZ2VxXCAwLjE3OTdcIG9yXCBcYmFye3h9X3tkaWZmfVwgXGxlcVwgLTAuMTc5NyB8XCBcbXVfe2RpZmZ9ID0gIDApDQokJA0KDQpUaGF0IHByb2JhYmlsaXR5IGlzIHRoZSBhcmVhIHVuZGVyIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gc2hhZGVkIGluIHJlZCBpbiB0aGUgcGxvdC4gSXQgY2FuIGJlIGNvbXB1dGVkIHVzaW5nIGBwbm9ybSgpYC4NCmBgYHtyfQ0KYXJlYSA8LSAyICogcG5vcm0ocSA9IGRpZmZfaW5fYXZnLCBtZWFuID0gbXVfZGlmZiwgc2QgPSBzZSwgbG93ZXIudGFpbCA9IEZBTFNFKQ0KIyBNdWx0aXBsaWVkIGJ5IDIgYmVjYXVzZSB0aGUgaHlwb3RoZXNpcyB0ZXN0IGlzIHR3by1zaWRlZC4NCmNhdCgiT3VyIHAtdmFsdWU6IiwgYXJlYSkNCmBgYA0KDQpTbyBvdXIgW3AtdmFsdWVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1AtdmFsdWUpLCB0aGUgcHJvYmFiaWxpdHkgb2YgZHJhd2luZyBhIHNhbXBsZSBwYWlyIHdpdGggJFxiYXJ7eH1fe2RpZmZ9PTAuMTc5NyQgb3IgaGlnaGVyLCBvciBvbmUgd2l0aCAkXGJhcnt4fV97ZGlmZn09LTAuMTc5NyQgb3IgbG93ZXIsIHVuZGVyIHRoZSBudWxsIGh5cG90aGVzaXMsIGlzIGFib3V0ICQwLjA0MyQuIEF0IHRoZSAkNVwlJCBzaWduaWZpY2FuY2UgbGV2ZWwsIHdlIGNhbiAoYmFyZWx5KSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcy4gTG9va2luZyBhdCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCwgd2UgbWlnaHQgaGF2ZSBzdXJtaXNlZCB0aGF0IGl0IHdhcyBnb2luZyB0byBiZSBjbG9zZSwgc2luY2UgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgYWxtb3N0IGluY2x1ZGVzIHRoZSBudWxsIHZhbHVlLCAkMCQuIFRoZSBsb3dlciBib3VuZCBvZiB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBmb3IgJFxiYXJ7eH1fe2RpZmZ9JCBpcyAkMC4wMDYxJCwgYW5kIG91ciBudWxsIHZhbHVlIGlzICRcbXVfe2RpZmZ9PTAkLg0KDQojIyBSZWZlcmVuY2VzDQoNCjEuIMOHZXRpbmtheWEtUnVuZGVsLCBNLiAqKipEYXRhIEFuYWx5c2lzIGFuZCBTdGF0aXN0aWNhbCBJbmZlcmVuY2UqKiouIFNwcmluZyAyMDE0LiBbQ291cnNlcmFdKGh0dHA6Ly93d3cuY291cnNlcmEub3JnKS4NCg0KMi4gRGlleiwgRC4sIEJhcnIsIEMuLCDDh2V0aW5rYXlhLVJ1bmRlbCwgTS4gKioqT3BlbkludHJvIFN0YXRpc3RpY3MsIFNlY29uZCBFZGl0aW9uKioqLiBQREYuDQoNCjMuIE5hdmlkaSwgVy4gKioqU3RhdGlzdGljcyBmb3IgZW5naW5lZXJzIGFuZCBzY2llbnRpc3RzLCBUaGlyZCBFZGl0aW9uKioqLiBOZXcgWW9yazogTWNHcmF3IEhpbGwsIDIwMTEuDQoNCjQuIFVDTEEgSW5zdGl0dXRlIGZvciBEaWdpdGFsIFJlc2VyYWNoIGFuZCBFZHVjYXRpb24sICoqKkhPVyBDQU4gSSBJTkNMVURFIEdSRUVLIExFVFRFUlMgSU4gTVkgUExPVCBMQUJFTFM/IHwgUiBDT0RFIEZSQUdNRU5UUyoqKi4gUmV0cmlldmVkIGZyb20gW2h0dHBzOi8vc3RhdHMuaWRyZS51Y2xhLmVkdV0oaHR0cHM6Ly9zdGF0cy5pZHJlLnVjbGEuZWR1L3IvY29kZWZyYWdtZW50cy9ncmVla19sZXR0ZXJzLykNCg0KNS4gS2FiYWNvZmYsIFIuICoqKlByb2JhYmlsaXR5IFBsb3RzKioqLiBSZXRyaWV2ZWQgZnJvbSBbaHR0cDovL3d3dy5zdGF0bWV0aG9kcy5uZXRdKGh0dHA6Ly93d3cuc3RhdG1ldGhvZHMubmV0L2FkdmdyYXBocy9wcm9iYWJpbGl0eS5odG1sKQ0KDQo2LiBDYXJsb3MgQ2luZWxsaSBhbmQgVG9tLCAqKipDb2RlIGNodW5rIGZvbnQgc2l6ZSBpbiBSbWFya2Rvd24gd2l0aCBrbml0ciBhbmQgbGF0ZXgqKiouIFJldHJpZXZlZCBmcm9tIFtodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tXShodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yNTY0NjMzMy9jb2RlLWNodW5rLWZvbnQtc2l6ZS1pbi1ybWFya2Rvd24td2l0aC1rbml0ci1hbmQtbGF0ZXgpDQoNCjcuIERyZXdDb253YXkgYW5kIENocmlzdG9waGVyIER1Qm9pcywgKioqR2V0dGluZyBMYVRlWCBpbnRvIFIgUGxvdHMqKiouIFJldHJpZXZlZCBmcm9tIFtodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tXShodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xMzk1MTA1L2dldHRpbmctbGF0ZXgtaW50by1yLXBsb3RzKQ==