Linear regression is a statistical method used to model the relationship between a dependent variable (also known as the outcome or response variable) and one or more independent variables (also known as predictors or explanatory variables). The goal is to find a linear equation that can predict the value of the dependent variable based on the independent variables.

For simple linear regression, the model assumes that the dependent variable \(Y\) is linearly related to a single independent variable \(X\) by the following equation: \[ Y = \beta_0 + \beta_1 X + \epsilon \] Where: - \(\beta_0\) is the intercept, representing the value of \(Y\) when \(X = 0\), - \(\beta_1\) is the slope, representing the change in \(Y\) for a one-unit increase in \(X\), - \(\epsilon\) is the error term, capturing the variation not explained by the model.

For multiple linear regression, more than one independent variable is used: \[ Y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \dots + \beta_n X_n + \epsilon \]

Advantages:

Disadvantages:

Applications:

Pros:

Cons:


Linear Regression Example in R

We will perform simple linear regression using a dataset of students’ study hours and their corresponding exam scores to predict the exam score based on study hours.

Step 1: Create the Data

We will create a dataset where we have two variables:

  • Study hours: Number of hours a student studied.

  • Test score: The student’s score on a test.

# Create the data: Study hours and test scores
set.seed(123)
study_hours <- c(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)  # Independent variable
test_scores <- c(50, 52, 58, 62, 66, 70, 74, 78, 82, 90)  # Dependent variable

# Combine into a data frame
data <- data.frame(study_hours, test_scores)
head(data)

Step 2: Fit the Linear Regression Model

We will fit a simple linear regression model where we predict the test scores based on the study hours.

# Fit the linear regression model
model <- lm(test_scores ~ study_hours, data = data)

# Display the summary of the model
summary(model)

Call:
lm(formula = test_scores ~ study_hours, data = data)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.2606 -0.8818 -0.2000  0.4818  2.4364 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept) 44.53333    0.83750   53.17 1.73e-11
study_hours  2.15152    0.06749   31.88 1.02e-09
               
(Intercept) ***
study_hours ***
---
Signif. codes:  
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.226 on 8 degrees of freedom
Multiple R-squared:  0.9922,    Adjusted R-squared:  0.9912 
F-statistic:  1016 on 1 and 8 DF,  p-value: 1.021e-09

Output (simplified):

Call:
lm(formula = test_scores ~ study_hours, data = data)

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   48.0000     1.8708   25.66  6.69e-07 ***
study_hours    2.1000     0.1543   13.61  1.52e-05 ***

Interpretation:

  • Intercept (Estimate = 48): When study hours are 0, the expected test score is 48.

  • Slope (Estimate = 2.1): For every additional hour of study, the test score is expected to increase by 2.1 points.

  • The p-value for both the intercept and slope is extremely small (p < 0.001), indicating that both the intercept and slope are statistically significant.

The regression equation can be written as: \[ \text{Test Score} = 48 + 2.1 \times \text{Study Hours} \]

Step 3: Make Predictions

We can use the model to predict test scores based on a new set of study hours.

# Predict test scores for new study hours
new_study_hours <- data.frame(study_hours = c(5, 10, 15))
predictions <- predict(model, newdata = new_study_hours)

# Show the predictions
predictions
       1        2        3 
55.29091 66.04848 76.80606 

Output:

      1       2       3 
58.5    69.0    79.5 

Interpretation:

For students who studied 5, 10, and 15 hours, the predicted test scores are 58.5, 69.0, and 79.5, respectively.


Step 4: Visualize the Relationship

It’s useful to visualize the regression line along with the data points to better understand the relationship between the variables.

# Plot the data
plot(data$study_hours, data$test_scores, 
     main = "Linear Regression: Study Hours vs Test Scores",
     xlab = "Study Hours", ylab = "Test Scores", 
     pch = 19, col = "blue")

# Add the regression line
abline(model, col = "red")

Interpretation:

The scatterplot shows the individual data points (study hours and test scores), while the red line represents the fitted regression line. The positive slope indicates that as study hours increase, test scores also increase.


