Introduction
Following packages and functions are used in this project.
## basic packages
library(knitr)
library(kableExtra)
library(tidyverse)
library(conflicted)
library(magrittr)
library(broom)
# library(car)
## paticular packages for this project
library(lmtest)
library(corrr)
library(tseries)
library(corrplot)
source("./funcs.R")
The data set is defined as follows based on file recs.csv:
set.seed(6)
dat <-
read_csv("../../data/recs.csv") %>%
dplyr::slice(sample(nrow(.), 300)) %>%
mutate(y = log(KWH / NHSLDMEM)) %>%
mutate(x8 = TOTROOMS + NCOMBATH + NHAFBATH) %>%
dplyr::select(y, x2 = NHSLDMEM, x3 = EDUCATION, x4 = MONEYPY, x5 = HHSEX,
x6 = HHAGE, x7 = ATHOME, x8) %>%
mutate_at(seq(2, 8), as.integer) %>% # make continuous variables discrete
mutate(x5 = - x5 + 2)
Different variables are summarized in the following table. y, the logarithm of averaged electricity consumption, is the variable that we are interested in. Specifically, The electricity consumption refers to the electricity usage of the house/studio where the respondent lives in 2015, measured in kilowatthours. The quantity is average by the number of household members in the house/studio. That way, it roughly represent the level of electricity consumption of the respondent. Other variables are discussion in the following table.
| z |
KWH |
electricity consumption |
| y |
LKWH.pers |
logarithm of KWH/NHSLDMEM |
| x2 |
NHSLDMEM |
number of household members |
| x3 |
EDUCATION |
highest education completed |
| x4 |
MONEYPY |
annual gross household income last year |
| x5 |
HHSEX |
gender |
| x6 |
HHAGE |
age |
| x7 |
ATHOME |
number of weekdays someone is at home |
| x8 |
TOTROOMS + |
number of rooms (including bathrooms) |
Note that x8 is a variable indicating the number of rooms of the house/studio of the respondent. It equals the summation of TOTROOMS, NCOMBATH and NHAFBATH in the original data set. x8 is not included in the initial analysis (sections 1 to 7).
x3, the education level of the respondent, is considered as a continuous variable in this project for simplicity. The detailed definition of different levels is shown in the following table.
| 1 |
Less than high school diploma or GED |
| 2 |
High school diploma or GED |
| 3 |
Some college or Associate’s degree |
| 4 |
Bachelor’s degree (for example: BA, BS) |
| 5 |
Master’s, Professional, or Doctorate degree |
The first 5 rows of the data set used can be visualized:
| y |
x2 |
x3 |
x4 |
x5 |
x6 |
x7 |
x8 |
| 7.540 |
5 |
3 |
8 |
1 |
39 |
5 |
15 |
| 8.193 |
1 |
2 |
2 |
0 |
85 |
5 |
14 |
| 8.678 |
3 |
1 |
1 |
0 |
71 |
5 |
8 |
| 7.846 |
4 |
3 |
5 |
1 |
39 |
5 |
8 |
| 9.755 |
1 |
3 |
3 |
0 |
57 |
0 |
10 |
In this project, we want to develop a model associating the continuous variable, average electricity consumption, with other variables. We will start by visualizing correlations between variables. In particular, the two variables x2 and x6, which highly correlate with y will be explored. The model regressing y on x2 will be discussed in section 2. Four assumptions will be made, three of which will be tested in section 3-5 by Jarque-Bera test (normality), White’s test (homoskedasticity) and RESET test (functional form) respectively. According the test results and discussion in section 6, data point 36 is excluded. Then, in section 7, more regressors are introduced and three new models are established. The detail regarding how regressors interact with each other, namely causality, is discussed in section 8. Based on the understanding of the underlying mechanism, a nonlinear term and x8 are included as new regressors. Two new models are estimated, based on the only model passing all tests in section 7. Finally, the model called mods[[7]] is chosen as the final for presentation and it is interpreted in section 10.
1. Data Visualization
It can be seen that y is highly correlated to x2 and x6 according to the following table.
| x |
y |
r |
| x2 |
y |
-0.51098 |
| x3 |
y |
0.03410 |
| x4 |
y |
0.04098 |
| x5 |
y |
-0.04260 |
| x6 |
y |
0.35346 |
| x7 |
y |
0.03966 |
| x8 |
y |
0.21329 |
It can be seen from the following covariance matrix that y is highly correlated to x2, x6 and x8. Besides, x3-x4, x2-x6, x4-x8 are high correlated, which will be discussed in section 9.

For each level of x2 a box indicating three quantiles (25%, 50%, 75%) of y is given. It shows that there is a tendency for y to decrease with x2 by looking at the median. The sizes of different boxes seem to vary with different values of x2. Besides, there are many observations when x2 is small. But it is assumed for now that the conditional variance is constant, which will be tested section 4. Three data points with extreme values 36, 241 and 163 is discussed in sections 3 and 5.

The box plot of y by x6 is given. It can be seen that the tendency is not strictly linear and the condition variance is not stable. So we will regress y on x2 first and use x6 as the second regressor in section 6.

2. Regress y on x2, Assumptions and Orthogonalization
mods[[1]] is obtained by regressing y on x2.
lm(formula = y ~ x2, data = dat)
| term |
estimate |
std.error |
statistic |
p.value |
| (Intercept) |
9.036 |
0.07526 |
120.06 |
2.214e-254 |
| x2 |
-0.270 |
0.02631 |
-10.26 |
2.352e-21 |
| r.squared |
adj.r.squared |
sigma |
statistic |
p.value |
df |
logLik |
AIC |
BIC |
deviance |
df.residual |
| 0.2611 |
0.2586 |
0.6309 |
105.3 |
2.352e-21 |
2 |
-286.5 |
579 |
590.1 |
118.6 |
298 |
By orthogonalizing x2 with respect to constant 1. the following reparameterized model can be obtained.
mods[[2]] <-
dat %>%
mutate(x1 = 1, x21 = x2 - mean(.$x2)) %>%
dplyr::select(y, x1, x21) %>%
{lm(y ~ x1 + x21, data = .)}
lm(formula = y ~ x1 + x21, data = .)
| term |
estimate |
std.error |
statistic |
p.value |
| (Intercept) |
8.36 |
0.03642 |
229.52 |
0.000e+00 |
| x21 |
-0.27 |
0.02631 |
-10.26 |
2.352e-21 |
| r.squared |
adj.r.squared |
sigma |
statistic |
p.value |
df |
logLik |
AIC |
BIC |
deviance |
df.residual |
| 0.2611 |
0.2586 |
0.6309 |
105.3 |
2.352e-21 |
2 |
-286.5 |
579 |
590.1 |
118.6 |
298 |
The estimated regression coefficient for x2 in mods[[1]] equals that for x21 in mods[[2]]. That is, slopes in these two models are the same. The standard error of the intercept is reduced by 51.60 %.
3. Normality and Jarque-Bera Test of mods[[1]]
The following four plots can be used to check the plausibility of normality assumptions:
- The upper left plot shows residuals against fitted values of
mods[[1]]. It is hard to trust indication the flat trending line because there are few data points with low fitted values. The variance seems to be stable when fitted values are high. The assumption of homoskedasticity is tested formally in section 4.
- Data points
36, 241 and 163 are mentioned in all but the lower right plots. They are examined in section 6.
- The assumption of conditional normality looks reasonable according to the upper right Q-Q plot. A formal Jarque-Bera test is performed later this section to examine this assumption in a quantitative manner.

