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:
| \(\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\).
Test Statistic: The \(t\)-statistic is calculated as \(t = \frac{\hat{\beta}_j -
0}{\text{SE}(\hat{\beta}_j)}\).
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\)):
- Linearity: The relationship between \(Y\) and the \(X\)’s is linear.
- Independence: The errors are independent of each
other. (Usually checked by context, e.g., houses are independent
observations).
- Normality: The errors are Normally
distributed.
- 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