Cuckoo dataset
The common cuckoo does not build its own nest: it prefers
to lay its eggs in another birds’ nest. It is known, since 1892,
that the type of cuckoo bird eggs are different between different
locations. In a study from 1940, it was shown that cuckoos return
to the same nesting area each year, and that they always pick
the same bird species to be a “foster parent” for their eggs.
Over the years, this has lead to the development of geographically
determined subspecies of cuckoos. These subspecies have evolved in
such a way that their eggs look as similar as possible as those
of their foster parents.
The cuckoo dataset contains information on 120 Cuckoo eggs,
obtained from randomly selected “foster” nests.
For these eggs, researchers have measured the length
(in mm)
and established the type
(species) of foster parent.
The type column is coded as follows:
type=1
: Meadow pipit
type=2
: Tree pipit
type=3
: Dunnock
type=4
: European robin
type=5
: White wagtail
type=6
: Eurasian wren
Goal
The researchers want totest if the type of foster parent
has an effect on the average length of the cuckoo eggs.
In theory, they want to study this for all six species.
Previously, we looked at a single pairwise comparison
between the European robin and the Eurasian wren with a
t-test. Here, we will analyse all types simultaneously
with ANOVA.
Load the required libraries
library(tidyverse)
library(multcomp)
## Warning: package 'mvtnorm' was built under R version 4.4.1
Import the data
Cuckoo <- read_tsv("https://raw.githubusercontent.com/statOmics/PSLSData/main/Cuckoo.txt")
head(Cuckoo)
ANOVA
To study if the observed differences in average egg length
between the different foster bird types are significant, we can perform
an ANOVA.
The model
We will fit the following linear model:
\[
E(Y_i) = \beta_0 + \beta_1 X_{i1} + \beta_2 X_{i2} +
\beta_3 X_{i3} + \beta_4 X_{i4} + \beta_5 X_{i5}
\]
where \(Y_i\) is the length of egg \(i\) and the coefficients \(beta_j\) corresond to
the additional expected length of a cuckoo egg fostered by bird type \(j + 1\). By
convention, the intercept is called \(\beta_0\) and it corresponds to the
reference bird type, in this case bird type 1 (the Meadow pipit). The variables
\(X_ij\) are dummy variables which take on the value 1 if egg \(i\) was fostered
by bird type \(j + 1\) and are 0 otherwise. Note that in this case, eggs are
always fostered by a single bird type, so only one of the X’s will be equal to
1.
For example, if egg \(i\) was fostered by the meadow pipit (type 1), all the \(X_{i1}, \dots, X_{i5}\) would be zero and we are left with:
\[E(Y_i | X_{i1} = \dots = X_{i5} = 0) = \beta_0\]
i.e. the intercept. If egg \(i\) was fostered by the European robin (type 4), we would have:
\[E(Y_i | X_{i3} = 1) = \beta_0 + \beta_3\]
So \(\beta_3\) can be interpreted as the change in average length of cuckoo eggs
between the reference bird type (the meadow pipit) and the European robin. The
coefficients can be negative or positive, so the change can be an increase or a
decrease.
To further aid with intepretation, we can visualize the model design using the ExploreModelMatrix package:
ExploreModelMatrix::VisualizeDesign(Cuckoo, ~type)$plotlist[[1]]

Parameter estimation
mod <- lm(length ~ type, Cuckoo)
summary(mod)
##
## Call:
## lm(formula = length ~ type, data = Cuckoo)
##
## Residuals:
## Min 1Q Median 3Q Max
## -4.8100 -0.7212 0.1333 0.7775 3.3800
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 22.5000 0.1963 114.611 < 2e-16 ***
## typetree 0.5900 0.3926 1.503 0.135687
## typedunnock 0.6214 0.4030 1.542 0.125854
## typerobin 0.0750 0.3833 0.196 0.845225
## typewagtail 0.4033 0.3926 1.027 0.306475
## typewren -1.3700 0.3926 -3.489 0.000689 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.317 on 114 degrees of freedom
## Multiple R-squared: 0.1723, Adjusted R-squared: 0.136
## F-statistic: 4.747 on 5 and 114 DF, p-value: 0.0005621
The output of the model suggests that there are indeed differences in the
average length of cuckoo eggs between different foster parents. Note, however,
that in the standard output of lm()
, the p-values are not adjusted for
multiple testing (a topic which we will touch upon later). In addition, this
model only shows the differences between foster types 2-6 and the reference
type (1), represented by the intercept.
The p-value of the F-test, given at the bottom of the summary, corresponds to a
one-way ANOVA where the full model is compared to a reduced model containing
only the intercept. Thus, it is testing the omnibus null hypothesis that all
slope coefficients (\(\beta_1\) - \(\beta_5\)) are equal to 0.
Check assumptions
Before we may proceed with the analysis, we must make sure that all
assumptions for ANOVA are met. ANOVA has three assumptions:
- The observations are independent of each other (in all groups)
- The data (length) must be normally distributed (in all groups)
- The variability within all groups is similar
The first assumption is met, as we may assume that there are no
specific patterns of correlation between the randomly selected nests.
To check the normality assumption, we will use QQ plots.

Cuckoo %>%
ggplot(aes(sample = length)) +
geom_qq() +
geom_qq_line() +
facet_grid(~type)

There seem to be no clear deviations from normality.
The third assumption of equal variances seems to be met based on the
visualization with the boxplots (see above).
As such, we may proceed with the ANOVA analysis.
Simulate to train your skills in assessing assumptions
set.seed(1031)
sigma <- mod %>% sigma()
dataHlp <- Cuckoo
simModels <- list()
plotList <- list()
plotListQQ1 <- list()
par(mfrow = c(3, 3))
for (i in 1:9)
{
nobs <- Cuckoo %>% nrow()
dataHlp$ySim <- mod$fit + rnorm(nobs, sd = sigma)
simModels[[i]] <- lm(ySim ~ type, dataHlp)
plot(simModels[[i]], which = 2)
plotList[[i]] <- dataHlp %>%
ggplot(aes(type, ySim)) +
geom_boxplot(outlier.shape = NA) +
geom_jitter()
plotListQQ1[[i]] <- dataHlp %>%
filter(type == "meadow") %>%
ggplot(aes(sample = ySim)) +
geom_qq() +
geom_qq_line() +
xlab("QQ for meadow")
}