The assumption of conditional normality is justified by JB test.
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| Jarque-Bera |
4.326 |
2 |
298 |
0.115 |
0.05 |
FALSE |
4. Homoskedasticity and White’s Test of mods[[1]]
mods[[1]] cannot pass the White’s test, which means the variances of residuals do vary with different values of y.
mods[[1]] %>% test_white(dat, resi2 ~ x2 + I(x2^2), 2) %>% tab_ti(F)
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| White |
6.028 |
2 |
298 |
0.04909 |
0.05 |
TRUE |
6. Regress y on x2 with 36 Data Point Excluded
36, 241 and 163 data points are mentioned in three plots regrading the analysis of residuals of mods[[1]] in section 3. According to the scatter plot in section 1, their values of y are too small compared to those with same values of x2. They seems to be well defined.
| index |
y |
x2 |
| 36 |
5.312 |
6 |
| 163 |
7.054 |
1 |
| 241 |
6.680 |
3 |
However, with just 8 other points when x2 equals 6, data point 36 will have a huge impact on the model, so it is excluded in the following model mods[[2]]. That is, a new model is estimated with the same formula as mods[[1]] but the data set excluding data point 36.
lm(formula = y ~ x2, data = .)
| term |
estimate |
std.error |
statistic |
p.value |
| (Intercept) |
9.0101 |
0.07431 |
121.254 |
5.324e-255 |
| x2 |
-0.2569 |
0.02612 |
-9.832 |
6.208e-20 |
| r.squared |
adj.r.squared |
sigma |
statistic |
p.value |
df |
logLik |
AIC |
BIC |
deviance |
df.residual |
| 0.2456 |
0.243 |
0.6197 |
96.67 |
6.208e-20 |
2 |
-280.2 |
566.4 |
577.5 |
114.1 |
297 |
Compared with mods[[1]], mods[[2]] has more accurate estimation. Besides, mods[[2]] passes all of the hypothesis tests. So data point 36 is exluded in the following models, and the corresponding new data set dat_2 is used.
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| Jarque-Bera |
4.383 |
2 |
297 |
0.1118 |
0.05 |
FALSE |
| White |
1.686 |
2 |
297 |
0.4304 |
0.05 |
FALSE |
| RESET |
1.986 |
1 |
298 |
0.1588 |
0.05 |
FALSE |
7. Models with More Regressors
7-1. Benchmark Model
mods[[3]] with x2 and x6 being regressors is a good model already and pass every test. It is chosen as the benchmark model after the discussion in subsection 7-4.
lm(formula = y ~ x2 + x6, data = dat_2)
| term |
estimate |
std.error |
statistic |
p.value |
| (Intercept) |
8.522218 |
0.167008 |
51.029 |
1.015e-148 |
| x2 |
-0.220207 |
0.028079 |
-7.842 |
8.080e-14 |
| x6 |
0.007576 |
0.002331 |
3.249 |
1.290e-03 |
| r.squared |
adj.r.squared |
sigma |
statistic |
p.value |
df |
logLik |
AIC |
BIC |
deviance |
df.residual |
| 0.2715 |
0.2666 |
0.61 |
55.17 |
4.32e-21 |
3 |
-275 |
557.9 |
572.7 |
110.1 |
296 |
results_test <- mods[[3]] %>% test_jb(dat_2)
results_test %<>%
bind_rows(test_white(mods[[3]], dat_2, resi2 ~ x2 + x6 + I(x2^2) + I(x6^2),
3)) %>%
bind_rows(test_white(mods[[3]], dat_2, resi2 ~ x2 + x6 + I(x2^2) + I(x6^2) +
I(x2 * x6), 6)) %>%
bind_rows(test_reset(mods[[3]], dat_2))
results_test %>% tab_ti(F)
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| Jarque-Bera |
3.46586 |
2 |
297 |
0.1768 |
0.05 |
FALSE |
| White |
1.32474 |
3 |
296 |
0.7233 |
0.05 |
FALSE |
| White |
3.24389 |
6 |
293 |
0.7777 |
0.05 |
FALSE |
| RESET |
0.04314 |
1 |
298 |
0.8355 |
0.05 |
FALSE |
7-2. Model with All Regressors
To construct mods[[4]], all of the variables (excluding x8) are included. mods[[4]] can pass Jarque-Bera test and two White’s tests, but cannot pass RESET test.
results_test <- mods[[4]] %>% test_jb(dat_2)
results_test %<>%
bind_rows(test_white(mods[[4]], dat_2, resi2 ~ x2 + x3 + x4 + x5 + x6 + x7 +
I(x2^2) + I(x3^2) + I(x4^2) + I(x5^2) + I(x6^2) + I(x7^2), 7)) %>%
bind_rows(test_white(mods[[4]], dat_2, resi2 ~ x2 + x3 + x4 + x5 + x6 + x7 +
I(x2^2) + I(x3^2) + I(x4^2) + I(x5^2) + I(x6^2) + I(x7^2) + I(x2 * x3) +
I(x2 * x4) + I(x2 * x5) + I(x2 * x6) + I(x2 * x7) + I(x4 * x3) +
I(x5 * x3) + I(x6 * x3) + I(x3 * x7) + I(x4 * x5) + I(x4 * x6) +
I(x4 * x7) + I(x5 * x6) + I(x5 * x7) + I(x6 * x7), 28)) %>%
bind_rows(test_reset(mods[[4]], dat_2))
results_test %>% tab_ti(F)
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| Jarque-Bera |
1.801 |
2 |
297 |
0.40632 |
0.05 |
FALSE |
| White |
12.334 |
7 |
292 |
0.09011 |
0.05 |
FALSE |
| White |
31.025 |
28 |
271 |
0.31598 |
0.05 |
FALSE |
| RESET |
4.103 |
1 |
298 |
0.04280 |
0.05 |
TRUE |
7-3. Likelihood Ratio Test
Likelihood ratio tests for restricting one parameter can be performed by using partial correlations. For example, to test the hypothesis that coefficient for x5 is 0 in mods[[4]], following calculation can be conducted. With p_value being 0.7581638, we cannot reject the hypothesis.
lr_x5 <- - 299 * log(1 - 0.0003170)
(1 - pchisq(lr_x5, 1))
[1] 0.7581638
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| logLik |
0.09479 |
1 |
299 |
0.7582 |
0.05 |
FALSE |
Likelihood tests for restricting more than one parameter can be only performed by using values of log likelihood in the original and restricted models. For example, to test the hypothesis that coefficients for x5 and x7 are both 0 in mods[[4]], following calculation can be conducted. We cannot reject the hypothesis according the function output.
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| logLik |
0.9188 |
2 |
298 |
0.3378 |
0.05 |
FALSE |
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| logLik |
0.824 |
1 |
299 |
0.364 |
0.05 |
FALSE |
The above three test statistics are related in an additive manner, so models with multiple regressors can be reduced in a step-wise procedure. During every step, partial correlations for regressors can be used as the indication of the next term to be reduced.
[1] TRUE
7-4. Automated Model Selection
Thus, mods[[5]] is determined by automated model selection using mods[[4]] with stats::step function. mods[[5]] can pass Jarque-Bera test and two White’s tests, but cannot pass RESET test.
lm(formula = y ~ x2 + x3 + x4 + x6, data = dat_2)
| term |
estimate |
std.error |
statistic |
p.value |
| (Intercept) |
8.602282 |
0.191431 |
44.937 |
1.003e-133 |
| x2 |
-0.244215 |
0.028598 |
-8.540 |
7.356e-16 |
| x3 |
-0.079886 |
0.036673 |
-2.178 |
3.018e-02 |
| x4 |
0.060276 |
0.018291 |
3.295 |
1.103e-03 |
| x6 |
0.007589 |
0.002297 |
3.304 |
1.070e-03 |
| r.squared |
adj.r.squared |
sigma |
statistic |
p.value |
df |
logLik |
AIC |
BIC |
deviance |
df.residual |
| 0.298 |
0.2885 |
0.6008 |
31.2 |
1.155e-21 |
5 |
-269.4 |
550.8 |
573 |
106.1 |
294 |
results_test <- mods[[5]] %>% test_jb(dat_2)
results_test %<>%
bind_rows(test_white(mods[[5]], dat_2, resi2 ~ x2 + x3 + x4 + x6 + I(x2^2) +
I(x3^2) + I(x4^2) + I(x6^2), 5)) %>%
bind_rows(test_white(mods[[5]], dat_2, resi2 ~ x2 + x3 + x4 + x6 +
I(x2^2) + I(x3^2) + I(x4^2) + I(x6^2) + I(x2 * x3) + I(x2 * x4) +
I(x2 * x6) + I(x4 * x3) + I(x6 * x3) +I(x4 * x6), 15)) %>%
bind_rows(test_reset(mods[[5]], dat_2))
results_test %>% tab_ti(F)
| whi |
stat |
df1 |
df2 |
p_value |
prob |
if_reject |
| Jarque-Bera |
1.985 |
2 |
297 |
0.37063 |
0.05 |
FALSE |
| White |
10.051 |
5 |
294 |
0.07380 |
0.05 |
FALSE |
| White |
19.371 |
15 |
284 |
0.19742 |
0.05 |
FALSE |
| RESET |
3.898 |
1 |
298 |
0.04836 |
0.05 |
TRUE |
According to results of five models, though mods[[4]] and mods[[5]] have lower AIC, mods[[3]] is the one with all tests passed and lowst AIC. It is discussed intensively in subsection 8-1, and acts as the benchmark model in section 9. Besides, mods[[3]] has the lowest BIC.
| index |
r.squared |
adj.r.squared |
sigma |
statistic |
p.value |
df |
logLik |
AIC |
BIC |
deviance |
df.residual |
| 1 |
0.2611 |
0.2586 |
0.6309 |
105.30 |
2.352e-21 |
2 |
-286.5 |
579.0 |
590.1 |
118.6 |
298 |
| 2 |
0.2611 |
0.2586 |
0.6309 |
105.30 |
2.352e-21 |
2 |
-286.5 |
579.0 |
590.1 |
118.6 |
298 |
| 3 |
0.2715 |
0.2666 |
0.6100 |
55.17 |
4.320e-21 |
3 |
-275.0 |
557.9 |
572.7 |
110.1 |
296 |
| 4 |
0.3002 |
0.2858 |
0.6020 |
20.87 |
2.372e-20 |
7 |
-269.0 |
553.9 |
583.5 |
105.8 |
292 |
| 5 |
0.2980 |
0.2885 |
0.6008 |
31.20 |
1.155e-21 |
5 |
-269.4 |
550.8 |
573.0 |
106.1 |
294 |
Additionally, mods[[4]] has the highest r.squared for including more regressors, but its adj.r.squared is penalized for that. The AIC and BIC are not low as well compared to those of mods[[3]] and mods[[5]].
10. Interpretation of mods[[7]]
10-1. Model Structure
The overall structure can be illustrated in the following figure. The income is correlated to the number of household memebers, which is probably caused by the correlation between numbers of people and rooms. Because those relations don’t contribute to the interpretation of consumptions directly, they are omitted.

10-2. Regressors
Electricity consumption is highly correlated to the number of household members of the respondent. When there are not too many household members, with more members, the quantity of consumption decreases, probably due to the fact that people tend to share the kitchen. However, the effect diminishes gradually when there are many household members (around 5-8).

Because y is the log of average electricity consumptions, the final relationship between electricity consumptions and numbers of household members and numbers of rooms are:
As for the effect of number of rooms on electricity consumptions,

