1. (Exercise 3.7.2) Carefully explain the differences between the KNN classifier and KNN regression methods.

In both methods, for a test observation, \(x_{0}\), a neighborhood is created by identifying the \(K\)-nearest training observations to \(x_{0}\), for some positive integer \(K\).

KNN Classifier Method: this method aims to correctly classify the test observation \(x_{0}\) by the value of a categorical response variable. It does so by estimating the conditional probability of each response class, \(i\), as the fraction of training observations with response value \(i\) in the neighborhood of \(x_{0}\). This method will assign the test observation \(x_{0}\) to whichever response class has the highest estimated conditional probability.

KNN Regression Method: this method aims to estimate the numerical response value [\(f(x_{0})\)] of the test observation \(x_{0}\). It does so by calculating the mean response value from the training observations in the neighborhood of \(x_{0}\) and assigning this mean as the estimate of \(f(x_{0})\).

2. (Exercise 3.7.9) This question involves the use of multiple linear regression on the Auto data set.

  1. Produce a scatterplot matrix which includes all of the variables in the data set.
#Load library containing data set and load Auto data
library(ISLR2)
data("Auto")
  
#create scatterplot matrix of all variables in the data
pairs(Auto)

  1. Compute the matrix of correlations between the variables using the function cor(). You will need to exclude the name variable, which is qualitative.
#cor matrix all Auto variables except name
cor(Auto[,1:8])
                    mpg  cylinders displacement horsepower     weight acceleration       year     origin
mpg           1.0000000 -0.7776175   -0.8051269 -0.7784268 -0.8322442    0.4233285  0.5805410  0.5652088
cylinders    -0.7776175  1.0000000    0.9508233  0.8429834  0.8975273   -0.5046834 -0.3456474 -0.5689316
displacement -0.8051269  0.9508233    1.0000000  0.8972570  0.9329944   -0.5438005 -0.3698552 -0.6145351
horsepower   -0.7784268  0.8429834    0.8972570  1.0000000  0.8645377   -0.6891955 -0.4163615 -0.4551715
weight       -0.8322442  0.8975273    0.9329944  0.8645377  1.0000000   -0.4168392 -0.3091199 -0.5850054
acceleration  0.4233285 -0.5046834   -0.5438005 -0.6891955 -0.4168392    1.0000000  0.2903161  0.2127458
year          0.5805410 -0.3456474   -0.3698552 -0.4163615 -0.3091199    0.2903161  1.0000000  0.1815277
origin        0.5652088 -0.5689316   -0.6145351 -0.4551715 -0.5850054    0.2127458  0.1815277  1.0000000
  1. Use the lm() function to perform a multiple linear regression with mpg as the response and all other variables except name as the predictors. Use the summary() function to print the results. Comment on the output. For instance:

    1. Is there a relationship between the predictors and the response?

    A relationship between the predictors and response does appear to be present; the overall p-value < 2.2e-16 tells us that there is sufficient evidence to suggest that the model relationship is statistically significant.

    1. Which predictors appear to have a statistically significant relationship to the response?

    The specific predictors which appear to be statistically significant here are displacement, weight, year, and origin.

    1. What does the coefficient for the year variable suggest?

    The coefficient for the year variable (0.750773) suggests that as the model year of a vehicle increases by 1 year, while all other variables are held constant, we can expect the gas mileage to increase by approximately 0.751 miles per gallon.

# create data frame of all variables without name
auto.new <- data.frame(Auto[, 1:8])

#MLR with resp mpg to all other vars w/o name and show reg summary
auto.reg <- lm(mpg ~., data = auto.new)
summary(auto.reg)

Call:
lm(formula = mpg ~ ., data = auto.new)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.5903 -2.1565 -0.1169  1.8690 13.0604 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)  -17.218435   4.644294  -3.707  0.00024 ***
cylinders     -0.493376   0.323282  -1.526  0.12780    
displacement   0.019896   0.007515   2.647  0.00844 ** 
horsepower    -0.016951   0.013787  -1.230  0.21963    
weight        -0.006474   0.000652  -9.929  < 2e-16 ***
acceleration   0.080576   0.098845   0.815  0.41548    
year           0.750773   0.050973  14.729  < 2e-16 ***
origin         1.426141   0.278136   5.127 4.67e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.328 on 384 degrees of freedom
Multiple R-squared:  0.8215,    Adjusted R-squared:  0.8182 
F-statistic: 252.4 on 7 and 384 DF,  p-value: < 2.2e-16
  1. Use the plot() function to produce diagnostic plots of the linear regression fit. Comment on any problems you see with the fit. Do the residual plots suggest any unusually large outliers? Does the leverage plot identify any observations with unusually high leverage?
# plot auto regression
par(mfrow = c(2,2), mar = c(3.4,3.5,1.2,0), mgp =c(2,1,0))
plot(auto.reg)

There are some problems with the fit. From the Residuals vs. Fitted plot, we can see that we do not have homoscedasticity (model has non-constant variance) as is indicated by the bowed fan shape of the the distribution. Additionally, the error may not be normally distributed given the departure from linearity seen on the high end observations in the Q-Q plot. Additionally, these plots indicate that observations 323, 326, and 327 may be outliers in the data. The Leverage plot does not identify any observations with unusually high leverage.

  1. Use the * and : symbols to fit linear regression models with interaction effects. Do any interactions appear to be statistically significant?
# reg with main/interaction effects between weight & acceleration
wt.acc.reg <- lm(mpg ~ weight + acceleration + weight:acceleration, data = auto.new)
summary(wt.acc.reg)

Call:
lm(formula = mpg ~ weight + acceleration + weight:acceleration, 
    data = auto.new)

Residuals:
     Min       1Q   Median       3Q      Max 
-10.5823  -2.6411  -0.3517   2.2611  15.6704 

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)          2.814e+01  4.872e+00   5.776 1.57e-08 ***
weight              -3.168e-03  1.461e-03  -2.168  0.03076 *  
acceleration         1.117e+00  3.097e-01   3.608  0.00035 ***
weight:acceleration -2.787e-04  9.694e-05  -2.875  0.00426 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.249 on 388 degrees of freedom
Multiple R-squared:  0.706, Adjusted R-squared:  0.7037 
F-statistic: 310.5 on 3 and 388 DF,  p-value: < 2.2e-16
# reg with main/interaction effects between horsepower & acceleration
hp.acc.reg <- lm(mpg ~ horsepower * acceleration, data = auto.new)
summary(hp.acc.reg)

Call:
lm(formula = mpg ~ horsepower * acceleration, data = auto.new)

Residuals:
     Min       1Q   Median       3Q      Max 
-13.3442  -2.7324  -0.4049   2.4210  15.8840 

Coefficients:
                         Estimate Std. Error t value Pr(>|t|)    
(Intercept)             33.512440   3.420187   9.798  < 2e-16 ***
horsepower               0.017590   0.027425   0.641 0.521664    
acceleration             0.800296   0.211899   3.777 0.000184 ***
horsepower:acceleration -0.015698   0.002003  -7.838 4.45e-14 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.426 on 388 degrees of freedom
Multiple R-squared:  0.6809,    Adjusted R-squared:  0.6784 
F-statistic: 275.9 on 3 and 388 DF,  p-value: < 2.2e-16