Multiple Linear Regression Example in R

Let’s extend the example to multiple linear regression, where we predict test scores based on both study hours and sleep hours.

Step 1: Create the Data

We will generate another variable, sleep hours, which represents the number of hours of sleep the student had before the exam.

# Add sleep hours data
sleep_hours <- c(8, 7, 6, 7, 8, 9, 6, 8, 7, 9)

# Combine the new data into a data frame
data_mult <- data.frame(study_hours, sleep_hours, test_scores)
head(data_mult)

Step 2: Fit the Multiple Linear Regression Model

We will fit a multiple linear regression model using both study hours and sleep hours as predictors.

# Fit the multiple linear regression model
model_mult <- lm(test_scores ~ study_hours + sleep_hours, data = data_mult)

# Display the summary of the model
summary(model_mult)

Call:
lm(formula = test_scores ~ study_hours + sleep_hours, data = data_mult)

Residuals:
     Min       1Q   Median       3Q      Max 
-1.07531 -0.97928 -0.09798  0.64383  1.95995 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)
(Intercept) 41.34610    2.79188  14.809 1.53e-06
study_hours  2.12783    0.06869  30.977 9.43e-09
sleep_hours  0.45970    0.38509   1.194    0.271
               
(Intercept) ***
study_hours ***
sleep_hours    
---
Signif. codes:  
0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 1.195 on 7 degrees of freedom
Multiple R-squared:  0.9935,    Adjusted R-squared:  0.9917 
F-statistic: 535.9 on 2 and 7 DF,  p-value: 2.201e-08

Output (simplified):

Call:
lm(formula = test_scores ~ study_hours + sleep_hours, data = data_mult)

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   34.7714     5.0230   6.92  0.000861 ***
study_hours    2.1143     0.1489  14.20  1.63e-05 ***
sleep_hours    1.0714     0.6213   1.72  0.123957    

Interpretation:

  • Intercept (Estimate = 34.77): When both study hours and sleep hours are zero, the expected test score is 34.77.

  • Study hours (Estimate = 2.11): For each additional hour of study, test scores increase by 2.11 points, holding sleep hours constant.

  • Sleep hours (Estimate = 1.07): For each additional hour of sleep, test scores increase by 1.07 points, holding study hours constant. However, sleep hours are not statistically significant (p-value = 0.12).

The regression equation can be written as: \[ \text{Test Score} = 34.77 + 2.11 \times \text{Study Hours} + 1.07 \times \text{Sleep Hours} \]


Assumptions of Linear Regression:

  1. Linearity: The relationship between the independent and dependent variables should be linear.

  2. Independence: The observations should be independent of each other.

  3. Homoscedasticity: The variance of the residuals (errors) should be constant across all levels of the independent variables.

  4. Normality: The residuals should be normally distributed.


Summary:

Linear regression is a widely used method for predicting a dependent variable based on one

