This lecture walks you through performing a multiple regression analysis in R the California Housing Price dataset. This dataset includes both numerical and categorical variables, allowing us to cover all the required topics.

We use the tidyverse package for data manipulation and visualization, and the base R functions for regression.

Setup and Data Preparation

First, we need to load the necessary library and a suitable dataset. The modeldata package contains the California Housing data.

# Install and load necessary packages (you only need to run install.packages once)
# install.packages(c("tidyverse", "modeldata"))
library(tidyverse)
library(modeldata)

# Load the California Housing dataset
data(ames) # This loads the Ames, Iowa housing data, a common choice for grad-level examples
housing_data <- ames %>%
  drop_na() %>%
  # Convert Sale_Price to log scale, which often improves model performance for price data
  mutate(log_Sale_Price = log(Sale_Price)) %>%
  # Select a few key variables and rename for clarity
  select(Gr_Liv_Area, Year_Built, Garage_Area, Total_Bsmt_SF, Garage_Cars, Year_Remod_Add, First_Flr_SF, Full_Bath, Garage_Type, Fireplaces, log_Sale_Price ) %>%
  # Filter out potential outliers for clean analysis (optional but good practice)
  filter(Gr_Liv_Area < 4000)

# Display the first few rows of the data
head(housing_data)

Our response variable (\(Y\)) is Sale_Price, and we’ll use several explanatory variables (\(X\)’s).

Multiple Regression Model

We start with a basic multiple regression model including only numerical explanatory variables: Gr_Liv_Area (Above Ground Living Area), Year_Built, and Garage_Area (Size of garage in square feet).

\[ \hat{y}_{\text{log_Sale_Price}} = \beta_0 + \beta_1x_{\text{Gr_Liv_Area}} + \beta_2x_{\text{Year_Built}} + \beta_3x_{\text{Garage_Area}} + \epsilon \]

# Fit the model in R using the lm() function
model_num <- lm(log_Sale_Price ~ Gr_Liv_Area + Year_Built + Garage_Area, data = housing_data)

# Print a summary of the model
summary(model_num)

Call:
lm(formula = log_Sale_Price ~ Gr_Liv_Area + Year_Built + Garage_Area, 
    data = housing_data)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.16196 -0.10463  0.00262  0.11702  0.80234 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) 9.571e-01  2.749e-01   3.482 0.000504 ***
Gr_Liv_Area 4.274e-04  8.784e-06  48.655  < 2e-16 ***
Year_Built  5.186e-03  1.416e-04  36.611  < 2e-16 ***
Garage_Area 4.276e-04  2.209e-05  19.359  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2032 on 2921 degrees of freedom
Multiple R-squared:  0.7497,    Adjusted R-squared:  0.7494 
F-statistic:  2916 on 3 and 2921 DF,  p-value: < 2.2e-16

Interpreting Parameter Coefficients

This linear model uses a log-transformed response variable (\(ln(\text{Sale_Price})\)), which means we interpret the coefficients in terms of percentage change in the sale price.

  • Intercept (\(\hat{\beta}_0\)): The estimated mean log-sale price is \(\mathbf{0.9571}\) when all predictors (Gr_Liv_Area, Year_Built, and Garage_Area) are zero. Exponentiating this (\(\exp(0.9571) \approx \$2.60\)) gives the estimated sale price under these (impractical) conditions.

  • Gr_Liv_Area (\(\hat{\beta}_1\) \(\approx 4.274 \times 10^{-4}\)): For every one square foot increase in above-ground living area, the mean sale price is estimated to increase by approximately \(\mathbf{0.04274\%}\) (since \(4.274 \times 10^{-4} \times 100\% = 0.04274\%\)), holding all other variables constant.

  • Year_Built (\(\hat{\beta}_2\) \(\approx 5.186 \times 10^{-3}\)): For every one year newer the house is, the mean sale price is estimated to increase by approximately \(\mathbf{0.5186\%}\) (since \(5.186 \times 10^{-3} \times 100\% = 0.5186\%\)), holding all other variables constant.

  • Garage_Area (\(\hat{\beta}_3\) \(\approx 4.276 \times 10^{-4}\)): For every one square foot increase in garage area, the mean sale price is estimated to increase by approximately \(\mathbf{0.04276\%}\) (since \(4.276 \times 10^{-4} \times 100\% = 0.04276\%\)), holding all other variables constant.

Since all \(P\)-values are extremely small (\(< 2e-16\)), all three explanatory variables are highly significant predictors of the log-transformed sale price. The biggest practical effect, on a percentage basis, comes from Year_Built.

Adding a Categorical Variable in Regression

We now add the categorical variable Garage_Type to the model. \(\mathbf{R}\) automatically handles categorical variables by creating dummy (indicator) variables.

Since Neighborhood has multiple levels, \(\mathbf{R}\) chooses one level as the reference level (usually the first one alphabetically) and creates \(k-1\) dummy variables for a categorical variable with \(k\) levels.

\[ \text{ln(Sale_Price)} = \beta_0 + \beta_1(\text{Gr_Liv_Area}) + \dots + \beta_4(\text{Garage_Type_Indicator_Attchd}) + \beta_5(\text{Garage_Type_Indicator_Basment}) + \dots + \epsilon \]

# Fit the model including the categorical variable Neighborhood
model_cat <- lm(log_Sale_Price ~ Gr_Liv_Area + Year_Built + Garage_Area  + Garage_Type, data = housing_data)

# Print a summary of the new model
summary(model_cat)

Call:
lm(formula = log_Sale_Price ~ Gr_Liv_Area + Year_Built + Garage_Area + 
    Garage_Type, data = housing_data)

Residuals:
     Min       1Q   Median       3Q      Max 
-2.17301 -0.09957  0.00092  0.11073  0.85350 

Coefficients:
                                 Estimate Std. Error t value Pr(>|t|)    
(Intercept)                     2.329e+00  3.264e-01   7.135 1.22e-12 ***
Gr_Liv_Area                     4.273e-04  9.194e-06  46.470  < 2e-16 ***
Year_Built                      4.517e-03  1.661e-04  27.201  < 2e-16 ***
Garage_Area                     3.992e-04  2.562e-05  15.583  < 2e-16 ***
Garage_TypeBasment             -1.038e-01  3.353e-02  -3.096  0.00198 ** 
Garage_TypeBuiltIn             -8.549e-02  1.600e-02  -5.342 9.89e-08 ***
Garage_TypeCarPort             -2.944e-01  5.165e-02  -5.699 1.32e-08 ***
Garage_TypeDetchd              -8.597e-02  1.045e-02  -8.228 2.83e-16 ***
Garage_TypeMore_Than_Two_Types -2.329e-01  4.260e-02  -5.467 4.97e-08 ***
Garage_TypeNo_Garage           -1.252e-01  2.010e-02  -6.232 5.28e-10 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1981 on 2915 degrees of freedom
Multiple R-squared:  0.7627,    Adjusted R-squared:  0.7619 
F-statistic:  1041 on 9 and 2915 DF,  p-value: < 2.2e-16

Interpreting Categorical Parameters for Garage_Type

Since the response variable is \(\ln(\text{Sale\_Price})\), the coefficients for the dummy variables represent the approximate percentage change in the mean Sale Price relative to the reference group, holding all other variables constant.

The categorical variable is Garage_Type, and the levels listed in the coefficient table are Basment, BuiltIn, CarPort, Detchd, More_Than_Two_Types, and No_Garage. This means the reference level (the level not included in the coefficients) is Attchd (Attached Garage).