In the first regression (weight + acceleration) all terms appear to be significant, including the interaction.

In the second regression (horsepower + acceleration) horsepower on its own was not shown to be significant, but acceleration and the interaction between horsepower and acceleration both appear to be highly significant.

  1. Try a few different transformations of the variables, such as log(\(X\)), \(\sqrt{X}\), \(X^{2}\). Comment on your findings.
#examine relationship: mpg & horsepower
par(mfrow = c(2,2))
plot(auto.new$horsepower, auto.new$mpg)
plot(log(auto.new$horsepower), auto.new$mpg)
plot(sqrt(auto.new$horsepower), auto.new$mpg)
plot((auto.new$horsepower)^2, auto.new$mpg)


# full reg with log-horsepower
log.hp.reg <- lm(mpg ~ cylinders + displacement + log(horsepower) + weight 
                 + acceleration + year + origin, data = auto.new)
summary(log.hp.reg)

Call:
lm(formula = mpg ~ cylinders + displacement + log(horsepower) + 
    weight + acceleration + year + origin, data = auto.new)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.3115 -2.0041 -0.1726  1.8393 12.6579 

Coefficients:
                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)     27.254005   8.589614   3.173  0.00163 ** 
cylinders       -0.486206   0.306692  -1.585  0.11372    
displacement     0.019456   0.006876   2.830  0.00491 ** 
log(horsepower) -9.506436   1.539619  -6.175 1.69e-09 ***
weight          -0.004266   0.000694  -6.148 1.97e-09 ***
acceleration    -0.292088   0.103804  -2.814  0.00515 ** 
year             0.705329   0.048456  14.556  < 2e-16 ***
origin           1.482435   0.259347   5.716 2.19e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.18 on 384 degrees of freedom
Multiple R-squared:  0.837, Adjusted R-squared:  0.834 
F-statistic: 281.6 on 7 and 384 DF,  p-value: < 2.2e-16
#examine relationship: mpg & acceleration
plot(auto.new$acceleration, auto.new$mpg)
plot(log(auto.new$acceleration), auto.new$mpg)
plot(sqrt(auto.new$acceleration), auto.new$mpg)
plot((auto.new$acceleration)^2, auto.new$mpg)


# full reg with log-acceleration
log.acc.reg <- lm(mpg ~ cylinders + displacement + horsepower + weight 
                 + log(acceleration) + year + origin, data = auto.new)
summary(log.acc.reg)

Call:
lm(formula = mpg ~ cylinders + displacement + horsepower + weight + 
    log(acceleration) + year + origin, data = auto.new)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.7774 -2.1790 -0.1636  1.8434 13.1268 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)       -15.174273   6.443614  -2.355   0.0190 *  
cylinders          -0.507167   0.323203  -1.569   0.1174    
displacement        0.019166   0.007595   2.524   0.0120 *  
horsepower         -0.024622   0.014198  -1.734   0.0837 .  
weight             -0.006190   0.000676  -9.157  < 2e-16 ***
log(acceleration)  -0.129499   1.631402  -0.079   0.9368    
year                0.747224   0.050993  14.654  < 2e-16 ***
origin              1.428083   0.278370   5.130  4.6e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.331 on 384 degrees of freedom
Multiple R-squared:  0.8212,    Adjusted R-squared:  0.8179 
F-statistic: 251.9 on 7 and 384 DF,  p-value: < 2.2e-16
# full reg with sqrt-acceleration
sqrt.acc.reg <- lm(mpg ~ cylinders + displacement + horsepower + weight 
                 + sqrt(acceleration) + year + origin, data = auto.new)
summary(sqrt.acc.reg)

Call:
lm(formula = mpg ~ cylinders + displacement + horsepower + weight + 
    sqrt(acceleration) + year + origin, data = auto.new)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.6792 -2.1496 -0.1413  1.8603 13.0920 

Coefficients:
                     Estimate Std. Error t value Pr(>|t|)    
(Intercept)        -1.696e+01  5.556e+00  -3.052  0.00243 ** 
cylinders          -5.022e-01  3.233e-01  -1.553  0.12117    
displacement        1.966e-02  7.550e-03   2.604  0.00958 ** 
horsepower         -2.052e-02  1.401e-02  -1.464  0.14395    
weight             -6.347e-03  6.639e-04  -9.560  < 2e-16 ***
sqrt(acceleration)  3.086e-01  8.101e-01   0.381  0.70343    
year                7.490e-01  5.100e-02  14.687  < 2e-16 ***
origin              1.428e+00  2.783e-01   5.131 4.58e-07 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.33 on 384 degrees of freedom
Multiple R-squared:  0.8212,    Adjusted R-squared:  0.818 
F-statistic:   252 on 7 and 384 DF,  p-value: < 2.2e-16

A logarithmic transformation on horsepower gives an approximately linear relationship to mpg and the regression on the full model with this transformation suggests that log(horsepower) is statistically significant.

None of the transformations used here provided much improvement on the acceleration data in terms of linearity. Regressions were performed on the full model using both transformations on this variable, but signifcance was not suggested for either transformation.

3. (Exercise 3.7.10) This question should be answered using the Carseats data set.

  1. Fit a multiple regression model to predict Sales using Price, Urban, and US.
data("Carseats")
# create data frame of appropriate variables
seats.new <- data.frame(Carseats[, c(1,6,10:11)])

#MLR 
seats.reg <- lm(Sales ~., data = seats.new)
summary(seats.reg)

Call:
lm(formula = Sales ~ ., data = seats.new)

Residuals:
    Min      1Q  Median      3Q     Max 
-6.9206 -1.6220 -0.0564  1.5786  7.0581 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 13.043469   0.651012  20.036  < 2e-16 ***
Price       -0.054459   0.005242 -10.389  < 2e-16 ***
UrbanYes    -0.021916   0.271650  -0.081    0.936    
USYes        1.200573   0.259042   4.635 4.86e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.472 on 396 degrees of freedom
Multiple R-squared:  0.2393,    Adjusted R-squared:  0.2335 
F-statistic: 41.52 on 3 and 396 DF,  p-value: < 2.2e-16
  1. Provide an interpretation of each coefficient in the model. Be careful - some of the variables in the model are qualitative!
  • Price: Holding all other variables constant, for every 1$ increase in the price of carseats charged by the company at each store, we expect the sales of carseats at that store to drop by approximately 54 units.
  • Urban: Holding all other variables constant, we expect that a store that is in an urban location will sell approximately 22 fewer carseats than a store in a rural location.
  • US: Holding all other variables constant, we expect that a store that is located in the US will sell approximately 1201 more carseats than a store located outside the US.
  1. Write out the model in equation form, being careful to handle the qualitative variables properly. \[ \begin{aligned} Y_{Sales} = 13.04 - 0.05445X_{Price} - 0.0219X_{Urban:Yes} + 1.2006X_{US:Yes} \end{aligned} \]

  2. For which of the predictors can you reject the null hypothesis \(H_{0}: \beta_{j} = 0\)?

We can reject this null hypothesis for Price and US as both have p-values which would suggest statistically that their respective \(\beta\) values are significantly different from zero.

  1. On the basis of your response to the previous question, fit a smaller model that only uses the predictors for which there is evidence of association with the outcome.