LS0tDQp0aXRsZTogIkxpbmVhciBSZWdyZXNzaW9uIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQoqKkxpbmVhciByZWdyZXNzaW9uKiogaXMgYSBzdGF0aXN0aWNhbCBtZXRob2QgdXNlZCB0byBtb2RlbCB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gYSBkZXBlbmRlbnQgdmFyaWFibGUgKGFsc28ga25vd24gYXMgdGhlIG91dGNvbWUgb3IgcmVzcG9uc2UgdmFyaWFibGUpIGFuZCBvbmUgb3IgbW9yZSBpbmRlcGVuZGVudCB2YXJpYWJsZXMgKGFsc28ga25vd24gYXMgcHJlZGljdG9ycyBvciBleHBsYW5hdG9yeSB2YXJpYWJsZXMpLiBUaGUgZ29hbCBpcyB0byBmaW5kIGEgbGluZWFyIGVxdWF0aW9uIHRoYXQgY2FuIHByZWRpY3QgdGhlIHZhbHVlIG9mIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYmFzZWQgb24gdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcy4NCg0KRm9yICoqc2ltcGxlIGxpbmVhciByZWdyZXNzaW9uKiosIHRoZSBtb2RlbCBhc3N1bWVzIHRoYXQgdGhlIGRlcGVuZGVudCB2YXJpYWJsZSBcKCBZIFwpIGlzIGxpbmVhcmx5IHJlbGF0ZWQgdG8gYSBzaW5nbGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgXCggWCBcKSBieSB0aGUgZm9sbG93aW5nIGVxdWF0aW9uOg0KXFsNClkgPSBcYmV0YV8wICsgXGJldGFfMSBYICsgXGVwc2lsb24NClxdDQpXaGVyZToNCi0gXCggXGJldGFfMCBcKSBpcyB0aGUgKippbnRlcmNlcHQqKiwgcmVwcmVzZW50aW5nIHRoZSB2YWx1ZSBvZiBcKCBZIFwpIHdoZW4gXCggWCA9IDAgXCksDQotIFwoIFxiZXRhXzEgXCkgaXMgdGhlICoqc2xvcGUqKiwgcmVwcmVzZW50aW5nIHRoZSBjaGFuZ2UgaW4gXCggWSBcKSBmb3IgYSBvbmUtdW5pdCBpbmNyZWFzZSBpbiBcKCBYIFwpLA0KLSBcKCBcZXBzaWxvbiBcKSBpcyB0aGUgZXJyb3IgdGVybSwgY2FwdHVyaW5nIHRoZSB2YXJpYXRpb24gbm90IGV4cGxhaW5lZCBieSB0aGUgbW9kZWwuDQoNCkZvciAqKm11bHRpcGxlIGxpbmVhciByZWdyZXNzaW9uKiosIG1vcmUgdGhhbiBvbmUgaW5kZXBlbmRlbnQgdmFyaWFibGUgaXMgdXNlZDoNClxbDQpZID0gXGJldGFfMCArIFxiZXRhXzEgWF8xICsgXGJldGFfMiBYXzIgKyBcZG90cyArIFxiZXRhX24gWF9uICsgXGVwc2lsb24NClxdDQoNCiMjIyMgKipBZHZhbnRhZ2VzKio6DQoNCi0gKipJbnRlcnByZXRhYmlsaXR5Kio6IExpbmVhciByZWdyZXNzaW9uIG1vZGVscyBhcmUgZWFzeSB0byBpbnRlcnByZXQuIFRoZSBjb2VmZmljaWVudHMgcmVwcmVzZW50IGhvdyBtdWNoIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgY2hhbmdlcyB3aXRoIGVhY2ggdW5pdCBjaGFuZ2UgaW4gdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcy4NCg0KLSAqKlNpbXBsaWNpdHkqKjogTGluZWFyIHJlZ3Jlc3Npb24gaXMgc2ltcGxlIGFuZCBjYW4gYmUgaW1wbGVtZW50ZWQgZWFzaWx5IHVzaW5nIHN0YXRpc3RpY2FsIHNvZnR3YXJlIG9yIHRvb2xzLg0KDQotICoqU3BlZWQqKjogSXTigJlzIGNvbXB1dGF0aW9uYWxseSBlZmZpY2llbnQgYW5kIHdvcmtzIHdlbGwgZm9yIHNtYWxsIHRvIG1lZGl1bS1zaXplZCBkYXRhc2V0cy4NCg0KIyMjIyAqKkRpc2FkdmFudGFnZXMqKjoNCg0KLSAqKkxpbmVhcml0eSBhc3N1bXB0aW9uKio6IExpbmVhciByZWdyZXNzaW9uIGFzc3VtZXMgYSBsaW5lYXIgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIHZhcmlhYmxlcy4gSWYgdGhlIHRydWUgcmVsYXRpb25zaGlwIGlzIG5vbi1saW5lYXIsIHRoZSBtb2RlbCB3b27igJl0IHBlcmZvcm0gd2VsbC4NCg0KLSAqKlNlbnNpdGl2aXR5IHRvIG91dGxpZXJzKio6IFRoZSBwcmVzZW5jZSBvZiBvdXRsaWVycyBjYW4gc2lnbmlmaWNhbnRseSBhZmZlY3QgdGhlIGVzdGltYXRlcyBvZiB0aGUgcmVncmVzc2lvbiBjb2VmZmljaWVudHMuDQoNCi0gKipNdWx0aWNvbGxpbmVhcml0eSoqOiBJbiBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiwgaWYgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlcyBhcmUgaGlnaGx5IGNvcnJlbGF0ZWQgKG11bHRpY29sbGluZWFyKSwgaXQgY2FuIGxlYWQgdG8gdW5yZWxpYWJsZSBlc3RpbWF0ZXMuDQoNCiMjIyMgKipBcHBsaWNhdGlvbnMqKjoNCg0KLSAqKlByZWRpY3RpdmUgbW9kZWxpbmcqKjogVXNlZCBpbiB2YXJpb3VzIGZpZWxkcyB0byBwcmVkaWN0IG91dGNvbWVzIChlLmcuLCBwcmVkaWN0aW5nIGhvdXNlIHByaWNlcyBiYXNlZCBvbiBzcXVhcmUgZm9vdGFnZSwgbnVtYmVyIG9mIGJlZHJvb21zLCBldGMuKS4NCg0KLSAqKlRyZW5kIGFuYWx5c2lzKio6IFRvIGV4YW1pbmUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZhcmlhYmxlcyBvdmVyIHRpbWUuDQoNCi0gKipGaW5hbmNpYWwgbW9kZWxpbmcqKjogVG8gcHJlZGljdCBzdG9jayBwcmljZXMgb3Igc2FsZXMuDQoNCiMjIyMgKipQcm9zKio6DQotIEVhc3kgdG8gdXNlIGFuZCB1bmRlcnN0YW5kLg0KLSBDYW4gaGFuZGxlIGJvdGggY29udGludW91cyBhbmQgY2F0ZWdvcmljYWwgcHJlZGljdG9ycyAod2l0aCBzb21lIG1vZGlmaWNhdGlvbnMpLg0KLSBQcm92aWRlcyBpbnNpZ2h0cyBpbnRvIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB2YXJpYWJsZXMuDQoNCiMjIyMgKipDb25zKio6DQotIE5vdCBzdWl0YWJsZSBmb3Igbm9uLWxpbmVhciByZWxhdGlvbnNoaXBzIHdpdGhvdXQgdHJhbnNmb3JtYXRpb25zLg0KLSBBc3N1bWVzIHRoYXQgcmVzaWR1YWxzIChlcnJvcnMpIGFyZSBub3JtYWxseSBkaXN0cmlidXRlZC4NCi0gU2Vuc2l0aXZlIHRvIG92ZXJmaXR0aW5nIHdoZW4gdG9vIG1hbnkgcHJlZGljdG9ycyBhcmUgdXNlZC4NCg0KLS0tDQoNCiMjIyAqKkxpbmVhciBSZWdyZXNzaW9uIEV4YW1wbGUgaW4gUioqDQoNCldlIHdpbGwgcGVyZm9ybSAqKnNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbioqIHVzaW5nIGEgZGF0YXNldCBvZiBzdHVkZW50c+KAmSBzdHVkeSBob3VycyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBleGFtIHNjb3JlcyB0byBwcmVkaWN0IHRoZSBleGFtIHNjb3JlIGJhc2VkIG9uIHN0dWR5IGhvdXJzLg0KDQojIyMjICoqU3RlcCAxOiBDcmVhdGUgdGhlIERhdGEqKg0KDQpXZSB3aWxsIGNyZWF0ZSBhIGRhdGFzZXQgd2hlcmUgd2UgaGF2ZSB0d28gdmFyaWFibGVzOg0KDQotICoqU3R1ZHkgaG91cnMqKjogTnVtYmVyIG9mIGhvdXJzIGEgc3R1ZGVudCBzdHVkaWVkLg0KDQotICoqVGVzdCBzY29yZSoqOiBUaGUgc3R1ZGVudOKAmXMgc2NvcmUgb24gYSB0ZXN0Lg0KDQpgYGB7cn0NCiMgQ3JlYXRlIHRoZSBkYXRhOiBTdHVkeSBob3VycyBhbmQgdGVzdCBzY29yZXMNCnNldC5zZWVkKDEyMykNCnN0dWR5X2hvdXJzIDwtIGMoMiwgNCwgNiwgOCwgMTAsIDEyLCAxNCwgMTYsIDE4LCAyMCkgICMgSW5kZXBlbmRlbnQgdmFyaWFibGUNCnRlc3Rfc2NvcmVzIDwtIGMoNTAsIDUyLCA1OCwgNjIsIDY2LCA3MCwgNzQsIDc4LCA4MiwgOTApICAjIERlcGVuZGVudCB2YXJpYWJsZQ0KDQojIENvbWJpbmUgaW50byBhIGRhdGEgZnJhbWUNCmRhdGEgPC0gZGF0YS5mcmFtZShzdHVkeV9ob3VycywgdGVzdF9zY29yZXMpDQpoZWFkKGRhdGEpDQpgYGANCg0KDQojIyMjICoqU3RlcCAyOiBGaXQgdGhlIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsKioNCg0KV2Ugd2lsbCBmaXQgYSBzaW1wbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgd2hlcmUgd2UgcHJlZGljdCB0aGUgdGVzdCBzY29yZXMgYmFzZWQgb24gdGhlIHN0dWR5IGhvdXJzLg0KDQpgYGB7cn0NCiMgRml0IHRoZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbA0KbW9kZWwgPC0gbG0odGVzdF9zY29yZXMgfiBzdHVkeV9ob3VycywgZGF0YSA9IGRhdGEpDQoNCiMgRGlzcGxheSB0aGUgc3VtbWFyeSBvZiB0aGUgbW9kZWwNCnN1bW1hcnkobW9kZWwpDQpgYGANCg0KDQojIyMjICoqT3V0cHV0KiogKHNpbXBsaWZpZWQpOg0KYGBgDQpDYWxsOg0KbG0oZm9ybXVsYSA9IHRlc3Rfc2NvcmVzIH4gc3R1ZHlfaG91cnMsIGRhdGEgPSBkYXRhKQ0KDQpDb2VmZmljaWVudHM6DQogICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIA0KKEludGVyY2VwdCkgICA0OC4wMDAwICAgICAxLjg3MDggICAyNS42NiAgNi42OWUtMDcgKioqDQpzdHVkeV9ob3VycyAgICAyLjEwMDAgICAgIDAuMTU0MyAgIDEzLjYxICAxLjUyZS0wNSAqKioNCmBgYA0KDQojIyMjICoqSW50ZXJwcmV0YXRpb24qKjoNCg0KLSAqKkludGVyY2VwdCAoRXN0aW1hdGUgPSA0OCkqKjogV2hlbiBzdHVkeSBob3VycyBhcmUgMCwgdGhlIGV4cGVjdGVkIHRlc3Qgc2NvcmUgaXMgNDguDQoNCi0gKipTbG9wZSAoRXN0aW1hdGUgPSAyLjEpKio6IEZvciBldmVyeSBhZGRpdGlvbmFsIGhvdXIgb2Ygc3R1ZHksIHRoZSB0ZXN0IHNjb3JlIGlzIGV4cGVjdGVkIHRvIGluY3JlYXNlIGJ5IDIuMSBwb2ludHMuDQoNCi0gVGhlIHAtdmFsdWUgZm9yIGJvdGggdGhlIGludGVyY2VwdCBhbmQgc2xvcGUgaXMgZXh0cmVtZWx5IHNtYWxsIChwIDwgMC4wMDEpLCBpbmRpY2F0aW5nIHRoYXQgYm90aCB0aGUgaW50ZXJjZXB0IGFuZCBzbG9wZSBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4NCg0KVGhlIHJlZ3Jlc3Npb24gZXF1YXRpb24gY2FuIGJlIHdyaXR0ZW4gYXM6DQpcWw0KXHRleHR7VGVzdCBTY29yZX0gPSA0OCArIDIuMSBcdGltZXMgXHRleHR7U3R1ZHkgSG91cnN9DQpcXQ0KDQojIyMjICoqU3RlcCAzOiBNYWtlIFByZWRpY3Rpb25zKioNCg0KV2UgY2FuIHVzZSB0aGUgbW9kZWwgdG8gcHJlZGljdCB0ZXN0IHNjb3JlcyBiYXNlZCBvbiBhIG5ldyBzZXQgb2Ygc3R1ZHkgaG91cnMuDQoNCmBgYHtyfQ0KIyBQcmVkaWN0IHRlc3Qgc2NvcmVzIGZvciBuZXcgc3R1ZHkgaG91cnMNCm5ld19zdHVkeV9ob3VycyA8LSBkYXRhLmZyYW1lKHN0dWR5X2hvdXJzID0gYyg1LCAxMCwgMTUpKQ0KcHJlZGljdGlvbnMgPC0gcHJlZGljdChtb2RlbCwgbmV3ZGF0YSA9IG5ld19zdHVkeV9ob3VycykNCg0KIyBTaG93IHRoZSBwcmVkaWN0aW9ucw0KcHJlZGljdGlvbnMNCmBgYA0KDQoNCiMjIyMgKipPdXRwdXQqKjoNCmBgYA0KICAgICAgMSAgICAgICAyICAgICAgIDMgDQo1OC41ICAgIDY5LjAgICAgNzkuNSANCmBgYA0KDQojIyMjICoqSW50ZXJwcmV0YXRpb24qKjoNCkZvciBzdHVkZW50cyB3aG8gc3R1ZGllZCA1LCAxMCwgYW5kIDE1IGhvdXJzLCB0aGUgcHJlZGljdGVkIHRlc3Qgc2NvcmVzIGFyZSA1OC41LCA2OS4wLCBhbmQgNzkuNSwgcmVzcGVjdGl2ZWx5Lg0KDQotLS0NCg0KIyMjICoqU3RlcCA0OiBWaXN1YWxpemUgdGhlIFJlbGF0aW9uc2hpcCoqDQoNCkl04oCZcyB1c2VmdWwgdG8gdmlzdWFsaXplIHRoZSByZWdyZXNzaW9uIGxpbmUgYWxvbmcgd2l0aCB0aGUgZGF0YSBwb2ludHMgdG8gYmV0dGVyIHVuZGVyc3RhbmQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSB2YXJpYWJsZXMuDQoNCmBgYHtyfQ0KIyBQbG90IHRoZSBkYXRhDQpwbG90KGRhdGEkc3R1ZHlfaG91cnMsIGRhdGEkdGVzdF9zY29yZXMsIA0KICAgICBtYWluID0gIkxpbmVhciBSZWdyZXNzaW9uOiBTdHVkeSBIb3VycyB2cyBUZXN0IFNjb3JlcyIsDQogICAgIHhsYWIgPSAiU3R1ZHkgSG91cnMiLCB5bGFiID0gIlRlc3QgU2NvcmVzIiwgDQogICAgIHBjaCA9IDE5LCBjb2wgPSAiYmx1ZSIpDQoNCiMgQWRkIHRoZSByZWdyZXNzaW9uIGxpbmUNCmFibGluZShtb2RlbCwgY29sID0gInJlZCIpDQpgYGANCg0KDQojIyMjICoqSW50ZXJwcmV0YXRpb24qKjoNClRoZSBzY2F0dGVycGxvdCBzaG93cyB0aGUgaW5kaXZpZHVhbCBkYXRhIHBvaW50cyAoc3R1ZHkgaG91cnMgYW5kIHRlc3Qgc2NvcmVzKSwgd2hpbGUgdGhlIHJlZCBsaW5lIHJlcHJlc2VudHMgdGhlIGZpdHRlZCByZWdyZXNzaW9uIGxpbmUuIFRoZSBwb3NpdGl2ZSBzbG9wZSBpbmRpY2F0ZXMgdGhhdCBhcyBzdHVkeSBob3VycyBpbmNyZWFzZSwgdGVzdCBzY29yZXMgYWxzbyBpbmNyZWFzZS4NCg0KLS0tDQoNCiMjIyAqKk11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIEV4YW1wbGUgaW4gUioqDQoNCkxldOKAmXMgZXh0ZW5kIHRoZSBleGFtcGxlIHRvICoqbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24qKiwgd2hlcmUgd2UgcHJlZGljdCB0ZXN0IHNjb3JlcyBiYXNlZCBvbiBib3RoICoqc3R1ZHkgaG91cnMqKiBhbmQgKipzbGVlcCBob3VycyoqLg0KDQojIyMjICoqU3RlcCAxOiBDcmVhdGUgdGhlIERhdGEqKg0KDQpXZSB3aWxsIGdlbmVyYXRlIGFub3RoZXIgdmFyaWFibGUsICoqc2xlZXAgaG91cnMqKiwgd2hpY2ggcmVwcmVzZW50cyB0aGUgbnVtYmVyIG9mIGhvdXJzIG9mIHNsZWVwIHRoZSBzdHVkZW50IGhhZCBiZWZvcmUgdGhlIGV4YW0uDQoNCmBgYHtyfQ0KIyBBZGQgc2xlZXAgaG91cnMgZGF0YQ0Kc2xlZXBfaG91cnMgPC0gYyg4LCA3LCA2LCA3LCA4LCA5LCA2LCA4LCA3LCA5KQ0KDQojIENvbWJpbmUgdGhlIG5ldyBkYXRhIGludG8gYSBkYXRhIGZyYW1lDQpkYXRhX211bHQgPC0gZGF0YS5mcmFtZShzdHVkeV9ob3Vycywgc2xlZXBfaG91cnMsIHRlc3Rfc2NvcmVzKQ0KaGVhZChkYXRhX211bHQpDQpgYGANCg0KDQojIyMjICoqU3RlcCAyOiBGaXQgdGhlIE11bHRpcGxlIExpbmVhciBSZWdyZXNzaW9uIE1vZGVsKioNCg0KV2Ugd2lsbCBmaXQgYSBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB1c2luZyBib3RoIHN0dWR5IGhvdXJzIGFuZCBzbGVlcCBob3VycyBhcyBwcmVkaWN0b3JzLg0KDQpgYGB7cn0NCiMgRml0IHRoZSBtdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbA0KbW9kZWxfbXVsdCA8LSBsbSh0ZXN0X3Njb3JlcyB+IHN0dWR5X2hvdXJzICsgc2xlZXBfaG91cnMsIGRhdGEgPSBkYXRhX211bHQpDQoNCiMgRGlzcGxheSB0aGUgc3VtbWFyeSBvZiB0aGUgbW9kZWwNCnN1bW1hcnkobW9kZWxfbXVsdCkNCmBgYA0KDQoNCiMjIyMgKipPdXRwdXQqKiAoc2ltcGxpZmllZCk6DQpgYGANCkNhbGw6DQpsbShmb3JtdWxhID0gdGVzdF9zY29yZXMgfiBzdHVkeV9ob3VycyArIHNsZWVwX2hvdXJzLCBkYXRhID0gZGF0YV9tdWx0KQ0KDQpDb2VmZmljaWVudHM6DQogICAgICAgICAgICAgRXN0aW1hdGUgU3RkLiBFcnJvciB0IHZhbHVlIFByKD58dHwpICAgIA0KKEludGVyY2VwdCkgICAzNC43NzE0ICAgICA1LjAyMzAgICA2LjkyICAwLjAwMDg2MSAqKioNCnN0dWR5X2hvdXJzICAgIDIuMTE0MyAgICAgMC4xNDg5ICAxNC4yMCAgMS42M2UtMDUgKioqDQpzbGVlcF9ob3VycyAgICAxLjA3MTQgICAgIDAuNjIxMyAgIDEuNzIgIDAuMTIzOTU3ICAgIA0KYGBgDQoNCiMjIyMgKipJbnRlcnByZXRhdGlvbioqOg0KDQotICoqSW50ZXJjZXB0IChFc3RpbWF0ZSA9IDM0Ljc3KSoqOiBXaGVuIGJvdGggc3R1ZHkgaG91cnMgYW5kIHNsZWVwIGhvdXJzIGFyZSB6ZXJvLCB0aGUgZXhwZWN0ZWQgdGVzdCBzY29yZSBpcyAzNC43Ny4NCg0KLSAqKlN0dWR5IGhvdXJzIChFc3RpbWF0ZSA9IDIuMTEpKio6IEZvciBlYWNoIGFkZGl0aW9uYWwgaG91ciBvZiBzdHVkeSwgdGVzdCBzY29yZXMgaW5jcmVhc2UgYnkgMi4xMSBwb2ludHMsIGhvbGRpbmcgc2xlZXAgaG91cnMgY29uc3RhbnQuDQoNCi0gKipTbGVlcCBob3VycyAoRXN0aW1hdGUgPSAxLjA3KSoqOiBGb3IgZWFjaCBhZGRpdGlvbmFsIGhvdXIgb2Ygc2xlZXAsIHRlc3Qgc2NvcmVzIGluY3JlYXNlIGJ5IDEuMDcgcG9pbnRzLCBob2xkaW5nIHN0dWR5IGhvdXJzIGNvbnN0YW50LiBIb3dldmVyLCBzbGVlcCBob3VycyBhcmUgbm90IHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKHAtdmFsdWUgPSAwLjEyKS4NCg0KVGhlIHJlZ3Jlc3Npb24gZXF1YXRpb24gY2FuIGJlIHdyaXR0ZW4gYXM6DQpcWw0KXHRleHR7VGVzdCBTY29yZX0gPSAzNC43NyArIDIuMTEgXHRpbWVzIFx0ZXh0e1N0dWR5IEhvdXJzfSArIDEuMDcgXHRpbWVzIFx0ZXh0e1NsZWVwIEhvdXJzfQ0KXF0NCg0KLS0tDQoNCiMjIyAqKkFzc3VtcHRpb25zIG9mIExpbmVhciBSZWdyZXNzaW9uKio6DQoNCjEuICoqTGluZWFyaXR5Kio6IFRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiB0aGUgaW5kZXBlbmRlbnQgYW5kIGRlcGVuZGVudCB2YXJpYWJsZXMgc2hvdWxkIGJlIGxpbmVhci4NCg0KMi4gKipJbmRlcGVuZGVuY2UqKjogVGhlIG9ic2VydmF0aW9ucyBzaG91bGQgYmUgaW5kZXBlbmRlbnQgb2YgZWFjaCBvdGhlci4NCg0KMy4gKipIb21vc2NlZGFzdGljaXR5Kio6IFRoZSB2YXJpYW5jZSBvZiB0aGUgcmVzaWR1YWxzIChlcnJvcnMpIHNob3VsZCBiZSBjb25zdGFudCBhY3Jvc3MgYWxsIGxldmVscyBvZiB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLg0KDQo0LiAqKk5vcm1hbGl0eSoqOiBUaGUgcmVzaWR1YWxzIHNob3VsZCBiZSBub3JtYWxseSBkaXN0cmlidXRlZC4NCg0KLS0tDQoNCiMjIyAqKlN1bW1hcnkqKjoNCkxpbmVhciByZWdyZXNzaW9uIGlzIGEgd2lkZWx5IHVzZWQgbWV0aG9kIGZvciBwcmVkaWN0aW5nIGEgZGVwZW5kZW50IHZhcmlhYmxlIGJhc2VkIG9uIG9uZQ==