10-3. Orthogonalization of Multiple Regressors
mods[[8]] <-
dat_2 %>%
mutate(z1 = lm(x2 ~ 1)$residuals) %>%
mutate(z2 = lm(x8 ~ x2 + 1)$residuals) %>%
mutate(x2.2 = x2^2) %>%
mutate(z3 = lm(x2.2 ~ x2 + x8 + 1)$residuals) %>%
{lm(y ~ z1 + z2 + z3, data = .)}
lm(formula = y ~ z1 + z2 + z3, data = .)
| term |
estimate |
std.error |
statistic |
p.value |
| (Intercept) |
8.37009 |
0.03349 |
249.911 |
0.000e+00 |
| z1 |
-0.25686 |
0.02441 |
-10.521 |
3.420e-22 |
| z2 |
0.06625 |
0.01093 |
6.060 |
4.145e-09 |
| z3 |
0.03563 |
0.01232 |
2.893 |
4.104e-03 |
| r.squared |
adj.r.squared |
sigma |
statistic |
p.value |
df |
logLik |
AIC |
BIC |
deviance |
df.residual |
| 0.3456 |
0.3389 |
0.5791 |
51.93 |
5.594e-27 |
4 |
-258.9 |
527.9 |
546.4 |
98.94 |
295 |
The intercept in mods[[8]] (8.37009) can be interpreted as the exptected value for an individual with average values of x2, x8 and I(x2^2), which can be verified by the prediction using mods[[7]].
( 8.77946 - 0.52071 * mean(dat_2$x2) + 0.07329 * mean(dat_2$x8) +
0.03563 * mean(dat_2$x2^2) ) - 8.37009 <= 1e-4
[1] TRUE
Since the standard errors in mods[[8]] are smaller than those in mods[[7]], mods[[8]] is used to conduct inference. Particularly, se for Intercept is reduced by 75.48%, and ses for first two regressors are reduced by 71.75% and 2.41%. The estimations for the last term are exactly the same, which is expected.
2.5 % 97.5 %
(Intercept) 8.30417224 8.43600027
z1 -0.30490653 -0.20881311
z2 0.04473184 0.08775875
z3 0.01138835 0.05986556
To reduce average electricity consumptions, people are encouraged to live together in houses with fewer rooms.
LS0tCnRpdGxlOiAiTGluZWFyIFJlZ3Jlc3Npb24gQW5hbHlzaXMgb2YgRWxlY3RyaWNpdHkgQ29uc3VtcHRpb24iCmF1dGhvcjogIkVkd2FyZCBKLiBYdSAoPGVkeHU5NkBvdXRsb29rLmNvbT4pIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCmRvY3VtZW50Y2xhc3M6IGFydGljbGUKY2xhc3NvcHRpb246IGE0cGFwZXIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGRmX3ByaW50OiBwYWdlZAogICAgZmlnX2NhcHRpb246IG5vCiAgICBmaWdfaGVpZ2h0OiA3LjUKICAgIGZpZ193aWR0aDogMTUKICAgIHNtb290aF9zY3JvbGw6IHllcwogICAgdGhlbWU6IGRlZmF1bHQKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IG5vCiAgIyAgIHRvYzogeWVzCiAgIyAgIGtlZXBfdGV4OiB5ZXMKICAjIHBkZl9kb2N1bWVudDoKZWRpdG9yX29wdGlvbnM6CiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCiMjIEludHJvZHVjdGlvbgoKYGBge3J9CnJtKGxpc3QgPSBscygpKQpgYGAKCkZvbGxvd2luZyBwYWNrYWdlcyBhbmQgZnVuY3Rpb25zIGFyZSB1c2VkIGluIHRoaXMgcHJvamVjdC4KCmBgYHtyLCBtZXNzYWdlID0gRkFMU0UsIGVjaG89VH0KIyMgYmFzaWMgcGFja2FnZXMKbGlicmFyeShrbml0cikKbGlicmFyeShrYWJsZUV4dHJhKQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShjb25mbGljdGVkKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGJyb29tKQojIGxpYnJhcnkoY2FyKQojIyBwYXRpY3VsYXIgcGFja2FnZXMgZm9yIHRoaXMgcHJvamVjdApsaWJyYXJ5KGxtdGVzdCkKbGlicmFyeShjb3JycikKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGNvcnJwbG90KQpzb3VyY2UoIi4vZnVuY3MuUiIpCmBgYAoKYGBge3IsIGluY2x1ZGU9RkFMU0V9CnNldHdkKCJ+L0dpdEh1Yi9UaWR5U2ltU3RhdC9leGFtcGxlcy9yZWdyZXNzIikKb3B0aW9ucyh3aWR0aCA9IDgwLCBwaWxsYXIuc2lnZmlnID0gNSkKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNvbW1lbnQgPSAiIz4iLAogIGVjaG8gPSBGQUxTRSwKICBmaWcuYWxpZ249ImNlbnRlciIKKQpgYGAKClRoZSBkYXRhIHNldCBpcyBkZWZpbmVkIGFzIGZvbGxvd3MgYmFzZWQgb24gZmlsZSBgcmVjcy5jc3ZgOgoKYGBge3IsIG1lc3NhZ2UgPSBGQUxTRSwgZWNobz1UfQpzZXQuc2VlZCg2KQpkYXQgPC0KICByZWFkX2NzdigiLi4vLi4vZGF0YS9yZWNzLmNzdiIpICU+JQogIGRwbHlyOjpzbGljZShzYW1wbGUobnJvdyguKSwgMzAwKSkgJT4lCiAgbXV0YXRlKHkgPSBsb2coS1dIIC8gTkhTTERNRU0pKSAlPiUKICBtdXRhdGUoeDggPSBUT1RST09NUyArIE5DT01CQVRIICsgTkhBRkJBVEgpICU+JQogIGRwbHlyOjpzZWxlY3QoeSwgeDIgPSBOSFNMRE1FTSwgeDMgPSBFRFVDQVRJT04sIHg0ID0gTU9ORVlQWSwgeDUgPSBISFNFWCwKICAgIHg2ID0gSEhBR0UsIHg3ID0gQVRIT01FLCB4OCkgJT4lCiAgbXV0YXRlX2F0KHNlcSgyLCA4KSwgYXMuaW50ZWdlcikgJT4lICAjIG1ha2UgY29udGludW91cyB2YXJpYWJsZXMgZGlzY3JldGUKICBtdXRhdGUoeDUgPSAtIHg1ICsgMikKYGBgCgpEaWZmZXJlbnQgdmFyaWFibGVzIGFyZSBzdW1tYXJpemVkIGluIHRoZSBmb2xsb3dpbmcgdGFibGUuIGB5YCwgdGhlIGxvZ2FyaXRobSBvZiBhdmVyYWdlZCBlbGVjdHJpY2l0eSBjb25zdW1wdGlvbiwgaXMgdGhlIHZhcmlhYmxlIHRoYXQgd2UgYXJlIGludGVyZXN0ZWQgaW4uIFNwZWNpZmljYWxseSwgVGhlIGVsZWN0cmljaXR5IGNvbnN1bXB0aW9uIHJlZmVycyB0byB0aGUgZWxlY3RyaWNpdHkgdXNhZ2Ugb2YgdGhlIGhvdXNlL3N0dWRpbyB3aGVyZSB0aGUgcmVzcG9uZGVudCBsaXZlcyBpbiAyMDE1LCBtZWFzdXJlZCBpbiBraWxvd2F0dGhvdXJzLiBUaGUgcXVhbnRpdHkgaXMgYXZlcmFnZSBieSB0aGUgbnVtYmVyIG9mIGhvdXNlaG9sZCBtZW1iZXJzIGluIHRoZSBob3VzZS9zdHVkaW8uIFRoYXQgd2F5LCBpdCByb3VnaGx5IHJlcHJlc2VudCB0aGUgbGV2ZWwgb2YgZWxlY3RyaWNpdHkgY29uc3VtcHRpb24gb2YgdGhlIHJlc3BvbmRlbnQuIE90aGVyIHZhcmlhYmxlcyBhcmUgZGlzY3Vzc2lvbiBpbiB0aGUgZm9sbG93aW5nIHRhYmxlLgoKfCBTeW0gfCBBYmJyICAgICAgIHwgRGVmaW5pdGlvbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCAtLS0gfCAtLS0tLS0tLS0tIHwgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHwKfCB6ICAgfCBLV0ggICAgICAgIHwgZWxlY3RyaWNpdHkgY29uc3VtcHRpb24gICAgICAgICAgICAgICAgIHwKfCB5ICAgfCBMS1dILnBlcnMgIHwgbG9nYXJpdGhtIG9mIEtXSC9OSFNMRE1FTSAgICAgICAgICAgICAgIHwKfCB4MiAgfCBOSFNMRE1FTSAgIHwgbnVtYmVyIG9mIGhvdXNlaG9sZCBtZW1iZXJzICAgICAgICAgICAgIHwKfCB4MyAgfCBFRFVDQVRJT04gIHwgaGlnaGVzdCBlZHVjYXRpb24gY29tcGxldGVkICAgICAgICAgICAgIHwKfCB4NCAgfCBNT05FWVBZICAgIHwgYW5udWFsIGdyb3NzIGhvdXNlaG9sZCBpbmNvbWUgbGFzdCB5ZWFyIHwKfCB4NSAgfCBISFNFWCAgICAgIHwgZ2VuZGVyICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCB4NiAgfCBISEFHRSAgICAgIHwgYWdlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCB4NyAgfCBBVEhPTUUgICAgIHwgbnVtYmVyIG9mIHdlZWtkYXlzIHNvbWVvbmUgaXMgYXQgaG9tZSAgIHwKfCB4OCAgfCBUT1RST09NUyArIHwgbnVtYmVyIG9mIHJvb21zIChpbmNsdWRpbmcgYmF0aHJvb21zKSAgIHwKCk5vdGUgdGhhdCBgeDhgIGlzIGEgdmFyaWFibGUgaW5kaWNhdGluZyB0aGUgbnVtYmVyIG9mIHJvb21zIG9mIHRoZSBob3VzZS9zdHVkaW8gb2YgdGhlIHJlc3BvbmRlbnQuIEl0IGVxdWFscyB0aGUgc3VtbWF0aW9uIG9mIGBUT1RST09NU2AsIGBOQ09NQkFUSGAgYW5kIGBOSEFGQkFUSGAgaW4gdGhlIG9yaWdpbmFsIGRhdGEgc2V0LiBgeDhgIGlzIG5vdCBpbmNsdWRlZCBpbiB0aGUgaW5pdGlhbCBhbmFseXNpcyAoc2VjdGlvbnMgMSB0byA3KS4gCgpgeDNgLCB0aGUgZWR1Y2F0aW9uIGxldmVsIG9mIHRoZSByZXNwb25kZW50LCBpcyBjb25zaWRlcmVkIGFzIGEgY29udGludW91cyB2YXJpYWJsZSBpbiB0aGlzIHByb2plY3QgZm9yIHNpbXBsaWNpdHkuIFRoZSBkZXRhaWxlZCBkZWZpbml0aW9uIG9mIGRpZmZlcmVudCBsZXZlbHMgaXMgc2hvd24gaW4gdGhlIGZvbGxvd2luZyB0YWJsZS4KCnwgTGV2ZWwgfCBEZWZpbml0aW9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHwKfCAtLS0tLSB8IC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gfAp8IDEgICAgIHwgTGVzcyB0aGFuIGhpZ2ggc2Nob29sIGRpcGxvbWEgb3IgR0VEICAgICAgICB8CnwgMiAgICAgfCBIaWdoIHNjaG9vbCBkaXBsb21hIG9yIEdFRCAgICAgICAgICAgICAgICAgIHwKfCAzICAgICB8IFNvbWUgY29sbGVnZSBvciBBc3NvY2lhdGXigJlzIGRlZ3JlZSAgICAgICAgICB8CnwgNCAgICAgfCBCYWNoZWxvcuKAmXMgZGVncmVlIChmb3IgZXhhbXBsZTogQkEsIEJTKSAgICAgfAp8IDUgICAgIHwgTWFzdGVy4oCZcywgUHJvZmVzc2lvbmFsLCBvciBEb2N0b3JhdGUgZGVncmVlIHwKClRoZSBmaXJzdCA1IHJvd3Mgb2YgdGhlIGRhdGEgc2V0IHVzZWQgY2FuIGJlIHZpc3VhbGl6ZWQ6CgpgYGB7cn0KaGVhZChkYXQsIDUpICU+JSB0YWJfdGkoRikKYGBgCgpJbiB0aGlzIHByb2plY3QsIHdlIHdhbnQgdG8gZGV2ZWxvcCBhIG1vZGVsIGFzc29jaWF0aW5nIHRoZSBjb250aW51b3VzIHZhcmlhYmxlLCBhdmVyYWdlIGVsZWN0cmljaXR5IGNvbnN1bXB0aW9uLCB3aXRoIG90aGVyIHZhcmlhYmxlcy4gV2Ugd2lsbCBzdGFydCBieSB2aXN1YWxpemluZyBjb3JyZWxhdGlvbnMgYmV0d2VlbiB2YXJpYWJsZXMuIEluIHBhcnRpY3VsYXIsIHRoZSB0d28gdmFyaWFibGVzIGB4MmAgYW5kIGB4NmAsIHdoaWNoIGhpZ2hseSBjb3JyZWxhdGUgd2l0aCBgeWAgd2lsbCBiZSBleHBsb3JlZC4gVGhlIG1vZGVsIHJlZ3Jlc3NpbmcgYHlgIG9uIGB4MmAgd2lsbCBiZSBkaXNjdXNzZWQgaW4gc2VjdGlvbiAyLiBGb3VyIGFzc3VtcHRpb25zIHdpbGwgYmUgbWFkZSwgdGhyZWUgb2Ygd2hpY2ggd2lsbCBiZSB0ZXN0ZWQgaW4gc2VjdGlvbiAzLTUgYnkgSmFycXVlLUJlcmEgdGVzdCAobm9ybWFsaXR5KSwgV2hpdGXigJlzIHRlc3QgKGhvbW9za2VkYXN0aWNpdHkpIGFuZCBSRVNFVCB0ZXN0IChmdW5jdGlvbmFsIGZvcm0pIHJlc3BlY3RpdmVseS4gQWNjb3JkaW5nIHRoZSB0ZXN0IHJlc3VsdHMgYW5kIGRpc2N1c3Npb24gaW4gc2VjdGlvbiA2LCBkYXRhIHBvaW50IGAzNmAgaXMgZXhjbHVkZWQuIFRoZW4sIGluIHNlY3Rpb24gNywgbW9yZSByZWdyZXNzb3JzIGFyZSBpbnRyb2R1Y2VkIGFuZCB0aHJlZSBuZXcgbW9kZWxzIGFyZSBlc3RhYmxpc2hlZC4gVGhlIGRldGFpbCByZWdhcmRpbmcgaG93IHJlZ3Jlc3NvcnMgaW50ZXJhY3Qgd2l0aCBlYWNoIG90aGVyLCBuYW1lbHkgY2F1c2FsaXR5LCBpcyBkaXNjdXNzZWQgaW4gc2VjdGlvbiA4LiBCYXNlZCBvbiB0aGUgdW5kZXJzdGFuZGluZyBvZiB0aGUgdW5kZXJseWluZyBtZWNoYW5pc20sIGEgbm9ubGluZWFyIHRlcm0gYW5kIGB4OGAgYXJlIGluY2x1ZGVkIGFzIG5ldyByZWdyZXNzb3JzLiBUd28gbmV3IG1vZGVscyBhcmUgZXN0aW1hdGVkLCBiYXNlZCBvbiB0aGUgb25seSBtb2RlbCBwYXNzaW5nIGFsbCB0ZXN0cyBpbiBzZWN0aW9uIDcuIEZpbmFsbHksIHRoZSBtb2RlbCBjYWxsZWQgYG1vZHNbWzddXWAgaXMgY2hvc2VuIGFzIHRoZSBmaW5hbCBmb3IgcHJlc2VudGF0aW9uIGFuZCBpdCBpcyBpbnRlcnByZXRlZCBpbiBzZWN0aW9uIDEwLgoKIyMgMS4gRGF0YSBWaXN1YWxpemF0aW9uCgpJdCBjYW4gYmUgc2VlbiB0aGF0IGB5YCBpcyBoaWdobHkgY29ycmVsYXRlZCB0byBgeDJgIGFuZCBgeDZgIGFjY29yZGluZyB0byB0aGUgZm9sbG93aW5nIHRhYmxlLgoKYGBge3J9CmRhdCAlPiUKICBjb3IoKSAlPiUKICBhc19jb3JkZigpICU+JQogIHN0cmV0Y2goKSAlPiUKICBkcGx5cjo6ZmlsdGVyKHkgPT0gInkiICYgeCAhPSAieSIpICU+JQogIHRhYl90aShGKQpgYGAKCkl0IGNhbiBiZSBzZWVuIGZyb20gdGhlIGZvbGxvd2luZyBjb3ZhcmlhbmNlIG1hdHJpeCB0aGF0IGB5YCBpcyBoaWdobHkgY29ycmVsYXRlZCB0byBgeDJgLCBgeDZgIGFuZCBgeDhgLiBCZXNpZGVzLCBgeDNgLWB4NGAsIGB4MmAtYHg2YCwgYHg0YC1geDhgIGFyZSBoaWdoIGNvcnJlbGF0ZWQsIHdoaWNoIHdpbGwgYmUgZGlzY3Vzc2VkIGluIHNlY3Rpb24gOS4KCmBgYHtyfQpkYXQgJT4lCiAgY29yKCkgJT4lCiAgY29ycnBsb3QodHlwZSA9ICJ1cHBlciIsIHRsLmNvbCA9ICJibGFjayIsIHRsLnNydCA9IDQ1KQpgYGAKCkZvciBlYWNoIGxldmVsIG9mIGB4MmAgYSBib3ggaW5kaWNhdGluZyB0aHJlZSBxdWFudGlsZXMgKDI1JSwgNTAlLCA3NSUpIG9mIGB5YCBpcyBnaXZlbi4gSXQgc2hvd3MgdGhhdCB0aGVyZSBpcyBhIHRlbmRlbmN5IGZvciBgeWAgdG8gZGVjcmVhc2Ugd2l0aCBgeDJgIGJ5IGxvb2tpbmcgYXQgdGhlIG1lZGlhbi4gVGhlIHNpemVzIG9mIGRpZmZlcmVudCBib3hlcyBzZWVtIHRvIHZhcnkgd2l0aCBkaWZmZXJlbnQgdmFsdWVzIG9mIGB4MmAuIEJlc2lkZXMsIHRoZXJlIGFyZSBtYW55IG9ic2VydmF0aW9ucyB3aGVuIGB4MmAgaXMgc21hbGwuIEJ1dCBpdCBpcyBhc3N1bWVkIGZvciBub3cgdGhhdCB0aGUgY29uZGl0aW9uYWwgdmFyaWFuY2UgaXMgY29uc3RhbnQsIHdoaWNoIHdpbGwgYmUgdGVzdGVkIHNlY3Rpb24gNC4gVGhyZWUgZGF0YSBwb2ludHMgd2l0aCBleHRyZW1lIHZhbHVlcyBgMzZgLCBgMjQxYCBhbmQgYDE2M2AgaXMgZGlzY3Vzc2VkIGluIHNlY3Rpb25zIDMgYW5kIDUuIAoKYGBge3J9CmRhdCAlPiUKICBtdXRhdGUoaW5kZXggPSByb3dfbnVtYmVyKCkpICU+JQogIGdncGxvdCgpICsKICAgIGdlb21fYm94cGxvdChhZXMoeDIsIHksIGdyb3VwID0gY3V0X3dpZHRoKHgyLCAxKSksIG91dGxpZXIuYWxwaGEgPSAwKSArCiAgICBnZW9tX3BvaW50KGFlcyh4MiwgeSksIHNoYXBlID0gMSkgKwogICAgZ2VvbV90ZXh0KGFlcyh4MiwgeSwgbGFiZWwgPSBpZmVsc2UoaW5kZXggPT0gMzYgfCBpbmRleCA9PSAxNjMgfAogICAgICBpbmRleCA9PSAyNDEsIGFzLmNoYXJhY3RlcihpbmRleCksICIiKSksIGhqdXN0PTEuNSwgdmp1c3Q9MCkKYGBgCgpUaGUgYm94IHBsb3Qgb2YgYHlgIGJ5IGB4NmAgaXMgZ2l2ZW4uIEl0IGNhbiBiZSBzZWVuIHRoYXQgdGhlIHRlbmRlbmN5IGlzIG5vdCBzdHJpY3RseSBsaW5lYXIgYW5kIHRoZSBjb25kaXRpb24gdmFyaWFuY2UgaXMgbm90IHN0YWJsZS4gU28gd2Ugd2lsbCByZWdyZXNzIGB5YCBvbiBgeDJgIGZpcnN0IGFuZCB1c2UgYHg2YCBhcyB0aGUgc2Vjb25kIHJlZ3Jlc3NvciBpbiBzZWN0aW9uIDYuCgpgYGB7cn0KZGF0ICU+JQogIGdncGxvdCgpICsKICBnZW9tX2JveHBsb3QoYWVzKHg2LCB5LCBncm91cCA9IGN1dF93aWR0aCh4NiwgMTApKSwgb3V0bGllci5hbHBoYSA9IDApKwogICAgZ2VvbV9wb2ludChhZXMoeDYsIHkpLCBzaGFwZSA9IDEpCmBgYAoKIyMgMi4gUmVncmVzcyBgeWAgb24gYHgyYCwgQXNzdW1wdGlvbnMgYW5kIE9ydGhvZ29uYWxpemF0aW9uCgpgbW9kc1tbMV1dYCBpcyBvYnRhaW5lZCBieSByZWdyZXNzaW5nIGB5YCBvbiBgeDJgLgoKYGBge3J9Cm1vZHMgPC0gbGlzdCgpCm1vZHNbWzFdXSA8LSBsbSh5IH4geDIsIGRhdGEgPSBkYXQpCgptb2RzW1sxXV0gLT4gbW9kZWwgICMgUHJpbnQgbW9kZWwgc3VtbWFyeQptb2RlbCRjYWxsCm1vZGVsICU+JSB0aWR5KCkgJT4lIHRhYl90aShGKQptb2RlbCAlPiUgZ2xhbmNlKCkgJT4lIHRhYl90aShGKQpybShtb2RlbCkKCnJlc3VsdHMgPC0gbmV3X3Jlc3VsdHMobW9kc1tbMV1dLCAxKQpgYGAKCkJ5IG9ydGhvZ29uYWxpemluZyBgeDJgIHdpdGggcmVzcGVjdCB0byBjb25zdGFudCAxLiB0aGUgZm9sbG93aW5nIHJlcGFyYW1ldGVyaXplZCBtb2RlbCBjYW4gYmUgb2J0YWluZWQuCgpgYGB7ciwgZWNobz1UfQptb2RzW1syXV0gPC0gCiAgZGF0ICU+JQogIG11dGF0ZSh4MSA9IDEsIHgyMSA9IHgyIC0gbWVhbiguJHgyKSkgJT4lCiAgZHBseXI6OnNlbGVjdCh5LCB4MSwgeDIxKSAlPiUKICB7bG0oeSB+IHgxICsgeDIxLCBkYXRhID0gLil9CmBgYAoKYGBge3J9CnJlc3VsdHMgJTw+JQogIGNvbGxlY3RfZ2xhbmNlKG1vZHNbWzJdXSwgMikKCm1vZHNbWzJdXSAtPiBtb2RlbCAgIyBQcmludCBtb2RlbCBzdW1tYXJ5Cm1vZGVsJGNhbGwKbW9kZWwgJT4lIHRpZHkoKSAlPiUgdGFiX3RpKEYpCm1vZGVsICU+JSBnbGFuY2UoKSAlPiUgdGFiX3RpKEYpCnJtKG1vZGVsKQpgYGAKClRoZSBlc3RpbWF0ZWQgcmVncmVzc2lvbiBjb2VmZmljaWVudCBmb3IgYHgyYCBpbiBgbW9kc1tbMV1dYCBlcXVhbHMgdGhhdCBmb3IgYHgyMWAgaW4gYG1vZHNbWzJdXWAuIFRoYXQgaXMsIHNsb3BlcyBpbiB0aGVzZSB0d28gbW9kZWxzIGFyZSB0aGUgc2FtZS4gVGhlIHN0YW5kYXJkIGVycm9yIG9mIHRoZSBpbnRlcmNlcHQgaXMgcmVkdWNlZCBieSA1MS42MCAlLgoKIyMgMy4gTm9ybWFsaXR5IGFuZCBKYXJxdWUtQmVyYSBUZXN0IG9mIGBtb2RzW1sxXV1gCgpUaGUgZm9sbG93aW5nIGZvdXIgcGxvdHMgY2FuIGJlIHVzZWQgdG8gY2hlY2sgdGhlIHBsYXVzaWJpbGl0eSBvZiBub3JtYWxpdHkgYXNzdW1wdGlvbnM6CgotIFRoZSB1cHBlciBsZWZ0IHBsb3Qgc2hvd3MgcmVzaWR1YWxzIGFnYWluc3QgZml0dGVkIHZhbHVlcyBvZiBgbW9kc1tbMV1dYC4gSXQgaXMgaGFyZCB0byB0cnVzdCBpbmRpY2F0aW9uIHRoZSBmbGF0IHRyZW5kaW5nIGxpbmUgYmVjYXVzZSB0aGVyZSBhcmUgZmV3IGRhdGEgcG9pbnRzIHdpdGggbG93IGZpdHRlZCB2YWx1ZXMuIFRoZSB2YXJpYW5jZSBzZWVtcyB0byBiZSBzdGFibGUgd2hlbiBmaXR0ZWQgdmFsdWVzIGFyZSBoaWdoLiBUaGUgYXNzdW1wdGlvbiBvZiBob21vc2tlZGFzdGljaXR5IGlzIHRlc3RlZCBmb3JtYWxseSBpbiBzZWN0aW9uIDQuCi0gRGF0YSBwb2ludHMgYDM2YCwgYDI0MWAgYW5kIGAxNjNgIGFyZSBtZW50aW9uZWQgaW4gYWxsIGJ1dCB0aGUgbG93ZXIgcmlnaHQgcGxvdHMuIFRoZXkgYXJlIGV4YW1pbmVkIGluIHNlY3Rpb24gNi4KLSBUaGUgYXNzdW1wdGlvbiBvZiBjb25kaXRpb25hbCBub3JtYWxpdHkgbG9va3MgcmVhc29uYWJsZSBhY2NvcmRpbmcgdG8gdGhlIHVwcGVyIHJpZ2h0IFEtUSBwbG90LiBBIGZvcm1hbCBKYXJxdWUtQmVyYSB0ZXN0IGlzIHBlcmZvcm1lZCBsYXRlciB0aGlzIHNlY3Rpb24gdG8gZXhhbWluZSB0aGlzIGFzc3VtcHRpb24gaW4gYSBxdWFudGl0YXRpdmUgbWFubmVyLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9CnBhcl9vcmdpbmFsIDwtIHBhcigpCnBhcihtZnJvdyA9IGMoMiwgMiksIG1haSA9IGMoMC4zLCAwLjMsIDAuMywgMC4zKSkKcGxvdChtb2RzW1sxXV0pCnBhcihwYXJfb3JnaW5hbCkKYGBgCgpUaGUgYXNzdW1wdGlvbiBvZiBjb25kaXRpb25hbCBub3JtYWxpdHkgaXMganVzdGlmaWVkIGJ5IEpCIHRlc3QuCgpgYGB7cn0KbW9kc1tbMV1dICU+JSB0ZXN0X2piKGRhdCkgJT4lIHRhYl90aShGKQpgYGAKCiMjIDQuIEhvbW9za2VkYXN0aWNpdHkgYW5kIFdoaXRlJ3MgVGVzdCBvZiBgbW9kc1tbMV1dYAoKYG1vZHNbWzFdXWAgY2Fubm90IHBhc3MgdGhlIFdoaXRlJ3MgdGVzdCwgd2hpY2ggbWVhbnMgdGhlIHZhcmlhbmNlcyBvZiByZXNpZHVhbHMgZG8gdmFyeSB3aXRoIGRpZmZlcmVudCB2YWx1ZXMgb2YgYHlgLgoKYGBge3IsIGVjaG89VH0KbW9kc1tbMV1dICU+JSB0ZXN0X3doaXRlKGRhdCwgcmVzaTIgfiB4MiArIEkoeDJeMiksIDIpICU+JSB0YWJfdGkoRikKYGBgCgojIyA1LiBGdW5jdGlvbmFsIEZvcm0gYW5kIFJFU0VUIFRlc3Qgb2YgYG1vZHNbWzFdXWAKCmBtb2RzW1sxXV1gIGNhbiBwYXNzIFJFU0VUIHRlc3QuCgpgYGB7cn0KbW9kc1tbMV1dICU+JSB0ZXN0X3Jlc2V0KGRhdCkgJT4lIHRhYl90aShGKQpgYGAKCiMjIDYuIFJlZ3Jlc3MgYHlgIG9uIGB4MmAgd2l0aCBgMzZgIERhdGEgUG9pbnQgRXhjbHVkZWQKCmAzNmAsIGAyNDFgIGFuZCBgMTYzYCBkYXRhIHBvaW50cyBhcmUgbWVudGlvbmVkIGluIHRocmVlIHBsb3RzIHJlZ3JhZGluZyB0aGUgYW5hbHlzaXMgb2YgcmVzaWR1YWxzIG9mIGBtb2RzW1sxXV1gIGluIHNlY3Rpb24gMy4gQWNjb3JkaW5nIHRvIHRoZSBzY2F0dGVyIHBsb3QgaW4gc2VjdGlvbiAxLCB0aGVpciB2YWx1ZXMgb2YgYHlgIGFyZSB0b28gc21hbGwgY29tcGFyZWQgdG8gdGhvc2Ugd2l0aCBzYW1lIHZhbHVlcyBvZiBgeDJgLiBUaGV5IHNlZW1zIHRvIGJlIHdlbGwgZGVmaW5lZC4gCgpgYGB7cn0KZGF0ICU+JQogIG11dGF0ZShpbmRleCA9IHJvd19udW1iZXIoKSkgJT4lCiAgZHBseXI6OmZpbHRlcihyb3dfbnVtYmVyKCkgPT0gMjQxIHwgcm93X251bWJlcigpID09IDE2MyB8IAogICAgcm93X251bWJlcigpID09IDM2KSAlPiUKICBkcGx5cjo6c2VsZWN0KGluZGV4LCB5LCB4MikgJT4lCiAgdGFiX3RpKEYpCmBgYAoKSG93ZXZlciwgd2l0aCBqdXN0IDggb3RoZXIgcG9pbnRzIHdoZW4gYHgyYCBlcXVhbHMgNiwgZGF0YSBwb2ludCBgMzZgIHdpbGwgaGF2ZSBhIGh1Z2UgaW1wYWN0IG9uIHRoZSBtb2RlbCwgc28gaXQgaXMgZXhjbHVkZWQgaW4gdGhlIGZvbGxvd2luZyBtb2RlbCBgbW9kc1tbMl1dYC4gVGhhdCBpcywgYSBuZXcgbW9kZWwgaXMgZXN0aW1hdGVkIHdpdGggdGhlIHNhbWUgZm9ybXVsYSBhcyBgbW9kc1tbMV1dYCBidXQgdGhlIGRhdGEgc2V0IGV4Y2x1ZGluZyBkYXRhIHBvaW50IGAzNmAuCgpgYGB7cn0KbW9kc1tbMl1dIDwtCiAgZGF0ICU+JQogIGRwbHlyOjpmaWx0ZXIocm93X251bWJlcigpICE9IDM2KSAlPiUKICB7bG0oeSB+IHgyLCBkYXRhID0gLil9Cgptb2RzW1syXV0gLT4gbW9kZWwgICMgUHJpbnQgbW9kZWwgc3VtbWFyeQptb2RlbCRjYWxsCm1vZGVsICU+JSB0aWR5KCkgJT4lIHRhYl90aShGKQptb2RlbCAlPiUgZ2xhbmNlKCkgJT4lIHRhYl90aShGKQpybShtb2RlbCkKYGBgCgpDb21wYXJlZCB3aXRoIGBtb2RzW1sxXV1gLCBgbW9kc1tbMl1dYCBoYXMgbW9yZSBhY2N1cmF0ZSBlc3RpbWF0aW9uLiBCZXNpZGVzLCBgbW9kc1tbMl1dYCBwYXNzZXMgYWxsIG9mIHRoZSBoeXBvdGhlc2lzIHRlc3RzLiBTbyBkYXRhIHBvaW50IGAzNmAgaXMgZXhsdWRlZCBpbiB0aGUgZm9sbG93aW5nIG1vZGVscywgYW5kIHRoZSBjb3JyZXNwb25kaW5nIG5ldyBkYXRhIHNldCBgZGF0XzJgIGlzIHVzZWQuCgpgYGB7cn0KZGF0XzIgPC0KICBkYXQgJT4lCiAgZHBseXI6OmZpbHRlcihyb3dfbnVtYmVyKCkgIT0gMzYpCgpyZXN1bHRzX3Rlc3QgPC0KICBtb2RzW1syXV0gJT4lCiAgdGVzdF9qYihkYXRfMikKCnJlc3VsdHNfdGVzdCAlPD4lCiAgYmluZF9yb3dzKHRlc3Rfd2hpdGUobW9kc1tbMl1dLCBkYXRfMiwgcmVzaTIgfiB4MiArIEkoeDJeMiksIDIpKSAlPiUKICBiaW5kX3Jvd3ModGVzdF9yZXNldChtb2RzW1syXV0sIGRhdF8yKSkKCnJlc3VsdHNfdGVzdCAlPiUgdGFiX3RpKEYpCmBgYAoKIyMgNy4gTW9kZWxzIHdpdGggTW9yZSBSZWdyZXNzb3JzCgojIyMgNy0xLiBCZW5jaG1hcmsgTW9kZWwKCmBtb2RzW1szXV1gIHdpdGggYHgyYCBhbmQgYHg2YCBiZWluZyByZWdyZXNzb3JzIGlzIGEgZ29vZCBtb2RlbCBhbHJlYWR5IGFuZCBwYXNzIGV2ZXJ5IHRlc3QuIEl0IGlzIGNob3NlbiBhcyB0aGUgYmVuY2htYXJrIG1vZGVsIGFmdGVyIHRoZSBkaXNjdXNzaW9uIGluIHN1YnNlY3Rpb24gNy00LgoKYGBge3J9Cm1vZHNbWzNdXSA8LSBsbSh5IH4geDIgKyB4NiwgZGF0YSA9IGRhdF8yKQpyZXN1bHRzICU8PiUgY29sbGVjdF9nbGFuY2UobW9kc1tbM11dLCAzKQoKIyMgUHJpbnQgbW9kZWwgc3VtbWFyeQptb2RlbCA8LSBtb2RzW1szXV0KbW9kZWwkY2FsbAptb2RlbCAlPiUgdGlkeSgpICU+JSB0YWJfdGkoRikKbW9kZWwgJT4lIGdsYW5jZSgpICU+JSB0YWJfdGkoRikKcm0obW9kZWwpCmBgYAoKYGBge3IsIGVjaG89VH0KcmVzdWx0c190ZXN0IDwtIG1vZHNbWzNdXSAlPiUgdGVzdF9qYihkYXRfMikKCnJlc3VsdHNfdGVzdCAlPD4lCiAgYmluZF9yb3dzKHRlc3Rfd2hpdGUobW9kc1tbM11dLCBkYXRfMiwgcmVzaTIgfiB4MiArIHg2ICsgSSh4Ml4yKSArIEkoeDZeMiksCiAgICAzKSkgJT4lCiAgYmluZF9yb3dzKHRlc3Rfd2hpdGUobW9kc1tbM11dLCBkYXRfMiwgcmVzaTIgfiB4MiArIHg2ICsgSSh4Ml4yKSArIEkoeDZeMikgKwogICAgSSh4MiAqIHg2KSwgNikpICU+JQogIGJpbmRfcm93cyh0ZXN0X3Jlc2V0KG1vZHNbWzNdXSwgZGF0XzIpKQoKcmVzdWx0c190ZXN0ICU+JSB0YWJfdGkoRikKYGBgCgojIyMgNy0yLiBNb2RlbCB3aXRoIEFsbCBSZWdyZXNzb3JzCgpUbyBjb25zdHJ1Y3QgYG1vZHNbWzRdXWAsIGFsbCBvZiB0aGUgdmFyaWFibGVzIChleGNsdWRpbmcgYHg4YCkgYXJlIGluY2x1ZGVkLiBgbW9kc1tbNF1dYCBjYW4gcGFzcyBKYXJxdWUtQmVyYSB0ZXN0IGFuZCB0d28gV2hpdGUncyB0ZXN0cywgYnV0IGNhbm5vdCBwYXNzICBSRVNFVCB0ZXN0LgoKYGBge3J9Cm1vZHNbWzRdXSA8LSBsbSh5IH4geDIgKyB4MyArIHg0ICsgeDUgKyB4NiArIHg3LCBkYXRhID0gZGF0XzIpCnJlc3VsdHMgJTw+JSBjb2xsZWN0X2dsYW5jZShtb2RzW1s0XV0sIDQpCm1vZHNbWzRdXSAlPiUgdGFiX3RpZHkoVCkKYGBgCgpgYGB7ciwgZWNobz1UfQpyZXN1bHRzX3Rlc3QgPC0gbW9kc1tbNF1dICU+JSB0ZXN0X2piKGRhdF8yKQoKcmVzdWx0c190ZXN0ICU8PiUKICBiaW5kX3Jvd3ModGVzdF93aGl0ZShtb2RzW1s0XV0sIGRhdF8yLCByZXNpMiB+IHgyICsgeDMgKyB4NCArIHg1ICsgeDYgKyB4NyArIAogICAgSSh4Ml4yKSArIEkoeDNeMikgKyBJKHg0XjIpICsgSSh4NV4yKSArIEkoeDZeMikgKyBJKHg3XjIpLCA3KSkgJT4lCiAgYmluZF9yb3dzKHRlc3Rfd2hpdGUobW9kc1tbNF1dLCBkYXRfMiwgcmVzaTIgfiB4MiArIHgzICsgeDQgKyB4NSArIHg2ICsgeDcgKyAKICAgIEkoeDJeMikgKyBJKHgzXjIpICsgSSh4NF4yKSArIEkoeDVeMikgKyBJKHg2XjIpICsgSSh4N14yKSArIEkoeDIgKiB4MykgKwogICAgSSh4MiAqIHg0KSArIEkoeDIgKiB4NSkgKyBJKHgyICogeDYpICsgSSh4MiAqIHg3KSArIEkoeDQgKiB4MykgKyAKICAgIEkoeDUgKiB4MykgKyBJKHg2ICogeDMpICsgSSh4MyAqIHg3KSArIEkoeDQgKiB4NSkgKyBJKHg0ICogeDYpICsgCiAgICBJKHg0ICogeDcpICsgSSh4NSAqIHg2KSArIEkoeDUgKiB4NykgKyBJKHg2ICogeDcpLCAyOCkpICU+JQogIGJpbmRfcm93cyh0ZXN0X3Jlc2V0KG1vZHNbWzRdXSwgZGF0XzIpKQoKcmVzdWx0c190ZXN0ICU+JSB0YWJfdGkoRikKYGBgCgojIyMgNy0zLiBMaWtlbGlob29kIFJhdGlvIFRlc3QKCkxpa2VsaWhvb2QgcmF0aW8gdGVzdHMgZm9yIHJlc3RyaWN0aW5nIG9uZSBwYXJhbWV0ZXIgY2FuIGJlIHBlcmZvcm1lZCBieSB1c2luZyBwYXJ0aWFsIGNvcnJlbGF0aW9ucy4gRm9yIGV4YW1wbGUsIHRvIHRlc3QgdGhlIGh5cG90aGVzaXMgdGhhdCBjb2VmZmljaWVudCBmb3IgYHg1YCBpcyAwIGluIGBtb2RzW1s0XV1gLCBmb2xsb3dpbmcgY2FsY3VsYXRpb24gY2FuIGJlIGNvbmR1Y3RlZC4gV2l0aCBgcF92YWx1ZWAgYmVpbmcgMC43NTgxNjM4LCB3ZSBjYW5ub3QgcmVqZWN0IHRoZSBoeXBvdGhlc2lzLgoKYGBge3IsIGVjaG89VH0KbHJfeDUgPC0gLSAyOTkgKiBsb2coMSAtIDAuMDAwMzE3MCkgCigxIC0gcGNoaXNxKGxyX3g1LCAxKSkKYGBgCgpgYGB7cn0KbW9kc19saWsgPC0gbGlzdCgpCm1vZHNfbGlrW1sxXV0gPC0gbG0oeSB+IHgyICsgeDMgKyB4NCArIHg2ICsgeDcsIGRhdGEgPSBkYXRfMikKdGVzdF9saWsobW9kc1tbNF1dLCBtb2RzX2xpa1tbMV1dKSAlPiUgdGFiX3RpKEYpCmBgYAoKTGlrZWxpaG9vZCB0ZXN0cyBmb3IgcmVzdHJpY3RpbmcgbW9yZSB0aGFuIG9uZSBwYXJhbWV0ZXIgY2FuIGJlIG9ubHkgcGVyZm9ybWVkIGJ5IHVzaW5nIHZhbHVlcyBvZiBsb2cgbGlrZWxpaG9vZCBpbiB0aGUgb3JpZ2luYWwgYW5kIHJlc3RyaWN0ZWQgbW9kZWxzLiBGb3IgZXhhbXBsZSwgdG8gdGVzdCB0aGUgaHlwb3RoZXNpcyB0aGF0IGNvZWZmaWNpZW50cyBmb3IgYHg1YCBhbmQgYHg3YCBhcmUgYm90aCAwIGluIGBtb2RzW1s0XV1gLCBmb2xsb3dpbmcgY2FsY3VsYXRpb24gY2FuIGJlIGNvbmR1Y3RlZC4gV2UgY2Fubm90IHJlamVjdCB0aGUgaHlwb3RoZXNpcyBhY2NvcmRpbmcgdGhlIGZ1bmN0aW9uIG91dHB1dC4KCmBgYHtyfQptb2RzX2xpa1tbMl1dIDwtIGxtKHkgfiB4MiArIHgzICsgeDQgKyB4NiwgZGF0YSA9IGRhdF8yKQp0ZXN0X2xpayhtb2RzW1s0XV0sIG1vZHNfbGlrW1syXV0pICU+JSB0YWJfdGkoRikKYGBgCgpgYGB7cn0KdGVzdF9saWsobW9kc19saWtbWzFdXSwgbW9kc19saWtbWzJdXSkgJT4lIHRhYl90aShGKQpgYGAKClRoZSBhYm92ZSB0aHJlZSB0ZXN0IHN0YXRpc3RpY3MgYXJlIHJlbGF0ZWQgaW4gYW4gYWRkaXRpdmUgbWFubmVyLCBzbyBtb2RlbHMgd2l0aCBtdWx0aXBsZSByZWdyZXNzb3JzIGNhbiBiZSByZWR1Y2VkIGluIGEgc3RlcC13aXNlIHByb2NlZHVyZS4gRHVyaW5nIGV2ZXJ5IHN0ZXAsIHBhcnRpYWwgY29ycmVsYXRpb25zIGZvciByZWdyZXNzb3JzIGNhbiBiZSB1c2VkIGFzIHRoZSBpbmRpY2F0aW9uIG9mIHRoZSBuZXh0IHRlcm0gdG8gYmUgcmVkdWNlZC4KCmBgYHtyfQp0ZXN0X2xpayhtb2RzW1s0XV0sIG1vZHNfbGlrW1sxXV0pJHN0YXQgKyAKICB0ZXN0X2xpayhtb2RzX2xpa1tbMV1dLCBtb2RzX2xpa1tbMl1dKSRzdGF0IC0KICB0ZXN0X2xpayhtb2RzW1s0XV0sIG1vZHNfbGlrW1syXV0pJHN0YXQgPD0gMWUtNQpgYGAKCiMjIyA3LTQuIEF1dG9tYXRlZCBNb2RlbCBTZWxlY3Rpb24KClRodXMsIGBtb2RzW1s1XV1gIGlzIGRldGVybWluZWQgYnkgYXV0b21hdGVkIG1vZGVsIHNlbGVjdGlvbiB1c2luZyBgbW9kc1tbNF1dYCB3aXRoIGBzdGF0czo6c3RlcGAgZnVuY3Rpb24uIGBtb2RzW1s1XV1gIGNhbiBwYXNzIEphcnF1ZS1CZXJhIHRlc3QgYW5kIHR3byBXaGl0ZSdzIHRlc3RzLCBidXQgY2Fubm90IHBhc3MgUkVTRVQgdGVzdC4KCmBgYHtyfQptb2RzW1s1XV0gPC0gcXVpZXQoc3RlcChtb2RzW1s0XV0pKQpyZXN1bHRzICU8PiUgY29sbGVjdF9nbGFuY2UobW9kc1tbNV1dLCA1KQoKbW9kc1tbNV1dIC0+IG1vZGVsICAjIFByaW50IG1vZGVsIHN1bW1hcnkKbW9kZWwkY2FsbAptb2RlbCAlPiUgdGlkeSgpICU+JSB0YWJfdGkoRikKbW9kZWwgJT4lIGdsYW5jZSgpICU+JSB0YWJfdGkoRikKcm0obW9kZWwpCmBgYAoKYGBge3IsIGVjaG89VH0KcmVzdWx0c190ZXN0IDwtIG1vZHNbWzVdXSAlPiUgdGVzdF9qYihkYXRfMikKCnJlc3VsdHNfdGVzdCAlPD4lCiAgYmluZF9yb3dzKHRlc3Rfd2hpdGUobW9kc1tbNV1dLCBkYXRfMiwgcmVzaTIgfiB4MiArIHgzICsgeDQgKyB4NiArIEkoeDJeMikgKwogICAgSSh4M14yKSArIEkoeDReMikgKyBJKHg2XjIpLCA1KSkgJT4lCiAgYmluZF9yb3dzKHRlc3Rfd2hpdGUobW9kc1tbNV1dLCBkYXRfMiwgcmVzaTIgfiB4MiArIHgzICsgeDQgKyB4NiArIAogICAgSSh4Ml4yKSArIEkoeDNeMikgKyBJKHg0XjIpICsgSSh4Nl4yKSArIEkoeDIgKiB4MykgKyBJKHgyICogeDQpICsgCiAgICBJKHgyICogeDYpICsgSSh4NCAqIHgzKSArIEkoeDYgKiB4MykgK0koeDQgKiB4NiksIDE1KSkgJT4lCiAgYmluZF9yb3dzKHRlc3RfcmVzZXQobW9kc1tbNV1dLCBkYXRfMikpCgpyZXN1bHRzX3Rlc3QgJT4lIHRhYl90aShGKQpgYGAKCkFjY29yZGluZyB0byByZXN1bHRzIG9mIGZpdmUgbW9kZWxzLCB0aG91Z2ggYG1vZHNbWzRdXWAgYW5kIGBtb2RzW1s1XV1gIGhhdmUgbG93ZXIgQUlDLCBgbW9kc1tbM11dYCBpcyB0aGUgb25lIHdpdGggYWxsIHRlc3RzIHBhc3NlZCBhbmQgbG93c3QgQUlDLiBJdCBpcyBkaXNjdXNzZWQgaW50ZW5zaXZlbHkgaW4gc3Vic2VjdGlvbiA4LTEsIGFuZCBhY3RzIGFzIHRoZSBiZW5jaG1hcmsgbW9kZWwgaW4gc2VjdGlvbiA5LiBCZXNpZGVzLCBgbW9kc1tbM11dYCBoYXMgdGhlIGxvd2VzdCBCSUMuCgpgYGB7cn0KcmVzdWx0cyAlPiUgdGFiX3RpKEYpCmBgYAoKQWRkaXRpb25hbGx5LCBgbW9kc1tbNF1dYCBoYXMgdGhlIGhpZ2hlc3QgYHIuc3F1YXJlZGAgZm9yIGluY2x1ZGluZyBtb3JlIHJlZ3Jlc3NvcnMsIGJ1dCBpdHMgYGFkai5yLnNxdWFyZWRgIGlzIHBlbmFsaXplZCBmb3IgdGhhdC4gVGhlIEFJQyBhbmQgQklDIGFyZSBub3QgbG93IGFzIHdlbGwgY29tcGFyZWQgdG8gdGhvc2Ugb2YgYG1vZHNbWzNdXWAgYW5kIGBtb2RzW1s1XV1gLiAKCiMjIDguIENhdXNhbGl0eSBhbmQgTWVkaWF0aW9uCgojIyMgOC0xLiBDYXVzYWxpdHkgb2YgYHgyYC1geDZgCgpJdCBjYW4gYmUgc2VlbiBmcm9tIHRoZSBmb2xsb3dpbmcgdHdvIG1vZGVscyB0aGF0IGB5YCBpcyBoaWdobHkgY29ycmVsYXRlZCB0byBgeDJgIGFuZCBgeDZgIHNlcGFyYXRlbHkuIEJlc2lkZXMsIGFjY29yZGluZyB0byBgbW9kc1tbM11dYCwgYHlgIGlzIGhpZ2hseSBjb3JyZWxhdGVkIHRvIGB4MmAgYW5kIGB4NmAgYXQgdGhlIHNhbWUgdGltZS4gCgpgYGB7cn0KbW9kc182MiA8LSBsaXN0KCkKbW9kc182MltbMV1dIDwtIGxtKHkgfiB4MiwgZGF0YSA9IGRhdF8yKQoKbW9kc182MltbMV1dIC0+IG1vZGVsICAjIFByaW50IG1vZGVsIHN1bW1hcnkKbW9kZWwkY2FsbAptb2RlbCAlPiUgdGlkeSgpICU+JSB0YWJfdGkoRikKbW9kZWwgJT4lIGdsYW5jZSgpICU+JSB0YWJfdGkoRikKcm0obW9kZWwpCmBgYAoKYGBge3J9Cm1vZHNfNjJbWzJdXSA8LSBsbSh5IH4geDYsIGRhdGEgPSBkYXRfMikKCm1vZHNfNjJbWzJdXSAtPiBtb2RlbCAgIyBQcmludCBtb2RlbCBzdW1tYXJ5Cm1vZGVsJGNhbGwKbW9kZWwgJT4lIHRpZHkoKSAlPiUgdGFiX3RpKEYpCm1vZGVsICU+JSBnbGFuY2UoKSAlPiUgdGFiX3RpKEYpCnJtKG1vZGVsKQpgYGAKCkl0IGlzIHJlYXNvbmFibGUgdG8gYXNzdW1lIHRoYXQgcGVvcGxlIHRlbmQgdG8gaGF2ZSBtb3JlIGFjY29tcGFuaWVzIGFzIGFnZSBpbmNyZWFzZXMgYWZ0ZXIgMTguIEFsc28sIHRoZSBmb2xsb3dpbmcgbW9kZWwgcHJvdmVzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBgeDJgIGFuZCBgeDZgLiBXZSBjYW4gc2F5IHRoYXQgdGhlIGVmZmVjdCBvZiBgeDZgIG9uIGB5YCBpcyBtZWRpYXRlZCBieSBgeDJgLiBXaXRoIGB4NmAgYWZmZWN0aW5nIGB5YCBhcyB3ZWxsLCBgeDJgIGRvZXMgbm90IG1lZGlhdGUgYHg2YCBjb21wbGV0ZWx5LiBTbyBgeDJgIGFuZCBgeDZgIGFyZSBib3RoIHN1cHBvc2VkIHRvIGFwcGVhciBpbiB0aGUgbW9kZWwgZm9yIGB5YC4gVGhlIG1lZGlhdGlvbiBmYWN0b3IgYHgyYCBtYXkgYWZmZWN0IGB5YCB0aG91Z2ggb3RoZXIgd2F5cywgd2hpY2ggd2lsbCBiZSBleHBsb3JlZCBpbiBzZWN0aW9uIDEwLiBCZXNpZGVzLCB3ZSBmaW5kIHRoYXQgYHg2YCBkb2VzIG5vdCBhZmZlY3QgYHlgIGluIG90aGVyIHdheXMgaW4gc2VjdGlvbiAxMC4KCmBgYHtyfQptb2RzXzYyW1szXV0gPC0gbG0oeDIgfiB4NiwgZGF0YSA9IGRhdF8yKQoKbW9kc182MltbM11dIC0+IG1vZGVsICAjIFByaW50IG1vZGVsIHN1bW1hcnkKbW9kZWwkY2FsbAptb2RlbCAlPiUgdGlkeSgpICU+JSB0YWJfdGkoRikKbW9kZWwgJT4lIGdsYW5jZSgpICU+JSB0YWJfdGkoRikKcm0obW9kZWwpCmBgYAoKIyMjIDgtMi4gQ2F1c2FsaXR5IG9mIGB4M2AtYHg0YAoKV2hlbiB0YWtpbmcgYHgzYCBhbmQgYHg0YCBpbnRvIGNvbnNpZGVyYXRpb24sIHRoZSBtb2RlbHMgYXNzb2NhdGluZyBgeWAgd2l0aCBgeDNgIG9yIGB4NGAgYm90aCBzaG93IG5vIHNpZ25pZmljYW5jZSwgdGhvdWdoIGB4M2AgYW5kIGB4NGAgYXJlIGhpZ2hseSBjb3JyZWxhdGVkLiBTbyBuZWl0aGVyIGB4M2Agbm9yIGB4NGAgc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZSBtb2RlbC4KCmBgYHtyfQptb2RzXzM0IDwtIGxpc3QoKQptb2RzXzM0W1sxXV0gPC0gbG0oeDQgfiB4MywgZGF0YSA9IGRhdF8yKQoKbW9kc18zNFtbMV1dIC0+IG1vZGVsICAjIFByaW50IG1vZGVsIHN1bW1hcnkKbW9kZWwkY2FsbAptb2RlbCAlPiUgdGlkeSgpICU+JSB0YWJfdGkoRikKbW9kZWwgJT4lIGdsYW5jZSgpICU+JSB0YWJfdGkoRikKcm0obW9kZWwpCmBgYAoKYGBge3J9Cm1vZHNfMzRbWzJdXSA8LSBsbShmb3JtdWxhID0geSB+IHgzICsgeDQsIGRhdGEgPSBkYXRfMikKCm1vZHNfMzRbWzJdXSAtPiBtb2RlbCAgIyBQcmludCBtb2RlbCBzdW1tYXJ5Cm1vZGVsJGNhbGwKbW9kZWwgJT4lIHRpZHkoKSAlPiUgdGFiX3RpKEYpCm1vZGVsICU+JSBnbGFuY2UoKSAlPiUgdGFiX3RpKEYpCnJtKG1vZGVsKQpgYGAKCgojIyMgOC0zLiBDYXVzYWxpdHkgb2YgYHg0YC1geDhgCgpJdCBjYW4gYmUgc2VlbiB0aGF0IGB5YCBpcyBoaWdobHkgY29ycmVsYXRlZCB0byBgeDhgLgoKYGBge3J9Cm1vZHNfNDggPC0gbGlzdCgpCm1vZHNfNDhbWzFdXSA8LSAgbG0oeSB+IHg4LCBkYXRhID0gZGF0XzIpCgptb2RzXzQ4W1sxXV0gLT4gbW9kZWwgICMgUHJpbnQgbW9kZWwgc3VtbWFyeQptb2RlbCRjYWxsCm1vZGVsICU+JSB0aWR5KCkgJT4lIHRhYl90aShGKQptb2RlbCAlPiUgZ2xhbmNlKCkgJT4lIHRhYl90aShGKQpybShtb2RlbCkKYGBgCgpBbHNvLCBgeDhgIGlzIGhpZ2hseSByZWxhdGVkIHRvIGB4NGAsIHdoaWNoIG1ha2VzIHNlbnNlLCBiZWNhdXNlIHBlb3BsZSB3aXRoIG1vcmUgaW5jb21lIHRlbmQgdG8gYnV5IGhvdXNlcyB3aXRoIG1vcmUgcm9vbXMuCgpgYGB7cn0KbW9kc180OFtbMl1dIDwtICBsbSh4OCB+IHg0LCBkYXRhID0gZGF0XzIpCgptb2RzXzQ4W1syXV0gLT4gbW9kZWwgICMgUHJpbnQgbW9kZWwgc3VtbWFyeQptb2RlbCRjYWxsCm1vZGVsICU+JSB0aWR5KCkgJT4lIHRhYl90aShGKQptb2RlbCAlPiUgZ2xhbmNlKCkgJT4lIHRhYl90aShGKQpybShtb2RlbCkKYGBgCgpIb3dldmVyLCBmcm9tIHN1YnNlY3Rpb24gOS4yIHdlIGFscmVhZHkga25vdyB0aGF0IGB5YCBpcyBub3QgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBgeDRgLCB3aGljaCBpcyBpbGx1c3RyYXRlZCBhZ2FpbiBieSB0aGUgZm9sbG93aW5nIG1vZGVsLiBTbyB3ZSBzYXkgdGhhdCB0aGUgZWZmZWN0IG9mIGB4NGAgb24gYHlgIGlzIGNvbXBsZXRlbHkgbWVkaWF0ZWQgYnkgYHg4YC4gVGhvdWdoIGl0IG1ha2VzIHNlbnNlIHRoYXQgcGVvcGxlIHdpdGggbW9yZSBpbmNvbWUgdGVuZCB0byBjb25zdW1lIG1vcmUgZW5lcmd5IG9uIGF2ZXJhZ2UsIHRoZSBkaXJlY3QgZWZmZWN0IGlzIGNvbXBsZXRlbHkgbWVkaWF0ZWQgdGhyb3VnaCBgeDhgIGFuZCBwb3NzaWJseSBvdGhlciBmYWN0b3JzLgoKYGBge3J9Cm1vZHNfNDhbWzNdXSA8LSBsbSh5IH4geDggKyB4NCwgZGF0YSA9IGRhdF8yKQoKbW9kc180OFtbM11dIC0+IG1vZGVsICAjIFByaW50IG1vZGVsIHN1bW1hcnkKbW9kZWwkY2FsbAptb2RlbCAlPiUgdGlkeSgpICU+JSB0YWJfdGkoRikKbW9kZWwgJT4lIGdsYW5jZSgpICU+JSB0YWJfdGkoRikKcm0obW9kZWwpCmBgYAoKIyMgOS4gYG1vZHNbWzNdXWAgd2l0aCBleHRyYSB0ZXJtcwoKSW4gYG1vZHNbWzZdXWAsIGB4MmAsIGB4NmAgYW5kIGB4OGAgYXJlIGtlcHQgYXQgdGhlIHNhbWUgdGltZS4KCmBgYHtyfQptb2RzW1s2XV0gPC0gbG0oeSB+IHgyICsgeDYgKyB4OCwgZGF0YSA9IGRhdF8yKQoKbW9kc1tbNl1dIC0+IG1vZGVsICAjIFByaW50IG1vZGVsIHN1bW1hcnkKbW9kZWwkY2FsbAptb2RlbCAlPiUgdGlkeSgpICU+JSB0YWJfdGkoRikKbW9kZWwgJT4lIGdsYW5jZSgpICU+JSB0YWJfdGkoRikKcm0obW9kZWwpCmBgYAoKYGBge3J9CnJlc3VsdHNfdGVzdCA8LSBtb2RzW1s2XV0gJT4lIHRlc3RfamIoZGF0XzIpCgpyZXN1bHRzX3Rlc3QgJTw+JQogIGJpbmRfcm93cyh0ZXN0X3doaXRlKG1vZHNbWzZdXSwgZGF0XzIsIHJlc2kyIH4geDIgKyB4NiArIHg4ICsgSSh4Ml4yKSArCiAgICBJKHg2XjIpICsgSSh4OF4yKSwgNCkpICU+JQogIGJpbmRfcm93cyh0ZXN0X3doaXRlKG1vZHNbWzZdXSwgZGF0XzIsIHJlc2kyIH4geDIgKyB4NiArIHg4ICsgSSh4Ml4yKSArCiAgICBJKHg2XjIpICsgSSh4OF4yKSArIEkoeDIgKiB4NikgKyBJKHgyICogeDgpICsgSSh4NiAqIHg4KSwgMTApKSAlPiUKICBiaW5kX3Jvd3ModGVzdF9yZXNldChtb2RzW1s2XV0sIGRhdF8yKSkKCnJlc3VsdHNfdGVzdCAlPiUgdGFiX3RpKEYpCmBgYAoKV2l0aCB0aGUgaWRlYSBvZiBkaW1pbmlzaGluZyBlZmZlY3RzIG9mIHRoZSBudW1iZXIgb2YgaG91c2Vob2xkIG1lbWJlcnMgaW4gbWluZCwgaXQgaXMgbmF0dXJhbCB0byBpbmNsdWRlIHRoZSBzcXVhcmUgb2YgdGhlIGhvdXNlaG9sZCBudW1iZXJzLiBJbiBhZGRpdGlvbiwgYHg4YCBpcyBpbmNsdWRlZCBhY2NvcmRpbmcgdG8gdGhlIGRpc2N1c3Npb24gaW4gc3Vic2VjdGlvbiA4LTMuIFRodXMsIGBtb2RzW1s3XV1gIGlzIGVzdGltYXRlZC4gQmVpbmcgaW5zaWduaWZpY2FudCwgYHg2YCBpcyBleGNsdWRlZCwgYmVjY2F1c2UgdGhlIGVmZmVjdCBvZiBgeDZgIG9uIGB5YCBzZWVtcyB0byBiZSBtZWRpYXRlZCBjb21wZWxldGVseSBieSBgeDJgIGFuZCBgeDJeMmAuCgpgYGB7cn0KbW9kc1tbN11dIDwtIGxtKHkgfiB4MiArIHg4ICsgSSh4Ml4yKSwgZGF0YSA9IGRhdF8yKQptb2RzW1s3XV0gJT4lIHRhYl90aWR5KFQpCmBgYAoKV2l0aCBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIGJlaW5nIDI5OSwgdGhlIG1vZGVsIGlzIHNlbnNpdGl2ZSB0byBleGx1c2lvbiBvZiBzb21lIHRlcm0gb25seSBpZiB0aGUgcGFydGlhbCBjb3JyZWxhdGlvbiBvZiB0aGF0IHRlcm0gaXMgc21hbGxlciB0aGFuIDAuMDEyNzY1NTEuIFRoYXQgaXMsIGlmIGBwLnIuc3F1YXJlZGAgb2Ygc29tZSB0ZXJtIGRpc3BsYXllZCBhYm92ZSBpcyBzbWFsbGVyIHRoYW4gMC4wMTI3NjU1MSwgdGhlIGh5cG90aGVzaXMgcmVnYXJpbmcgdGhlIGNvZWZmaWNpZW50IGZvciB0aGF0IHRlcm0gaW4gdGhlIGxpa2VsaWhvb2QgcmF0aW8gdGVzdCB3b3VsZCBub3QgYmUgcmVqZWN0ZWQuIFRoZSB2YWx1ZSBgMC4wMTI3NjU1MWAgaXMgb2J0YWluZWQgYWNjb3JkaW5nIHRvIHRoZSBkaXNjdXNzaW9uIGluIHN1YnNlY3Rpb24gNy0zLiBCZXNpZGVzLCBzbWFsbCBgcC52YWx1ZWBzIGluZGljYXRlIHRoYXQgdGVybXMgY2Fubm90IGJlIGV4Y2x1ZGVkIGFzIHdlbGwuIAoKYGBge3IsIGluY2x1ZGU9Rn0KbHJfeDUgPC0gLSAyOTkgKiBsb2coMSAtIDAuMDEyNzY1NTEpCigxIC0gcGNoaXNxKGxyX3g1LCAxKSkKYGBgCgpgYGB7cn0KcmVzdWx0c190ZXN0IDwtIG1vZHNbWzddXSAlPiUgdGVzdF9qYihkYXRfMikKCnJlc3VsdHNfdGVzdCAlPD4lCiAgYmluZF9yb3dzKHRlc3Rfd2hpdGUobW9kc1tbN11dLCBkYXRfMiwgcmVzaTIgfiB4MiArIHg4ICsgSSh4Ml4yKSArIEkoeDheMiksCiAgICAzKSkgJT4lCiAgYmluZF9yb3dzKHRlc3Rfd2hpdGUobW9kc1tbN11dLCBkYXRfMiwgcmVzaTIgfiB4MiArIHg4ICsgSSh4Ml4yKSArCiAgICBJKHg4XjIpICsgSSh4MiAqIHg4KSwgNikpICU+JQogIGJpbmRfcm93cyh0ZXN0X3Jlc2V0KG1vZHNbWzddXSwgZGF0XzIpKQoKcmVzdWx0c190ZXN0ICU+JSB0YWJfdGkoRikKYGBgCgpgbW9kc1tbN11dYCBoYXMgYSBsb3dlciBBSUMgdGhhbiBgbW9kc1tbNl1dYCBhbmQgYG1vZHNbWzNdXWAsIHNvIGl0IGlzIGNob29zZW4gYXMgdGhlIGZpbmFsIG1vZGVsIGZvciBwcmVzZW50YXRpb24gYW5kIGNvbmNsdXNpb24uCgpgYGB7cn0KQUlDKG1vZHNbWzddXSwgbW9kc1tbNl1dLCBtb2RzW1szXV0pICU+JSB0YWJfdGkoRikKYGBgCgojIyAxMC4gSW50ZXJwcmV0YXRpb24gb2YgYG1vZHNbWzddXWAKCiMjIyAxMC0xLiBNb2RlbCBTdHJ1Y3R1cmUKClRoZSBvdmVyYWxsIHN0cnVjdHVyZSBjYW4gYmUgaWxsdXN0cmF0ZWQgaW4gdGhlIGZvbGxvd2luZyBmaWd1cmUuIFRoZSBpbmNvbWUgaXMgY29ycmVsYXRlZCB0byB0aGUgbnVtYmVyIG9mIGhvdXNlaG9sZCBtZW1lYmVycywgd2hpY2ggaXMgcHJvYmFibHkgY2F1c2VkIGJ5IHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIG51bWJlcnMgb2YgcGVvcGxlIGFuZCByb29tcy4gQmVjYXVzZSB0aG9zZSByZWxhdGlvbnMgZG9uJ3QgY29udHJpYnV0ZSB0byB0aGUgaW50ZXJwcmV0YXRpb24gb2YgY29uc3VtcHRpb25zIGRpcmVjdGx5LCB0aGV5IGFyZSBvbWl0dGVkLgoKIVtJbGx1c3RyYXRpb24gb2YgdGhlIG1vZGVsIHN0cnVjdHVyZS5dKC4vaW1hZ2VzLzEucG5nKQoKIyMjIDEwLTIuIFJlZ3Jlc3NvcnMKCkVsZWN0cmljaXR5IGNvbnN1bXB0aW9uIGlzIGhpZ2hseSBjb3JyZWxhdGVkIHRvIHRoZSBudW1iZXIgb2YgaG91c2Vob2xkIG1lbWJlcnMgb2YgdGhlIHJlc3BvbmRlbnQuIFdoZW4gdGhlcmUgYXJlIG5vdCB0b28gbWFueSBob3VzZWhvbGQgbWVtYmVycywgd2l0aCBtb3JlIG1lbWJlcnMsIHRoZSBxdWFudGl0eSBvZiBjb25zdW1wdGlvbiBkZWNyZWFzZXMsIHByb2JhYmx5IGR1ZSB0byB0aGUgZmFjdCB0aGF0IHBlb3BsZSB0ZW5kIHRvIHNoYXJlIHRoZSBraXRjaGVuLiBIb3dldmVyLCB0aGUgZWZmZWN0IGRpbWluaXNoZXMgZ3JhZHVhbGx5IHdoZW4gdGhlcmUgYXJlIG1hbnkgaG91c2Vob2xkIG1lbWJlcnMgKGFyb3VuZCA1LTgpLgoKYGBge3J9CnRpIDwtIHRpYmJsZSh4ID0gc2VxKDE6OCksIHkgPSA4Ljc3OTQ2ICsgMC4wMzU2MyAqIHNlcSgxOjgpXjIgLSAKICAwLjUyMDcxICogc2VxKDE6OCkgKyAwLjA3MzI5ICogbWVhbihkYXQkeDgpKQoKZGF0ICU+JQogIG11dGF0ZShpbmRleCA9IHJvd19udW1iZXIoKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9ib3hwbG90KGFlcyh4MiwgeSwgZ3JvdXAgPSBjdXRfd2lkdGgoeDIsIDEpKSwgb3V0bGllci5hbHBoYSA9IDApICsKICAgIGdlb21fcG9pbnQoYWVzKHgyLCB5KSwgc2hhcGUgPSAxKSArCiAgICBnZW9tX3RleHQoYWVzKHgyLCB5LCBsYWJlbCA9IGlmZWxzZShpbmRleCA9PSAzNiB8IGluZGV4ID09IDE2MyB8CiAgICAgIGluZGV4ID09IDI0MSwgYXMuY2hhcmFjdGVyKGluZGV4KSwgIiIpKSwgaGp1c3Q9MS41LCB2anVzdD0wKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IHRpLCBtYXBwaW5nID0gYWVzKHgsIHkpLCBjb2xvciA9ICIjRjg3NjZEIiwgc2l6ZSA9IDIpCmBgYAoKQmVjYXVzZSBgeWAgaXMgdGhlIGxvZyBvZiBhdmVyYWdlIGVsZWN0cmljaXR5IGNvbnN1bXB0aW9ucywgdGhlIGZpbmFsIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGVsZWN0cmljaXR5IGNvbnN1bXB0aW9ucyBhbmQgbnVtYmVycyBvZiBob3VzZWhvbGQgbWVtYmVycyBhbmQgbnVtYmVycyBvZiByb29tcyBhcmU6CgpBcyBmb3IgdGhlIGVmZmVjdCBvZiBudW1iZXIgb2Ygcm9vbXMgb24gZWxlY3RyaWNpdHkgY29uc3VtcHRpb25zLCAKCmBgYHtyfQp0aSA8LSB0aWJibGUoeCA9IHNlcSgyLCAyMiksIHkgPSA4Ljc3OTQ2ICsgMC4wNzMyOSAqIHNlcSgyLCAyMikgLSAKICAwLjUyMDcxICogbWVhbihkYXQkeDIpICsgMC4wMzU2MyAqIG1lYW4oZGF0JHgyXjIpKQoKZGF0ICU+JQogIG11dGF0ZShpbmRleCA9IHJvd19udW1iZXIoKSkgJT4lCiAgZ2dwbG90KCkgKwogICAgZ2VvbV9ib3hwbG90KGFlcyh4OCwgeSwgZ3JvdXAgPSBjdXRfd2lkdGgoeDgsIDEpKSwgb3V0bGllci5hbHBoYSA9IDApICsKICAgIGdlb21fcG9pbnQoYWVzKHg4LCB5KSwgc2hhcGUgPSAxKSArCiAgICBnZW9tX2xpbmUoZGF0YSA9IHRpLCBtYXBwaW5nID0gYWVzKHgsIHkpLCBjb2xvciA9ICIjRjg3NjZEIiwgc2l6ZSA9IDIpCmBgYAoKIyMjIDEwLTMuIE9ydGhvZ29uYWxpemF0aW9uIG9mIE11bHRpcGxlIFJlZ3Jlc3NvcnMKCmBgYHtyLCBlY2hvPVR9Cm1vZHNbWzhdXSA8LQogIGRhdF8yICU+JQogIG11dGF0ZSh6MSA9IGxtKHgyIH4gMSkkcmVzaWR1YWxzKSAlPiUKICBtdXRhdGUoejIgPSBsbSh4OCB+IHgyICsgMSkkcmVzaWR1YWxzKSAlPiUKICBtdXRhdGUoeDIuMiA9IHgyXjIpICU+JQogIG11dGF0ZSh6MyA9IGxtKHgyLjIgfiB4MiArIHg4ICsgMSkkcmVzaWR1YWxzKSAlPiUKICB7bG0oeSB+IHoxICsgejIgKyB6MywgZGF0YSA9IC4pfQpgYGAKCmBgYHtyfQptb2RzW1s4XV0gLT4gbW9kZWwgICMgUHJpbnQgbW9kZWwgc3VtbWFyeQptb2RlbCRjYWxsCm1vZGVsICU+JSB0aWR5KCkgJT4lIHRhYl90aShGKQptb2RlbCAlPiUgZ2xhbmNlKCkgJT4lIHRhYl90aShGKQpybShtb2RlbCkKYGBgCgpUaGUgaW50ZXJjZXB0IGluIGBtb2RzW1s4XV1gICg4LjM3MDA5KSBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgdGhlIGV4cHRlY3RlZCB2YWx1ZSBmb3IgYW4gaW5kaXZpZHVhbCB3aXRoIGF2ZXJhZ2UgdmFsdWVzIG9mIGB4MmAsIGB4OGAgYW5kIGBJKHgyXjIpYCwgd2hpY2ggY2FuIGJlIHZlcmlmaWVkIGJ5IHRoZSBwcmVkaWN0aW9uIHVzaW5nIGBtb2RzW1s3XV1gLgoKYGBge3IsIGVjaG89VH0KKCA4Ljc3OTQ2IC0gMC41MjA3MSAqIG1lYW4oZGF0XzIkeDIpICsgMC4wNzMyOSAqIG1lYW4oZGF0XzIkeDgpICsgCiAgMC4wMzU2MyAqIG1lYW4oZGF0XzIkeDJeMikgKSAtIDguMzcwMDkgPD0gMWUtNApgYGAKClNpbmNlIHRoZSBzdGFuZGFyZCBlcnJvcnMgaW4gYG1vZHNbWzhdXWAgYXJlIHNtYWxsZXIgdGhhbiB0aG9zZSBpbiBgbW9kc1tbN11dYCwgYG1vZHNbWzhdXWAgaXMgdXNlZCB0byBjb25kdWN0IGluZmVyZW5jZS4gUGFydGljdWxhcmx5LCBgc2VgIGZvciBgSW50ZXJjZXB0YCBpcyByZWR1Y2VkIGJ5IDc1LjQ4JSwgYW5kIGBzZWBzIGZvciBmaXJzdCB0d28gcmVncmVzc29ycyBhcmUgcmVkdWNlZCBieSA3MS43NSUgYW5kIDIuNDElLiBUaGUgZXN0aW1hdGlvbnMgZm9yIHRoZSBsYXN0IHRlcm0gYXJlIGV4YWN0bHkgdGhlIHNhbWUsIHdoaWNoIGlzIGV4cGVjdGVkLgoKYGBge3J9Cm1vZHNbWzhdXSAlPiUgY29uZmludCgpCmBgYAoKVG8gcmVkdWNlIGF2ZXJhZ2UgZWxlY3RyaWNpdHkgY29uc3VtcHRpb25zLCBwZW9wbGUgYXJlIGVuY291cmFnZWQgdG8gbGl2ZSB0b2dldGhlciBpbiBob3VzZXMgd2l0aCBmZXdlciByb29tcy4KCjwhLS0gIyMgMTEuIE9uZS1TaWRlZCB0LVRlc3Qgb2YgYG1vZHNbWzFdXWAgLS0+Cgo8IS0tIGBgYHtyLCBlY2hvPVR9IC0tPgo8IS0tIG1vZHNbWzFdXSAlPiUgLS0+CjwhLS0gICBzdW1tYXJ5KCkgJT4lIC0tPgo8IS0tICAge3B0KGNvZWYoLilbMiwgM10sIG1vZHNbWzFdXSRkZiwgbG93ZXIgPSBGQUxTRSl9ICU+JSAtLT4KPCEtLSAgIHsuIDw9IHFjaGlzcSgwLjk1LCAxLCBsb3dlci50YWlsID0gVFJVRSwgbG9nLnAgPSBGQUxTRSl9IC0tPgo8IS0tIGBgYCAtLT4K