data("Carseats")
# create data frame of appropriate variables
seats.new <- data.frame(Carseats[, c(1,6,10:11)])

#MLR reduced
seats.reg.red <- lm(Sales ~ Price + US, data = seats.new)
summary(seats.reg.red)

Call:
lm(formula = Sales ~ Price + US, data = seats.new)

Residuals:
    Min      1Q  Median      3Q     Max 
-6.9269 -1.6286 -0.0574  1.5766  7.0515 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 13.03079    0.63098  20.652  < 2e-16 ***
Price       -0.05448    0.00523 -10.416  < 2e-16 ***
USYes        1.19964    0.25846   4.641 4.71e-06 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.469 on 397 degrees of freedom
Multiple R-squared:  0.2393,    Adjusted R-squared:  0.2354 
F-statistic: 62.43 on 2 and 397 DF,  p-value: < 2.2e-16
  1. How well do the models in (a) and (e) fit the data?

These models are poorly fit to the data with both having an R2 = 0.2393 which means that the models only account for about 24% of the variance in the data.

  1. Using the model from (e), obtain 95% confidence intervals for the coefficient(s).
confint(seats.reg.red, level = 0.95)
                  2.5 %      97.5 %
(Intercept) 11.79032020 14.27126531
Price       -0.06475984 -0.04419543
USYes        0.69151957  1.70776632
  1. Is there evidence of outliers or high leverage observations in the model from (e)?
# Get regression plots
par(mfrow = c(2,2), mar = c(3.4,3.5,1.2,0), mgp =c(2,1,0))
plot(seats.reg.red)

# Get summary of potentially influential obs
summary(influence.measures(seats.reg.red))

# Remove obs from data and re-run reg
pips <- c(26,29,43,50,51,58,69,126,160,166,172,175,210,270,298,314,353,357,368,377,384,387,396)
seats.no.pips <- seats.new[-pips, ]
reg.no.pips2 <- lm(Sales ~ Price + US, data = seats.no.pips)
summary(reg.no.pips2)

The regression plots don’t immediately suggest that any influential observations are present. We generate a list of potentially influential observations, remove these from the data and re-run the regression.

The models are very similar and the coefficient estimates in the model without potential influential points are contained by the confidence intervals obtained using the model fit with all observations. Therefore we can safely include all observations without fear of influential observations.

4. (Exercise 3.7.12) This problem involves simple linear regression without an intercept.

  1. Recall that the coefficient estimate \(\hat{\beta}\) for the linear regression of \(Y\) onto \(X\) without an intercept is given by (3.38). Under what circumstance is the coefficient estimate for the regression of \(X\) onto \(Y\) the same as the coefficient estimate for the regression of \(Y\) onto \(X\)?

From (3.38) we have that: \[\begin{align*} \hat{\beta}_{Y \to X} &= \frac{\sum_{i=1}^{n} x_{i}y_{i}}{\sum_{i=1}^{n} x_{i}^{2}} \\ \implies \hat{\beta}_{X \to Y} &= \frac{\sum_{i=1}^{n} x_{i}y_{i}}{\sum_{i=1}^{n} y_{i}^{2}} \\ \end{align*}\]

Then, \[\begin{align*} \hat{\beta}_{Y \to X} &= \hat{\beta}_{X \to Y} \\ \implies \frac{\sum_{i=1}^{n} x_{i}y_{i}}{\sum_{i=1}^{n} x_{i}^{2}} &= \frac{\sum_{i=1}^{n} x_{i}y_{i}}{\sum_{i=1}^{n} y_{i}^{2}} \\ \implies \sum_{i=1}^{n} y_{i}^{2} &= \sum_{i=1}^{n} x_{i}^{2} \end{align*}\]

Therefore, the circumstance under which the coefficient estimate for the regression of \(X\) onto \(Y\) the same as the coefficient estimate for the regression of \(Y\) onto \(X\) is when \(\sum_{i=1}^{n} y_{i}^{2} = \sum_{i=1}^{n} x_{i}^{2}\).

  1. Generate an example in R with \(n = 100\) observations in which the coefficient estimate for the regression of \(X\) onto \(Y\) is different from the coefficient estimate for the regression of \(Y\) onto \(X\).
x <- 1:100
sum(x^2)
[1] 338350
y.diff <- 2*x 
sum(y.diff^2)
[1] 1353400
reg.yx.diff <- lm(y.diff ~ 0 + x)
reg.xy.diff <- lm(x ~ 0 + y.diff)
summary(reg.yx.diff)

Call:
lm(formula = y.diff ~ 0 + x)

Residuals:
       Min         1Q     Median         3Q        Max 
-4.677e-13 -3.180e-15  6.000e-17  3.080e-15  1.537e-14 

Coefficients:
   Estimate Std. Error   t value Pr(>|t|)    
x 2.000e+00  8.144e-17 2.456e+16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.737e-14 on 99 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 6.03e+32 on 1 and 99 DF,  p-value: < 2.2e-16
summary(reg.xy.diff)

Call:
lm(formula = x ~ 0 + y.diff)

Residuals:
       Min         1Q     Median         3Q        Max 
-2.338e-13 -1.589e-15  2.900e-17  1.540e-15  7.683e-15 

Coefficients:
        Estimate Std. Error   t value Pr(>|t|)    
y.diff 5.000e-01  2.036e-17 2.456e+16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.369e-14 on 99 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 6.03e+32 on 1 and 99 DF,  p-value: < 2.2e-16
  1. Generate an example in R with \(n = 100\) observations in which the coefficient estimate for the regression of \(X\) onto \(Y\) is the same as the coefficient estimate for the regression of \(Y\) onto \(X\).
x <- 1:100
sum(x^2)
[1] 338350
y.same <- -1:-100 
sum(y.same^2)
[1] 338350
reg.yx.same <- lm(y.same ~ 0 + x)
reg.xy.same <- lm(x ~ 0 + y.same)
summary(reg.yx.same)

Call:
lm(formula = y.same ~ 0 + x)

Residuals:
       Min         1Q     Median         3Q        Max 
-7.683e-15 -1.540e-15 -2.900e-17  1.589e-15  2.338e-13 

Coefficients:
    Estimate Std. Error    t value Pr(>|t|)    
x -1.000e+00  4.072e-17 -2.456e+16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.369e-14 on 99 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 6.03e+32 on 1 and 99 DF,  p-value: < 2.2e-16
summary(reg.xy.same)

Call:
lm(formula = x ~ 0 + y.same)

Residuals:
       Min         1Q     Median         3Q        Max 
-2.338e-13 -1.589e-15  2.900e-17  1.540e-15  7.683e-15 

Coefficients:
         Estimate Std. Error    t value Pr(>|t|)    
