1 Correlations with 2 or more variables

  • Correlations with more than 2 variables present a new challenge
  • What if a third variable (X2) actually explains the relationship between X1 and Y?
  • We need to find a way to figure out how X2 might relate to X1 and Y!

1.1 Ice cream example, part 2

  • Ice cream scopes (X1)
  • Brownies squares (X2)
  • Happiness score (Y)
  • Question, how much does ice cream and brownies predict/explain happiness scores
  • Lets rebuild our dataset with new variable.
#packages we will need to conduct to create and graph our data
library(MASS) #create data
library(car) #graph data
py1 =.6 #Cor between X1 (ice cream) and happiness
py2 =.4 #Cor between X2 (Brownies) and happiness
p12= .2 #Cor between X1 (ice cream) and X2 (Brownies)

Means.X1X2Y<- c(10,10,10) #set the means of X and Y variables
CovMatrix.X1X2Y <- matrix(c(1,p12,py1,
                            p12,1,py2,
                            py1,py2,1),3,3) # creates the covariate matrix 

CovMatrix.X1X2Y #nice and simple 2x2 matrix
##      [,1] [,2] [,3]
## [1,]  1.0  0.2  0.6
## [2,]  0.2  1.0  0.4
## [3,]  0.6  0.4  1.0
#build the correlated variables. Note: empirical=TRUE means make the correlation EXACTLY r. 
# if we say empirical=FALSE, the correlation would be normally distributed around r
set.seed(42)
CorrDataT<-mvrnorm(n=100, mu=Means.X1X2Y,Sigma=CovMatrix.X1X2Y, empirical=TRUE)

#Covert them to a "Data.Frame", which is like SPSS data window
CorrDataT<-as.data.frame(CorrDataT)

#lets add our labels to the vectors we created
colnames(CorrDataT) <- c("IceCream","Brownies","Happiness")

#Lets view the first few subjects
head(CorrDataT)
##    IceCream  Brownies Happiness
## 1 10.929755 11.094210 12.569467
## 2  8.840701  9.715172  9.878706
## 3  9.963873 10.388029  8.870038
## 4  7.692480 11.354929  9.252980
## 5 11.365400  9.962197 11.040250
## 6 10.541688  9.668536 10.923514
#make the scatter plot
scatterplot(Happiness~IceCream,CorrDataT, smoother=FALSE)

scatterplot(Happiness~Brownies,CorrDataT, smoother=FALSE)

scatterplot(Brownies~IceCream,CorrDataT, smoother=FALSE)

#
ry1<-cor(CorrDataT$Happiness,CorrDataT$IceCream)
ry2<-cor(CorrDataT$Happiness,CorrDataT$Brownies)
r12<-cor(CorrDataT$Brownies,CorrDataT$IceCream)
ry1
## [1] 0.6
ry2
## [1] 0.4
r12
## [1] 0.2

1.1.1 What the problem?

  • Ice Cream can explain happiness 0.36
  • Brownies can explain happiness, 0.16
  • But how we do know whether Ice Cream and Brownies are explaining the same variance?
  • At least brownies and Ice Cream do not explain each other to much,0.04
  • In other words, when people eat Brownies they font eat too many spoons of ice cream

1.1.2 Multiple R

  • We use the capital letter, \(R\),now cause we have multiple X variables
  • \(R_{Y.12} = \sqrt{\frac{r_{Y1}^2 + r_{Y2}^2 - 2r_{Y1} r_{Y2} r_{12}} {1 - r_{12}^2}}\)
  • \(R_{Y.12} =\) 0.6645801
  • if we square that value, 0.3916667, we get the Multiple \(R^2\)
  • or the total variance explained by these variables on happiness

2 Semipartial (part) correlation

  • We need to define to contribution of each X variable on Y
  • Semipartial (also called part) is one of two methods, the other is called partial
  • is called semi, cause it removes the effect of one IV relative to the other without removing the relationship to Y
  • Semipartial correlations indicate the “unique” contribution of an independent variable.
Ballantine for X1, X2, and Y

Ballantine for X1, X2, and Y

  • \(R_{Y.12}^2 = a + b + c\)
  • \(sr_1^2: a = R_{Y.12}^2 - r_{Y2}^2\)
  • \(sr_2^2:b = R_{Y.12}^2 - r_{Y1}^2\)

2.1 Calcuation

