View the
latest recording of this lecture
So far we have focused on regression models, where a continuous
random response variable is modelled as a function of one or more
numerical explanatory variables.
Another common situation is where the explanatory variables are
categorical variables, or what we will often call
factors.
In this lecture we will begin to look at such models, and will focus
in particular on one-way models.
The One-Way Model
The one-way (or one factor) model is used when a continuous numerical
response Y is dependent on a single factor (categorical
explanatory variable).
In such models, the categories defined by a factor are called the
levels of the factor.
Stimulating Effects of Caffeine
Question: does caffeine stimulation affect the rate at which
individuals can tap their fingers?
Thirty male students randomly allocated to three treatment groups of
10 students each. Groups treated as follows:
Group 1: zero caffeine dose
Group 2: low caffeine dose
Group 3: high caffeine dose
Allocation to treatment groups was blind (subjects did not know their
caffeine dosage).
Two hours after treatment, each subject tapped fingers as quickly as
possible for a minute. Number of taps recorded.
Number of taps is the response variable, caffeine dose is the
explanatory variable. Here caffeine dose is a factor with 3 levels -
zero, low and high. Does apparent trend in boxplot provide convincing
evidence that caffeine affects tapping rate?
Download caffeine.csv
## Caffeine <- read.csv(file = "caffeine.csv", header = T)
boxplot(Taps ~ Dose, data = Caffeine)
Parameterisation of the One-Way Model
However, as it stands, the model appears to be
overparameterised.
That is, we have \(K\) means and we
are trying to estimate K+1 parameters \(\mu,\alpha_1,...,\alpha_K\)
We cannot estimate K+1 numbers from k bits of
information.
Solution to Overparameterisation
We impose a constraint on the parameters \(\alpha_1, \alpha_2, \ldots, \alpha_K\).
The two most popular (and easily interpretable) constraints are:
Sum constraints: \(\sum_{j=1}^K
\alpha_j = 0\).
In this case \(\mu\) can be interpreted
as a kind of “grand mean”, and \(\alpha_1,
\alpha_2, \ldots, \alpha_K\) measure deviations from this grand
mean.
Treatment constraint: \(\alpha_1 =
0\).
In this case level 1 of the factor is regarded as the baseline or
reference level, and \(\alpha_2,
\alpha_3 \ldots, \alpha_K\) measure deviations from this
baseline. This is highly appropriate if level 1 corresponds to a control
group, for example.
We will work with the treatment constraint. It is also used by
default for factors in R.
Expressing Factor Models as Regression Models
We can express a one-way factor model as a regression model by using
dummy (indicator) variables.
Define dummy variables \(z_{11}, z_{12},
\ldots, z_{n K}\) by \[z_{ij} =
\left \{
\begin{array}{ll}
1 & \mbox{unit i observed at factor level j}\\
0 & \mbox{otherwise.}
\end{array}
\right .\]
Modelling the Caffeine Data
Our one-way factor model, where the factor has three levels, can be
expressed as follows: \[y_i = \mu + \alpha_2
z_{i2} + \alpha_{3} z_{i3} + \varepsilon_i\]
where: yi is the number of taps recorded for the
ith subject; zi2 = 1 if subject i
is on low dose; zi2 = 0 otherwise; and
zi3 = 1 if subject i is on high dose;
zi3 = 0 otherwise.
Then, \(\mu\) is mean response for a
subject on zero dose; \(\alpha_2\) is
the effect of low dose in contrast to zero dose; and, \(\alpha_3\) is the effect of high dose in
contrast to zero dose.
Expressing Factorial Models using Matrices
Since factorial models can be expressed as linear regression models,
they may be described using matrix notation as we saw earlier.
For a one-way factorial model with treatment constraint: \[{\boldsymbol{y}} = X {\boldsymbol{\beta}} +
\varepsilon\] where: \[{\boldsymbol{y}} = \left [
\begin{array}{c}
Y_1\\
Y_2\\
\vdots\\
Y_n
\end{array}
\right ]
~~~~X = \left [
\begin{array}{cccc}
1 & z_{12} & \ldots & z_{1K}\\
1 & z_{22} & \ldots & z_{2K}\\
\vdots & \vdots & \ddots & \vdots\\
1 & z_{n2} & \ldots & z_{nK}
\end{array}
\right ]
~~~
{\boldsymbol{\beta}} = \left [
\begin{array}{c}
\mu\\
\alpha_2\\
\vdots\\
\alpha_K\\
\end{array}
\right ]
~~~
\boldsymbol{\varepsilon} = \left [
\begin{array}{c}
\varepsilon_1\\
\varepsilon_2\\
\vdots\\
\varepsilon_n\\
\end{array}
\right ]\]
There is no \(\alpha_1\) in the
parameter vector, and no row for \(z_{i1}\) in the design matrix, because of
the treatment constraint.
The following shows the design matrix for the
one-way model for the caffeine data.
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
0 |
0 |
Factor Models as Regression Models
Since factor models can be regarded as regression models, all ideas
about parameter estimation, fitted values etc. follow in the natural
manner.
Parameter estimation can be done by the method of least squares, to
give vector of estimates \(\hat
{\boldsymbol{\beta}} = (\hat \mu, \hat \alpha_2, \ldots,
\hat \alpha_K)^T\).
Fitted values and residuals defined in the usual way.
Back to the Caffeine Data
R Code
The factor levels of Dose have a natural ordering. In particular, it
is intuitive to set the zero level as baseline (factor level 1).
## Caffeine <- read.csv(file = "caffeine.csv", header = T)
str(Caffeine)
'data.frame': 30 obs. of 2 variables:
$ Taps: int 242 245 244 248 247 248 242 244 246 242 ...
$ Dose: chr "Zero" "Zero" "Zero" "Zero" ...
Taps Dose
1 242 Zero
2 245 Zero
3 244 Zero
4 248 Zero
5 247 Zero
6 248 Zero
7 242 Zero
8 244 Zero
9 246 Zero
10 242 Zero
11 248 Low
12 246 Low
13 245 Low
14 247 Low
15 248 Low
16 250 Low
17 247 Low
18 246 Low
19 243 Low
20 244 Low
21 246 High
22 248 High
23 250 High
24 252 High
25 248 High
26 250 High
27 246 High
28 248 High
29 245 High
30 250 High
We fix up the order of the factor levels (default is
alphabetical).
NULL
Caffeine$Dose <- factor(Caffeine$Dose, levels = c("Zero", "Low", "High"))
levels(Caffeine$Dose)
[1] "Zero" "Low" "High"
The syntax using the factor()
command (with specified
levels) reorders the factor levels so that zero, low and high dose are
interpreted as levels 1, 2 and 3 respectively.
Fitting the Model
We can use the lm()
function in R to fit model in the
same manner as for regression models.
Caffeine.lm <- lm(Taps ~ Dose, data = Caffeine)
summary(Caffeine.lm)
Call:
lm(formula = Taps ~ Dose, data = Caffeine)
Residuals:
Min 1Q Median 3Q Max
-3.400 -2.075 -0.300 1.675 3.700
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 244.8000 0.7047 347.359 < 2e-16 ***
DoseLow 1.6000 0.9967 1.605 0.12005
DoseHigh 3.5000 0.9967 3.512 0.00158 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 2.229 on 27 degrees of freedom
Multiple R-squared: 0.3141, Adjusted R-squared: 0.2633
F-statistic: 6.181 on 2 and 27 DF, p-value: 0.006163
Using the notation introduced earlier, the parameter estimates are
\(\hat \mu = 244.8\), \(\hat \alpha_2 = 1.6\) and \(\hat \alpha_3 = 3.5\).
fitted values
Zero (1) |
\(\mu\) |
244.8 |
Low (2) |
\(\mu + \alpha_2\) |
246.4 |
High (3) |
\(\mu + \alpha_3\) |
248.3 |
Hypothesis tests
There are three ways we can think of the hypothesis test.
The first formulation of the model (with \(H_0: ~~~ \mu_1 = \mu_2 = ... =\mu_K\)) can
be tested by just looking at the \(F\)
test at the bottom of the summary(lm) output, or applying the anova()
command to the output.
Analysis of Variance Table
Response: Taps
Df Sum Sq Mean Sq F value Pr(>F)
Dose 2 61.4 30.7000 6.1812 0.006163 **
Residuals 27 134.1 4.9667
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
On the other hand writing the Factor models (using the treatment
constraint) can be written as multiple linear regression models, using
dummy variables:
\[Y_i = \mu + \alpha_2 z_{i2} + \ldots +
\alpha_K z_{iK} + \varepsilon_i \quad(i=1,2,\ldots,n)\]
we can regard the F test as testing the hypothesis that all slopes
are zero \(H_0: \alpha_2 = ...=\alpha_K =
0\), which gives the same omnibus F test.
z2 = Caffeine$Dose == "Low"
z3 = Caffeine$Dose == "High"
Caffeine.lm2 = lm(Caffeine$Taps ~ z2 + z3)
summary(Caffeine.lm2)
Call:
lm(formula = Caffeine$Taps ~ z2 + z3)
Residuals:
Min 1Q Median 3Q Max
-3.400 -2.075 -0.300 1.675 3.700
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 244.8000 0.7047 347.359 < 2e-16 ***
z2TRUE 1.6000 0.9967 1.605 0.12005
z3TRUE 3.5000 0.9967 3.512 0.00158 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 2.229 on 27 degrees of freedom
Multiple R-squared: 0.3141, Adjusted R-squared: 0.2633
F-statistic: 6.181 on 2 and 27 DF, p-value: 0.006163
Finally we can consider the problem as a comparison of two models
\[M0:~~~~ Y_i = \mu + \varepsilon_i \quad
(i=1,2,\ldots,n)\] and \[M1:~~~~ Y_i =
\mu + \alpha_2 z_{i2} + \ldots + \alpha_K z_{iK} + \varepsilon_i \quad
(i=1,2,\ldots,n)\] Thus
Caffeine.M0 = lm(Caffeine$Taps ~ 1)
Caffeine.M1 = lm(Caffeine$Taps ~ z2 + z3)
anova(Caffeine.M0, Caffeine.M1)
Analysis of Variance Table
Model 1: Caffeine$Taps ~ 1
Model 2: Caffeine$Taps ~ z2 + z3
Res.Df RSS Df Sum of Sq F Pr(>F)
1 29 195.5
2 27 134.1 2 61.4 6.1812 0.006163 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Important:
- In a multiple linear regression model it makes sense to add or
remove a single explanatory variable.
- In a factor model it (usually) only makes sense to add or remove a
whole factor, not single levels of a factor.
- This will usually require F tests (not just t-tests for
single parameters).
Conclusions from the ANOVA table
The observed F-statistic for testing for the significance of
caffeine dose is f = 6.181 on K-1 = 2 and n-K
= 27 degrees of freedom.
The corresponding P-value is P=0.0062; we therefore
have very strong evidence against H0; i.e. finger
tapping speed does seem to be related to caffeine dose.
The table of coefficients in the R output shows that the mean
response difference between the high dose and control groups is a little
more than twice as big as the difference between low dose and control
group.
Interpretation of the anova output
Use the anova output produced by R to answer the following questions
on the caffeine data.
What is the residual sum of squares for the full model
M1?
What is the mean sum of squares for the model
M1?
What is the residual sum of squares for the null model
M0, given below? \[M0: Y_i = \mu +
\varepsilon_i~~~~~~~(i=1,2,\ldots,30)\]
What is the mean sum of squares for the model
M0?
LS0tDQp0aXRsZTogIkxlY3R1cmUgMTk6IExpbmVhciBNb2RlbHMgd2l0aCBPbmUgRmFjdG9yIg0Kc3VidGl0bGU6IDE2MS4yNTEgUmVncmVzc2lvbiBNb2RlbGxpbmcNCmF1dGhvcjogIlByZXNlbnRlZCBieSBKb25hdGhhbiBHb2RmcmV5IDxhLmouZ29kZnJleUBtYXNzZXkuYWMubno+IiAgDQpkYXRlOiAiV2VlayA3IG9mIFNlbWVzdGVyIDIsIGByIGx1YnJpZGF0ZTo6eWVhcihsdWJyaWRhdGU6Om5vdygpKWAiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHRoZW1lOiB5ZXRpDQogICAgaGlnaGxpZ2h0OiB0YW5nbw0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICB0aGVtZTogeWV0aQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgaW9zbGlkZXNfcHJlc2VudGF0aW9uOg0KICAgIHdpZGVzY3JlZW46IHRydWUNCiAgICBzbWFsbGVyOiB0cnVlDQogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgc2xpZHlfcHJlc2VudGF0aW9uOiANCiAgICB0aGVtZTogeWV0aQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KDQoNCg0KDQpbVmlldyB0aGUgbGF0ZXN0IHJlY29yZGluZyBvZiB0aGlzIGxlY3R1cmVdKGh0dHBzOi8vUi1SZXNvdXJjZXMubWFzc2V5LmFjLm56L3ZpZGVvcy8yNTFMMTkubXA0KQ0KPCEtLS0gRGF0YSBpcyBvbg0KaHR0cHM6Ly9yLXJlc291cmNlcy5tYXNzZXkuYWMubnovZGF0YS8xNjEyNTEvDQotLS0+DQoNCmBgYHtyIHNldHVwLCBwdXJsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQ0KbGlicmFyeShrbml0cikNCm9wdHNfY2h1bmskc2V0KGRldj1jKCJwbmciLCAicGRmIikpDQpvcHRzX2NodW5rJHNldChmaWcuaGVpZ2h0PTYsIGZpZy53aWR0aD03LCBmaWcucGF0aD0iRmlndXJlcy8iLCBmaWcuYWx0PSJ1bmxhYmVsbGVkIikNCm9wdHNfY2h1bmskc2V0KGNvbW1lbnQ9IiIsIGZpZy5hbGlnbj0iY2VudGVyIiwgdGlkeT1UUlVFKQ0Kb3B0aW9ucyhrbml0ci5rYWJsZS5OQSA9ICcnKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGJyb29tKQ0KYGBgDQoNCg0KPCEtLS0gRG8gbm90IGVkaXQgYW55dGhpbmcgYWJvdmUgdGhpcyBsaW5lLiAtLS0+DQoNClNvIGZhciB3ZSBoYXZlIGZvY3VzZWQgb24gcmVncmVzc2lvbiBtb2RlbHMsIHdoZXJlIGEgY29udGludW91cyAgICAgcmFuZG9tIHJlc3BvbnNlIHZhcmlhYmxlIGlzIG1vZGVsbGVkIGFzIGEgZnVuY3Rpb24gb2Ygb25lIG9yIG1vcmUgbnVtZXJpY2FsIGV4cGxhbmF0b3J5IHZhcmlhYmxlcy4NCg0KQW5vdGhlciBjb21tb24gc2l0dWF0aW9uIGlzIHdoZXJlIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZXMgYXJlDQogICAgY2F0ZWdvcmljYWwgdmFyaWFibGVzLCBvciB3aGF0IHdlIHdpbGwgb2Z0ZW4gY2FsbCAqKmZhY3RvcnMqKi4NCg0KSW4gdGhpcyBsZWN0dXJlIHdlIHdpbGwgYmVnaW4gdG8gbG9vayBhdCBzdWNoIG1vZGVscywgYW5kIHdpbGwNCiAgICBmb2N1cyBpbiBwYXJ0aWN1bGFyIG9uICoqb25lLXdheSBtb2RlbHMqKi4NCg0KIyMgVGhlIE9uZS1XYXkgTW9kZWwNCg0KVGhlIG9uZS13YXkgKG9yIG9uZSBmYWN0b3IpIG1vZGVsIGlzIHVzZWQgd2hlbiBhIGNvbnRpbnVvdXMNCiAgICBudW1lcmljYWwgcmVzcG9uc2UgKlkqIGlzIGRlcGVuZGVudCBvbiBhIHNpbmdsZQ0KICAgIGZhY3RvciAoY2F0ZWdvcmljYWwgZXhwbGFuYXRvcnkgdmFyaWFibGUpLg0KDQpJbiBzdWNoIG1vZGVscywgdGhlIGNhdGVnb3JpZXMgZGVmaW5lZCBieSBhIGZhY3RvciBhcmUgY2FsbGVkIHRoZSAgICoqbGV2ZWxzKiogb2YgdGhlIGZhY3Rvci4NCg0KIyMgU3RpbXVsYXRpbmcgRWZmZWN0cyBvZiBDYWZmZWluZQ0KDQpRdWVzdGlvbjogZG9lcyBjYWZmZWluZSBzdGltdWxhdGlvbiBhZmZlY3QgdGhlIHJhdGUgYXQgd2hpY2gNCiAgICBpbmRpdmlkdWFscyBjYW4gdGFwIHRoZWlyIGZpbmdlcnM/DQoNClRoaXJ0eSBtYWxlIHN0dWRlbnRzIHJhbmRvbWx5IGFsbG9jYXRlZCB0byB0aHJlZSB0cmVhdG1lbnQgZ3JvdXBzIG9mDQogICAgMTAgc3R1ZGVudHMgZWFjaC4gR3JvdXBzIHRyZWF0ZWQgYXMgZm9sbG93czoNCg0KR3JvdXAgMTogemVybyBjYWZmZWluZSBkb3NlDQogICAgDQpHcm91cCAyOiBsb3cgY2FmZmVpbmUgZG9zZQ0KICAgIA0KR3JvdXAgMzogaGlnaCBjYWZmZWluZSBkb3NlDQoNCkFsbG9jYXRpb24gdG8gdHJlYXRtZW50IGdyb3VwcyB3YXMgYmxpbmQgKHN1YmplY3RzIGRpZCBub3Qga25vdyB0aGVpcg0KICAgIGNhZmZlaW5lIGRvc2FnZSkuDQoNClR3byBob3VycyBhZnRlciB0cmVhdG1lbnQsIGVhY2ggc3ViamVjdCB0YXBwZWQgZmluZ2VycyBhcyBxdWlja2x5IGFzDQogICAgcG9zc2libGUgZm9yIGEgbWludXRlLiBOdW1iZXIgb2YgdGFwcyByZWNvcmRlZC4NCg0KDQoNCg0KTnVtYmVyIG9mIHRhcHMgaXMgdGhlIHJlc3BvbnNlIHZhcmlhYmxlLCBjYWZmZWluZSBkb3NlIGlzIHRoZSBleHBsYW5hdG9yeSB2YXJpYWJsZS4NCkhlcmUgY2FmZmVpbmUgZG9zZSBpcyBhIGZhY3RvciB3aXRoIDMgbGV2ZWxzIC0gemVybywgbG93IGFuZCBoaWdoLg0KRG9lcyBhcHBhcmVudCB0cmVuZCBpbiBib3hwbG90IHByb3ZpZGUgY29udmluY2luZyBldmlkZW5jZSB0aGF0IGNhZmZlaW5lIGFmZmVjdHMgdGFwcGluZyByYXRlPw0KDQpgciB4ZnVuOjplbWJlZF9maWxlKCIuLi8uLi9kYXRhL2NhZmZlaW5lLmNzdiIpYA0KDQpgYGB7ciBnZXRDYWZmZWluZURhdGEsIGV2YWw9LTEsIGVjaG89LTJ9DQpDYWZmZWluZSA8LSByZWFkLmNzdihmaWxlPSJjYWZmZWluZS5jc3YiLGhlYWRlcj1UKQ0KQ2FmZmVpbmUgPC0gcmVhZC5jc3YoZmlsZT0iLi4vLi4vZGF0YS9jYWZmZWluZS5jc3YiLCBoZWFkZXI9VFJVRSkNCmJveHBsb3QoVGFwc35Eb3NlLCBkYXRhPUNhZmZlaW5lKSANCmBgYA0KDQojIyBNYXRoZW1hdGljYWwgRm9ybXVsYXRpb24gb2YgdGhlIE9uZS1XYXkgTW9kZWwNCg0KSXQgaXMgY29tbW9uIHRvIGV4cHJlc3MgdGhlIE9uZS13YXkgbW9kZWwgYXMNCg0KJCR5X3tpan0gPSBcbXVfaiArIFx2YXJlcHNpbG9uX3tpan1+fn5+fn5+fihqPTEsXGxkb3RzLEssfn5+fn5pPTEsXGxkb3RzLG5faikkJCANCg0Kd2hlcmU6ICp5fmlqfiogaXMgdGhlIHJlc3BvbnNlIG9mIHRoZSAqaSpedGheIHVuaXQgYXQgdGhlICpqKl50aF4gbGV2ZWwgICAgIG9mIHRoZSBmYWN0b3I7DQoqSyogZGVub3RlcyB0aGUgbnVtYmVyIG9mIGxldmVsczsNCiRcbXVfaiQgaXMgdGhlICh1bmtub3duKSBwb3B1bGF0aW9uIG1lYW4gZm9yIGxldmVsICRqJA0KDQoqbn5qfiogdGhlIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgKHJlcGxpY2F0aW9ucykgYXQgbGV2ZWwgKmoqIG9mICAgICB0aGUgZmFjdG9yOyBhbmQsIA0KdGhlIHZhbHVlcyAkXHZhcmVwc2lsb25fezExfSwuLixcdmFyZXBzaWxvbl97S25fS30kIGFyZSByYW5kb20gZXJyb3JzIHNhdGlzZnlpbmcNCiAgICBhc3N1bXB0aW9ucyAoQTEpLShBNCkgIA0KICAgIA0KDQpUaGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRoZW4gZXhwcmVzc2VkIGFzIA0KDQokJEhfMDogIH5+fiBcbXVfMSA9IFxtdV8yID0gLi4uID1cbXVfSyAkJA0KYW5kIHRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIGlzIA0KDQokJEhfMTogfn5+XG1ib3h7IG1lYW5zIG5vdCBhbGwgZXF1YWwufSQkIA0KDQpBbm90aGVyIHdheSBvZiB3cml0aW5nIHRoaXMgaXMgDQokJHlfe2lqfSA9IFxtdSArIFxhbHBoYV9qICsgXHZhcmVwc2lsb25fe2lqfX5+fn5+fn5+KGo9MSxcbGRvdHMsSyx+fn5+fmk9MSxcbGRvdHMsbl9pKSQkIA0KDQp3aGVyZSAkXGFscGhhX2ogPSBcbXVfaiAtIFxtdSQgKG1lYW4gZGlmZmVyZW5jZSB0byB0aGUgYmFzZWxpbmUpICBmb3IgICRqPTEsLi4uLEskLiAgDQoNClRoZSBtZWFuIHJlc3BvbnNlIGlzICQkRVtZX3tpan1dID0gXG11ICsgXGFscGhhX2okJA0KDQojIyBQYXJhbWV0ZXJpc2F0aW9uIG9mIHRoZSBPbmUtV2F5IE1vZGVsDQoNCkhvd2V2ZXIsIGFzIGl0IHN0YW5kcywgdGhlIG1vZGVsIGFwcGVhcnMgdG8gYmUgICoqb3ZlcnBhcmFtZXRlcmlzZWQqKi4NCg0KVGhhdCBpcywgd2UgaGF2ZSAkSyQgbWVhbnMgYW5kIHdlIGFyZSB0cnlpbmcgdG8gZXN0aW1hdGUgKksrMSogcGFyYW1ldGVycyAkXG11LFxhbHBoYV8xLC4uLixcYWxwaGFfSyQNCg0KV2UgY2Fubm90IGVzdGltYXRlICpLKzEqIG51bWJlcnMgZnJvbSAqayogYml0cyBvZiBpbmZvcm1hdGlvbi4gDQogDQoNCiMjIFNvbHV0aW9uIHRvIE92ZXJwYXJhbWV0ZXJpc2F0aW9uDQoNCldlIGltcG9zZSBhIGNvbnN0cmFpbnQgb24gdGhlIHBhcmFtZXRlcnMNCiAgICAkXGFscGhhXzEsIFxhbHBoYV8yLCBcbGRvdHMsIFxhbHBoYV9LJC4NCg0KDQpUaGUgdHdvIG1vc3QgcG9wdWxhciAoYW5kIGVhc2lseSBpbnRlcnByZXRhYmxlKSBjb25zdHJhaW50cyBhcmU6DQogICAgDQotIFN1bSBjb25zdHJhaW50czogJFxzdW1fe2o9MX1eSyBcYWxwaGFfaiA9IDAkLiAgDQogICAgICAgIEluIHRoaXMgY2FzZSAkXG11JCBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgYSBraW5kIG9mICJncmFuZA0KICAgICAgICBtZWFuIiwgYW5kICRcYWxwaGFfMSwgXGFscGhhXzIsIFxsZG90cywgXGFscGhhX0skIG1lYXN1cmUNCiAgICAgICAgZGV2aWF0aW9ucyBmcm9tIHRoaXMgZ3JhbmQgbWVhbi4NCiAgICANCi0gVHJlYXRtZW50IGNvbnN0cmFpbnQ6ICRcYWxwaGFfMSA9IDAkLiAgDQogICAgICAgIEluIHRoaXMgY2FzZSBsZXZlbCAxIG9mIHRoZSBmYWN0b3IgaXMgcmVnYXJkZWQgYXMgdGhlDQogICAgICAgIGJhc2VsaW5lIG9yIHJlZmVyZW5jZSBsZXZlbCwgYW5kDQogICAgICAgICRcYWxwaGFfMiwgDQogICAgICAgIFxhbHBoYV8zIFxsZG90cywgXGFscGhhX0skIG1lYXN1cmUgZGV2aWF0aW9ucyBmcm9tIHRoaXMNCiAgICAgICAgYmFzZWxpbmUuIFRoaXMgaXMgaGlnaGx5IGFwcHJvcHJpYXRlIGlmIGxldmVsIDEgY29ycmVzcG9uZHMgdG8gYQ0KICAgICAgICBjb250cm9sIGdyb3VwLCBmb3IgZXhhbXBsZS4NCg0KV2Ugd2lsbCB3b3JrIHdpdGggdGhlIHRyZWF0bWVudCBjb25zdHJhaW50LiBJdCBpcyBhbHNvIHVzZWQgYnkgICAgICBkZWZhdWx0IGZvciBmYWN0b3JzIGluIFIuDQoNCiMjIEV4cHJlc3NpbmcgRmFjdG9yIE1vZGVscyBhcyBSZWdyZXNzaW9uIE1vZGVscw0KDQpXZSBjYW4gZXhwcmVzcyBhIG9uZS13YXkgZmFjdG9yIG1vZGVsIGFzIGEgcmVncmVzc2lvbiBtb2RlbCBieSAgICAgIHVzaW5nIGR1bW15IChpbmRpY2F0b3IpIHZhcmlhYmxlcy4NCg0KRGVmaW5lIGR1bW15IHZhcmlhYmxlcyAkel97MTF9LCB6X3sxMn0sIFxsZG90cywgel97biBLfSQgYnkNCiAgICAkJHpfe2lqfSA9IA0KICAgIFxsZWZ0IFx7IA0KICAgIFxiZWdpbnthcnJheX17bGx9DQogICAgMSAmIFxtYm94e3VuaXQgaSBvYnNlcnZlZCBhdCBmYWN0b3IgbGV2ZWwgan1cXA0KICAgIDAgJiBcbWJveHtvdGhlcndpc2UufQ0KICAgIFxlbmR7YXJyYXl9DQogICAgXHJpZ2h0IC4kJA0KDQoNCiMjIFJlZ3Jlc3Npb24gZm9ybSBvZiBvbmUtd2F5IGZhY3RvciBtb2RlbA0KDQpBIG9uZS13YXkgZmFjdG9yIG1vZGVsIGNhbiBiZSBleHByZXNzZWQgYXMgZm9sbG93czoNCiQkeV9pID0gXG11ICsgXGFscGhhXzEgel97aTF9ICsgXGFscGhhXzIgel97aTJ9ICsgXGxkb3RzICsgXGFscGhhX0sgel97aUt9ICsgXHZhcmVwc2lsb25faX5+fn5+KGk9MSwyLFxsZG90cyxuKSQkDQoNClRoaXMgaGFzIHRoZSBmb3JtIG9mIGEgbXVsdGlwbGUgIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLg0KDQpUaGUgcGFyYW1ldGVyICRcbXUkIGlzIHRoZSByZWdyZXNzaW9uIGludGVyY2VwdCBhbmQsIHVuZGVyIHRoZSAgIHRyZWF0bWVudCBjb25zdHJhaW50ICgkXGFscGhhXzEgPSAwJCksIHRoZSBtZWFuIGJhc2VsaW5lIChmYWN0b3IgbGV2ZWwgIDEpIHJlc3BvbnNlLg0KDQojIyBNb2RlbGxpbmcgdGhlIENhZmZlaW5lIERhdGENCg0KT3VyIG9uZS13YXkgZmFjdG9yIG1vZGVsLCB3aGVyZSB0aGUgZmFjdG9yIGhhcyB0aHJlZSBsZXZlbHMsIGNhbiBiZQ0KZXhwcmVzc2VkIGFzIGZvbGxvd3M6DQokJHlfaSA9IFxtdSArIFxhbHBoYV8yIHpfe2kyfSArIFxhbHBoYV97M30gel97aTN9ICsgXHZhcmVwc2lsb25faSQkDQoNCndoZXJlOiAqeX5pfiogaXMgdGhlIG51bWJlciBvZiB0YXBzIHJlY29yZGVkIGZvciB0aGUgKmkqdGggc3ViamVjdDsgKnp+aTJ+ID0gMSogaWYgc3ViamVjdCAqaSogaXMgb24gbG93IGRvc2U7ICp6fmkyfiA9IDAqDQogICAgb3RoZXJ3aXNlOyBhbmQgKnp+aTN+ID0gMSogaWYgc3ViamVjdCAqaSogaXMgb24gaGlnaCBkb3NlOyAqen5pM34gPSAwKg0KICAgIG90aGVyd2lzZS4NCg0KVGhlbiwgICAkXG11JCBpcyBtZWFuIHJlc3BvbnNlIGZvciBhIHN1YmplY3Qgb24gemVybyBkb3NlOyAkXGFscGhhXzIkIGlzIHRoZSBlZmZlY3Qgb2YgbG93IGRvc2UgaW4gY29udHJhc3QgdG8gemVybyBkb3NlOyBhbmQsICRcYWxwaGFfMyQgaXMgdGhlIGVmZmVjdCBvZiBoaWdoIGRvc2UgaW4gY29udHJhc3QgdG8gemVybyBkb3NlLg0KDQojIyBFeHByZXNzaW5nIEZhY3RvcmlhbCBNb2RlbHMgdXNpbmcgTWF0cmljZXMNCg0KU2luY2UgZmFjdG9yaWFsIG1vZGVscyBjYW4gYmUgZXhwcmVzc2VkIGFzIGxpbmVhciByZWdyZXNzaW9uIG1vZGVscywNCiAgICB0aGV5IG1heSBiZSBkZXNjcmliZWQgdXNpbmcgbWF0cml4IG5vdGF0aW9uIGFzIHdlIHNhdyBlYXJsaWVyLg0KDQpGb3IgYSBvbmUtd2F5IGZhY3RvcmlhbCBtb2RlbCB3aXRoIHRyZWF0bWVudCBjb25zdHJhaW50Og0KICAgICQke1xib2xkc3ltYm9se3l9fSA9IFgge1xib2xkc3ltYm9se1xiZXRhfX0gKyBcdmFyZXBzaWxvbiQkIHdoZXJlOiAkJHtcYm9sZHN5bWJvbHt5fX0gPSBcbGVmdCBbDQogICAgXGJlZ2lue2FycmF5fXtjfQ0KICAgIFlfMVxcDQogICAgWV8yXFwNCiAgICBcdmRvdHNcXA0KICAgIFlfbg0KICAgIFxlbmR7YXJyYXl9DQogICAgXHJpZ2h0IF0NCiAgICB+fn5+WCA9IFxsZWZ0IFsNCiAgICBcYmVnaW57YXJyYXl9e2NjY2N9DQogICAgMSAmIHpfezEyfSAmIFxsZG90cyAmIHpfezFLfVxcDQogICAgMSAmIHpfezIyfSAmIFxsZG90cyAmIHpfezJLfVxcDQogICAgXHZkb3RzICYgXHZkb3RzICYgXGRkb3RzICYgXHZkb3RzXFwNCiAgICAxICYgel97bjJ9ICYgXGxkb3RzICYgel97bkt9DQogICAgXGVuZHthcnJheX0NCiAgICBccmlnaHQgXQ0KICAgIH5+fg0KICAgIHtcYm9sZHN5bWJvbHtcYmV0YX19ID0gXGxlZnQgWw0KICAgIFxiZWdpbnthcnJheX17Y30NCiAgICBcbXVcXA0KICAgIFxhbHBoYV8yXFwNCiAgICBcdmRvdHNcXA0KICAgIFxhbHBoYV9LXFwNCiAgICBcZW5ke2FycmF5fQ0KICAgIFxyaWdodCBdDQogICAgfn5+DQogICAgXGJvbGRzeW1ib2x7XHZhcmVwc2lsb259ID0gXGxlZnQgWw0KICAgIFxiZWdpbnthcnJheX17Y30NCiAgICBcdmFyZXBzaWxvbl8xXFwNCiAgICBcdmFyZXBzaWxvbl8yXFwNCiAgICBcdmRvdHNcXA0KICAgIFx2YXJlcHNpbG9uX25cXA0KICAgIFxlbmR7YXJyYXl9DQogICAgXHJpZ2h0IF0kJA0KDQpUaGVyZSBpcyBubyAkXGFscGhhXzEkIGluIHRoZSBwYXJhbWV0ZXIgdmVjdG9yLCBhbmQgbm8gcm93IGZvcg0KICAgICR6X3tpMX0kIGluIHRoZSBkZXNpZ24gbWF0cml4LCBiZWNhdXNlIG9mIHRoZSB0cmVhdG1lbnQNCiAgICBjb25zdHJhaW50Lg0KICAgIA0KVGhlIGZvbGxvd2luZyBzaG93cyAgdGhlICoqZGVzaWduIG1hdHJpeCoqIGZvciB0aGUgb25lLXdheSBtb2RlbCBmb3IgdGhlIGNhZmZlaW5lIGRhdGEuDQoNCmBgYHtyIGdldE1vZGVsTWF0cml4LCBlY2hvPUZBTFNFfQ0KQ2FmZmVpbmUubG0gPC0gbG0oVGFwc35Eb3NlLCBkYXRhPUNhZmZlaW5lKSANCkNhZmZlaW5lLmxtIHw+IG1vZGVsLm1hdHJpeCgpIHw+IGtuaXRyOjprYWJsZSgpDQpgYGANCg0KDQoNCiMjIEZhY3RvciBNb2RlbHMgYXMgUmVncmVzc2lvbiBNb2RlbHMNCg0KDQpTaW5jZSBmYWN0b3IgIG1vZGVscyBjYW4gYmUgcmVnYXJkZWQgYXMgcmVncmVzc2lvbiBtb2RlbHMsIGFsbCBpZGVhcyBhYm91dCBwYXJhbWV0ZXIgZXN0aW1hdGlvbiwgZml0dGVkIHZhbHVlcyBldGMuIGZvbGxvdyBpbiB0aGUgbmF0dXJhbCAgbWFubmVyLg0KDQpQYXJhbWV0ZXIgZXN0aW1hdGlvbiBjYW4gYmUgZG9uZSBieSB0aGUgbWV0aG9kIG9mIGxlYXN0IHNxdWFyZXMsIHRvDQogICAgZ2l2ZSB2ZWN0b3Igb2YgZXN0aW1hdGVzDQogICAgJFxoYXQge1xib2xkc3ltYm9se1xiZXRhfX0gPSAoXGhhdCBcbXUsIFxoYXQgXGFscGhhXzIsIFxsZG90cywgDQogICAgXGhhdCBcYWxwaGFfSyleVCQuDQoNCkZpdHRlZCB2YWx1ZXMgYW5kIHJlc2lkdWFscyBkZWZpbmVkIGluIHRoZSB1c3VhbCB3YXkuDQoNCiMjIEJhY2sgdG8gdGhlIENhZmZlaW5lIERhdGENCg0KIyMjIFIgQ29kZQ0KDQpUaGUgZmFjdG9yIGxldmVscyBvZiBEb3NlIGhhdmUgYSBuYXR1cmFsIG9yZGVyaW5nLiBJbiBwYXJ0aWN1bGFyLCBpdCBpcw0KaW50dWl0aXZlIHRvIHNldCB0aGUgemVybyBsZXZlbCBhcyBiYXNlbGluZSAoZmFjdG9yIGxldmVsIDEpLg0KDQoNCg0KYGBge3IgZ2V0Q2FmZmVpbmVEYXRhMiwgZXZhbD0tMX0NCkNhZmZlaW5lIDwtIHJlYWQuY3N2KGZpbGU9ImNhZmZlaW5lLmNzdiIsaGVhZGVyPVQpDQpzdHIoQ2FmZmVpbmUpDQpDYWZmZWluZQ0KYGBgDQoNCldlIGZpeCB1cCB0aGUgb3JkZXIgb2YgdGhlIGZhY3RvciBsZXZlbHMgKGRlZmF1bHQgaXMgYWxwaGFiZXRpY2FsKS4NCg0KYGBge3IgZ2V0Q2FmZmVpbmVEYXRhIDIgfQ0KbGV2ZWxzKENhZmZlaW5lJERvc2UpDQpDYWZmZWluZSREb3NlIDwtIGZhY3RvcihDYWZmZWluZSREb3NlLCBsZXZlbHM9YygiWmVybyIsDQoiTG93IiwgIkhpZ2giKSkNCmxldmVscyhDYWZmZWluZSREb3NlKQ0KYGBgDQpUaGUgc3ludGF4IHVzaW5nIHRoZSBgZmFjdG9yKClgIGNvbW1hbmQgKHdpdGggc3BlY2lmaWVkIGxldmVscykgcmVvcmRlcnMNCnRoZSBmYWN0b3IgbGV2ZWxzIHNvIHRoYXQgemVybywgbG93IGFuZCBoaWdoIGRvc2UgYXJlIGludGVycHJldGVkIGFzDQpsZXZlbHMgMSwgMiBhbmQgMyByZXNwZWN0aXZlbHkuDQoNCg0KKipGaXR0aW5nIHRoZSBNb2RlbCoqDQoNCldlIGNhbiB1c2UgdGhlIGBsbSgpYCBmdW5jdGlvbiBpbiBSIHRvIGZpdCBtb2RlbA0KaW4gdGhlIHNhbWUgbWFubmVyIGFzIGZvciByZWdyZXNzaW9uIG1vZGVscy4NCg0KYGBge3IgQ2FmZmVpbmUubG19DQpDYWZmZWluZS5sbSA8LSBsbShUYXBzfkRvc2UsIGRhdGE9Q2FmZmVpbmUpIA0Kc3VtbWFyeShDYWZmZWluZS5sbSkNCmBgYA0KDQoNClVzaW5nIHRoZSBub3RhdGlvbiBpbnRyb2R1Y2VkIGVhcmxpZXIsIHRoZSBwYXJhbWV0ZXIgZXN0aW1hdGVzIGFyZQ0KICAgICRcaGF0IFxtdSA9IDI0NC44JCwgJFxoYXQgXGFscGhhXzIgPSAxLjYkIGFuZA0KICAgICRcaGF0IFxhbHBoYV8zID0gMy41JC4NCg0KDQojIyAgIGZpdHRlZCB2YWx1ZXMgIyMNCkRvc2UgKGxldmVsKSB8IG1lYW4gcmVzcG9uc2UgICAgICB8IGZpdHRlZCB2YWx1ZSANCi0tLSB8IC0tLSB8IC0tLSANClplcm8gKDEpICAgfCAkXG11JCAgICAgICAgICAgIHwgMjQ0LjggICAgICAgIA0KTG93ICgyKSAgICAgIHwgJFxtdSArIFxhbHBoYV8yJCB8IDI0Ni40ICAgICAgICANCkhpZ2ggKDMpICAgICB8ICRcbXUgKyBcYWxwaGFfMyQgfCAyNDguMyAgICANCg0KDQoNCiMjIEh5cG90aGVzaXMgdGVzdHMNCg0KVGhlcmUgYXJlIHRocmVlIHdheXMgd2UgY2FuIHRoaW5rIG9mIHRoZSBoeXBvdGhlc2lzIHRlc3QuIA0KDQpUaGUgZmlyc3QgZm9ybXVsYXRpb24gb2YgdGhlIG1vZGVsICh3aXRoICRIXzA6ICB+fn4gXG11XzEgPSBcbXVfMiA9IC4uLiA9XG11X0skKSBjYW4gYmUgdGVzdGVkIGJ5IGp1c3QgbG9va2luZyBhdCB0aGUgJEYkIHRlc3QgYXQgdGhlIGJvdHRvbSBvZiB0aGUgc3VtbWFyeShsbSkgIG91dHB1dCwgb3IgYXBwbHlpbmcgdGhlIGFub3ZhKCkgY29tbWFuZCB0byB0aGUgb3V0cHV0LiANCmBgYHtyIGFub3ZhIHZlcnNpb259DQphbm92YShDYWZmZWluZS5sbSkNCmBgYA0KDQpPbiB0aGUgb3RoZXIgaGFuZCB3cml0aW5nIHRoZSBGYWN0b3IgIG1vZGVscyAodXNpbmcgdGhlIHRyZWF0bWVudCBjb25zdHJhaW50KSBjYW4gYmUgd3JpdHRlbiBhcw0KbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWxzLCB1c2luZyBkdW1teQ0KdmFyaWFibGVzOg0KDQokJFlfaSA9IFxtdSArIFxhbHBoYV8yIHpfe2kyfSArIFxsZG90cyArIFxhbHBoYV9LIHpfe2lLfSArIFx2YXJlcHNpbG9uX2kgXHF1YWQoaT0xLDIsXGxkb3RzLG4pJCQNCg0Kd2UgY2FuIHJlZ2FyZCB0aGUgRiB0ZXN0IGFzIHRlc3RpbmcgdGhlIGh5cG90aGVzaXMgdGhhdCBhbGwgc2xvcGVzIGFyZSB6ZXJvICRIXzA6IFxhbHBoYV8yID0gLi4uPVxhbHBoYV9LID0gMCQsDQp3aGljaCBnaXZlcyB0aGUgc2FtZSBvbW5pYnVzIEYgdGVzdC4gDQoNCmBgYHtyIHJlZ3Jlc3Npb24gdmVyc2lvbn0NCnoyID0gICBDYWZmZWluZSREb3NlID09ICJMb3ciDQp6MyA9ICAgQ2FmZmVpbmUkRG9zZSA9PSAiSGlnaCIgDQpDYWZmZWluZS5sbTIgPSBsbSggQ2FmZmVpbmUkVGFwcyB+IHoyICsgejMgKQ0Kc3VtbWFyeShDYWZmZWluZS5sbTIpDQpgYGANCg0KRmluYWxseSB3ZSBjYW4gY29uc2lkZXIgdGhlIHByb2JsZW0gYXMgYSBjb21wYXJpc29uIG9mIHR3byBtb2RlbHMgIA0KDQogICAkJE0wOn5+fn4gWV9pID0gXG11ICsgXHZhcmVwc2lsb25faSBccXVhZCAoaT0xLDIsXGxkb3RzLG4pJCQgYW5kDQogICAgJCRNMTp+fn5+IFlfaSA9IFxtdSArIFxhbHBoYV8yIHpfe2kyfSArIFxsZG90cyArIFxhbHBoYV9LIHpfe2lLfSArIFx2YXJlcHNpbG9uX2kgIFxxdWFkIChpPTEsMixcbGRvdHMsbikkJA0KVGh1cyANCmBgYHtyIGNvbXBhcmlzb259DQpDYWZmZWluZS5NMCA9IGxtKENhZmZlaW5lJFRhcHMgfiAxKQ0KQ2FmZmVpbmUuTTEgPSBsbShDYWZmZWluZSRUYXBzIH4gejIgKyB6MykNCmFub3ZhKENhZmZlaW5lLk0wLCBDYWZmZWluZS5NMSkNCmBgYA0KDQoNCioqSW1wb3J0YW50Kio6DQogICAgDQotIEluIGEgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaXQgbWFrZXMgc2Vuc2UgdG8gYWRkIG9yICAgICAgICAgcmVtb3ZlIGEgc2luZ2xlIGV4cGxhbmF0b3J5IHZhcmlhYmxlLg0KLSBJbiBhIGZhY3RvciAgbW9kZWwgaXQgKHVzdWFsbHkpIG9ubHkgbWFrZXMgc2Vuc2UgdG8gYWRkIG9yDQogICAgICAgIHJlbW92ZSBhIHdob2xlIGZhY3Rvciwgbm90IHNpbmdsZSBsZXZlbHMgb2YgYSBmYWN0b3IuDQotIFRoaXMgd2lsbCB1c3VhbGx5IHJlcXVpcmUgKkYqIHRlc3RzIChub3QganVzdCB0LXRlc3RzIGZvcg0KICAgIHNpbmdsZSBwYXJhbWV0ZXJzKS4NCg0KDQojIyMjIENvbmNsdXNpb25zIGZyb20gdGhlIEFOT1ZBIHRhYmxlDQoNClRoZSBvYnNlcnZlZCAqRiotc3RhdGlzdGljIGZvciB0ZXN0aW5nIGZvciB0aGUgc2lnbmlmaWNhbmNlIG9mDQogICAgY2FmZmVpbmUgZG9zZSBpcyAqZiogPSBgciByb3VuZChzdW1tYXJ5KENhZmZlaW5lLmxtKSRmc3RhdGlzdGljWyJ2YWx1ZSJdLCAzKWAgb24gKkstMSogPSBgciBzdW1tYXJ5KENhZmZlaW5lLmxtKSRmc3RhdGlzdGljWyJudW1kZiJdYCBhbmQgKm4tSyogPSBgciBzdW1tYXJ5KENhZmZlaW5lLmxtKSRmc3RhdGlzdGljWyJkZW5kZiJdYA0KICAgIGRlZ3JlZXMgb2YgZnJlZWRvbS4NCg0KVGhlIGNvcnJlc3BvbmRpbmcgKlAqLXZhbHVlIGlzICpQKj1gciByb3VuZChhbm92YShDYWZmZWluZS5sbSlbIkRvc2UiLCAiUHIoPkYpIl0sIDQpYDsgd2UgdGhlcmVmb3JlIGhhdmUgdmVyeQ0KICAgIHN0cm9uZyBldmlkZW5jZSBhZ2FpbnN0ICpIfjB+KjsgaS5lLsKgZmluZ2VyIHRhcHBpbmcgc3BlZWQgZG9lcyBzZWVtDQogICAgdG8gYmUgcmVsYXRlZCB0byBjYWZmZWluZSBkb3NlLg0KDQpUaGUgdGFibGUgb2YgY29lZmZpY2llbnRzIGluIHRoZSBSIG91dHB1dCBzaG93cyB0aGF0IHRoZSBtZWFuDQogICAgcmVzcG9uc2UgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBoaWdoIGRvc2UgYW5kIGNvbnRyb2wgZ3JvdXBzIGlzIGENCiAgICBsaXR0bGUgbW9yZSB0aGFuIHR3aWNlIGFzIGJpZyBhcyB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIGxvdyBkb3NlIGFuZA0KICAgIGNvbnRyb2wgZ3JvdXAuDQoNCiMjIyBJbnRlcnByZXRhdGlvbiBvZiB0aGUgYW5vdmEgb3V0cHV0DQoNClVzZSB0aGUgYW5vdmEgb3V0cHV0IHByb2R1Y2VkIGJ5IFIgdG8gYW5zd2VyIHRoZSBmb2xsb3dpbmcgcXVlc3Rpb25zIG9uDQp0aGUgY2FmZmVpbmUgZGF0YS4NCg0KMS4gIFdoYXQgaXMgdGhlIHJlc2lkdWFsIHN1bSBvZiBzcXVhcmVzIGZvciB0aGUgZnVsbCBtb2RlbCAqTTEqPw0KDQoyLiAgV2hhdCBpcyB0aGUgbWVhbiBzdW0gb2Ygc3F1YXJlcyBmb3IgdGhlIG1vZGVsICpNMSo/DQoNCjMuICBXaGF0IGlzIHRoZSByZXNpZHVhbCBzdW0gb2Ygc3F1YXJlcyBmb3IgdGhlIG51bGwgbW9kZWwgKk0wKiwgZ2l2ZW4NCiAgICBiZWxvdz8gJCRNMDogWV9pID0gXG11ICsgXHZhcmVwc2lsb25faX5+fn5+fn4oaT0xLDIsXGxkb3RzLDMwKSQkDQoNCjQuICBXaGF0IGlzIHRoZSBtZWFuIHN1bSBvZiBzcXVhcmVzIGZvciB0aGUgbW9kZWwgKk0wKj8NCg0K