y.same -1.000e+00  4.072e-17 -2.456e+16   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.369e-14 on 99 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic: 6.03e+32 on 1 and 99 DF,  p-value: < 2.2e-16
LS0tCnRpdGxlOiAiU1RBIDY1NDMgQXNzaWdubWVudCAyIgphdXRob3I6ICJBbGx5c3NhIFdlaW5icmVjaHQiCmRhdGU6ICIyMDI1LTAyLTI4IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCi0tLQoKYGBge3IgZWNobz1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNvbGxhcHNlID0gVFJVRSwKICBmaWcuYWxpZ249ImNlbnRlciIsCiAgZmlnLnBvcz0iYiIsCiAgc3RyaXAud2hpdGUgPSBUUlVFCikKYGBgCgoqKjEuIChFeGVyY2lzZSAzLjcuMikgQ2FyZWZ1bGx5IGV4cGxhaW4gdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIEtOTiBjbGFzc2lmaWVyIGFuZCBLTk4gcmVncmVzc2lvbiBtZXRob2RzLioqCgpJbiBib3RoIG1ldGhvZHMsIGZvciBhIHRlc3Qgb2JzZXJ2YXRpb24sICR4X3swfSQsIGEgbmVpZ2hib3Job29kIGlzIGNyZWF0ZWQgYnkgaWRlbnRpZnlpbmcgdGhlICRLJC1uZWFyZXN0IHRyYWluaW5nIG9ic2VydmF0aW9ucyB0byAkeF97MH0kLCBmb3Igc29tZSBwb3NpdGl2ZSBpbnRlZ2VyICRLJC4KCktOTiBDbGFzc2lmaWVyIE1ldGhvZDogdGhpcyBtZXRob2QgYWltcyB0byBjb3JyZWN0bHkgY2xhc3NpZnkgdGhlIHRlc3Qgb2JzZXJ2YXRpb24gJHhfezB9JCBieSB0aGUgdmFsdWUgb2YgYSBjYXRlZ29yaWNhbCByZXNwb25zZSB2YXJpYWJsZS4gSXQgZG9lcyBzbyBieSBlc3RpbWF0aW5nIHRoZSBjb25kaXRpb25hbCBwcm9iYWJpbGl0eSBvZiBlYWNoIHJlc3BvbnNlIGNsYXNzLCAkaSQsIGFzIHRoZSBmcmFjdGlvbiBvZiB0cmFpbmluZyBvYnNlcnZhdGlvbnMgd2l0aCByZXNwb25zZSB2YWx1ZSAkaSQgaW4gdGhlIG5laWdoYm9yaG9vZCBvZiAkeF97MH0kLiBUaGlzIG1ldGhvZCB3aWxsIGFzc2lnbiB0aGUgdGVzdCBvYnNlcnZhdGlvbiAkeF97MH0kIHRvIHdoaWNoZXZlciByZXNwb25zZSBjbGFzcyBoYXMgdGhlIGhpZ2hlc3QgZXN0aW1hdGVkIGNvbmRpdGlvbmFsIHByb2JhYmlsaXR5LgoKS05OIFJlZ3Jlc3Npb24gTWV0aG9kOiB0aGlzIG1ldGhvZCBhaW1zIHRvIGVzdGltYXRlIHRoZSBudW1lcmljYWwgcmVzcG9uc2UgdmFsdWUgWyRmKHhfezB9KSRdIG9mIHRoZSB0ZXN0IG9ic2VydmF0aW9uICR4X3swfSQuIEl0IGRvZXMgc28gYnkgY2FsY3VsYXRpbmcgdGhlIG1lYW4gcmVzcG9uc2UgdmFsdWUgZnJvbSB0aGUgdHJhaW5pbmcgb2JzZXJ2YXRpb25zIGluIHRoZSBuZWlnaGJvcmhvb2Qgb2YgJHhfezB9JCBhbmQgYXNzaWduaW5nIHRoaXMgbWVhbiBhcyB0aGUgZXN0aW1hdGUgb2YgJGYoeF97MH0pJC4KCioqMi4gKEV4ZXJjaXNlIDMuNy45KSBUaGlzIHF1ZXN0aW9uIGludm9sdmVzIHRoZSB1c2Ugb2YgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gb24gdGhlIGBBdXRvYCBkYXRhIHNldC4qKgoKKGEpIFByb2R1Y2UgYSBzY2F0dGVycGxvdCBtYXRyaXggd2hpY2ggaW5jbHVkZXMgYWxsIG9mIHRoZSB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgc2V0LgoKYGBge3IgUHJvYjJhfQojTG9hZCBsaWJyYXJ5IGNvbnRhaW5pbmcgZGF0YSBzZXQgYW5kIGxvYWQgQXV0byBkYXRhCmxpYnJhcnkoSVNMUjIpCmRhdGEoIkF1dG8iKQogIAojY3JlYXRlIHNjYXR0ZXJwbG90IG1hdHJpeCBvZiBhbGwgdmFyaWFibGVzIGluIHRoZSBkYXRhCnBhaXJzKEF1dG8pCmBgYAoKKGIpIENvbXB1dGUgdGhlIG1hdHJpeCBvZiBjb3JyZWxhdGlvbnMgYmV0d2VlbiB0aGUgdmFyaWFibGVzIHVzaW5nIHRoZSBmdW5jdGlvbiBgY29yKClgLiBZb3Ugd2lsbCBuZWVkIHRvIGV4Y2x1ZGUgdGhlIGBuYW1lYCB2YXJpYWJsZSwgd2hpY2ggaXMgcXVhbGl0YXRpdmUuCgpgYGB7ciBQcm9iMmJ9CiNjb3IgbWF0cml4IGFsbCBBdXRvIHZhcmlhYmxlcyBleGNlcHQgbmFtZQpjb3IoQXV0b1ssMTo4XSkKYGBgCgooYykgVXNlIHRoZSBgbG0oKWAgZnVuY3Rpb24gdG8gcGVyZm9ybSBhIG11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uIHdpdGggYG1wZ2AgYXMgdGhlIHJlc3BvbnNlIGFuZCBhbGwgb3RoZXIgdmFyaWFibGVzIGV4Y2VwdCBgbmFtZWAgYXMgdGhlIHByZWRpY3RvcnMuIFVzZSB0aGUgYHN1bW1hcnkoKWAgZnVuY3Rpb24gdG8gcHJpbnQgdGhlIHJlc3VsdHMuIENvbW1lbnQgb24gdGhlIG91dHB1dC4gRm9yIGluc3RhbmNlOgoKICAgIChpKSBJcyB0aGVyZSBhIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSBwcmVkaWN0b3JzIGFuZCB0aGUgcmVzcG9uc2U/CgogICAgQSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgcHJlZGljdG9ycyBhbmQgcmVzcG9uc2UgZG9lcyBhcHBlYXIgdG8gYmUgcHJlc2VudDsgdGhlIG92ZXJhbGwgcC12YWx1ZSBcPCAyLjJlLTE2IHRlbGxzIHVzIHRoYXQgdGhlcmUgaXMgc3VmZmljaWVudCBldmlkZW5jZSB0byBzdWdnZXN0IHRoYXQgdGhlIG1vZGVsIHJlbGF0aW9uc2hpcCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LgoKICAgIChpaSkgV2hpY2ggcHJlZGljdG9ycyBhcHBlYXIgdG8gaGF2ZSBhIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgcmVsYXRpb25zaGlwIHRvIHRoZSByZXNwb25zZT8KCiAgICBUaGUgc3BlY2lmaWMgcHJlZGljdG9ycyB3aGljaCBhcHBlYXIgdG8gYmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBoZXJlIGFyZSBgZGlzcGxhY2VtZW50YCwgYHdlaWdodGAsIGB5ZWFyYCwgYW5kIGBvcmlnaW5gLgoKICAgIChpaWkpIFdoYXQgZG9lcyB0aGUgY29l76yAaWNpZW50IGZvciB0aGUgeWVhciB2YXJpYWJsZSBzdWdnZXN0PwoKICAgIFRoZSBjb2VmZmljaWVudCBmb3IgdGhlIGB5ZWFyYCB2YXJpYWJsZSAoMC43NTA3NzMpIHN1Z2dlc3RzIHRoYXQgYXMgdGhlIG1vZGVsIHllYXIgb2YgYSB2ZWhpY2xlIGluY3JlYXNlcyBieSAxIHllYXIsIHdoaWxlIGFsbCBvdGhlciB2YXJpYWJsZXMgYXJlIGhlbGQgY29uc3RhbnQsIHdlIGNhbiBleHBlY3QgdGhlIGdhcyBtaWxlYWdlIHRvIGluY3JlYXNlIGJ5IGFwcHJveGltYXRlbHkgMC43NTEgbWlsZXMgcGVyIGdhbGxvbi4KCmBgYHtyIFByb2IyY30KIyBjcmVhdGUgZGF0YSBmcmFtZSBvZiBhbGwgdmFyaWFibGVzIHdpdGhvdXQgbmFtZQphdXRvLm5ldyA8LSBkYXRhLmZyYW1lKEF1dG9bLCAxOjhdKQoKI01MUiB3aXRoIHJlc3AgbXBnIHRvIGFsbCBvdGhlciB2YXJzIHcvbyBuYW1lIGFuZCBzaG93IHJlZyBzdW1tYXJ5CmF1dG8ucmVnIDwtIGxtKG1wZyB+LiwgZGF0YSA9IGF1dG8ubmV3KQpzdW1tYXJ5KGF1dG8ucmVnKQpgYGAKCihkKSBVc2UgdGhlIGBwbG90KClgIGZ1bmN0aW9uIHRvIHByb2R1Y2UgZGlhZ25vc3RpYyBwbG90cyBvZiB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gZml0LiBDb21tZW50IG9uIGFueSBwcm9ibGVtcyB5b3Ugc2VlIHdpdGggdGhlIGZpdC4gRG8gdGhlIHJlc2lkdWFsIHBsb3RzIHN1Z2dlc3QgYW55IHVudXN1YWxseSBsYXJnZSBvdXRsaWVycz8gRG9lcyB0aGUgbGV2ZXJhZ2UgcGxvdCBpZGVudGlmeSBhbnkgb2JzZXJ2YXRpb25zIHdpdGggdW51c3VhbGx5IGhpZ2ggbGV2ZXJhZ2U/CgpgYGB7ciBQcm9iMmR9CiMgcGxvdCBhdXRvIHJlZ3Jlc3Npb24KcGFyKG1mcm93ID0gYygyLDIpLCBtYXIgPSBjKDMuNCwzLjUsMS4yLDApLCBtZ3AgPWMoMiwxLDApKQpwbG90KGF1dG8ucmVnKQpgYGAKClRoZXJlIGFyZSBzb21lIHByb2JsZW1zIHdpdGggdGhlIGZpdC4gRnJvbSB0aGUgUmVzaWR1YWxzIHZzLiBGaXR0ZWQgcGxvdCwgd2UgY2FuIHNlZSB0aGF0IHdlIGRvIG5vdCBoYXZlIGhvbW9zY2VkYXN0aWNpdHkgKG1vZGVsIGhhcyBub24tY29uc3RhbnQgdmFyaWFuY2UpIGFzIGlzIGluZGljYXRlZCBieSB0aGUgYm93ZWQgZmFuIHNoYXBlIG9mIHRoZSB0aGUgZGlzdHJpYnV0aW9uLiBBZGRpdGlvbmFsbHksIHRoZSBlcnJvciBtYXkgbm90IGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkIGdpdmVuIHRoZSBkZXBhcnR1cmUgZnJvbSBsaW5lYXJpdHkgc2VlbiBvbiB0aGUgaGlnaCBlbmQgb2JzZXJ2YXRpb25zIGluIHRoZSBRLVEgcGxvdC4gQWRkaXRpb25hbGx5LCB0aGVzZSBwbG90cyBpbmRpY2F0ZSB0aGF0IG9ic2VydmF0aW9ucyAzMjMsIDMyNiwgYW5kIDMyNyBtYXkgYmUgb3V0bGllcnMgaW4gdGhlIGRhdGEuIFRoZSBMZXZlcmFnZSBwbG90IGRvZXMgbm90IGlkZW50aWZ5IGFueSBvYnNlcnZhdGlvbnMgd2l0aCB1bnVzdWFsbHkgaGlnaCBsZXZlcmFnZS4KCihlKSBVc2UgdGhlIGAqYCBhbmQgYDpgIHN5bWJvbHMgdG8gZml0IGxpbmVhciByZWdyZXNzaW9uIG1vZGVscyB3aXRoIGludGVyYWN0aW9uIGVmZmVjdHMuIERvIGFueSBpbnRlcmFjdGlvbnMgYXBwZWFyIHRvIGJlIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQ/CgpgYGB7ciBQcm9iMmV9CiMgcmVnIHdpdGggbWFpbi9pbnRlcmFjdGlvbiBlZmZlY3RzIGJldHdlZW4gd2VpZ2h0ICYgYWNjZWxlcmF0aW9uCnd0LmFjYy5yZWcgPC0gbG0obXBnIH4gd2VpZ2h0ICsgYWNjZWxlcmF0aW9uICsgd2VpZ2h0OmFjY2VsZXJhdGlvbiwgZGF0YSA9IGF1dG8ubmV3KQpzdW1tYXJ5KHd0LmFjYy5yZWcpCgojIHJlZyB3aXRoIG1haW4vaW50ZXJhY3Rpb24gZWZmZWN0cyBiZXR3ZWVuIGhvcnNlcG93ZXIgJiBhY2NlbGVyYXRpb24KaHAuYWNjLnJlZyA8LSBsbShtcGcgfiBob3JzZXBvd2VyICogYWNjZWxlcmF0aW9uLCBkYXRhID0gYXV0by5uZXcpCnN1bW1hcnkoaHAuYWNjLnJlZykKYGBgCgpJbiB0aGUgZmlyc3QgcmVncmVzc2lvbiAoYHdlaWdodGAgKyBgYWNjZWxlcmF0aW9uYCkgYWxsIHRlcm1zIGFwcGVhciB0byBiZSBzaWduaWZpY2FudCwgaW5jbHVkaW5nIHRoZSBpbnRlcmFjdGlvbi4KCkluIHRoZSBzZWNvbmQgcmVncmVzc2lvbiAoYGhvcnNlcG93ZXJgICsgYGFjY2VsZXJhdGlvbmApIGhvcnNlcG93ZXIgb24gaXRzIG93biB3YXMgbm90IHNob3duIHRvIGJlIHNpZ25pZmljYW50LCBidXQgYGFjY2VsZXJhdGlvbmAgYW5kIHRoZSBpbnRlcmFjdGlvbiBiZXR3ZWVuIGBob3JzZXBvd2VyYCBhbmQgYGFjY2VsZXJhdGlvbmAgYm90aCBhcHBlYXIgdG8gYmUgaGlnaGx5IHNpZ25pZmljYW50LgoKKGYpIFRyeSBhIGZldyBkaWZmZXJlbnQgdHJhbnNmb3JtYXRpb25zIG9mIHRoZSB2YXJpYWJsZXMsIHN1Y2ggYXMgbG9nKCRYJCksICRcc3FydHtYfSQsICRYXnsyfSQuIENvbW1lbnQgb24geW91ciBmaW5kaW5ncy4KCmBgYHtyIFByb2IyZn0KI2V4YW1pbmUgcmVsYXRpb25zaGlwOiBtcGcgJiBob3JzZXBvd2VyCnBhcihtZnJvdyA9IGMoMiwyKSkKcGxvdChhdXRvLm5ldyRob3JzZXBvd2VyLCBhdXRvLm5ldyRtcGcpCnBsb3QobG9nKGF1dG8ubmV3JGhvcnNlcG93ZXIpLCBhdXRvLm5ldyRtcGcpCnBsb3Qoc3FydChhdXRvLm5ldyRob3JzZXBvd2VyKSwgYXV0by5uZXckbXBnKQpwbG90KChhdXRvLm5ldyRob3JzZXBvd2VyKV4yLCBhdXRvLm5ldyRtcGcpCgojIGZ1bGwgcmVnIHdpdGggbG9nLWhvcnNlcG93ZXIKbG9nLmhwLnJlZyA8LSBsbShtcGcgfiBjeWxpbmRlcnMgKyBkaXNwbGFjZW1lbnQgKyBsb2coaG9yc2Vwb3dlcikgKyB3ZWlnaHQgCiAgICAgICAgICAgICAgICAgKyBhY2NlbGVyYXRpb24gKyB5ZWFyICsgb3JpZ2luLCBkYXRhID0gYXV0by5uZXcpCnN1bW1hcnkobG9nLmhwLnJlZykKCiNleGFtaW5lIHJlbGF0aW9uc2hpcDogbXBnICYgYWNjZWxlcmF0aW9uCnBsb3QoYXV0by5uZXckYWNjZWxlcmF0aW9uLCBhdXRvLm5ldyRtcGcpCnBsb3QobG9nKGF1dG8ubmV3JGFjY2VsZXJhdGlvbiksIGF1dG8ubmV3JG1wZykKcGxvdChzcXJ0KGF1dG8ubmV3JGFjY2VsZXJhdGlvbiksIGF1dG8ubmV3JG1wZykKcGxvdCgoYXV0by5uZXckYWNjZWxlcmF0aW9uKV4yLCBhdXRvLm5ldyRtcGcpCgojIGZ1bGwgcmVnIHdpdGggbG9nLWFjY2VsZXJhdGlvbgpsb2cuYWNjLnJlZyA8LSBsbShtcGcgfiBjeWxpbmRlcnMgKyBkaXNwbGFjZW1lbnQgKyBob3JzZXBvd2VyICsgd2VpZ2h0IAogICAgICAgICAgICAgICAgICsgbG9nKGFjY2VsZXJhdGlvbikgKyB5ZWFyICsgb3JpZ2luLCBkYXRhID0gYXV0by5uZXcpCnN1bW1hcnkobG9nLmFjYy5yZWcpCgojIGZ1bGwgcmVnIHdpdGggc3FydC1hY2NlbGVyYXRpb24Kc3FydC5hY2MucmVnIDwtIGxtKG1wZyB+IGN5bGluZGVycyArIGRpc3BsYWNlbWVudCArIGhvcnNlcG93ZXIgKyB3ZWlnaHQgCiAgICAgICAgICAgICAgICAgKyBzcXJ0KGFjY2VsZXJhdGlvbikgKyB5ZWFyICsgb3JpZ2luLCBkYXRhID0gYXV0by5uZXcpCnN1bW1hcnkoc3FydC5hY2MucmVnKQpgYGAKCkEgbG9nYXJpdGhtaWMgdHJhbnNmb3JtYXRpb24gb24gYGhvcnNlcG93ZXJgIGdpdmVzIGFuIGFwcHJveGltYXRlbHkgbGluZWFyIHJlbGF0aW9uc2hpcCB0byBgbXBnYCBhbmQgdGhlIHJlZ3Jlc3Npb24gb24gdGhlIGZ1bGwgbW9kZWwgd2l0aCB0aGlzIHRyYW5zZm9ybWF0aW9uIHN1Z2dlc3RzIHRoYXQgYGxvZyhob3JzZXBvd2VyKWAgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KCk5vbmUgb2YgdGhlIHRyYW5zZm9ybWF0aW9ucyB1c2VkIGhlcmUgcHJvdmlkZWQgbXVjaCBpbXByb3ZlbWVudCBvbiB0aGUgYGFjY2VsZXJhdGlvbmAgZGF0YSBpbiB0ZXJtcyBvZiBsaW5lYXJpdHkuIFJlZ3Jlc3Npb25zIHdlcmUgcGVyZm9ybWVkIG9uIHRoZSBmdWxsIG1vZGVsIHVzaW5nIGJvdGggdHJhbnNmb3JtYXRpb25zIG9uIHRoaXMgdmFyaWFibGUsIGJ1dCBzaWduaWZjYW5jZSB3YXMgbm90IHN1Z2dlc3RlZCBmb3IgZWl0aGVyIHRyYW5zZm9ybWF0aW9uLgoKKiozLiAoRXhlcmNpc2UgMy43LjEwKSBUaGlzIHF1ZXN0aW9uIHNob3VsZCBiZSBhbnN3ZXJlZCB1c2luZyB0aGUgYENhcnNlYXRzYCBkYXRhIHNldC4qKgoKKGEpIEZpdCBhIG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWwgdG8gcHJlZGljdCBgU2FsZXNgIHVzaW5nIGBQcmljZWAsIGBVcmJhbmAsIGFuZCBgVVNgLgoKYGBge3IgUHJvYjNhfQpkYXRhKCJDYXJzZWF0cyIpCiMgY3JlYXRlIGRhdGEgZnJhbWUgb2YgYXBwcm9wcmlhdGUgdmFyaWFibGVzCnNlYXRzLm5ldyA8LSBkYXRhLmZyYW1lKENhcnNlYXRzWywgYygxLDYsMTA6MTEpXSkKCiNNTFIgCnNlYXRzLnJlZyA8LSBsbShTYWxlcyB+LiwgZGF0YSA9IHNlYXRzLm5ldykKc3VtbWFyeShzZWF0cy5yZWcpCmBgYAoKKGIpIFByb3ZpZGUgYW4gaW50ZXJwcmV0YXRpb24gb2YgZWFjaCBjb2XvrIBpY2llbnQgaW4gdGhlIG1vZGVsLiBCZSBjYXJlZnVsIC0gc29tZSBvZiB0aGUgdmFyaWFibGVzIGluIHRoZSBtb2RlbCBhcmUgcXVhbGl0YXRpdmUhCgotICAgUHJpY2U6IEhvbGRpbmcgYWxsIG90aGVyIHZhcmlhYmxlcyBjb25zdGFudCwgZm9yIGV2ZXJ5IDFcJCBpbmNyZWFzZSBpbiB0aGUgcHJpY2Ugb2YgY2Fyc2VhdHMgY2hhcmdlZCBieSB0aGUgY29tcGFueSBhdCBlYWNoIHN0b3JlLCB3ZSBleHBlY3QgdGhlIHNhbGVzIG9mIGNhcnNlYXRzIGF0IHRoYXQgc3RvcmUgdG8gZHJvcCBieSBhcHByb3hpbWF0ZWx5IDU0IHVuaXRzLgotICAgVXJiYW46IEhvbGRpbmcgYWxsIG90aGVyIHZhcmlhYmxlcyBjb25zdGFudCwgd2UgZXhwZWN0IHRoYXQgYSBzdG9yZSB0aGF0IGlzIGluIGFuIHVyYmFuIGxvY2F0aW9uIHdpbGwgc2VsbCBhcHByb3hpbWF0ZWx5IDIyIGZld2VyIGNhcnNlYXRzIHRoYW4gYSBzdG9yZSBpbiBhIHJ1cmFsIGxvY2F0aW9uLgotICAgVVM6IEhvbGRpbmcgYWxsIG90aGVyIHZhcmlhYmxlcyBjb25zdGFudCwgd2UgZXhwZWN0IHRoYXQgYSBzdG9yZSB0aGF0IGlzIGxvY2F0ZWQgaW4gdGhlIFVTIHdpbGwgc2VsbCBhcHByb3hpbWF0ZWx5IDEyMDEgbW9yZSBjYXJzZWF0cyB0aGFuIGEgc3RvcmUgbG9jYXRlZCBvdXRzaWRlIHRoZSBVUy4KCihjKSBXcml0ZSBvdXQgdGhlIG1vZGVsIGluIGVxdWF0aW9uIGZvcm0sIGJlaW5nIGNhcmVmdWwgdG8gaGFuZGxlIHRoZSBxdWFsaXRhdGl2ZSB2YXJpYWJsZXMgcHJvcGVybHkuICQkICAKICAgIFxiZWdpbnthbGlnbmVkfQogICAgICBZX3tTYWxlc30gPSAxMy4wNCAtIDAuMDU0NDVYX3tQcmljZX0gLSAwLjAyMTlYX3tVcmJhbjpZZXN9ICsgMS4yMDA2WF97VVM6WWVzfQogICAgXGVuZHthbGlnbmVkfQogICAgJCQKCihkKSBGb3Igd2hpY2ggb2YgdGhlIHByZWRpY3RvcnMgY2FuIHlvdSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyAkSF97MH06IFxiZXRhX3tqfSA9IDAkPwoKV2UgY2FuIHJlamVjdCB0aGlzIG51bGwgaHlwb3RoZXNpcyBmb3IgYFByaWNlYCBhbmQgYFVTYCBhcyBib3RoIGhhdmUgcC12YWx1ZXMgd2hpY2ggd291bGQgc3VnZ2VzdCBzdGF0aXN0aWNhbGx5IHRoYXQgdGhlaXIgcmVzcGVjdGl2ZSAkXGJldGEkIHZhbHVlcyBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB6ZXJvLgoKKGUpIE9uIHRoZSBiYXNpcyBvZiB5b3VyIHJlc3BvbnNlIHRvIHRoZSBwcmV2aW91cyBxdWVzdGlvbiwgZml0IGEgc21hbGxlciBtb2RlbCB0aGF0IG9ubHkgdXNlcyB0aGUgcHJlZGljdG9ycyBmb3Igd2hpY2ggdGhlcmUgaXMgZXZpZGVuY2Ugb2YgYXNzb2NpYXRpb24gd2l0aCB0aGUgb3V0Y29tZS4KCmBgYHtyIFByb2IzZX0KZGF0YSgiQ2Fyc2VhdHMiKQojIGNyZWF0ZSBkYXRhIGZyYW1lIG9mIGFwcHJvcHJpYXRlIHZhcmlhYmxlcwpzZWF0cy5uZXcgPC0gZGF0YS5mcmFtZShDYXJzZWF0c1ssIGMoMSw2LDEwOjExKV0pCgojTUxSIHJlZHVjZWQKc2VhdHMucmVnLnJlZCA8LSBsbShTYWxlcyB+IFByaWNlICsgVVMsIGRhdGEgPSBzZWF0cy5uZXcpCnN1bW1hcnkoc2VhdHMucmVnLnJlZCkKYGBgCgooZikgSG93IHdlbGwgZG8gdGhlIG1vZGVscyBpbiAoYSkgYW5kIChlKSBmaXQgdGhlIGRhdGE/CgpUaGVzZSBtb2RlbHMgYXJlIHBvb3JseSBmaXQgdG8gdGhlIGRhdGEgd2l0aCBib3RoIGhhdmluZyBhbiBSXjJeID0gMC4yMzkzIHdoaWNoIG1lYW5zIHRoYXQgdGhlIG1vZGVscyBvbmx5IGFjY291bnQgZm9yIGFib3V0IDI0JSBvZiB0aGUgdmFyaWFuY2UgaW4gdGhlIGRhdGEuCgooZykgVXNpbmcgdGhlIG1vZGVsIGZyb20gKGUpLCBvYnRhaW4gOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciB0aGUgY29l76yAaWNpZW50KHMpLgoKYGBge3IgUHJvYjNnfQpjb25maW50KHNlYXRzLnJlZy5yZWQsIGxldmVsID0gMC45NSkKYGBgCgooaCkgSXMgdGhlcmUgZXZpZGVuY2Ugb2Ygb3V0bGllcnMgb3IgaGlnaCBsZXZlcmFnZSBvYnNlcnZhdGlvbnMgaW4gdGhlIG1vZGVsIGZyb20gKGUpPwoKYGBge3IgUHJvYjNofQojIEdldCByZWdyZXNzaW9uIHBsb3RzCnBhcihtZnJvdyA9IGMoMiwyKSwgbWFyID0gYygzLjQsMy41LDEuMiwwKSwgbWdwID1jKDIsMSwwKSkKcGxvdChzZWF0cy5yZWcucmVkKQoKIyBHZXQgc3VtbWFyeSBvZiBwb3RlbnRpYWxseSBpbmZsdWVudGlhbCBvYnMKc3VtbWFyeShpbmZsdWVuY2UubWVhc3VyZXMoc2VhdHMucmVnLnJlZCkpCgojIFJlbW92ZSBvYnMgZnJvbSBkYXRhIGFuZCByZS1ydW4gcmVnCnBpcHMgPC0gYygyNiwyOSw0Myw1MCw1MSw1OCw2OSwxMjYsMTYwLDE2NiwxNzIsMTc1LDIxMCwyNzAsMjk4LDMxNCwzNTMsMzU3LDM2OCwzNzcsMzg0LDM4NywzOTYpCnNlYXRzLm5vLnBpcHMgPC0gc2VhdHMubmV3Wy1waXBzLCBdCnJlZy5uby5waXBzMiA8LSBsbShTYWxlcyB+IFByaWNlICsgVVMsIGRhdGEgPSBzZWF0cy5uby5waXBzKQpzdW1tYXJ5KHJlZy5uby5waXBzMikKYGBgCgpUaGUgcmVncmVzc2lvbiBwbG90cyBkb24ndCBpbW1lZGlhdGVseSBzdWdnZXN0IHRoYXQgYW55IGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucyBhcmUgcHJlc2VudC4gV2UgZ2VuZXJhdGUgYSBsaXN0IG9mIHBvdGVudGlhbGx5IGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucywgcmVtb3ZlIHRoZXNlIGZyb20gdGhlIGRhdGEgYW5kIHJlLXJ1biB0aGUgcmVncmVzc2lvbi4KClRoZSBtb2RlbHMgYXJlIHZlcnkgc2ltaWxhciBhbmQgdGhlIGNvZWZmaWNpZW50IGVzdGltYXRlcyBpbiB0aGUgbW9kZWwgd2l0aG91dCBwb3RlbnRpYWwgaW5mbHVlbnRpYWwgcG9pbnRzIGFyZSBjb250YWluZWQgYnkgdGhlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIG9idGFpbmVkIHVzaW5nIHRoZSBtb2RlbCBmaXQgd2l0aCBhbGwgb2JzZXJ2YXRpb25zLiBUaGVyZWZvcmUgd2UgY2FuIHNhZmVseSBpbmNsdWRlIGFsbCBvYnNlcnZhdGlvbnMgd2l0aG91dCBmZWFyIG9mIGluZmx1ZW50aWFsIG9ic2VydmF0aW9ucy4KCioqNC4gKEV4ZXJjaXNlIDMuNy4xMikgVGhpcyBwcm9ibGVtIGludm9sdmVzIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiB3aXRob3V0IGFuIGludGVyY2VwdC4qKgoKICAoYSkgUmVjYWxsIHRoYXQgdGhlIGNvZe+sgGljaWVudCBlc3RpbWF0ZSAkXGhhdHtcYmV0YX0kIGZvciB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gb2YgJFkkIG9udG8gJFgkIHdpdGhvdXQgYW4gaW50ZXJjZXB0IGlzIGdpdmVuIGJ5ICgzLjM4KS4gVW5kZXIgd2hhdCBjaXJjdW1zdGFuY2UgaXMgdGhlIGNvZe+sgGljaWVudCBlc3RpbWF0ZSBmb3IgdGhlIHJlZ3Jlc3Npb24gb2YgJFgkIG9udG8gJFkkIHRoZSBzYW1lIGFzIHRoZSBjb2XvrIBpY2llbnQgZXN0aW1hdGUgZm9yIHRoZSByZWdyZXNzaW9uIG9mICRZJCBvbnRvICRYJD8KICAKICBGcm9tICgzLjM4KSB3ZSBoYXZlIHRoYXQ6CiAgXGJlZ2lue2FsaWduKn0gCiAgICBcaGF0e1xiZXRhfV97WSBcdG8gWH0gJj0gXGZyYWN7XHN1bV97aT0xfV57bn0geF97aX15X3tpfX17XHN1bV97aT0xfV57bn0geF97aX1eezJ9fSBcXAogICAgXGltcGxpZXMgXGhhdHtcYmV0YX1fe1ggXHRvIFl9ICY9IFxmcmFje1xzdW1fe2k9MX1ee259IHhfe2l9eV97aX19e1xzdW1fe2k9MX1ee259IHlfe2l9XnsyfX0gXFwKICBcZW5ke2FsaWduKn0KICAKICBUaGVuLAogIFxiZWdpbnthbGlnbip9IAogICAgXGhhdHtcYmV0YX1fe1kgXHRvIFh9ICY9IFxoYXR7XGJldGF9X3tYIFx0byBZfSBcXAogICAgXGltcGxpZXMgXGZyYWN7XHN1bV97aT0xfV57bn0geF97aX15X3tpfX17XHN1bV97aT0xfV57bn0geF97aX1eezJ9fSAmPSBcZnJhY3tcc3VtX3tpPTF9XntufSB4X3tpfXlfe2l9fXtcc3VtX3tpPTF9XntufSB5X3tpfV57Mn19IFxcCiAgICBcaW1wbGllcyBcc3VtX3tpPTF9XntufSB5X3tpfV57Mn0gJj0gXHN1bV97aT0xfV57bn0geF97aX1eezJ9CiAgXGVuZHthbGlnbip9CiAgCiAgVGhlcmVmb3JlLCB0aGUgY2lyY3Vtc3RhbmNlIHVuZGVyIHdoaWNoIHRoZSBjb2XvrIBpY2llbnQgZXN0aW1hdGUgZm9yIHRoZSByZWdyZXNzaW9uIG9mICRYJCBvbnRvICRZJCB0aGUgc2FtZSBhcyB0aGUgY29l76yAaWNpZW50IGVzdGltYXRlIGZvciB0aGUgcmVncmVzc2lvbiBvZiAkWSQgb250byAkWCQgaXMgd2hlbiAkXHN1bV97aT0xfV57bn0geV97aX1eezJ9ID0gXHN1bV97aT0xfV57bn0geF97aX1eezJ9JC4KCiAgKGIpIEdlbmVyYXRlIGFuIGV4YW1wbGUgaW4gYFJgIHdpdGggJG4gPSAxMDAkIG9ic2VydmF0aW9ucyBpbiB3aGljaCB0aGUgY29l76yAaWNpZW50IGVzdGltYXRlIGZvciB0aGUgcmVncmVzc2lvbiBvZiAkWCQgb250byAkWSQgaXMgKmRpZmZlcmVudCogZnJvbSB0aGUgY29l76yAaWNpZW50IGVzdGltYXRlIGZvciB0aGUgcmVncmVzc2lvbiBvZiAkWSQgb250byAkWCQuCiAgCmBgYCB7ciBQcm9iNGIsIHdhcm5pbmc9RkFMU0V9CnggPC0gMToxMDAKc3VtKHheMikKCnkuZGlmZiA8LSAyKnggCnN1bSh5LmRpZmZeMikKCgpyZWcueXguZGlmZiA8LSBsbSh5LmRpZmYgfiAwICsgeCkKcmVnLnh5LmRpZmYgPC0gbG0oeCB+IDAgKyB5LmRpZmYpCnN1bW1hcnkocmVnLnl4LmRpZmYpCnN1bW1hcnkocmVnLnh5LmRpZmYpCmBgYAoKICAoYykgR2VuZXJhdGUgYW4gZXhhbXBsZSBpbiBgUmAgd2l0aCAkbiA9IDEwMCQgb2JzZXJ2YXRpb25zIGluIHdoaWNoIHRoZSBjb2XvrIBpY2llbnQgZXN0aW1hdGUgZm9yIHRoZSByZWdyZXNzaW9uIG9mICRYJCBvbnRvICRZJCBpcyAqdGhlIHNhbWUqIGFzIHRoZSBjb2XvrIBpY2llbnQgZXN0aW1hdGUgZm9yIHRoZSByZWdyZXNzaW9uIG9mICRZJCBvbnRvICRYJC4KICAKYGBgIHtyIFByb2I0Yywgd2FybmluZz1GQUxTRX0KeCA8LSAxOjEwMApzdW0oeF4yKQoKeS5zYW1lIDwtIC0xOi0xMDAgCnN1bSh5LnNhbWVeMikKCgpyZWcueXguc2FtZSA8LSBsbSh5LnNhbWUgfiAwICsgeCkKcmVnLnh5LnNhbWUgPC0gbG0oeCB+IDAgKyB5LnNhbWUpCnN1bW1hcnkocmVnLnl4LnNhbWUpCnN1bW1hcnkocmVnLnh5LnNhbWUpCmBgYAo=