The following interpretations compare each garage type to the Attached Garage (Attchd) reference group, assuming that the numerical variables (Gr_Liv_Area, Year_Built, and Garage_Area) are the same.

  • Garage_TypeBasment (\(\hat{\beta} \approx -0.1038\)): A house with a Basement garage is estimated to have a mean sale price that is approximately \(10.38\%\) lower than a comparable house with an Attached garage, holding all other variables constant.

  • Garage_TypeBuiltIn (\(\hat{\beta} \approx -0.0855\)): A house with a Built-In garage is estimated to have a mean sale price that is approximately \(8.55\%\) lower than a comparable house with an Attached garage, holding all other variables constant.

  • Garage_TypeCarPort (\(\hat{\beta} \approx -0.2944\)): A house with a Car Port is estimated to have a mean sale price that is approximately \(29.44\%\) lower than a comparable house with an Attached garage, holding all other variables constant. This represents the largest negative impact among the types.

  • Garage_TypeDetchd (\(\hat{\beta} \approx -0.0860\)): A house with a Detached garage is estimated to have a mean sale price that is approximately \(8.60\%\) lower than a comparable house with an Attached garage, holding all other variables constant.

  • Garage_TypeMore_Than_Two_Types (\(\hat{\beta} \approx -0.2329\)): A house with More Than Two Types of garage is estimated to have a mean sale price that is approximately \(23.29\%\) lower than a comparable house with an Attached garage, holding all other variables constant.

  • Garage_TypeNo_Garage (\(\hat{\beta} \approx -0.1252\)): A house with No Garage is estimated to have a mean sale price that is approximately \(12.52\%\) lower than a comparable house with an Attached garage, holding all other variables constant.

Inference for Regression Parameters (and A Case Study)

The \(\mathbf{R}\) summary() output provides the necessary information for inference:

Term Estimate Std. Error t value Pr(\(>|t|\))
\(\dots\) \(\dots\) \(\dots\) \(\dots\) \(\dots\)

Inference for Regression Parameters

For each coefficient \(\beta_j\), we test the null hypothesis \(H_0: \beta_j = 0\) against the alternative \(H_a: \beta_j \ne 0\).

  1. Test Statistic: The \(t\)-statistic is calculated as \(t = \frac{\hat{\beta}_j - 0}{\text{SE}(\hat{\beta}_j)}\).

  2. P-value: The \(\mathbf{P}\)-value (Pr($>|t|$)) is the probability of observing a \(t\)-statistic as extreme as the one calculated, assuming \(H_0\) is true.

Case Study: Gr_Liv_Area

The \(t\)-value for Gr_Liv_Area is typically very large, and the \(\mathbf{P}\)-value is typically extremely small (\(< 2 \times 10^{-16}\)).

  • Conclusion: Since the \(\mathbf{P}\)-value is much less than a standard significance level like \(\alpha=0.05\), we reject the null hypothesis \(H_0: \beta_{\text{Gr\_Liv\_Area}} = 0\).

  • Interpretation: There is strong statistical evidence that \(\mathbf{Gr\_Liv\_Area}\) has a linear relationship with \(\mathbf{Sale\_Price}\), controlling for the other predictors in the model. In other words, its coefficient is significantly different from zero.

Confidence Intervals

We often use confidence intervals (CIs) to estimate the true population parameter \(\beta_j\). A \(95\%\) CI is \((\hat{\beta}_j \pm t^* \times \text{SE}(\hat{\beta}_j))\).

# Get confidence intervals for all coefficients
confint(model_cat, level = 0.95)
                                       2.5 %        97.5 %
(Intercept)                     1.6888233837  2.9687612498
Gr_Liv_Area                     0.0004092390  0.0004452955
Year_Built                      0.0041913047  0.0048424996
Garage_Area                     0.0003489689  0.0004494272
Garage_TypeBasment             -0.1695750108 -0.0380743640
Garage_TypeBuiltIn             -0.1168644361 -0.0541109002
Garage_TypeCarPort             -0.3956534502 -0.1931036982
Garage_TypeDetchd              -0.1064609915 -0.0654859349
Garage_TypeMore_Than_Two_Types -0.3163980070 -0.1493448294
Garage_TypeNo_Garage           -0.1646482187 -0.0858345788

Interpretation of CI for Gr_Liv_Area (e.g., [\(\mathbf{0.0409\%}\), \(\mathbf{0.0445\%}\)]): We are \(95\%\) confident that the true population mean increase in Sale Price for a one-unit increase in Gr_Liv_Area, holding all other variables constant, is between \(\mathbf{0.0409\%}\) and \(\mathbf{0.0445\%}\).

Correlations Between Explanatory Variables (Multicollinearity)

Multicollinearity occurs when two or more explanatory variables in a multiple regression model are highly linearly correlated. It doesn’t bias the estimates but makes them less precise (larger Standard Errors and \(P\)-values), making interpretation unstable.

# Check correlation among the numerical predictors
cor_data <- housing_data %>%
  mutate(Garage_Type=as.numeric(Garage_Type)) %>%
  select(Gr_Liv_Area, Year_Built, Garage_Area, Garage_Type)
cor(cor_data)
            Gr_Liv_Area Year_Built Garage_Area Garage_Type
Gr_Liv_Area   1.0000000  0.2393052   0.4749449  -0.2351748
Year_Built    0.2393052  1.0000000   0.4795550  -0.5427980
Garage_Area   0.4749449  0.4795550   1.0000000  -0.4193524
Garage_Type  -0.2351748 -0.5427980  -0.4193524   1.0000000

The correlation matrix will show the pairwise correlation coefficients. If any absolute correlation value is high (e.g., \(|r| > 0.8\)), we should be concerned. Nothing here causes concern.

If multicollinearity is a concern, consider dropping one of the highly correlated variables or creating an index/composite score.


Interactions

An interaction term allows the effect of one predictor on the response variable to depend on the value of another predictor.

We hypothesize that the effect of Gr_Liv_Area on Sale_Price might depend on the Year_Built of the house. A square foot of living space might be more valuable in a older home than a newer one.

\[ \text{ln(Sale_Price)} = \beta_0 + \beta_1(\text{Gr_Liv_Area}) + \dots + \beta_4(\mathbf{\text{Gr_Liv_Area} \times \text{Year_Built}}) + \epsilon \]

# Fit a model with an interaction term
# The colon ":" indicates an interaction between two variables
model_int <- lm(log_Sale_Price ~ Gr_Liv_Area + Year_Built + Gr_Liv_Area:Year_Built, data = housing_data)

summary(model_int)

Call:
lm(formula = log_Sale_Price ~ Gr_Liv_Area + Year_Built + Gr_Liv_Area:Year_Built, 
    data = housing_data)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.0406 -0.1214  0.0130  0.1270  0.6729 

Coefficients:
                         Estimate Std. Error t value Pr(>|t|)    
(Intercept)            -1.643e-01  8.626e-01  -0.190    0.849    
Gr_Liv_Area            -1.955e-04  5.189e-04  -0.377    0.706    
Year_Built              5.801e-03  4.390e-04  13.215   <2e-16 ***
Gr_Liv_Area:Year_Built  3.530e-07  2.636e-07   1.339    0.181    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2158 on 2921 degrees of freedom
Multiple R-squared:  0.7177,    Adjusted R-squared:  0.7175 
F-statistic:  2476 on 3 and 2921 DF,  p-value: < 2.2e-16

I’d be happy to provide that interpretation. When analyzing this log-linear model, remember that the interaction coefficient, \(\hat{\beta}_{\text{int}}\), represents the change in the rate of percentage change in the sale price.

Interpreting Interaction Parameters

