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)

unlabelled

Mathematical Formulation of the One-Way Model

It is common to express the One-way model as

\[y_{ij} = \mu_j + \varepsilon_{ij}~~~~~~~~(j=1,\ldots,K,~~~~~i=1,\ldots,n_j)\]

where: yij is the response of the ith unit at the jth level of the factor; K denotes the number of levels; \(\mu_j\) is the (unknown) population mean for level \(j\)

nj the number of observations (replications) at level j of the factor; and, the values \(\varepsilon_{11},..,\varepsilon_{Kn_K}\) are random errors satisfying assumptions (A1)-(A4)

The null hypothesis is then expressed as

\[H_0: ~~~ \mu_1 = \mu_2 = ... =\mu_K \] and the alternative hypothesis is

\[H_1: ~~~\mbox{ means not all equal.}\]

Another way of writing this is \[y_{ij} = \mu + \alpha_j + \varepsilon_{ij}~~~~~~~~(j=1,\ldots,K,~~~~~i=1,\ldots,n_i)\]

where \(\alpha_j = \mu_j - \mu\) (mean difference to the baseline) for \(j=1,...,K\).

The mean response is \[E[Y_{ij}] = \mu + \alpha_j\]

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:

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 .\]

Regression form of one-way factor model

A one-way factor model can be expressed as follows: \[y_i = \mu + \alpha_1 z_{i1} + \alpha_2 z_{i2} + \ldots + \alpha_K z_{iK} + \varepsilon_i~~~~~(i=1,2,\ldots,n)\]

This has the form of a multiple linear regression model.

The parameter \(\mu\) is the regression intercept and, under the treatment constraint (\(\alpha_1 = 0\)), the mean baseline (factor level 1) response.

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.

(Intercept) DoseLow DoseZero
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" ...
Caffeine
   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).

levels(Caffeine$Dose)
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

Dose (level) mean response fitted value
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.

anova(Caffeine.lm)
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:

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.

  1. What is the residual sum of squares for the full model M1?

  2. What is the mean sum of squares for the model M1?

  3. 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)\]

  4. 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