do.call(gridExtra::grid.arrange, plotList)

do.call(gridExtra::grid.arrange, plotListQQ1)

The most deviating QQ-plot of the residuals in the nine simulation runs:
par(mfrow = c(1, 1))
plot(simModels[[8]], which = 2)

ANOVA model
We perform the ANOVA test using the results of the linear regression model.
Essentially, we test the following null hypothesis:
\[
H_0:\ \beta_1 = \beta_2 = \beta_3 = \beta_4 = \beta_5 = 0
\]
with the alternative being that at least one of the parameters is different from
0.
The p-value of the ANOVA analysis is extremely significant
(p-value < 0.001),
so we reject the null hypothesis that the mean
egg length is equal between the different bird types.
We can say that the mean egg length is significantly different
between at least two bird types on the 5% significance level.
Based on this analysis, we do not yet know between which particular
bird types there is a significant difference. To study this, we will
perform a Tukey post-hoc analysis.
Post-hoc analysis
We will perform a post-hoc analysis, to look at the difference
in egg length between each pairwise comparison of bird types.
Importantly, with this strategy, the p-values will be correctly
adjusted for multiple testing.
The null hypothesis for each pairwise test is that there is no
difference in the mean egg length between both bird types.
The alternative hypothesis for each pairwise test states that there
is indeed a difference in the mean egg length between both bird types.
We will also calculate the confidence interval on the mean differences.
The post-hoc analysis is carried out using the glht()
(“General Linear
Hypotheses”) function from the multcomp package. We apply this to our linear
model object mod
and specify in the linfct=
argument that we want to perform
multiple comparisons (mcp
), using Tukey’s method. We store the output of
glht()
and then display the results using the summary()
function and
calculating confidence intervals.
mcp <- glht(mod, linfct = mcp(type = "Tukey"))
summary(mcp)
##
## Simultaneous Tests for General Linear Hypotheses
##
## Multiple Comparisons of Means: Tukey Contrasts
##
##
## Fit: lm(formula = length ~ type, data = Cuckoo)
##
## Linear Hypotheses:
## Estimate Std. Error t value Pr(>|t|)
## tree - meadow == 0 0.59000 0.39263 1.503 0.65686
## dunnock - meadow == 0 0.62143 0.40301 1.542 0.63147
## robin - meadow == 0 0.07500 0.38332 0.196 0.99996
## wagtail - meadow == 0 0.40333 0.39263 1.027 0.90518
## wren - meadow == 0 -1.37000 0.39263 -3.489 0.00847 **
## dunnock - tree == 0 0.03143 0.48939 0.064 1.00000
## robin - tree == 0 -0.51500 0.47330 -1.088 0.88202
## wagtail - tree == 0 -0.18667 0.48087 -0.388 0.99878
## wren - tree == 0 -1.96000 0.48087 -4.076 0.00114 **
## robin - dunnock == 0 -0.54643 0.48195 -1.134 0.86268
## wagtail - dunnock == 0 -0.21810 0.48939 -0.446 0.99764
## wren - dunnock == 0 -1.99143 0.48939 -4.069 0.00115 **
## wagtail - robin == 0 0.32833 0.47330 0.694 0.98170
## wren - robin == 0 -1.44500 0.47330 -3.053 0.03198 *
## wren - wagtail == 0 -1.77333 0.48087 -3.688 0.00433 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## (Adjusted p values reported -- single-step method)
##
## Simultaneous Confidence Intervals
##
## Multiple Comparisons of Means: Tukey Contrasts
##
##
## Fit: lm(formula = length ~ type, data = Cuckoo)
##
## Quantile = 2.8889
## 95% family-wise confidence level
##
##
## Linear Hypotheses:
## Estimate lwr upr
## tree - meadow == 0 0.59000 -0.54429 1.72429
## dunnock - meadow == 0 0.62143 -0.54285 1.78571
## robin - meadow == 0 0.07500 -1.03239 1.18239
## wagtail - meadow == 0 0.40333 -0.73096 1.53763
## wren - meadow == 0 -1.37000 -2.50429 -0.23571
## dunnock - tree == 0 0.03143 -1.38238 1.44524
## robin - tree == 0 -0.51500 -1.88234 0.85234
## wagtail - tree == 0 -0.18667 -1.57589 1.20255
## wren - tree == 0 -1.96000 -3.34922 -0.57078
## robin - dunnock == 0 -0.54643 -1.93875 0.84589
## wagtail - dunnock == 0 -0.21810 -1.63190 1.19571
## wren - dunnock == 0 -1.99143 -3.40524 -0.57762
## wagtail - robin == 0 0.32833 -1.03901 1.69567
## wren - robin == 0 -1.44500 -2.81234 -0.07766
## wren - wagtail == 0 -1.77333 -3.16255 -0.38411
We can also visualize the confidence interval by calling plot()
on the mcp
object:

Conclusion
The association between the mean length of a cuckoo’s egg and the foster bird species is extremely significant (p << 0.001).
The mean length of cuckoo’s eggs in nests of the Eurasian
wren are smaller as compared to those from all other bird
species in the study:
- the meadow pipit (adjusted p-value = 0.009, mean difference = -1.4mm, 95% CI [-2.5, -0.2])
- the tree pipit (adjusted p-value = 0.001, mean difference = -2mm, 95% CI [-3.3, -0.6])
- the dunnock (adjusted p-value = 0.001, mean difference = -2mm, 95% CI [-3.4, -0.6])
- the European robin (adjusted p-value = 0.03, mean difference = -1.4mm, 95% CI [-2.8, -0.1])
- the white wagtail (adjusted p-value = 0.004, mean difference = -1.8mm, 95% CI [-3.2, -0.4])
There is no evidence taht the mean length of the cuckoo bird’s eggs for all
other pairwise comparisons between foster bird species are significantly
different at the 5% level.
LS0tCnRpdGxlOiAiRXhlcmNpc2UgNy4yOiBBTk9WQSBvbiB0aGUgY3Vja29vIGRhdGFzZXQgLSBzb2x1dGlvbiIKYXV0aG9yOiAiTGlldmVuIENsZW1lbnQsIEplcm9lbiBHaWxpcyBhbmQgTWlsYW4gTWFsZmFpdCIKZGF0ZTogInN0YXRPbWljcywgR2hlbnQgVW5pdmVyc2l0eSAoaHR0cHM6Ly9zdGF0b21pY3MuZ2l0aHViLmlvKSIKLS0tCgojIEN1Y2tvbyBkYXRhc2V0CgpUaGUgY29tbW9uIGN1Y2tvbyBkb2VzIG5vdCBidWlsZCBpdHMgb3duIG5lc3Q6IGl0IHByZWZlcnMKdG8gbGF5IGl0cyBlZ2dzIGluIGFub3RoZXIgYmlyZHMnIG5lc3QuIEl0IGlzIGtub3duLCBzaW5jZSAxODkyLAp0aGF0IHRoZSB0eXBlIG9mIGN1Y2tvbyBiaXJkIGVnZ3MgYXJlIGRpZmZlcmVudCBiZXR3ZWVuIGRpZmZlcmVudApsb2NhdGlvbnMuIEluIGEgc3R1ZHkgZnJvbSAxOTQwLCBpdCB3YXMgc2hvd24gdGhhdCBjdWNrb29zIHJldHVybgp0byB0aGUgc2FtZSBuZXN0aW5nIGFyZWEgZWFjaCB5ZWFyLCBhbmQgdGhhdCB0aGV5IGFsd2F5cyBwaWNrCnRoZSBzYW1lIGJpcmQgc3BlY2llcyB0byBiZSBhICJmb3N0ZXIgcGFyZW50IiBmb3IgdGhlaXIgZWdncy4KCk92ZXIgdGhlIHllYXJzLCB0aGlzIGhhcyBsZWFkIHRvIHRoZSBkZXZlbG9wbWVudCBvZiBnZW9ncmFwaGljYWxseQpkZXRlcm1pbmVkIHN1YnNwZWNpZXMgb2YgY3Vja29vcy4gVGhlc2Ugc3Vic3BlY2llcyBoYXZlIGV2b2x2ZWQgaW4Kc3VjaCBhIHdheSB0aGF0IHRoZWlyIGVnZ3MgbG9vayBhcyBzaW1pbGFyIGFzIHBvc3NpYmxlIGFzIHRob3NlCm9mIHRoZWlyIGZvc3RlciBwYXJlbnRzLgoKVGhlIGN1Y2tvbyBkYXRhc2V0IGNvbnRhaW5zIGluZm9ybWF0aW9uIG9uIDEyMCBDdWNrb28gZWdncywKb2J0YWluZWQgZnJvbSByYW5kb21seSBzZWxlY3RlZCAiZm9zdGVyIiBuZXN0cy4KRm9yIHRoZXNlIGVnZ3MsIHJlc2VhcmNoZXJzIGhhdmUgbWVhc3VyZWQgdGhlIGBsZW5ndGhgIChpbiBtbSkKYW5kIGVzdGFibGlzaGVkIHRoZSBgdHlwZWAgKHNwZWNpZXMpIG9mIGZvc3RlciBwYXJlbnQuClRoZSB0eXBlIGNvbHVtbiBpcyBjb2RlZCBhcyBmb2xsb3dzOgoKLSBgdHlwZT0xYDogTWVhZG93IHBpcGl0Ci0gYHR5cGU9MmA6IFRyZWUgcGlwaXQKLSBgdHlwZT0zYDogRHVubm9jawotIGB0eXBlPTRgOiBFdXJvcGVhbiByb2JpbgotIGB0eXBlPTVgOiBXaGl0ZSB3YWd0YWlsCi0gYHR5cGU9NmA6IEV1cmFzaWFuIHdyZW4KCiMgR29hbAoKVGhlIHJlc2VhcmNoZXJzIHdhbnQgdG90ZXN0IGlmIHRoZSB0eXBlIG9mIGZvc3RlciBwYXJlbnQKaGFzIGFuIGVmZmVjdCBvbiB0aGUgYXZlcmFnZSBsZW5ndGggb2YgdGhlIGN1Y2tvbyBlZ2dzLgoKSW4gdGhlb3J5LCB0aGV5IHdhbnQgdG8gc3R1ZHkgdGhpcyBmb3IgYWxsIHNpeCBzcGVjaWVzLgpQcmV2aW91c2x5LCB3ZSBsb29rZWQgYXQgYSBzaW5nbGUgcGFpcndpc2UgY29tcGFyaXNvbgpiZXR3ZWVuIHRoZSBFdXJvcGVhbiByb2JpbiBhbmQgdGhlIEV1cmFzaWFuIHdyZW4gd2l0aCBhCnQtdGVzdC4gSGVyZSwgd2Ugd2lsbCBhbmFseXNlIGFsbCB0eXBlcyBzaW11bHRhbmVvdXNseQp3aXRoIEFOT1ZBLgoKTG9hZCB0aGUgcmVxdWlyZWQgbGlicmFyaWVzCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkobXVsdGNvbXApCmBgYAoKIyMgSW1wb3J0IHRoZSBkYXRhCgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KQ3Vja29vIDwtIHJlYWRfdHN2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3RhdE9taWNzL1BTTFNEYXRhL21haW4vQ3Vja29vLnR4dCIpCmhlYWQoQ3Vja29vKQpgYGAKCiMgRGF0YSB0aWR5aW5nCgpJdCBzZWVtcyB0aGF0IHRoZSBgdHB5ZWAgY29sdW1uIGlzIGEgYGRvdWJsZWAgcmF0aGVyIHRoYW4gYSBgZmFjdG9yYC4KTGV0J3MgZml4IHRoaXM6CgpgYGB7cn0KQ3Vja29vIDwtIEN1Y2tvbyAlPiUKICBtdXRhdGUodHlwZSA9IGFzLmZhY3Rvcih0eXBlKSkgJT4lCiAgbXV0YXRlKHR5cGUgPSByZWNvZGUodHlwZSwKICAgICIxIiA9ICJtZWFkb3ciLAogICAgIjIiID0gInRyZWUiLAogICAgIjMiID0gImR1bm5vY2siLAogICAgIjQiID0gInJvYmluIiwKICAgICI1IiA9ICJ3YWd0YWlsIiwKICAgICI2IiA9ICJ3cmVuIgogICkpCmBgYAoKCiMgRGF0YSBleHBsb3JhdGlvbgoKSG93IG1hbnkgYmlyZHMgZG8gd2UgaGF2ZSBmb3IgZWFjaCB0eXBlPwoKYGBge3J9CkN1Y2tvbyAlPiUKICBjb3VudCh0eXBlKQpgYGAKClZpc3VhbGl6ZSB0aGUgZGF0YQoKYGBge3J9CkN1Y2tvbyAlPiUKICBnZ3Bsb3QoYWVzKHggPSB0eXBlLCB5ID0gbGVuZ3RoLCBmaWxsID0gdHlwZSkpICsKICB0aGVtZV9idygpICsKICBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlID0gIlJkR3kiKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGdlb21faml0dGVyKHdpZHRoID0gMC4yKSArCiAgZ2d0aXRsZSgiQm94cGxvdCBvZiB0aGUgbGVuZ3RoIG9mIGVnZ3MgcGVyIHR5cGUiKSArCiAgeWxhYigibGVuZ3RoIChtbSkiKSArCiAgc3RhdF9zdW1tYXJ5KAogICAgZnVuID0gbWVhbiwgZ2VvbSA9ICJwb2ludCIsCiAgICBzaGFwZSA9IDUsIHNpemUgPSAzLCBjb2xvciA9ICJibGFjayIKICApCmBgYAoKIyBBTk9WQQoKVG8gc3R1ZHkgaWYgdGhlIG9ic2VydmVkIGRpZmZlcmVuY2VzIGluIGF2ZXJhZ2UgZWdnIGxlbmd0aApiZXR3ZWVuIHRoZSBkaWZmZXJlbnQgZm9zdGVyIGJpcmQgdHlwZXMgYXJlIHNpZ25pZmljYW50LCB3ZSBjYW4gcGVyZm9ybQphbiBBTk9WQS4KCiMjIFRoZSBtb2RlbAoKV2Ugd2lsbCBmaXQgdGhlIGZvbGxvd2luZyBsaW5lYXIgbW9kZWw6CgokJApFKFlfaSkgPSBcYmV0YV8wICsgXGJldGFfMSBYX3tpMX0gKyBcYmV0YV8yIFhfe2kyfSArCiAgXGJldGFfMyBYX3tpM30gKyBcYmV0YV80IFhfe2k0fSArIFxiZXRhXzUgWF97aTV9CiQkCgp3aGVyZSAkWV9pJCBpcyB0aGUgbGVuZ3RoIG9mIGVnZyAkaSQgYW5kIHRoZSBjb2VmZmljaWVudHMgJGJldGFfaiQgY29ycmVzb25kIHRvCnRoZSAqKmFkZGl0aW9uYWwgZXhwZWN0ZWQqKiBsZW5ndGggb2YgYSBjdWNrb28gZWdnIGZvc3RlcmVkIGJ5IGJpcmQgdHlwZSAkaiArIDEkLiBCeQpjb252ZW50aW9uLCB0aGUgaW50ZXJjZXB0IGlzIGNhbGxlZCAkXGJldGFfMCQgYW5kIGl0IGNvcnJlc3BvbmRzIHRvIHRoZQpyZWZlcmVuY2UgYmlyZCB0eXBlLCBpbiB0aGlzIGNhc2UgYmlyZCB0eXBlIDEgKHRoZSBNZWFkb3cgcGlwaXQpLiBUaGUgdmFyaWFibGVzCiRYX2lqJCBhcmUgKipkdW1teSB2YXJpYWJsZXMqKiB3aGljaCB0YWtlIG9uIHRoZSB2YWx1ZSAxIGlmIGVnZyAkaSQgd2FzIGZvc3RlcmVkCmJ5IGJpcmQgdHlwZSAkaiArIDEkIGFuZCBhcmUgMCBvdGhlcndpc2UuIE5vdGUgdGhhdCBpbiB0aGlzIGNhc2UsIGVnZ3MgYXJlCmFsd2F5cyBmb3N0ZXJlZCBieSBhIHNpbmdsZSBiaXJkIHR5cGUsIHNvIG9ubHkgb25lIG9mIHRoZSBYJ3Mgd2lsbCBiZSBlcXVhbCB0bwoxLgoKRm9yIGV4YW1wbGUsIGlmIGVnZyAkaSQgd2FzIGZvc3RlcmVkIGJ5IHRoZSBtZWFkb3cgcGlwaXQgKHR5cGUgMSksIGFsbCB0aGUgJFhfe2kxfSwgXGRvdHMsIFhfe2k1fSQgd291bGQgYmUgemVybyBhbmQgd2UgYXJlIGxlZnQgd2l0aDoKCiQkRShZX2kgfCBYX3tpMX0gPSBcZG90cyA9IFhfe2k1fSA9IDApID0gXGJldGFfMCQkCgppLmUuIHRoZSBpbnRlcmNlcHQuIElmIGVnZyAkaSQgd2FzIGZvc3RlcmVkIGJ5IHRoZSBFdXJvcGVhbiByb2JpbiAodHlwZSA0KSwgd2Ugd291bGQgaGF2ZToKCiQkRShZX2kgfCBYX3tpM30gPSAxKSA9IFxiZXRhXzAgKyBcYmV0YV8zJCQKClNvICRcYmV0YV8zJCBjYW4gYmUgaW50ZXJwcmV0ZWQgYXMgdGhlICpjaGFuZ2UqIGluIGF2ZXJhZ2UgbGVuZ3RoIG9mIGN1Y2tvbyBlZ2dzCmJldHdlZW4gdGhlIHJlZmVyZW5jZSBiaXJkIHR5cGUgKHRoZSBtZWFkb3cgcGlwaXQpIGFuZCB0aGUgRXVyb3BlYW4gcm9iaW4uIFRoZQpjb2VmZmljaWVudHMgY2FuIGJlIG5lZ2F0aXZlIG9yIHBvc2l0aXZlLCBzbyB0aGUgY2hhbmdlIGNhbiBiZSBhbiBpbmNyZWFzZSBvciBhCmRlY3JlYXNlLgoKVG8gZnVydGhlciBhaWQgd2l0aCBpbnRlcHJldGF0aW9uLCB3ZSBjYW4gdmlzdWFsaXplIHRoZSBtb2RlbCBkZXNpZ24gdXNpbmcgdGhlICoqRXhwbG9yZU1vZGVsTWF0cml4KiogcGFja2FnZToKCmBgYHtyfQpFeHBsb3JlTW9kZWxNYXRyaXg6OlZpc3VhbGl6ZURlc2lnbihDdWNrb28sIH50eXBlKSRwbG90bGlzdFtbMV1dCmBgYAoKCiMjIEZvcm11bGF0ZSBudWxsIGFuZCBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzCgpUaGUgbnVsbCBoeXBvdGhlc2lzIG9mIEFOT1ZBIHN0YXRlcyB0aGF0OgoKJEgwJDogVGhlIG1lYW4gZWdnIGxlbmd0aCBpcyBlcXVhbCBiZXR3ZWVuIHRoZSBkaWZmZXJlbnQgYmlyZCB0eXBlcy4KCkluIHRlcm1zIG9mIHRoZSBsaW5lYXIgbW9kZWw6CgokJApIXzA6XCBcYmV0YV8xID0gXGJldGFfMiA9IFxiZXRhXzMgPSBcYmV0YV80ID0gXGJldGFfNSA9IDAKJCQKClRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIG9mIEFOT1ZBIHN0YXRlcyB0aGF0OgokSEEkOiBUaGUgbWVhbiBlZ2cgbGVuZ3RoIGZvciBhdCBsZWFzdCBvbmUgYmlyZCB0eXBlIGlzIGRpZmZlcmVudApmcm9tIHRoZSBtZWFuIGVnZyBsZW5ndGggaW4gYXQgbGVhc3Qgb25lIG90aGVyIGJpcmQgdHlwZS4KCiQkCkhfQTpcIFxiZXRhX2kgXG5lcSBcYmV0YV9qIFx0ZXh0eyBmb3IgYXQgbGVhc3Qgb25lIH0gaSBcbmVxIGoKJCQKCiMjIFBhcmFtZXRlciBlc3RpbWF0aW9uCgpgYGB7cn0KbW9kIDwtIGxtKGxlbmd0aCB+IHR5cGUsIEN1Y2tvbykKc3VtbWFyeShtb2QpCmBgYAoKVGhlIG91dHB1dCBvZiB0aGUgbW9kZWwgc3VnZ2VzdHMgdGhhdCB0aGVyZSBhcmUgaW5kZWVkIGRpZmZlcmVuY2VzIGluIHRoZQoqYXZlcmFnZSogbGVuZ3RoIG9mIGN1Y2tvbyBlZ2dzIGJldHdlZW4gZGlmZmVyZW50IGZvc3RlciBwYXJlbnRzLiBOb3RlLCBob3dldmVyLAp0aGF0IGluIHRoZSBzdGFuZGFyZCBvdXRwdXQgb2YgYGxtKClgLCB0aGUgcC12YWx1ZXMgYXJlIG5vdCBhZGp1c3RlZCBmb3IKbXVsdGlwbGUgdGVzdGluZyAoYSB0b3BpYyB3aGljaCB3ZSB3aWxsIHRvdWNoIHVwb24gbGF0ZXIpLiBJbiBhZGRpdGlvbiwgdGhpcwptb2RlbCBvbmx5IHNob3dzIHRoZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIGZvc3RlciB0eXBlcyAyLTYgYW5kIHRoZSAqKnJlZmVyZW5jZQp0eXBlKiogKDEpLCByZXByZXNlbnRlZCBieSB0aGUgaW50ZXJjZXB0LgoKVGhlIHAtdmFsdWUgb2YgdGhlIEYtdGVzdCwgZ2l2ZW4gYXQgdGhlIGJvdHRvbSBvZiB0aGUgc3VtbWFyeSwgY29ycmVzcG9uZHMgdG8gYQoqKm9uZS13YXkgQU5PVkEqKiB3aGVyZSB0aGUgZnVsbCBtb2RlbCBpcyBjb21wYXJlZCB0byBhIHJlZHVjZWQgbW9kZWwgY29udGFpbmluZwpvbmx5IHRoZSBpbnRlcmNlcHQuIFRodXMsIGl0IGlzIHRlc3RpbmcgdGhlICpvbW5pYnVzKiBudWxsIGh5cG90aGVzaXMgdGhhdCBhbGwKc2xvcGUgY29lZmZpY2llbnRzICgkXGJldGFfMSQgLSAkXGJldGFfNSQpIGFyZSBlcXVhbCB0byAwLgoKIyMgQ2hlY2sgYXNzdW1wdGlvbnMKCkJlZm9yZSB3ZSBtYXkgcHJvY2VlZCB3aXRoIHRoZSBhbmFseXNpcywgd2UgbXVzdCBtYWtlIHN1cmUgdGhhdCBhbGwKYXNzdW1wdGlvbnMgZm9yIEFOT1ZBIGFyZSBtZXQuIEFOT1ZBIGhhcyB0aHJlZSBhc3N1bXB0aW9uczoKCjEuIFRoZSBvYnNlcnZhdGlvbnMgYXJlIGluZGVwZW5kZW50IG9mIGVhY2ggb3RoZXIgKGluIGFsbCBncm91cHMpCjIuIFRoZSBkYXRhIChsZW5ndGgpIG11c3QgYmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgKGluIGFsbCBncm91cHMpCjMuIFRoZSB2YXJpYWJpbGl0eSB3aXRoaW4gYWxsIGdyb3VwcyBpcyBzaW1pbGFyCgpUaGUgZmlyc3QgYXNzdW1wdGlvbiBpcyBtZXQsIGFzIHdlIG1heSBhc3N1bWUgdGhhdCB0aGVyZSBhcmUgbm8Kc3BlY2lmaWMgcGF0dGVybnMgb2YgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgcmFuZG9tbHkgc2VsZWN0ZWQgbmVzdHMuCgpUbyBjaGVjayB0aGUgbm9ybWFsaXR5IGFzc3VtcHRpb24sIHdlIHdpbGwgdXNlIFFRIHBsb3RzLgoKYGBge3J9CnBsb3QobW9kLCB3aGljaCA9IDIpCmBgYAoKYGBge3J9CkN1Y2tvbyAlPiUKICBnZ3Bsb3QoYWVzKHNhbXBsZSA9IGxlbmd0aCkpICsKICBnZW9tX3FxKCkgKwogIGdlb21fcXFfbGluZSgpICsKICBmYWNldF9ncmlkKH50eXBlKQpgYGAKClRoZXJlIHNlZW0gdG8gYmUgbm8gY2xlYXIgZGV2aWF0aW9ucyBmcm9tIG5vcm1hbGl0eS4KClRoZSB0aGlyZCBhc3N1bXB0aW9uIG9mIGVxdWFsIHZhcmlhbmNlcyBzZWVtcyB0byBiZSBtZXQgYmFzZWQgb24gdGhlCnZpc3VhbGl6YXRpb24gd2l0aCB0aGUgYm94cGxvdHMgKHNlZSBhYm92ZSkuCgpBcyBzdWNoLCB3ZSBtYXkgcHJvY2VlZCB3aXRoIHRoZSBBTk9WQSBhbmFseXNpcy4KCgojIyMgU2ltdWxhdGUgdG8gdHJhaW4geW91ciBza2lsbHMgaW4gYXNzZXNzaW5nIGFzc3VtcHRpb25zCgpgYGB7cn0Kc2V0LnNlZWQoMTAzMSkKc2lnbWEgPC0gbW9kICU+JSBzaWdtYSgpCmRhdGFIbHAgPC0gQ3Vja29vCgpzaW1Nb2RlbHMgPC0gbGlzdCgpCnBsb3RMaXN0IDwtIGxpc3QoKQpwbG90TGlzdFFRMSA8LSBsaXN0KCkKCnBhcihtZnJvdyA9IGMoMywgMykpCmZvciAoaSBpbiAxOjkpCnsKICBub2JzIDwtIEN1Y2tvbyAlPiUgbnJvdygpCiAgZGF0YUhscCR5U2ltIDwtIG1vZCRmaXQgKyBybm9ybShub2JzLCBzZCA9IHNpZ21hKQogIHNpbU1vZGVsc1tbaV1dIDwtIGxtKHlTaW0gfiB0eXBlLCBkYXRhSGxwKQogIHBsb3Qoc2ltTW9kZWxzW1tpXV0sIHdoaWNoID0gMikKICBwbG90TGlzdFtbaV1dIDwtIGRhdGFIbHAgJT4lCiAgICBnZ3Bsb3QoYWVzKHR5cGUsIHlTaW0pKSArCiAgICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BKSArCiAgICBnZW9tX2ppdHRlcigpCiAgcGxvdExpc3RRUTFbW2ldXSA8LSBkYXRhSGxwICU+JQogICAgZmlsdGVyKHR5cGUgPT0gIm1lYWRvdyIpICU+JQogICAgZ2dwbG90KGFlcyhzYW1wbGUgPSB5U2ltKSkgKwogICAgZ2VvbV9xcSgpICsKICAgIGdlb21fcXFfbGluZSgpICsKICAgIHhsYWIoIlFRIGZvciBtZWFkb3ciKQp9Cgpkby5jYWxsKGdyaWRFeHRyYTo6Z3JpZC5hcnJhbmdlLCBwbG90TGlzdCkKZG8uY2FsbChncmlkRXh0cmE6OmdyaWQuYXJyYW5nZSwgcGxvdExpc3RRUTEpCmBgYAoKVGhlIG1vc3QgZGV2aWF0aW5nIFFRLXBsb3Qgb2YgdGhlIHJlc2lkdWFscyBpbiB0aGUgbmluZSBzaW11bGF0aW9uIHJ1bnM6CgpgYGB7cn0KcGFyKG1mcm93ID0gYygxLCAxKSkKcGxvdChzaW1Nb2RlbHNbWzhdXSwgd2hpY2ggPSAyKQpgYGAKCgojIyBBTk9WQSBtb2RlbAoKV2UgcGVyZm9ybSB0aGUgQU5PVkEgdGVzdCB1c2luZyB0aGUgcmVzdWx0cyBvZiB0aGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwuCkVzc2VudGlhbGx5LCB3ZSB0ZXN0IHRoZSBmb2xsb3dpbmcgbnVsbCBoeXBvdGhlc2lzOgoKJCQKSF8wOlwgXGJldGFfMSA9IFxiZXRhXzIgPSBcYmV0YV8zID0gXGJldGFfNCA9IFxiZXRhXzUgPSAwCiQkCgp3aXRoIHRoZSBhbHRlcm5hdGl2ZSBiZWluZyB0aGF0IGF0IGxlYXN0IG9uZSBvZiB0aGUgcGFyYW1ldGVycyBpcyBkaWZmZXJlbnQgZnJvbQowLgoKYGBge3J9CmFub3ZhKG1vZCkKYGBgCgpUaGUgcC12YWx1ZSBvZiB0aGUgQU5PVkEgYW5hbHlzaXMgaXMgZXh0cmVtZWx5IHNpZ25pZmljYW50CihwLXZhbHVlIDwgMC4wMDEpLApzbyB3ZSByZWplY3QgdGhlIG51bGwgaHlwb3RoZXNpcyB0aGF0IHRoZSBtZWFuCmVnZyBsZW5ndGggaXMgZXF1YWwgYmV0d2VlbiB0aGUgZGlmZmVyZW50IGJpcmQgdHlwZXMuCldlIGNhbiBzYXkgdGhhdCB0aGUgbWVhbiBlZ2cgbGVuZ3RoIGlzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50CmJldHdlZW4gYXQgbGVhc3QgdHdvIGJpcmQgdHlwZXMgb24gdGhlIDUlIHNpZ25pZmljYW5jZSBsZXZlbC4KCkJhc2VkIG9uIHRoaXMgYW5hbHlzaXMsIHdlIGRvIG5vdCB5ZXQga25vdyBiZXR3ZWVuIHdoaWNoIHBhcnRpY3VsYXIKYmlyZCB0eXBlcyB0aGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UuIFRvIHN0dWR5IHRoaXMsIHdlIHdpbGwKcGVyZm9ybSBhICoqVHVrZXkgcG9zdC1ob2MgYW5hbHlzaXMqKi4KCiMjIFBvc3QtaG9jIGFuYWx5c2lzCgpXZSB3aWxsIHBlcmZvcm0gYSBwb3N0LWhvYyBhbmFseXNpcywgdG8gbG9vayBhdCB0aGUgZGlmZmVyZW5jZQppbiBlZ2cgbGVuZ3RoIGJldHdlZW4gZWFjaCBwYWlyd2lzZSBjb21wYXJpc29uIG9mIGJpcmQgdHlwZXMuCkltcG9ydGFudGx5LCB3aXRoIHRoaXMgc3RyYXRlZ3ksIHRoZSBwLXZhbHVlcyB3aWxsIGJlIGNvcnJlY3RseQphZGp1c3RlZCBmb3IgbXVsdGlwbGUgdGVzdGluZy4KClRoZSBudWxsIGh5cG90aGVzaXMgZm9yIGVhY2ggcGFpcndpc2UgdGVzdCBpcyB0aGF0IHRoZXJlIGlzIG5vCmRpZmZlcmVuY2UgaW4gdGhlIG1lYW4gZWdnIGxlbmd0aCBiZXR3ZWVuIGJvdGggYmlyZCB0eXBlcy4KClRoZSBhbHRlcm5hdGl2ZSBoeXBvdGhlc2lzIGZvciBlYWNoIHBhaXJ3aXNlIHRlc3Qgc3RhdGVzIHRoYXQgdGhlcmUKaXMgaW5kZWVkIGEgZGlmZmVyZW5jZSBpbiB0aGUgbWVhbiBlZ2cgbGVuZ3RoIGJldHdlZW4gYm90aCBiaXJkIHR5cGVzLgoKV2Ugd2lsbCBhbHNvIGNhbGN1bGF0ZSB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBvbiB0aGUgbWVhbiBkaWZmZXJlbmNlcy4KClRoZSBwb3N0LWhvYyBhbmFseXNpcyBpcyBjYXJyaWVkIG91dCB1c2luZyB0aGUgYGdsaHQoKWAgKCJHZW5lcmFsIExpbmVhcgpIeXBvdGhlc2VzIikgZnVuY3Rpb24gZnJvbSB0aGUgKm11bHRjb21wKiBwYWNrYWdlLiBXZSBhcHBseSB0aGlzIHRvIG91ciBsaW5lYXIKbW9kZWwgb2JqZWN0IGBtb2RgIGFuZCBzcGVjaWZ5IGluIHRoZSBgbGluZmN0PWAgYXJndW1lbnQgdGhhdCB3ZSB3YW50IHRvIHBlcmZvcm0KKm11bHRpcGxlIGNvbXBhcmlzb25zKiAoYG1jcGApLCB1c2luZyBUdWtleSdzIG1ldGhvZC4gV2Ugc3RvcmUgdGhlIG91dHB1dCBvZgpgZ2xodCgpYCBhbmQgdGhlbiBkaXNwbGF5IHRoZSByZXN1bHRzIHVzaW5nIHRoZSBgc3VtbWFyeSgpYCBmdW5jdGlvbiBhbmQKY2FsY3VsYXRpbmcgY29uZmlkZW5jZSBpbnRlcnZhbHMuCgpgYGB7cn0KbWNwIDwtIGdsaHQobW9kLCBsaW5mY3QgPSBtY3AodHlwZSA9ICJUdWtleSIpKQpzdW1tYXJ5KG1jcCkKY29uZmludChtY3ApCmBgYAoKV2UgY2FuIGFsc28gdmlzdWFsaXplIHRoZSBjb25maWRlbmNlIGludGVydmFsIGJ5IGNhbGxpbmcgYHBsb3QoKWAgb24gdGhlIGBtY3BgIG9iamVjdDoKCmBgYHtyfQpwbG90KG1jcCkKYGBgCgojIyBDb25jbHVzaW9uCgpUaGUgYXNzb2NpYXRpb24gYmV0d2VlbiB0aGUgbWVhbiBsZW5ndGggb2YgYSBjdWNrb28ncyBlZ2cgYW5kIHRoZSBmb3N0ZXIgYmlyZCBzcGVjaWVzIGlzIGV4dHJlbWVseSBzaWduaWZpY2FudCAocCA8PCAwLjAwMSkuCgpUaGUgbWVhbiBsZW5ndGggb2YgY3Vja29vJ3MgZWdncyBpbiBuZXN0cyBvZiB0aGUgRXVyYXNpYW4Kd3JlbiBhcmUgc21hbGxlciBhcyBjb21wYXJlZCB0byB0aG9zZSBmcm9tIGFsbCBvdGhlciBiaXJkCnNwZWNpZXMgaW4gdGhlIHN0dWR5OgoKLSB0aGUgbWVhZG93IHBpcGl0IChhZGp1c3RlZCBwLXZhbHVlID0gYHIgc3VtbWFyeShtY3ApJHRlc3QkcHZhbHVlc1tuYW1lcyhzdW1tYXJ5KG1jcCkkdGVzdCR0c3RhdCkgPT0gIndyZW4gLSBtZWFkb3ciXSAlPiUgZm9ybWF0KGRpZ2l0cz0xKWAsIG1lYW4gZGlmZmVyZW5jZSA9IGByIHJvdW5kKGNvbmZpbnQobWNwKSRjb25maW50WyJ3cmVuIC0gbWVhZG93IiwxXSwxKWBtbSwgOTUlIENJIFtgciByb3VuZChjb25maW50KG1jcCkkY29uZmludFsid3JlbiAtIG1lYWRvdyIsLTFdLDEpYF0pCi0gdGhlIHRyZWUgcGlwaXQgKGFkanVzdGVkIHAtdmFsdWUgPSBgciBzdW1tYXJ5KG1jcCkkdGVzdCRwdmFsdWVzW25hbWVzKHN1bW1hcnkobWNwKSR0ZXN0JHRzdGF0KSA9PSAid3JlbiAtIHRyZWUiXSAlPiUgZm9ybWF0KGRpZ2l0cz0xKWAsIG1lYW4gZGlmZmVyZW5jZSA9IGByIHJvdW5kKGNvbmZpbnQobWNwKSRjb25maW50WyJ3cmVuIC0gdHJlZSIsMV0sMSlgbW0sIDk1JSBDSSBbYHIgcm91bmQoY29uZmludChtY3ApJGNvbmZpbnRbIndyZW4gLSB0cmVlIiwtMV0sMSlgXSkKLSB0aGUgZHVubm9jayAoYWRqdXN0ZWQgcC12YWx1ZSA9IGByIHN1bW1hcnkobWNwKSR0ZXN0JHB2YWx1ZXNbbmFtZXMoc3VtbWFyeShtY3ApJHRlc3QkdHN0YXQpID09ICJ3cmVuIC0gZHVubm9jayJdICU+JSBmb3JtYXQoZGlnaXRzPTEpYCwgbWVhbiBkaWZmZXJlbmNlID0gYHIgcm91bmQoY29uZmludChtY3ApJGNvbmZpbnRbIndyZW4gLSBkdW5ub2NrIiwxXSwxKWBtbSwgOTUlIENJIFtgciByb3VuZChjb25maW50KG1jcCkkY29uZmludFsid3JlbiAtIGR1bm5vY2siLC0xXSwxKWBdKQotIHRoZSBFdXJvcGVhbiByb2JpbiAoYWRqdXN0ZWQgcC12YWx1ZSA9IGByIHN1bW1hcnkobWNwKSR0ZXN0JHB2YWx1ZXNbbmFtZXMoc3VtbWFyeShtY3ApJHRlc3QkdHN0YXQpID09ICJ3cmVuIC0gcm9iaW4iXSAlPiUgZm9ybWF0KGRpZ2l0cz0xKWAsIG1lYW4gZGlmZmVyZW5jZSA9IGByIHJvdW5kKGNvbmZpbnQobWNwKSRjb25maW50WyJ3cmVuIC0gcm9iaW4iLDFdLDEpYG1tLCA5NSUgQ0kgW2ByIHJvdW5kKGNvbmZpbnQobWNwKSRjb25maW50WyJ3cmVuIC0gcm9iaW4iLC0xXSwxKWBdKQotIHRoZSB3aGl0ZSB3YWd0YWlsIChhZGp1c3RlZCBwLXZhbHVlID0gYHIgc3VtbWFyeShtY3ApJHRlc3QkcHZhbHVlc1tuYW1lcyhzdW1tYXJ5KG1jcCkkdGVzdCR0c3RhdCkgPT0gIndyZW4gLSB3YWd0YWlsIl0gJT4lIGZvcm1hdChkaWdpdHM9MSlgLCBtZWFuIGRpZmZlcmVuY2UgPSBgciByb3VuZChjb25maW50KG1jcCkkY29uZmludFsid3JlbiAtIHdhZ3RhaWwiLDFdLDEpYG1tLCA5NSUgQ0kgW2ByIHJvdW5kKGNvbmZpbnQobWNwKSRjb25maW50WyJ3cmVuIC0gd2FndGFpbCIsLTFdLDEpYF0pCgpUaGVyZSBpcyBubyBldmlkZW5jZSB0YWh0IHRoZSBtZWFuIGxlbmd0aCBvZiB0aGUgY3Vja29vIGJpcmQncyBlZ2dzIGZvciBhbGwKb3RoZXIgcGFpcndpc2UgY29tcGFyaXNvbnMgYmV0d2VlbiBmb3N0ZXIgYmlyZCBzcGVjaWVzIGFyZSBzaWduaWZpY2FudGx5CmRpZmZlcmVudCBhdCB0aGUgNSUgbGV2ZWwuCg==