R2y.12<-sqrt((ry1^2+ry2^2 - (2*ry1*ry2*r12))/(1-r12^2))^2
R2y.12
## [1] 0.4416667
a = R2y.12 -ry2^2 
b = R2y.12 -ry1^2 

in other words,

  • In total we explained, 0.4416667 of the happiness ratings
  • ice cream uniquely explained, 0.2816667 of happiness ratings
  • brownies uniquely explained, 0.0816667 of happiness ratings
  • We should not solve for c cause it can be negative (in some cases)

2.1.1 Seeing control in action

Another way to understand it:

  • What if you want to know about happiness and how ice cream uniquely explains it? [controlling the effect of brownies on ice cream]
  • We can remove affect of brownies on ice cream by extracting the residuals lm(X1~X2)
  • Remember the residuals are the left over (after extracting what was explainable)
  • Next we can correlate happiness with the residualized ice cream.
#control for brownies
CorrDataT$Ice.control.Brownies<-residuals(lm(IceCream~Brownies, CorrDataT))
plot(CorrDataT$Happiness,CorrDataT$Ice.control.Brownies)

Sr1.alt<-cor(CorrDataT$Ice.control.Brownies,CorrDataT$Happiness)
Sr1.alt
## [1] 0.5307228

If we square the correlation value we got 0.2816667, it becomes 0.2816667 which matches our \(a\) from the analysis above.

-We can repeat this analysis but changing our control to find \(b\).

#control for ice cream
CorrDataT$Brownies.control.Ice<-residuals(lm(Brownies~IceCream, CorrDataT))
plot(CorrDataT$Brownies.control.Ice,CorrDataT$Happiness)

Sr2.alt<-cor(CorrDataT$Happiness,CorrDataT$Brownies.control.Ice)
Sr2.alt^2
## [1] 0.08166667

2.2 Semipartial notes:

  • note, it can be written as \(sr\) or more specifically, \(sr_1\) for X1 (with X2 removed) and \(sr_2\) (with X1 removed)
  • correlations with no control variables are called the zero-order correlations
  • in R you can calculate the \(sr\) rather quickly using the ppcor library
library(ppcor)
#last variable is the control variable!

Sr1<-spcor.test(CorrDataT$Happiness, CorrDataT$IceCream, CorrDataT$Brownies)
Sr1
##    estimate      p.value statistic   n gp  Method
## 1 0.5307228 1.598901e-08  6.167236 100  1 pearson
Sr2<-spcor.test(CorrDataT$Happiness, CorrDataT$Brownies, CorrDataT$IceCream)
Sr2
##    estimate     p.value statistic   n gp  Method
## 1 0.2857738 0.004139206  2.937028 100  1 pearson
# Note to convert them to R2 values, you just need to square the correlations
Sr1$estimate^2
## [1] 0.2816667
Sr2$estimate^2
## [1] 0.08166667
#notice they match our a and b values exactly. 

3 Partial correlation

  • Partial correlation asks how much of the Y variance, which is not estimated by the other IVs, is estimated by this variable.
  • It removes the shared variance of the control variable (Say x2) from both Y and X1.

  • \(pr_1^2: = \frac{a}{a+e} = \frac{R_{Y.12}^2 - r_{Y2}^2}{1-r_{Y2}^2}\)
  • \(pr_2^2: \frac{b}{b+e} = \frac{R_{Y.12}^2 - r_{Y1}^2}{1-r_{Y1}^2}\)

3.1 Seeing control in action

Another way to understand it:

  • What if you want to know about happiness and ice cream while controlling for brownies (cause brownies affect both happiness and ice cream)
  • We take residuals of lm(Y~X2) and correlate it with the residuals of lm(X1~X2)
  • Remember the residuals are the left over (after extracting what was explainable)
  • if you want to control for ice cream you would: residuals of lm(Y~X1) with the residuals of lm(X2~X1)
#control for brownies
CorrDataT$Happy.control.Brownies<-residuals(lm(Happiness~Brownies, CorrDataT))
CorrDataT$Ice.control.Brownies<-residuals(lm(IceCream~Brownies, CorrDataT))
plot(CorrDataT$Ice.control.Brownies,CorrDataT$Happy.control.Brownies)

cor(CorrDataT$Ice.control.Brownies,CorrDataT$Happy.control.Brownies)
## [1] 0.579066
#control for ice cream
CorrDataT$Happy.control.ice<-residuals(lm(Happiness~IceCream, CorrDataT))
CorrDataT$Brownies.control.ice<-residuals(lm(Brownies~IceCream, CorrDataT))