The interaction coefficient, \(\hat{\beta}_{\text{int}}\) (for Gr_Liv_Area:Year_Built), estimates how the slope (the percentage effect) of Gr_Liv_Area changes for a one-year increase in Year_Built.

  • Effective Slope: The relationship between Living Area and log Sale Price is now conditional. The effective increase in \(\ln(\text{Sale_Price})\) for one additional square foot of Gr_Liv_Area is:

    \[\text{Effective Slope}_{\text{Gr_Liv_Area}} = (-1.955 \times 10^{-4}) + (3.530 \times 10^{-7}) \times \text{Year_Built}\]

  • Interpretation of the Estimate: The positive interaction coefficient (\(\hat{\beta}_{\text{int}} \approx 3.530 \times 10^{-7}\)) suggests that the marginal benefit (the value) of an additional square foot of living area increases slightly for newer homes (i.e., as Year_Built increases), holding all other variables constant.

  • Inference: With a P-value of \(0.181\), the interaction term is not statistically significant at a standard \(\alpha=0.05\) level. This means we cannot conclude there is strong evidence that the effect of living area on sale price significantly depends on the year the house was built. The non-interactive model might provide a more parsimonious fit.

Checking the Conditions for Inference (The “LINE” Conditions)

Reliable inference (P-values and CIs) relies on four key assumptions about the model errors (\(\epsilon\)):

  1. Linearity: The relationship between \(Y\) and the \(X\)’s is linear.
  2. Independence: The errors are independent of each other. (Usually checked by context, e.g., houses are independent observations).
  3. Normality: The errors are Normally distributed.
  4. Equal Variance (Homoscedasticity): The errors have constant variance across all levels of the predictors.

These are primarily checked by examining the Residuals (the difference between the observed \(Y\) and the predicted \(\hat{Y}\)).

# 1 & 4. Linearity and Equal Variance (Homoscedasticity)
# Plot of Residuals vs. Fitted Values
plot(model_cat, which = 1)

  • Ideal Plot: A random scatter of points around the horizontal line at \(0\).

  • What to look for: A fan shape (heteroscedasticity) or a curved pattern (non-linearity). The housing data often shows a fan shape, indicating heteroscedasticity. This is a common issue with price data, often fixed by log-transforming the response variable: lm(log(Sale_Price) ~ ...)

# 3. Normality of Residuals
# Q-Q Plot
plot(model_cat, which = 2)

  • Ideal Plot: Points lie closely along the diagonal straight line.

  • What to look for: Significant deviation from the line, especially in the tails, indicating non-Normality.

If conditions are severely violated, transformations (like log) or more advanced methods (e.g., Robust Regression, Generalized Least Squares) are required.

LS0tDQp0aXRsZTogIk11bHRpcGxlIFJlZ3Jlc3Npb246IEEgQ2FzZSBTdHVkeSBpbiBSZWFsIEVzdGF0ZSBWYWx1YXRpb24iDQpvdXRwdXQ6IA0KICBodG1sX25vdGVib29rOg0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KLS0tDQoNClRoaXMgbGVjdHVyZSB3YWxrcyB5b3UgdGhyb3VnaCBwZXJmb3JtaW5nIGEgbXVsdGlwbGUgcmVncmVzc2lvbiBhbmFseXNpcyBpbiBgUmAgdGhlIFtDYWxpZm9ybmlhIEhvdXNpbmcgUHJpY2UgZGF0YXNldF0oaHR0cHM6Ly9qc2UuYW1zdGF0Lm9yZy92MTluMy9kZWNvY2svRGF0YURvY3VtZW50YXRpb24udHh0KS4gVGhpcyBkYXRhc2V0IGluY2x1ZGVzIGJvdGggbnVtZXJpY2FsIGFuZCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMsIGFsbG93aW5nIHVzIHRvIGNvdmVyIGFsbCB0aGUgcmVxdWlyZWQgdG9waWNzLg0KDQpXZSB1c2UgdGhlIGB0aWR5dmVyc2VgIHBhY2thZ2UgZm9yIGRhdGEgbWFuaXB1bGF0aW9uIGFuZCB2aXN1YWxpemF0aW9uLCBhbmQgdGhlIGJhc2UgYFJgIGZ1bmN0aW9ucyBmb3IgcmVncmVzc2lvbi4NCg0KIyMgU2V0dXAgYW5kIERhdGEgUHJlcGFyYXRpb24NCg0KRmlyc3QsIHdlIG5lZWQgdG8gbG9hZCB0aGUgbmVjZXNzYXJ5IGxpYnJhcnkgYW5kIGEgc3VpdGFibGUgZGF0YXNldC4gVGhlIGBtb2RlbGRhdGFgIHBhY2thZ2UgY29udGFpbnMgdGhlIENhbGlmb3JuaWEgSG91c2luZyBkYXRhLg0KDQpgYGB7cn0NCiMgSW5zdGFsbCBhbmQgbG9hZCBuZWNlc3NhcnkgcGFja2FnZXMgKHlvdSBvbmx5IG5lZWQgdG8gcnVuIGluc3RhbGwucGFja2FnZXMgb25jZSkNCiMgaW5zdGFsbC5wYWNrYWdlcyhjKCJ0aWR5dmVyc2UiLCAibW9kZWxkYXRhIikpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobW9kZWxkYXRhKQ0KDQojIExvYWQgdGhlIENhbGlmb3JuaWEgSG91c2luZyBkYXRhc2V0DQpkYXRhKGFtZXMpICMgVGhpcyBsb2FkcyB0aGUgQW1lcywgSW93YSBob3VzaW5nIGRhdGEsIGEgY29tbW9uIGNob2ljZSBmb3IgZ3JhZC1sZXZlbCBleGFtcGxlcw0KaG91c2luZ19kYXRhIDwtIGFtZXMgJT4lDQogIGRyb3BfbmEoKSAlPiUNCiAgIyBDb252ZXJ0IFNhbGVfUHJpY2UgdG8gbG9nIHNjYWxlLCB3aGljaCBvZnRlbiBpbXByb3ZlcyBtb2RlbCBwZXJmb3JtYW5jZSBmb3IgcHJpY2UgZGF0YQ0KICBtdXRhdGUobG9nX1NhbGVfUHJpY2UgPSBsb2coU2FsZV9QcmljZSkpICU+JQ0KICAjIFNlbGVjdCBhIGZldyBrZXkgdmFyaWFibGVzIGFuZCByZW5hbWUgZm9yIGNsYXJpdHkNCiAgc2VsZWN0KEdyX0xpdl9BcmVhLCBZZWFyX0J1aWx0LCBHYXJhZ2VfQXJlYSwgVG90YWxfQnNtdF9TRiwgR2FyYWdlX0NhcnMsIFllYXJfUmVtb2RfQWRkLCBGaXJzdF9GbHJfU0YsIEZ1bGxfQmF0aCwgR2FyYWdlX1R5cGUsIEZpcmVwbGFjZXMsIGxvZ19TYWxlX1ByaWNlICkgJT4lDQogICMgRmlsdGVyIG91dCBwb3RlbnRpYWwgb3V0bGllcnMgZm9yIGNsZWFuIGFuYWx5c2lzIChvcHRpb25hbCBidXQgZ29vZCBwcmFjdGljZSkNCiAgZmlsdGVyKEdyX0xpdl9BcmVhIDwgNDAwMCkNCg0KIyBEaXNwbGF5IHRoZSBmaXJzdCBmZXcgcm93cyBvZiB0aGUgZGF0YQ0KaGVhZChob3VzaW5nX2RhdGEpDQpgYGANCg0KDQpPdXIgKipyZXNwb25zZSB2YXJpYWJsZSoqICgkWSQpIGlzICoqYFNhbGVfUHJpY2VgKiosIGFuZCB3ZSdsbCB1c2Ugc2V2ZXJhbCAqKmV4cGxhbmF0b3J5IHZhcmlhYmxlcyoqICgkWCQncykuDQoNCiMjIE11bHRpcGxlIFJlZ3Jlc3Npb24gTW9kZWwNCg0KV2Ugc3RhcnQgd2l0aCBhIGJhc2ljIG11bHRpcGxlIHJlZ3Jlc3Npb24gbW9kZWwgaW5jbHVkaW5nIG9ubHkgKipudW1lcmljYWwqKiBleHBsYW5hdG9yeSB2YXJpYWJsZXM6IGBHcl9MaXZfQXJlYWAgKEFib3ZlIEdyb3VuZCBMaXZpbmcgQXJlYSksIGBZZWFyX0J1aWx0YCwgYW5kIGBHYXJhZ2VfQXJlYWAgKFNpemUgb2YgZ2FyYWdlIGluIHNxdWFyZSBmZWV0KS4NCg0KJCQNClxoYXR7eX1fe1x0ZXh0e2xvZ19TYWxlX1ByaWNlfX0gPSBcYmV0YV8wICsgXGJldGFfMXhfe1x0ZXh0e0dyX0xpdl9BcmVhfX0gKyBcYmV0YV8yeF97XHRleHR7WWVhcl9CdWlsdH19ICsgXGJldGFfM3hfe1x0ZXh0e0dhcmFnZV9BcmVhfX0gKyBcZXBzaWxvbg0KJCQNCg0KYGBge3J9DQojIEZpdCB0aGUgbW9kZWwgaW4gUiB1c2luZyB0aGUgbG0oKSBmdW5jdGlvbg0KbW9kZWxfbnVtIDwtIGxtKGxvZ19TYWxlX1ByaWNlIH4gR3JfTGl2X0FyZWEgKyBZZWFyX0J1aWx0ICsgR2FyYWdlX0FyZWEsIGRhdGEgPSBob3VzaW5nX2RhdGEpDQoNCiMgUHJpbnQgYSBzdW1tYXJ5IG9mIHRoZSBtb2RlbA0Kc3VtbWFyeShtb2RlbF9udW0pDQpgYGANCg0KIyMjIEludGVycHJldGluZyBQYXJhbWV0ZXIgQ29lZmZpY2llbnRzDQoNClRoaXMgbGluZWFyIG1vZGVsIHVzZXMgYSBsb2ctdHJhbnNmb3JtZWQgcmVzcG9uc2UgdmFyaWFibGUgKCRsbihcdGV4dHtTYWxlX1ByaWNlfSkkKSwgd2hpY2ggbWVhbnMgd2UgaW50ZXJwcmV0IHRoZSBjb2VmZmljaWVudHMgaW4gdGVybXMgb2YgKipwZXJjZW50YWdlIGNoYW5nZSoqIGluIHRoZSBzYWxlIHByaWNlLg0KDQoqICoqSW50ZXJjZXB0ICgkXGhhdHtcYmV0YX1fMCQpOioqIFRoZSBlc3RpbWF0ZWQgbWVhbiBsb2ctc2FsZSBwcmljZSBpcyAkXG1hdGhiZnswLjk1NzF9JCB3aGVuIGFsbCBwcmVkaWN0b3JzIChgR3JfTGl2X0FyZWFgLCBgWWVhcl9CdWlsdGAsIGFuZCBgR2FyYWdlX0FyZWFgKSBhcmUgemVyby4gRXhwb25lbnRpYXRpbmcgdGhpcyAoJFxleHAoMC45NTcxKSBcYXBwcm94IFwkMi42MCQpIGdpdmVzIHRoZSBlc3RpbWF0ZWQgc2FsZSBwcmljZSB1bmRlciB0aGVzZSAoaW1wcmFjdGljYWwpIGNvbmRpdGlvbnMuDQoNCiogKipgR3JfTGl2X0FyZWFgICgkXGhhdHtcYmV0YX1fMSQgJFxhcHByb3ggNC4yNzQgXHRpbWVzIDEwXnstNH0kKToqKiBGb3IgZXZlcnkgb25lIHNxdWFyZSBmb290IGluY3JlYXNlIGluIGFib3ZlLWdyb3VuZCBsaXZpbmcgYXJlYSwgdGhlIG1lYW4gc2FsZSBwcmljZSBpcyBlc3RpbWF0ZWQgdG8gaW5jcmVhc2UgYnkgYXBwcm94aW1hdGVseSAkXG1hdGhiZnswLjA0Mjc0XCV9JCAoc2luY2UgJDQuMjc0IFx0aW1lcyAxMF57LTR9IFx0aW1lcyAxMDBcJSA9IDAuMDQyNzRcJSQpLCAqaG9sZGluZyBhbGwgb3RoZXIgdmFyaWFibGVzIGNvbnN0YW50Ki4NCg0KKiAqKmBZZWFyX0J1aWx0YCAoJFxoYXR7XGJldGF9XzIkICRcYXBwcm94IDUuMTg2IFx0aW1lcyAxMF57LTN9JCk6KiogRm9yIGV2ZXJ5IG9uZSB5ZWFyIG5ld2VyIHRoZSBob3VzZSBpcywgdGhlIG1lYW4gc2FsZSBwcmljZSBpcyBlc3RpbWF0ZWQgdG8gaW5jcmVhc2UgYnkgYXBwcm94aW1hdGVseSAkXG1hdGhiZnswLjUxODZcJX0kIChzaW5jZSAkNS4xODYgXHRpbWVzIDEwXnstM30gXHRpbWVzIDEwMFwlID0gMC41MTg2XCUkKSwgKmhvbGRpbmcgYWxsIG90aGVyIHZhcmlhYmxlcyBjb25zdGFudCouDQoNCiogKipgR2FyYWdlX0FyZWFgICgkXGhhdHtcYmV0YX1fMyQgJFxhcHByb3ggNC4yNzYgXHRpbWVzIDEwXnstNH0kKToqKiBGb3IgZXZlcnkgb25lIHNxdWFyZSBmb290IGluY3JlYXNlIGluIGdhcmFnZSBhcmVhLCB0aGUgbWVhbiBzYWxlIHByaWNlIGlzIGVzdGltYXRlZCB0byBpbmNyZWFzZSBieSBhcHByb3hpbWF0ZWx5ICRcbWF0aGJmezAuMDQyNzZcJX0kIChzaW5jZSAkNC4yNzYgXHRpbWVzIDEwXnstNH0gXHRpbWVzIDEwMFwlID0gMC4wNDI3NlwlJCksICpob2xkaW5nIGFsbCBvdGhlciB2YXJpYWJsZXMgY29uc3RhbnQqLg0KDQpTaW5jZSBhbGwgJFAkLXZhbHVlcyBhcmUgZXh0cmVtZWx5IHNtYWxsICgkPCAyZS0xNiQpLCBhbGwgdGhyZWUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGFyZSBoaWdobHkgc2lnbmlmaWNhbnQgcHJlZGljdG9ycyBvZiB0aGUgbG9nLXRyYW5zZm9ybWVkIHNhbGUgcHJpY2UuIFRoZSBiaWdnZXN0IHByYWN0aWNhbCBlZmZlY3QsIG9uIGEgcGVyY2VudGFnZSBiYXNpcywgY29tZXMgZnJvbSAqKmBZZWFyX0J1aWx0YCoqLg0KDQojIyBBZGRpbmcgYSBDYXRlZ29yaWNhbCBWYXJpYWJsZSBpbiBSZWdyZXNzaW9uDQoNCldlIG5vdyBhZGQgdGhlIGNhdGVnb3JpY2FsIHZhcmlhYmxlICoqYEdhcmFnZV9UeXBlYCoqIHRvIHRoZSBtb2RlbC4gJFxtYXRoYmZ7Un0kIGF1dG9tYXRpY2FsbHkgaGFuZGxlcyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYnkgY3JlYXRpbmcgW2R1bW15IChpbmRpY2F0b3IpIHZhcmlhYmxlc10oaHR0cHM6Ly9vbmxpbmUuc3RhdC5wc3UuZWR1L3N0YXQ0NjIvbm9kZS8xNjEvKS4NCg0KU2luY2UgYE5laWdoYm9yaG9vZGAgaGFzIG11bHRpcGxlIGxldmVscywgJFxtYXRoYmZ7Un0kIGNob29zZXMgb25lIGxldmVsIGFzIHRoZSAqKnJlZmVyZW5jZSBsZXZlbCoqICh1c3VhbGx5IHRoZSBmaXJzdCBvbmUgYWxwaGFiZXRpY2FsbHkpIGFuZCBjcmVhdGVzICRrLTEkIGR1bW15IHZhcmlhYmxlcyBmb3IgYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB3aXRoICRrJCBsZXZlbHMuDQoNCiQkDQpcdGV4dHtsbihTYWxlX1ByaWNlKX0gPSBcYmV0YV8wICsgXGJldGFfMShcdGV4dHtHcl9MaXZfQXJlYX0pICsgXGRvdHMgKyBcYmV0YV80KFx0ZXh0e0dhcmFnZV9UeXBlX0luZGljYXRvcl9BdHRjaGR9KSArIFxiZXRhXzUoXHRleHR7R2FyYWdlX1R5cGVfSW5kaWNhdG9yX0Jhc21lbnR9KSArIFxkb3RzICsgXGVwc2lsb24NCiQkDQoNCmBgYHtyfQ0KIyBGaXQgdGhlIG1vZGVsIGluY2x1ZGluZyB0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgTmVpZ2hib3Job29kDQptb2RlbF9jYXQgPC0gbG0obG9nX1NhbGVfUHJpY2UgfiBHcl9MaXZfQXJlYSArIFllYXJfQnVpbHQgKyBHYXJhZ2VfQXJlYSAgKyBHYXJhZ2VfVHlwZSwgZGF0YSA9IGhvdXNpbmdfZGF0YSkNCg0KIyBQcmludCBhIHN1bW1hcnkgb2YgdGhlIG5ldyBtb2RlbA0Kc3VtbWFyeShtb2RlbF9jYXQpDQpgYGANCg0KIyMjIEludGVycHJldGluZyBDYXRlZ29yaWNhbCBQYXJhbWV0ZXJzIGZvciBgR2FyYWdlX1R5cGVgDQoNClNpbmNlIHRoZSByZXNwb25zZSB2YXJpYWJsZSBpcyAkXGxuKFx0ZXh0e1NhbGVcX1ByaWNlfSkkLCB0aGUgY29lZmZpY2llbnRzIGZvciB0aGUgZHVtbXkgdmFyaWFibGVzIHJlcHJlc2VudCB0aGUgKiphcHByb3hpbWF0ZSBwZXJjZW50YWdlIGNoYW5nZSoqIGluIHRoZSBtZWFuIFNhbGUgUHJpY2UgcmVsYXRpdmUgdG8gdGhlIHJlZmVyZW5jZSBncm91cCwgaG9sZGluZyBhbGwgb3RoZXIgdmFyaWFibGVzIGNvbnN0YW50Lg0KDQpUaGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgaXMgYEdhcmFnZV9UeXBlYCwgYW5kIHRoZSBsZXZlbHMgbGlzdGVkIGluIHRoZSBjb2VmZmljaWVudCB0YWJsZSBhcmUgYEJhc21lbnRgLCBgQnVpbHRJbmAsIGBDYXJQb3J0YCwgYERldGNoZGAsIGBNb3JlX1RoYW5fVHdvX1R5cGVzYCwgYW5kIGBOb19HYXJhZ2VgLiBUaGlzIG1lYW5zIHRoZSAqKnJlZmVyZW5jZSBsZXZlbCoqICh0aGUgbGV2ZWwgKm5vdCogaW5jbHVkZWQgaW4gdGhlIGNvZWZmaWNpZW50cykgaXMgKipgQXR0Y2hkYCoqIChBdHRhY2hlZCBHYXJhZ2UpLg0KDQpUaGUgZm9sbG93aW5nIGludGVycHJldGF0aW9ucyBjb21wYXJlIGVhY2ggZ2FyYWdlIHR5cGUgdG8gdGhlICoqQXR0YWNoZWQgR2FyYWdlIChgQXR0Y2hkYCkqKiByZWZlcmVuY2UgZ3JvdXAsIGFzc3VtaW5nIHRoYXQgdGhlIG51bWVyaWNhbCB2YXJpYWJsZXMgKGBHcl9MaXZfQXJlYWAsIGBZZWFyX0J1aWx0YCwgYW5kIGBHYXJhZ2VfQXJlYWApIGFyZSB0aGUgc2FtZS4NCg0KKiAqKmBHYXJhZ2VfVHlwZUJhc21lbnRgICgkXGhhdHtcYmV0YX0gXGFwcHJveCAtMC4xMDM4JCk6KiogQSBob3VzZSB3aXRoIGEgKipCYXNlbWVudCoqIGdhcmFnZSBpcyBlc3RpbWF0ZWQgdG8gaGF2ZSBhIG1lYW4gc2FsZSBwcmljZSB0aGF0IGlzIGFwcHJveGltYXRlbHkgKiokMTAuMzhcJSQgbG93ZXIqKiB0aGFuIGEgY29tcGFyYWJsZSBob3VzZSB3aXRoIGFuIEF0dGFjaGVkIGdhcmFnZSwgaG9sZGluZyBhbGwgb3RoZXIgdmFyaWFibGVzIGNvbnN0YW50Lg0KDQoqICoqYEdhcmFnZV9UeXBlQnVpbHRJbmAgKCRcaGF0e1xiZXRhfSBcYXBwcm94IC0wLjA4NTUkKToqKiBBIGhvdXNlIHdpdGggYSAqKkJ1aWx0LUluKiogZ2FyYWdlIGlzIGVzdGltYXRlZCB0byBoYXZlIGEgbWVhbiBzYWxlIHByaWNlIHRoYXQgaXMgYXBwcm94aW1hdGVseSAqKiQ4LjU1XCUkIGxvd2VyKiogdGhhbiBhIGNvbXBhcmFibGUgaG91c2Ugd2l0aCBhbiBBdHRhY2hlZCBnYXJhZ2UsIGhvbGRpbmcgYWxsIG90aGVyIHZhcmlhYmxlcyBjb25zdGFudC4NCg0KKiAqKmBHYXJhZ2VfVHlwZUNhclBvcnRgICgkXGhhdHtcYmV0YX0gXGFwcHJveCAtMC4yOTQ0JCk6KiogQSBob3VzZSB3aXRoIGEgKipDYXIgUG9ydCoqIGlzIGVzdGltYXRlZCB0byBoYXZlIGEgbWVhbiBzYWxlIHByaWNlIHRoYXQgaXMgYXBwcm94aW1hdGVseSAqKiQyOS40NFwlJCBsb3dlcioqIHRoYW4gYSBjb21wYXJhYmxlIGhvdXNlIHdpdGggYW4gQXR0YWNoZWQgZ2FyYWdlLCBob2xkaW5nIGFsbCBvdGhlciB2YXJpYWJsZXMgY29uc3RhbnQuIFRoaXMgcmVwcmVzZW50cyB0aGUgbGFyZ2VzdCBuZWdhdGl2ZSBpbXBhY3QgYW1vbmcgdGhlIHR5cGVzLg0KDQoqICoqYEdhcmFnZV9UeXBlRGV0Y2hkYCAoJFxoYXR7XGJldGF9IFxhcHByb3ggLTAuMDg2MCQpOioqIEEgaG91c2Ugd2l0aCBhICoqRGV0YWNoZWQqKiBnYXJhZ2UgaXMgZXN0aW1hdGVkIHRvIGhhdmUgYSBtZWFuIHNhbGUgcHJpY2UgdGhhdCBpcyBhcHByb3hpbWF0ZWx5ICoqJDguNjBcJSQgbG93ZXIqKiB0aGFuIGEgY29tcGFyYWJsZSBob3VzZSB3aXRoIGFuIEF0dGFjaGVkIGdhcmFnZSwgaG9sZGluZyBhbGwgb3RoZXIgdmFyaWFibGVzIGNvbnN0YW50Lg0KDQoqICoqYEdhcmFnZV9UeXBlTW9yZV9UaGFuX1R3b19UeXBlc2AgKCRcaGF0e1xiZXRhfSBcYXBwcm94IC0wLjIzMjkkKToqKiBBIGhvdXNlIHdpdGggKipNb3JlIFRoYW4gVHdvIFR5cGVzKiogb2YgZ2FyYWdlIGlzIGVzdGltYXRlZCB0byBoYXZlIGEgbWVhbiBzYWxlIHByaWNlIHRoYXQgaXMgYXBwcm94aW1hdGVseSAqKiQyMy4yOVwlJCBsb3dlcioqIHRoYW4gYSBjb21wYXJhYmxlIGhvdXNlIHdpdGggYW4gQXR0YWNoZWQgZ2FyYWdlLCBob2xkaW5nIGFsbCBvdGhlciB2YXJpYWJsZXMgY29uc3RhbnQuDQoNCiogKipgR2FyYWdlX1R5cGVOb19HYXJhZ2VgICgkXGhhdHtcYmV0YX0gXGFwcHJveCAtMC4xMjUyJCk6KiogQSBob3VzZSB3aXRoICoqTm8gR2FyYWdlKiogaXMgZXN0aW1hdGVkIHRvIGhhdmUgYSBtZWFuIHNhbGUgcHJpY2UgdGhhdCBpcyBhcHByb3hpbWF0ZWx5ICoqJDEyLjUyXCUkIGxvd2VyKiogdGhhbiBhIGNvbXBhcmFibGUgaG91c2Ugd2l0aCBhbiBBdHRhY2hlZCBnYXJhZ2UsIGhvbGRpbmcgYWxsIG90aGVyIHZhcmlhYmxlcyBjb25zdGFudC4NCg0KDQoNCiMjIEluZmVyZW5jZSBmb3IgUmVncmVzc2lvbiBQYXJhbWV0ZXJzIChhbmQgQSBDYXNlIFN0dWR5KQ0KDQpUaGUgJFxtYXRoYmZ7Un0kIGBzdW1tYXJ5KClgIG91dHB1dCBwcm92aWRlcyB0aGUgbmVjZXNzYXJ5IGluZm9ybWF0aW9uIGZvciBpbmZlcmVuY2U6DQoNCnwgVGVybSB8IEVzdGltYXRlIHwgU3RkLiBFcnJvciB8IHQgdmFsdWUgfCBQcigkPnx0fCQpIHwNCnwgOi0tLSB8IDotLS06IHwgOi0tLTogfCA6LS0tOiB8IDotLS06IHwNCnwgJFxkb3RzJCB8ICRcZG90cyQgfCAkXGRvdHMkIHwgJFxkb3RzJCB8ICRcZG90cyQgfA0KDQojIyMgSW5mZXJlbmNlIGZvciBSZWdyZXNzaW9uIFBhcmFtZXRlcnMNCg0KRm9yIGVhY2ggY29lZmZpY2llbnQgJFxiZXRhX2okLCB3ZSB0ZXN0IHRoZSBudWxsIGh5cG90aGVzaXMgJEhfMDogXGJldGFfaiA9IDAkIGFnYWluc3QgdGhlIGFsdGVybmF0aXZlICRIX2E6IFxiZXRhX2ogXG5lIDAkLg0KDQoxLiAgKipUZXN0IFN0YXRpc3RpYzoqKiBUaGUgJHQkLXN0YXRpc3RpYyBpcyBjYWxjdWxhdGVkIGFzICR0ID0gXGZyYWN7XGhhdHtcYmV0YX1faiAtIDB9e1x0ZXh0e1NFfShcaGF0e1xiZXRhfV9qKX0kLg0KDQoyLiAgKipQLXZhbHVlOioqIFRoZSAkXG1hdGhiZntQfSQtdmFsdWUgKGBQcigkPnx0fCQpYCkgaXMgdGhlIHByb2JhYmlsaXR5IG9mIG9ic2VydmluZyBhICR0JC1zdGF0aXN0aWMgYXMgZXh0cmVtZSBhcyB0aGUgb25lIGNhbGN1bGF0ZWQsIGFzc3VtaW5nICRIXzAkIGlzIHRydWUuDQoNCioqQ2FzZSBTdHVkeTogYEdyX0xpdl9BcmVhYCoqDQoNClRoZSAkdCQtdmFsdWUgZm9yIGBHcl9MaXZfQXJlYWAgaXMgdHlwaWNhbGx5IHZlcnkgbGFyZ2UsIGFuZCB0aGUgJFxtYXRoYmZ7UH0kLXZhbHVlIGlzIHR5cGljYWxseSBleHRyZW1lbHkgc21hbGwgKCQ8IDIgXHRpbWVzIDEwXnstMTZ9JCkuDQoNCiAgKiAqKkNvbmNsdXNpb246KiogU2luY2UgdGhlICRcbWF0aGJme1B9JC12YWx1ZSBpcyBtdWNoIGxlc3MgdGhhbiBhIHN0YW5kYXJkIHNpZ25pZmljYW5jZSBsZXZlbCBsaWtlICRcYWxwaGE9MC4wNSQsIHdlICoqcmVqZWN0IHRoZSBudWxsIGh5cG90aGVzaXMqKiAkSF8wOiBcYmV0YV97XHRleHR7R3JcX0xpdlxfQXJlYX19ID0gMCQuDQogIA0KICAqICoqSW50ZXJwcmV0YXRpb246KiogVGhlcmUgaXMgKipzdHJvbmcgc3RhdGlzdGljYWwgZXZpZGVuY2UqKiB0aGF0ICRcbWF0aGJme0dyXF9MaXZcX0FyZWF9JCBoYXMgYSBsaW5lYXIgcmVsYXRpb25zaGlwIHdpdGggJFxtYXRoYmZ7U2FsZVxfUHJpY2V9JCwgKipjb250cm9sbGluZyBmb3IgdGhlIG90aGVyIHByZWRpY3RvcnMqKiBpbiB0aGUgbW9kZWwuIEluIG90aGVyIHdvcmRzLCBpdHMgY29lZmZpY2llbnQgaXMgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgZnJvbSB6ZXJvLg0KDQojIyMgQ29uZmlkZW5jZSBJbnRlcnZhbHMNCg0KV2Ugb2Z0ZW4gdXNlICoqY29uZmlkZW5jZSBpbnRlcnZhbHMgKENJcykqKiB0byBlc3RpbWF0ZSB0aGUgdHJ1ZSBwb3B1bGF0aW9uIHBhcmFtZXRlciAkXGJldGFfaiQuIEEgJDk1XCUkIENJIGlzICQoXGhhdHtcYmV0YX1faiBccG0gdF4qIFx0aW1lcyBcdGV4dHtTRX0oXGhhdHtcYmV0YX1faikpJC4NCg0KYGBge3J9DQojIEdldCBjb25maWRlbmNlIGludGVydmFscyBmb3IgYWxsIGNvZWZmaWNpZW50cw0KY29uZmludChtb2RlbF9jYXQsIGxldmVsID0gMC45NSkNCmBgYA0KDQoqKkludGVycHJldGF0aW9uIG9mIENJIGZvciBgR3JfTGl2X0FyZWFgIChlLmcuLCBbJFxtYXRoYmZ7MC4wNDA5XCV9JCwgJFxtYXRoYmZ7MC4wNDQ1XCV9JF0pOioqIFdlIGFyZSAkOTVcJSQgY29uZmlkZW50IHRoYXQgdGhlICoqdHJ1ZSBwb3B1bGF0aW9uIG1lYW4gaW5jcmVhc2UqKiBpbiBTYWxlIFByaWNlIGZvciBhIG9uZS11bml0IGluY3JlYXNlIGluIGBHcl9MaXZfQXJlYWAsIGhvbGRpbmcgYWxsIG90aGVyIHZhcmlhYmxlcyBjb25zdGFudCwgaXMgYmV0d2VlbiAqKiRcbWF0aGJmezAuMDQwOVwlfSQgYW5kICRcbWF0aGJmezAuMDQ0NVwlfSQqKi4NCg0KDQojIyBDb3JyZWxhdGlvbnMgQmV0d2VlbiBFeHBsYW5hdG9yeSBWYXJpYWJsZXMgKE11bHRpY29sbGluZWFyaXR5KQ0KDQoqKk11bHRpY29sbGluZWFyaXR5Kiogb2NjdXJzIHdoZW4gdHdvIG9yIG1vcmUgZXhwbGFuYXRvcnkgdmFyaWFibGVzIGluIGEgbXVsdGlwbGUgcmVncmVzc2lvbiBtb2RlbCBhcmUgaGlnaGx5IGxpbmVhcmx5IGNvcnJlbGF0ZWQuIEl0IGRvZXNuJ3QgYmlhcyB0aGUgZXN0aW1hdGVzIGJ1dCBtYWtlcyB0aGVtIGxlc3MgcHJlY2lzZSAobGFyZ2VyIFN0YW5kYXJkIEVycm9ycyBhbmQgJFAkLXZhbHVlcyksIG1ha2luZyBpbnRlcnByZXRhdGlvbiB1bnN0YWJsZS4NCg0KYGBge3J9DQojIENoZWNrIGNvcnJlbGF0aW9uIGFtb25nIHRoZSBudW1lcmljYWwgcHJlZGljdG9ycw0KY29yX2RhdGEgPC0gaG91c2luZ19kYXRhICU+JQ0KICBtdXRhdGUoR2FyYWdlX1R5cGU9YXMubnVtZXJpYyhHYXJhZ2VfVHlwZSkpICU+JQ0KICBzZWxlY3QoR3JfTGl2X0FyZWEsIFllYXJfQnVpbHQsIEdhcmFnZV9BcmVhLCBHYXJhZ2VfVHlwZSkNCmNvcihjb3JfZGF0YSkNCmBgYA0KDQpUaGUgY29ycmVsYXRpb24gbWF0cml4IHdpbGwgc2hvdyB0aGUgcGFpcndpc2UgY29ycmVsYXRpb24gY29lZmZpY2llbnRzLiBJZiBhbnkgYWJzb2x1dGUgY29ycmVsYXRpb24gdmFsdWUgaXMgaGlnaCAoZS5nLiwgJHxyfCA+IDAuOCQpLCB3ZSBzaG91bGQgYmUgY29uY2VybmVkLiBOb3RoaW5nIGhlcmUgY2F1c2VzIGNvbmNlcm4uDQoNCklmIG11bHRpY29sbGluZWFyaXR5IGlzIGEgY29uY2VybiwgY29uc2lkZXIgZHJvcHBpbmcgb25lIG9mIHRoZSBoaWdobHkgY29ycmVsYXRlZCB2YXJpYWJsZXMgb3IgY3JlYXRpbmcgYW4gaW5kZXgvY29tcG9zaXRlIHNjb3JlLg0KDQotLS0tLQ0KDQojIyBJbnRlcmFjdGlvbnMNCg0KQW4gKippbnRlcmFjdGlvbiB0ZXJtKiogYWxsb3dzIHRoZSBlZmZlY3Qgb2Ygb25lIHByZWRpY3RvciBvbiB0aGUgcmVzcG9uc2UgdmFyaWFibGUgdG8gZGVwZW5kIG9uIHRoZSB2YWx1ZSBvZiBhbm90aGVyIHByZWRpY3Rvci4NCg0KV2UgaHlwb3RoZXNpemUgdGhhdCB0aGUgZWZmZWN0IG9mICoqYEdyX0xpdl9BcmVhYCoqIG9uICoqYFNhbGVfUHJpY2VgKiogbWlnaHQgZGVwZW5kIG9uIHRoZSAqKmBZZWFyX0J1aWx0YCoqIG9mIHRoZSBob3VzZS4gQSBzcXVhcmUgZm9vdCBvZiBsaXZpbmcgc3BhY2UgbWlnaHQgYmUgbW9yZSB2YWx1YWJsZSBpbiBhIG9sZGVyIGhvbWUgdGhhbiBhIG5ld2VyIG9uZS4NCg0KJCQNClx0ZXh0e2xuKFNhbGVfUHJpY2UpfSA9IFxiZXRhXzAgKyBcYmV0YV8xKFx0ZXh0e0dyX0xpdl9BcmVhfSkgKyBcZG90cyArIFxiZXRhXzQoXG1hdGhiZntcdGV4dHtHcl9MaXZfQXJlYX0gXHRpbWVzIFx0ZXh0e1llYXJfQnVpbHR9fSkgKyBcZXBzaWxvbg0KJCQNCg0KYGBge3J9DQojIEZpdCBhIG1vZGVsIHdpdGggYW4gaW50ZXJhY3Rpb24gdGVybQ0KIyBUaGUgY29sb24gIjoiIGluZGljYXRlcyBhbiBpbnRlcmFjdGlvbiBiZXR3ZWVuIHR3byB2YXJpYWJsZXMNCm1vZGVsX2ludCA8LSBsbShsb2dfU2FsZV9QcmljZSB+IEdyX0xpdl9BcmVhICsgWWVhcl9CdWlsdCArIEdyX0xpdl9BcmVhOlllYXJfQnVpbHQsIGRhdGEgPSBob3VzaW5nX2RhdGEpDQoNCnN1bW1hcnkobW9kZWxfaW50KQ0KYGBgDQoNCkknZCBiZSBoYXBweSB0byBwcm92aWRlIHRoYXQgaW50ZXJwcmV0YXRpb24uIFdoZW4gYW5hbHl6aW5nIHRoaXMgbG9nLWxpbmVhciBtb2RlbCwgcmVtZW1iZXIgdGhhdCB0aGUgaW50ZXJhY3Rpb24gY29lZmZpY2llbnQsICRcaGF0e1xiZXRhfV97XHRleHR7aW50fX0kLCByZXByZXNlbnRzIHRoZSBjaGFuZ2UgaW4gdGhlICpyYXRlKiBvZiBwZXJjZW50YWdlIGNoYW5nZSBpbiB0aGUgc2FsZSBwcmljZS4NCg0KIyMjIEludGVycHJldGluZyBJbnRlcmFjdGlvbiBQYXJhbWV0ZXJzDQoNClRoZSBpbnRlcmFjdGlvbiBjb2VmZmljaWVudCwgJFxoYXR7XGJldGF9X3tcdGV4dHtpbnR9fSQgKGZvciBgR3JfTGl2X0FyZWE6WWVhcl9CdWlsdGApLCBlc3RpbWF0ZXMgaG93IHRoZSAqKnNsb3BlKiogKHRoZSBwZXJjZW50YWdlIGVmZmVjdCkgb2YgYEdyX0xpdl9BcmVhYCBjaGFuZ2VzIGZvciBhIG9uZS15ZWFyIGluY3JlYXNlIGluIGBZZWFyX0J1aWx0YC4NCg0KKiAqKkVmZmVjdGl2ZSBTbG9wZToqKiBUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gTGl2aW5nIEFyZWEgYW5kIGxvZyBTYWxlIFByaWNlIGlzIG5vdyBjb25kaXRpb25hbC4gVGhlIGVmZmVjdGl2ZSBpbmNyZWFzZSBpbiAkXGxuKFx0ZXh0e1NhbGVfUHJpY2V9KSQgZm9yIG9uZSBhZGRpdGlvbmFsIHNxdWFyZSBmb290IG9mIGBHcl9MaXZfQXJlYWAgaXM6DQoNCiAgICAkJFx0ZXh0e0VmZmVjdGl2ZSBTbG9wZX1fe1x0ZXh0e0dyX0xpdl9BcmVhfX0gPSAoLTEuOTU1IFx0aW1lcyAxMF57LTR9KSArICgzLjUzMCBcdGltZXMgMTBeey03fSkgXHRpbWVzIFx0ZXh0e1llYXJfQnVpbHR9JCQNCg0KKiAqKkludGVycHJldGF0aW9uIG9mIHRoZSBFc3RpbWF0ZToqKiBUaGUgcG9zaXRpdmUgaW50ZXJhY3Rpb24gY29lZmZpY2llbnQgKCRcaGF0e1xiZXRhfV97XHRleHR7aW50fX0gXGFwcHJveCAzLjUzMCBcdGltZXMgMTBeey03fSQpIHN1Z2dlc3RzIHRoYXQgdGhlIG1hcmdpbmFsIGJlbmVmaXQgKHRoZSB2YWx1ZSkgb2YgYW4gYWRkaXRpb25hbCBzcXVhcmUgZm9vdCBvZiBsaXZpbmcgYXJlYSAqKmluY3JlYXNlcyBzbGlnaHRseSoqIGZvciBuZXdlciBob21lcyAoaS5lLiwgYXMgYFllYXJfQnVpbHRgIGluY3JlYXNlcyksICpob2xkaW5nIGFsbCBvdGhlciB2YXJpYWJsZXMgY29uc3RhbnQqLg0KDQoqICoqSW5mZXJlbmNlOioqIFdpdGggYSBQLXZhbHVlIG9mICQwLjE4MSQsIHRoZSBpbnRlcmFjdGlvbiB0ZXJtIGlzICoqbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQqKiBhdCBhIHN0YW5kYXJkICRcYWxwaGE9MC4wNSQgbGV2ZWwuIFRoaXMgbWVhbnMgd2UgY2Fubm90IGNvbmNsdWRlIHRoZXJlIGlzIHN0cm9uZyBldmlkZW5jZSB0aGF0IHRoZSBlZmZlY3Qgb2YgbGl2aW5nIGFyZWEgb24gc2FsZSBwcmljZSBzaWduaWZpY2FudGx5IGRlcGVuZHMgb24gdGhlIHllYXIgdGhlIGhvdXNlIHdhcyBidWlsdC4gVGhlIG5vbi1pbnRlcmFjdGl2ZSBtb2RlbCBtaWdodCBwcm92aWRlIGEgbW9yZSBwYXJzaW1vbmlvdXMgZml0Lg0KDQojIyBDaGVja2luZyB0aGUgQ29uZGl0aW9ucyBmb3IgSW5mZXJlbmNlIChUaGUgIkxJTkUiIENvbmRpdGlvbnMpDQoNClJlbGlhYmxlIGluZmVyZW5jZSAoUC12YWx1ZXMgYW5kIENJcykgcmVsaWVzIG9uIGZvdXIga2V5IGFzc3VtcHRpb25zIGFib3V0IHRoZSBtb2RlbCBlcnJvcnMgKCRcZXBzaWxvbiQpOg0KDQoxLiAgKipMaW5lYXJpdHk6KiogVGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuICRZJCBhbmQgdGhlICRYJCdzIGlzIGxpbmVhci4NCjIuICAqKkluZGVwZW5kZW5jZToqKiBUaGUgZXJyb3JzIGFyZSBpbmRlcGVuZGVudCBvZiBlYWNoIG90aGVyLiAoVXN1YWxseSBjaGVja2VkIGJ5IGNvbnRleHQsIGUuZy4sIGhvdXNlcyBhcmUgaW5kZXBlbmRlbnQgb2JzZXJ2YXRpb25zKS4NCjMuICAqKk5vcm1hbGl0eToqKiBUaGUgZXJyb3JzIGFyZSBOb3JtYWxseSBkaXN0cmlidXRlZC4NCjQuICAqKkVxdWFsIFZhcmlhbmNlIChIb21vc2NlZGFzdGljaXR5KToqKiBUaGUgZXJyb3JzIGhhdmUgY29uc3RhbnQgdmFyaWFuY2UgYWNyb3NzIGFsbCBsZXZlbHMgb2YgdGhlIHByZWRpY3RvcnMuDQoNClRoZXNlIGFyZSBwcmltYXJpbHkgY2hlY2tlZCBieSBleGFtaW5pbmcgdGhlICoqUmVzaWR1YWxzKiogKHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIG9ic2VydmVkICRZJCBhbmQgdGhlIHByZWRpY3RlZCAkXGhhdHtZfSQpLg0KDQpgYGB7cn0NCiMgMSAmIDQuIExpbmVhcml0eSBhbmQgRXF1YWwgVmFyaWFuY2UgKEhvbW9zY2VkYXN0aWNpdHkpDQojIFBsb3Qgb2YgUmVzaWR1YWxzIHZzLiBGaXR0ZWQgVmFsdWVzDQpwbG90KG1vZGVsX2NhdCwgd2hpY2ggPSAxKQ0KYGBgDQoNCiAgKiAqKklkZWFsIFBsb3Q6KiogQSByYW5kb20gc2NhdHRlciBvZiBwb2ludHMgYXJvdW5kIHRoZSBob3Jpem9udGFsIGxpbmUgYXQgJDAkLg0KICANCiAgKiAqKldoYXQgdG8gbG9vayBmb3I6KiogQSBmYW4gc2hhcGUgKGhldGVyb3NjZWRhc3RpY2l0eSkgb3IgYSBjdXJ2ZWQgcGF0dGVybiAobm9uLWxpbmVhcml0eSkuIFRoZSBob3VzaW5nIGRhdGEgb2Z0ZW4gc2hvd3MgYSAqKmZhbiBzaGFwZSoqLCBpbmRpY2F0aW5nICoqaGV0ZXJvc2NlZGFzdGljaXR5KiouIFRoaXMgaXMgYSBjb21tb24gaXNzdWUgd2l0aCBwcmljZSBkYXRhLCBvZnRlbiBmaXhlZCBieSAqKmxvZy10cmFuc2Zvcm1pbmcqKiB0aGUgcmVzcG9uc2UgdmFyaWFibGU6IGBsbShsb2coU2FsZV9QcmljZSkgfiAuLi4pYA0KDQoNCmBgYHtyfQ0KIyAzLiBOb3JtYWxpdHkgb2YgUmVzaWR1YWxzDQojIFEtUSBQbG90DQpwbG90KG1vZGVsX2NhdCwgd2hpY2ggPSAyKQ0KYGBgDQoNCiAgKiAqKklkZWFsIFBsb3Q6KiogUG9pbnRzIGxpZSBjbG9zZWx5IGFsb25nIHRoZSBkaWFnb25hbCBzdHJhaWdodCBsaW5lLg0KICANCiAgKiAqKldoYXQgdG8gbG9vayBmb3I6KiogU2lnbmlmaWNhbnQgZGV2aWF0aW9uIGZyb20gdGhlIGxpbmUsIGVzcGVjaWFsbHkgaW4gdGhlIHRhaWxzLCBpbmRpY2F0aW5nIG5vbi1Ob3JtYWxpdHkuDQoNCklmIGNvbmRpdGlvbnMgYXJlIHNldmVyZWx5IHZpb2xhdGVkLCB0cmFuc2Zvcm1hdGlvbnMgKGxpa2UgbG9nKSBvciBtb3JlIGFkdmFuY2VkIG1ldGhvZHMgKGUuZy4sIFJvYnVzdCBSZWdyZXNzaW9uLCBHZW5lcmFsaXplZCBMZWFzdCBTcXVhcmVzKSBhcmUgcmVxdWlyZWQu