plot(CorrDataT$Brownies.control.ice,CorrDataT$Happy.control.ice)

cor(CorrDataT$Brownies.control.ice,CorrDataT$Happy.control.ice)
## [1] 0.3572173
  • in R you can calculate the \(pr\) directly via the functions
pr1<-pcor.test(CorrDataT$Happiness, CorrDataT$IceCream, CorrDataT$Brownies)
pr1
##   estimate      p.value statistic   n gp  Method
## 1 0.579066 3.413442e-10  6.995308 100  1 pearson
pr2<-pcor.test(CorrDataT$Happiness, CorrDataT$Brownies, CorrDataT$IceCream)
pr2
##    estimate      p.value statistic   n gp  Method
## 1 0.3572173 0.0002838052  3.766704 100  1 pearson
# Note to convert them to R2 values, you just need to square the correlations
pr1$estimate^2
## [1] 0.3353175
pr2$estimate^2
## [1] 0.1276042
LS0tDQp0aXRsZTogIlBhcnRpYWwgYW5kIFNlbWlwYXJ0aWFsIChwYXJ0KSBDb3JyZWxhdGlvbiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBmb250c2l6ZTogOHB0DQogICAgaGlnaGxpZ2h0OiB0ZXh0bWF0ZQ0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IGZsYXRseQ0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0Og0KICAgICAgY29sbGFwc2VkOiBubw0KLS0tDQoNCiMgQ29ycmVsYXRpb25zIHdpdGggMiBvciBtb3JlIHZhcmlhYmxlcw0KLSBDb3JyZWxhdGlvbnMgd2l0aCBtb3JlIHRoYW4gMiB2YXJpYWJsZXMgcHJlc2VudCBhIG5ldyBjaGFsbGVuZ2UgDQotIFdoYXQgaWYgYSB0aGlyZCB2YXJpYWJsZSAoWDIpIGFjdHVhbGx5IGV4cGxhaW5zIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBYMSBhbmQgWT8NCi0gV2UgbmVlZCB0byBmaW5kIGEgd2F5IHRvIGZpZ3VyZSBvdXQgaG93IFgyIG1pZ2h0IHJlbGF0ZSB0byBYMSBhbmQgWSEgDQoNCiMjIEljZSBjcmVhbSBleGFtcGxlLCBwYXJ0IDINCi0gSWNlIGNyZWFtIHNjb3BlcyAoWDEpDQotIEJyb3duaWVzIHNxdWFyZXMgKFgyKQ0KLSBIYXBwaW5lc3Mgc2NvcmUgKFkpDQotIFF1ZXN0aW9uLCBob3cgbXVjaCBkb2VzIGljZSBjcmVhbSBhbmQgYnJvd25pZXMgcHJlZGljdC9leHBsYWluIGhhcHBpbmVzcyBzY29yZXMNCi0gTGV0cyByZWJ1aWxkIG91ciBkYXRhc2V0IHdpdGggbmV3IHZhcmlhYmxlLiANCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCiNwYWNrYWdlcyB3ZSB3aWxsIG5lZWQgdG8gY29uZHVjdCB0byBjcmVhdGUgYW5kIGdyYXBoIG91ciBkYXRhDQpsaWJyYXJ5KE1BU1MpICNjcmVhdGUgZGF0YQ0KbGlicmFyeShjYXIpICNncmFwaCBkYXRhDQpgYGANCg0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KcHkxID0uNiAjQ29yIGJldHdlZW4gWDEgKGljZSBjcmVhbSkgYW5kIGhhcHBpbmVzcw0KcHkyID0uNCAjQ29yIGJldHdlZW4gWDIgKEJyb3duaWVzKSBhbmQgaGFwcGluZXNzDQpwMTI9IC4yICNDb3IgYmV0d2VlbiBYMSAoaWNlIGNyZWFtKSBhbmQgWDIgKEJyb3duaWVzKQ0KDQpNZWFucy5YMVgyWTwtIGMoMTAsMTAsMTApICNzZXQgdGhlIG1lYW5zIG9mIFggYW5kIFkgdmFyaWFibGVzDQpDb3ZNYXRyaXguWDFYMlkgPC0gbWF0cml4KGMoMSxwMTIscHkxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIHAxMiwxLHB5MiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBweTEscHkyLDEpLDMsMykgIyBjcmVhdGVzIHRoZSBjb3ZhcmlhdGUgbWF0cml4IA0KDQpDb3ZNYXRyaXguWDFYMlkgI25pY2UgYW5kIHNpbXBsZSAyeDIgbWF0cml4DQoNCiNidWlsZCB0aGUgY29ycmVsYXRlZCB2YXJpYWJsZXMuIE5vdGU6IGVtcGlyaWNhbD1UUlVFIG1lYW5zIG1ha2UgdGhlIGNvcnJlbGF0aW9uIEVYQUNUTFkgci4gDQojIGlmIHdlIHNheSBlbXBpcmljYWw9RkFMU0UsIHRoZSBjb3JyZWxhdGlvbiB3b3VsZCBiZSBub3JtYWxseSBkaXN0cmlidXRlZCBhcm91bmQgcg0Kc2V0LnNlZWQoNDIpDQpDb3JyRGF0YVQ8LW12cm5vcm0obj0xMDAsIG11PU1lYW5zLlgxWDJZLFNpZ21hPUNvdk1hdHJpeC5YMVgyWSwgZW1waXJpY2FsPVRSVUUpDQoNCiNDb3ZlcnQgdGhlbSB0byBhICJEYXRhLkZyYW1lIiwgd2hpY2ggaXMgbGlrZSBTUFNTIGRhdGEgd2luZG93DQpDb3JyRGF0YVQ8LWFzLmRhdGEuZnJhbWUoQ29yckRhdGFUKQ0KDQojbGV0cyBhZGQgb3VyIGxhYmVscyB0byB0aGUgdmVjdG9ycyB3ZSBjcmVhdGVkDQpjb2xuYW1lcyhDb3JyRGF0YVQpIDwtIGMoIkljZUNyZWFtIiwiQnJvd25pZXMiLCJIYXBwaW5lc3MiKQ0KDQojTGV0cyB2aWV3IHRoZSBmaXJzdCBmZXcgc3ViamVjdHMNCmhlYWQoQ29yckRhdGFUKQ0KDQojbWFrZSB0aGUgc2NhdHRlciBwbG90DQpzY2F0dGVycGxvdChIYXBwaW5lc3N+SWNlQ3JlYW0sQ29yckRhdGFULCBzbW9vdGhlcj1GQUxTRSkNCnNjYXR0ZXJwbG90KEhhcHBpbmVzc35Ccm93bmllcyxDb3JyRGF0YVQsIHNtb290aGVyPUZBTFNFKQ0Kc2NhdHRlcnBsb3QoQnJvd25pZXN+SWNlQ3JlYW0sQ29yckRhdGFULCBzbW9vdGhlcj1GQUxTRSkNCg0KIw0KcnkxPC1jb3IoQ29yckRhdGFUJEhhcHBpbmVzcyxDb3JyRGF0YVQkSWNlQ3JlYW0pDQpyeTI8LWNvcihDb3JyRGF0YVQkSGFwcGluZXNzLENvcnJEYXRhVCRCcm93bmllcykNCnIxMjwtY29yKENvcnJEYXRhVCRCcm93bmllcyxDb3JyRGF0YVQkSWNlQ3JlYW0pDQpyeTENCnJ5Mg0KcjEyDQpgYGANCg0KDQojIyMgV2hhdCB0aGUgcHJvYmxlbT8NCi0gSWNlIENyZWFtIGNhbiBleHBsYWluIGhhcHBpbmVzcyBgciByeTFeMmANCi0gQnJvd25pZXMgY2FuIGV4cGxhaW4gaGFwcGluZXNzLCBgciByeTJeMmANCi0gQnV0IGhvdyB3ZSBkbyBrbm93IHdoZXRoZXIgSWNlIENyZWFtIGFuZCBCcm93bmllcyBhcmUgZXhwbGFpbmluZyB0aGUgc2FtZSB2YXJpYW5jZT8gIA0KLSBBdCBsZWFzdCBicm93bmllcyBhbmQgSWNlIENyZWFtIGRvIG5vdCBleHBsYWluIGVhY2ggb3RoZXIgdG8gbXVjaCxgciByMTJeMmANCi0gSW4gb3RoZXIgd29yZHMsIHdoZW4gcGVvcGxlIGVhdCBCcm93bmllcyB0aGV5IGZvbnQgZWF0IHRvbyBtYW55IHNwb29ucyBvZiBpY2UgY3JlYW0NCg0KIyMjIE11bHRpcGxlIFIgDQotIFdlIHVzZSB0aGUgY2FwaXRhbCBsZXR0ZXIsICRSJCxub3cgY2F1c2Ugd2UgaGF2ZSBtdWx0aXBsZSBYIHZhcmlhYmxlcw0KLSAkUl97WS4xMn0gPSBcc3FydHtcZnJhY3tyX3tZMX1eMiArIHJfe1kyfV4yIC0gMnJfe1kxfSByX3tZMn0gcl97MTJ9fSB7MSAtIHJfezEyfV4yfX0kIA0KLSAkUl97WS4xMn0gPSQgYHIgc3FydCgocnkxXjIrcnkyXjIgLSAyKnJ5MSpyeTIqcjEyKS8oMS1yMTJeMikpYA0KLSBpZiB3ZSBzcXVhcmUgdGhhdCB2YWx1ZSwgYHIgc3FydCgocnkxXjIrcnkyXjIgLSAyKnJ5MSpyeTEqcjEyKS8oMS1yMTJeMikpXjJgLCB3ZSBnZXQgdGhlIE11bHRpcGxlICRSXjIkIA0KLSBvciB0aGUgdG90YWwgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IHRoZXNlIHZhcmlhYmxlcyBvbiBoYXBwaW5lc3MgDQoNCiMgU2VtaXBhcnRpYWwgKHBhcnQpIGNvcnJlbGF0aW9uDQotIFdlIG5lZWQgdG8gZGVmaW5lIHRvIGNvbnRyaWJ1dGlvbiBvZiBlYWNoIFggdmFyaWFibGUgb24gWQ0KLSBTZW1pcGFydGlhbCAoYWxzbyBjYWxsZWQgcGFydCkgaXMgb25lIG9mIHR3byBtZXRob2RzLCB0aGUgb3RoZXIgaXMgY2FsbGVkIHBhcnRpYWwNCi0gaXMgY2FsbGVkIHNlbWksIGNhdXNlIGl0IHJlbW92ZXMgdGhlIGVmZmVjdCBvZiBvbmUgSVYgcmVsYXRpdmUgdG8gdGhlIG90aGVyIHdpdGhvdXQgcmVtb3ZpbmcgdGhlIHJlbGF0aW9uc2hpcCB0byBZDQotICBTZW1pcGFydGlhbCBjb3JyZWxhdGlvbnMgaW5kaWNhdGUgdGhlICJ1bmlxdWUiIGNvbnRyaWJ1dGlvbiBvZiBhbiBpbmRlcGVuZGVudCB2YXJpYWJsZS4gDQoNCiFbQmFsbGFudGluZSBmb3IgWDEsIFgyLCBhbmQgWV0oUmVncmVzc2lvbkNsYXNzL0wyX1BhcnRDb3JyL0JhbGxhbnRpbmUuanBnKQ0KIA0KLSAkUl97WS4xMn1eMiA9IGEgKyBiICsgYyQNCi0gJHNyXzFeMjogYSA9IFJfe1kuMTJ9XjIgLSByX3tZMn1eMiQNCi0gJHNyXzJeMjpiID0gUl97WS4xMn1eMiAtIHJfe1kxfV4yJA0KDQojIyBDYWxjdWF0aW9uDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQpSMnkuMTI8LXNxcnQoKHJ5MV4yK3J5Ml4yIC0gKDIqcnkxKnJ5MipyMTIpKS8oMS1yMTJeMikpXjINClIyeS4xMg0KDQphID0gUjJ5LjEyIC1yeTJeMiANCmIgPSBSMnkuMTIgLXJ5MV4yIA0KDQoNCmBgYA0KDQppbiBvdGhlciB3b3JkcywNCg0KKyBJbiB0b3RhbCB3ZSBleHBsYWluZWQsIGByIFIyeS4xMmAgb2YgdGhlIGhhcHBpbmVzcyByYXRpbmdzDQorIGljZSBjcmVhbSB1bmlxdWVseSBleHBsYWluZWQsIGByIGFgIG9mIGhhcHBpbmVzcyByYXRpbmdzDQorIGJyb3duaWVzIHVuaXF1ZWx5IGV4cGxhaW5lZCwgYHIgYmAgb2YgaGFwcGluZXNzIHJhdGluZ3MgDQorIFdlIHNob3VsZCBub3Qgc29sdmUgZm9yIGMgY2F1c2UgaXQgY2FuIGJlIG5lZ2F0aXZlIChpbiBzb21lIGNhc2VzKQ0KDQojIyMgU2VlaW5nIGNvbnRyb2wgaW4gYWN0aW9uDQpBbm90aGVyIHdheSB0byB1bmRlcnN0YW5kIGl0OiANCg0KLSBXaGF0IGlmIHlvdSB3YW50IHRvIGtub3cgYWJvdXQgaGFwcGluZXNzIGFuZCBob3cgaWNlIGNyZWFtIHVuaXF1ZWx5IGV4cGxhaW5zIGl0PyBbY29udHJvbGxpbmcgdGhlIGVmZmVjdCBvZiBicm93bmllcyBvbiBpY2UgY3JlYW1dDQotIFdlIGNhbiByZW1vdmUgYWZmZWN0IG9mIGJyb3duaWVzIG9uIGljZSBjcmVhbSBieSBleHRyYWN0aW5nIHRoZSByZXNpZHVhbHMgbG0oWDF+WDIpDQotIFJlbWVtYmVyIHRoZSByZXNpZHVhbHMgYXJlIHRoZSBsZWZ0IG92ZXIgKGFmdGVyIGV4dHJhY3Rpbmcgd2hhdCB3YXMgZXhwbGFpbmFibGUpDQotIE5leHQgd2UgY2FuIGNvcnJlbGF0ZSBoYXBwaW5lc3Mgd2l0aCB0aGUgcmVzaWR1YWxpemVkIGljZSBjcmVhbS4gDQoNCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCiNjb250cm9sIGZvciBicm93bmllcw0KQ29yckRhdGFUJEljZS5jb250cm9sLkJyb3duaWVzPC1yZXNpZHVhbHMobG0oSWNlQ3JlYW1+QnJvd25pZXMsIENvcnJEYXRhVCkpDQpwbG90KENvcnJEYXRhVCRIYXBwaW5lc3MsQ29yckRhdGFUJEljZS5jb250cm9sLkJyb3duaWVzKQ0KU3IxLmFsdDwtY29yKENvcnJEYXRhVCRJY2UuY29udHJvbC5Ccm93bmllcyxDb3JyRGF0YVQkSGFwcGluZXNzKQ0KU3IxLmFsdA0KYGBgDQoNCklmIHdlIHNxdWFyZSB0aGUgY29ycmVsYXRpb24gdmFsdWUgd2UgZ290IGByIFNyMS5hbHReMmAsIGl0IGJlY29tZXMgYHIgU3IxLmFsdF4yYCB3aGljaCBtYXRjaGVzIG91ciAkYSQgZnJvbSB0aGUgYW5hbHlzaXMgYWJvdmUuIA0KDQotV2UgY2FuIHJlcGVhdCB0aGlzIGFuYWx5c2lzIGJ1dCBjaGFuZ2luZyBvdXIgY29udHJvbCB0byBmaW5kICRiJC4NCg0KDQpgYGB7ciwgZWNobz1UUlVFLCB3YXJuaW5nPUZBTFNFfQ0KI2NvbnRyb2wgZm9yIGljZSBjcmVhbQ0KQ29yckRhdGFUJEJyb3duaWVzLmNvbnRyb2wuSWNlPC1yZXNpZHVhbHMobG0oQnJvd25pZXN+SWNlQ3JlYW0sIENvcnJEYXRhVCkpDQpwbG90KENvcnJEYXRhVCRCcm93bmllcy5jb250cm9sLkljZSxDb3JyRGF0YVQkSGFwcGluZXNzKQ0KDQpTcjIuYWx0PC1jb3IoQ29yckRhdGFUJEhhcHBpbmVzcyxDb3JyRGF0YVQkQnJvd25pZXMuY29udHJvbC5JY2UpDQpTcjIuYWx0XjINCmBgYA0KDQoNCiMjIFNlbWlwYXJ0aWFsIG5vdGVzOiANCi0gbm90ZSwgaXQgY2FuIGJlIHdyaXR0ZW4gYXMgJHNyJCBvciBtb3JlIHNwZWNpZmljYWxseSwgJHNyXzEkIGZvciBYMSAod2l0aCBYMiByZW1vdmVkKSBhbmQgJHNyXzIkICh3aXRoIFgxIHJlbW92ZWQpIA0KLSBjb3JyZWxhdGlvbnMgd2l0aCBubyBjb250cm9sIHZhcmlhYmxlcyBhcmUgY2FsbGVkIHRoZSB6ZXJvLW9yZGVyIGNvcnJlbGF0aW9ucw0KLSBpbiBSIHlvdSBjYW4gY2FsY3VsYXRlIHRoZSAkc3IkIHJhdGhlciBxdWlja2x5IHVzaW5nIHRoZSBwcGNvciBsaWJyYXJ5DQoNCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCmxpYnJhcnkocHBjb3IpDQojbGFzdCB2YXJpYWJsZSBpcyB0aGUgY29udHJvbCB2YXJpYWJsZSENCg0KU3IxPC1zcGNvci50ZXN0KENvcnJEYXRhVCRIYXBwaW5lc3MsIENvcnJEYXRhVCRJY2VDcmVhbSwgQ29yckRhdGFUJEJyb3duaWVzKQ0KU3IxDQpTcjI8LXNwY29yLnRlc3QoQ29yckRhdGFUJEhhcHBpbmVzcywgQ29yckRhdGFUJEJyb3duaWVzLCBDb3JyRGF0YVQkSWNlQ3JlYW0pDQpTcjINCg0KIyBOb3RlIHRvIGNvbnZlcnQgdGhlbSB0byBSMiB2YWx1ZXMsIHlvdSBqdXN0IG5lZWQgdG8gc3F1YXJlIHRoZSBjb3JyZWxhdGlvbnMNClNyMSRlc3RpbWF0ZV4yDQpTcjIkZXN0aW1hdGVeMg0KDQojbm90aWNlIHRoZXkgbWF0Y2ggb3VyIGEgYW5kIGIgdmFsdWVzIGV4YWN0bHkuIA0KDQpgYGANCg0KDQojIFBhcnRpYWwgY29ycmVsYXRpb24NCi0gUGFydGlhbCBjb3JyZWxhdGlvbiBhc2tzIGhvdyBtdWNoIG9mIHRoZSBZIHZhcmlhbmNlLCB3aGljaCBpcyBub3QgZXN0aW1hdGVkIGJ5IHRoZSBvdGhlciBJVnMsIGlzIGVzdGltYXRlZCBieSB0aGlzIHZhcmlhYmxlLg0KLSBJdCByZW1vdmVzIHRoZSBzaGFyZWQgdmFyaWFuY2Ugb2YgdGhlIGNvbnRyb2wgdmFyaWFibGUgKFNheSB4MikgZnJvbSBib3RoIFkgYW5kIFgxLiANCg0KLSAkcHJfMV4yOiA9IFxmcmFje2F9e2ErZX0gPSBcZnJhY3tSX3tZLjEyfV4yIC0gcl97WTJ9XjJ9ezEtcl97WTJ9XjJ9JA0KLSAkcHJfMl4yOiBcZnJhY3tifXtiK2V9ID0gXGZyYWN7Ul97WS4xMn1eMiAtIHJfe1kxfV4yfXsxLXJfe1kxfV4yfSQNCg0KIyMgU2VlaW5nIGNvbnRyb2wgaW4gYWN0aW9uDQpBbm90aGVyIHdheSB0byB1bmRlcnN0YW5kIGl0OiANCg0KLSBXaGF0IGlmIHlvdSB3YW50IHRvIGtub3cgYWJvdXQgaGFwcGluZXNzIGFuZCBpY2UgY3JlYW0gd2hpbGUgY29udHJvbGxpbmcgZm9yIGJyb3duaWVzIChjYXVzZSBicm93bmllcyBhZmZlY3QgYm90aCBoYXBwaW5lc3MgYW5kIGljZSBjcmVhbSkNCi0gV2UgdGFrZSByZXNpZHVhbHMgb2YgbG0oWX5YMikgYW5kIGNvcnJlbGF0ZSBpdCB3aXRoIHRoZSByZXNpZHVhbHMgb2YgbG0oWDF+WDIpDQotIFJlbWVtYmVyIHRoZSByZXNpZHVhbHMgYXJlIHRoZSBsZWZ0IG92ZXIgKGFmdGVyIGV4dHJhY3Rpbmcgd2hhdCB3YXMgZXhwbGFpbmFibGUpDQotIGlmIHlvdSB3YW50IHRvIGNvbnRyb2wgZm9yIGljZSBjcmVhbSB5b3Ugd291bGQ6IHJlc2lkdWFscyBvZiBsbShZflgxKSB3aXRoIHRoZSByZXNpZHVhbHMgb2YgbG0oWDJ+WDEpDQoNCmBgYHtyLCBlY2hvPVRSVUUsIHdhcm5pbmc9RkFMU0V9DQojY29udHJvbCBmb3IgYnJvd25pZXMNCkNvcnJEYXRhVCRIYXBweS5jb250cm9sLkJyb3duaWVzPC1yZXNpZHVhbHMobG0oSGFwcGluZXNzfkJyb3duaWVzLCBDb3JyRGF0YVQpKQ0KQ29yckRhdGFUJEljZS5jb250cm9sLkJyb3duaWVzPC1yZXNpZHVhbHMobG0oSWNlQ3JlYW1+QnJvd25pZXMsIENvcnJEYXRhVCkpDQpwbG90KENvcnJEYXRhVCRJY2UuY29udHJvbC5Ccm93bmllcyxDb3JyRGF0YVQkSGFwcHkuY29udHJvbC5Ccm93bmllcykNCmNvcihDb3JyRGF0YVQkSWNlLmNvbnRyb2wuQnJvd25pZXMsQ29yckRhdGFUJEhhcHB5LmNvbnRyb2wuQnJvd25pZXMpDQoNCiNjb250cm9sIGZvciBpY2UgY3JlYW0NCkNvcnJEYXRhVCRIYXBweS5jb250cm9sLmljZTwtcmVzaWR1YWxzKGxtKEhhcHBpbmVzc35JY2VDcmVhbSwgQ29yckRhdGFUKSkNCkNvcnJEYXRhVCRCcm93bmllcy5jb250cm9sLmljZTwtcmVzaWR1YWxzKGxtKEJyb3duaWVzfkljZUNyZWFtLCBDb3JyRGF0YVQpKQ0KDQpwbG90KENvcnJEYXRhVCRCcm93bmllcy5jb250cm9sLmljZSxDb3JyRGF0YVQkSGFwcHkuY29udHJvbC5pY2UpDQpjb3IoQ29yckRhdGFUJEJyb3duaWVzLmNvbnRyb2wuaWNlLENvcnJEYXRhVCRIYXBweS5jb250cm9sLmljZSkNCmBgYA0KDQotIGluIFIgeW91IGNhbiBjYWxjdWxhdGUgdGhlICRwciQgZGlyZWN0bHkgdmlhIHRoZSBmdW5jdGlvbnMNCg0KYGBge3IsIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRX0NCnByMTwtcGNvci50ZXN0KENvcnJEYXRhVCRIYXBwaW5lc3MsIENvcnJEYXRhVCRJY2VDcmVhbSwgQ29yckRhdGFUJEJyb3duaWVzKQ0KcHIxDQpwcjI8LXBjb3IudGVzdChDb3JyRGF0YVQkSGFwcGluZXNzLCBDb3JyRGF0YVQkQnJvd25pZXMsIENvcnJEYXRhVCRJY2VDcmVhbSkNCnByMg0KDQojIE5vdGUgdG8gY29udmVydCB0aGVtIHRvIFIyIHZhbHVlcywgeW91IGp1c3QgbmVlZCB0byBzcXVhcmUgdGhlIGNvcnJlbGF0aW9ucw0KcHIxJGVzdGltYXRlXjINCnByMiRlc3RpbWF0ZV4yDQoNCg0KYGBgDQoNCg0KDQo8c2NyaXB0Pg0KICAoZnVuY3Rpb24oaSxzLG8sZyxyLGEsbSl7aVsnR29vZ2xlQW5hbHl0aWNzT2JqZWN0J109cjtpW3JdPWlbcl18fGZ1bmN0aW9uKCl7DQogIChpW3JdLnE9aVtyXS5xfHxbXSkucHVzaChhcmd1bWVudHMpfSxpW3JdLmw9MSpuZXcgRGF0ZSgpO2E9cy5jcmVhdGVFbGVtZW50KG8pLA0KICBtPXMuZ2V0RWxlbWVudHNCeVRhZ05hbWUobylbMF07YS5hc3luYz0xO2Euc3JjPWc7bS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShhLG0pDQogIH0pKHdpbmRvdyxkb2N1bWVudCwnc2NyaXB0JywnaHR0cHM6Ly93d3cuZ29vZ2xlLWFuYWx5dGljcy5jb20vYW5hbHl0aWNzLmpzJywnZ2EnKTsNCg0KICBnYSgnY3JlYXRlJywgJ1VBLTkwNDE1MTYwLTEnLCAnYXV0bycpOw0KICBnYSgnc2VuZCcsICdwYWdldmlldycpOw0KDQo8L3NjcmlwdD4=