Getting started

Aims

There is further information in the Introduction to revdbayes vignette.

# We need the evdbayes, revdbayes, ggplot2, bayesplot and coda packages
pkg <- c("evdbayes", "revdbayes", "ggplot2", "bayesplot", "coda")
pkg_list <- pkg[!pkg %in% installed.packages()[, "Package"]]
install.packages(pkg_list)
# Load all packages
invisible(lapply(pkg, library, character.only = TRUE))
# Simulation sample size
n <- 10000

GP model for threshold excesses

GP priors

# Information about the set_prior() function
# You can choose from a set of options, or create your own
?set_prior
# Set the threshold
u <- quantile(gom, probs = 0.65)
# Set an 'uninformative' prior for the GP parameters
fp <- set_prior(prior = "flat", model = "gp", min_xi = -1)

GP posteriors

# Information about the rpost function
?rpost
# Information about the gom (significant wave heights) data
?gom
# Sample on (sigma_u, xi) scale
gp1 <- rpost(n = n, model = "gp", prior = fp, thresh = u, data = gom,
             rotate = FALSE)
# Rotation
gp2 <- rpost(n = n, model = "gp", prior = fp, thresh = u, data = gom)
# Box-Cox transformation (after transformation to positivity)
gp3 <- rpost(n = n, model = "gp", prior = fp, thresh = u, data = gom,
             rotate = FALSE, trans = "BC")
# Box-Cox transformation and then rotation
gp4 <- rpost(n = n, model = "gp", prior = fp, thresh = u, data = gom,
             trans = "BC")

Comparing approaches

# Samples and posterior density contours
plot(gp1, main = paste("mode relocation only, pa = ", round(gp1$pa, 3)))
plot(gp2, ru_scale = TRUE, main = paste("rotation, pa = ", round(gp2$pa, 3)))
plot(gp3, ru_scale = TRUE, main = paste("Box-Cox, pa = ", round(gp3$pa, 3)))
plot(gp4, ru_scale = TRUE, main = paste("Box-Cox and rotation, pa = ",
                                        round(gp4$pa, 3)))

rpost_rcpp() is faster than rpost(). See the rusting faster vignette.

gp2 <- rpost_rcpp(n = n, model = "gp", prior = fp, thresh = u, data = gom)

Suggestion: increase the threshold and see how the appearance of the posterior changes.

Posterior predictive checking

There is further information in the Posterior predictive EV inference vignette.

# nrep = 50 asks for 50 fake replicates of the original data
# For each of 50 posterior samples of the parameters a dataset is simulated 
gpg <- rpost(n = n, model = "gp", prior = fp, thresh = u, data = gom, 
             nrep = 50)
# Information about pp_check.evpost
?pp_check.evpost
# Compare real and fake datasets
pp_check(gpg, type = "multiple", subtype = "dens") + ggtitle("GP kernel density estimates")
# Compare real and fake summary statistics
pp_check(gpg, stat = "max")

Posterior predictive EV inference

Binomial-GP model for threshold exceedances

Modelling threshold excesses is only part of the story. We also need to model the proportion of observations that exceed the threshold.

bp <- set_bin_prior(prior = "jeffreys")
# We need to provide the mean number of observations per year 
# The data cover a period of 105 years
npy_gom <- length(gom)/105
bgpg <- rpost(n = 1000, model = "bingp", prior = fp, thresh = u, data = gom,
              bin_prior = bp, npy = npy_gom, nrep = 50)

We can make predictive inferences about the largest value \(M_N\) to be observed over a time horizon of \(N\) years.

# Information about pp_check.evpost
?predict.evpost
# Predictive density of the largest value in `n_years' years
plot(predict(bgpg, type = "d", n_years = 200))
# Predictive intervals (equi-tailed and shortest possible)
i_bgpp <- predict(bgpg, n_years = 200, level = c(95, 99), hpd = TRUE)
plot(i_bgpp, which_int = "both")
i_bgpp$short 
# The predictive 100, 200 and 500 year return levels 
predict(bgpg, type = "q", n_years = 1, x = c(0.99, 0.995, 0.998))$y

See Northrop and Attalides (2017) for an analysis of these data using an informative prior.

PP model for threshold exceedances

We compare three ways to sample from a PP posterior distribution

  1. Parameterise in terms of annual maxima
  2. Wadsworth et al. (2010): parameterise to make \(\mu\) orthogonal to \((\sigma, \xi)\)
  3. Empirical rotation to reduce association
# Information about the rainfall data
?revdbayes::rainfall
# Set a threshold and use the prior from the evdbayes user guide
rthresh <- 40
prrain <- evdbayes::prior.quant(shape = c(38.9,7.1,47), scale = c(1.5,6.3,2.6))
# 1. Number of blocks = number of years of data (54)
r1 <- rpost(n = n, model = "pp", prior = prrain, data = rainfall,
            thresh = rthresh, noy = 54, rotate = FALSE)
plot(r1)
# 2. Number of blocks = number of threshold excesses (use_noy = FALSE)
n_exc <- sum(rainfall > rthresh, na.rm = TRUE)
r2 <- rpost(n = n, model = "pp", prior = prrain, data = rainfall, 
            thresh = rthresh, noy = 54, use_noy = FALSE, rotate = FALSE)
plot(r2, ru_scale = TRUE)
# 3. # Rotation about maximum a posteriori estimate (MAP)
r3 <- rpost(n = n, model = "pp", prior = prrain, data = rainfall, 
            thresh = rthresh, noy = 54)
plot(r3, ru_scale = TRUE)
c(r1$pa, r2$pa, r3$pa)

GEV model for block maxima

# Information about the portpirie data
?revdbayes::portpirie
# Use the prior from the evdbayes user guide
mat <- diag(c(10000, 10000, 100))         
pn <- set_prior(prior = "norm", model = "gev", mean = c(0, 0, 0), cov = mat)

revdbayes

mat <- diag(c(10000, 10000, 100))
gevp  <- rpost_rcpp(n = n, model = "gev", prior = pn, data = portpirie)
# Information about plot.evpost
?plot.evpost
# Can use the plots from the bayesplot package
plot(gevp, use_bayesplot = TRUE, fun_name = "dens")
plot(gevp, use_bayesplot = TRUE, pars = "xi", prob = 0.95)

evdbayes

# evdbayes has a function ar.choice to help set the proposal SDs
# It does this by searching for values that achieve approximately
# target values for the acceptance rates (default 0.4 for all parameters)
?ar.choice
# Initialise evdbayes' Markov chain at the estimated posterior mean
init <- colMeans(gevp$sim_vals)
prop.sd.auto <- ar.choice(init = init, prior = pn, lh = "gev", 
                          data = portpirie, psd = rep(0.01, 3), 
                          tol = rep(0.02, 3))$psd
post <- posterior(n, init = init, prior = pn, lh = "gev", 
                  data = portpirie, psd = prop.sd.auto)
for (i in 1:3) plot(post[, i], ylab = c("mu","sigma","xi")[i]) 
post_for_coda <- coda::mcmc(post)
# Assuming no burn-in period
burnin <- 0                 
post_for_coda <- window(post_for_coda, start = burnin + 1)
# Trace plots and KDEs
plot(post_for_coda)
# The sampled values are autocorrelated
coda::acfplot(post_for_coda)
# Effective sample sizes (10,000 for revdbayes)
coda::effectiveSize(post_for_coda)
  • In practice one would run multiple chains and use the Gelman-Rubin convergence diagnostic, e.g. gelman.diag in the coda package.
  • The Introduction to revdbayes shows that the posterior samples from evdbayes and revdbayes are in agreement.
LS0tCnRpdGxlOiAiRVZBIDIwMjEgcmV2ZGJheWVzIGV4ZXJjaXNlcyAyIgpzdWJ0aXRsZTogIkVWIGluZmVyZW5jZSB1c2luZyByZXZkYmF5ZXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIEdldHRpbmcgc3RhcnRlZAoKKiBJbnN0YWxsIFtSU3R1ZGlvIERlc2t0b3BdKGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3Byb2R1Y3RzL3JzdHVkaW8vZG93bmxvYWQvI2Rvd25sb2FkKSAoaWYgeW91IGRvIG5vdCBhbHJlYWR5IGhhdmUgaXQpIGFuZCBvcGVuIGl0CiogU2F2ZSBbZXgycmV2ZGJheWVzLlJtZF0oaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3BhdWxub3J0aHJvcC9yZXZkYmF5ZXMvbWFzdGVyL3ZpZ25ldHRlcy9leDJyZXZkYmF5ZXMuUm1kKSB0byB5b3VyIGNvbXB1dGVyICh0aGVyZSBpcyBhbHNvIGEgbGluayB0byBpdCBhYm92ZSkKKiBPcGVuIGBleDJyZXZkYmF5ZXMuUm1kYCBpbiBSc3R1ZGlvCiogVGhlIFIgY29kZSBpcyBhcnJhbmdlZCBpbiAqY2h1bmtzKiBoaWdobGlnaHRlZCBpbiBncmV5CiogWW91IGNhbiBydW4gdGhlIGNvZGUgaW4gYSBjaHVuayBieSBjbGlja2luZyBvbiB0aGUgKipncmVlbiB0cmlhbmdsZSoqIG9uIHRoZSB0b3AgcmlnaHQgb2YgdGhlIGNodW5rCiogVGhlcmUgaXMgaW5mb3JtYXRpb24gYWJvdXQgRXhlcmNpc2VzIDIgKGFuZCBFeGVyY2lzZXMgMSkgaW4gdGhlIFtFVkEyMDIxIHJldmRiYXllcyBzbGlkZXNdKGh0dHBzOi8vcGF1bG5vcnRocm9wLmdpdGh1Yi5pby9yZXZkYmF5ZXMvYXJ0aWNsZXMvRVZBMjAyMXJldmRiYXllcy5odG1sKQoKIyMgQWltcwoKKiBDb21wYXJlIFJPVSBhcHByb2FjaGVzIGZvciBzYW1wbGluZyBmcm9tIGEgR1AgcG9zdGVyaW9yCiogUGVyZm9ybSBwb3N0ZXJpb3IgcHJlZGljdGl2ZSBjaGVja2luZyBhbmQgaW5mZXJlbmNlCiogQ29uc2lkZXIgaG93IHRvIHNhbXBsZSBlZmZpY2llbnRseSBmcm9tIGEgUFAgcG9zdGVyaW9yIAoqIENvbXBhcmUgYHJldmRiYXllc2AgYW5kIGBldmRiYXllc2AgZm9yIHNhbXBsaW5nIGZyb20gYSBHRVYgcG9zdGVyaW9yCgpUaGVyZSBpcyBmdXJ0aGVyIGluZm9ybWF0aW9uIGluIHRoZSBbSW50cm9kdWN0aW9uIHRvIHJldmRiYXllc10oaHR0cHM6Ly9wYXVsbm9ydGhyb3AuZ2l0aHViLmlvL3JldmRiYXllcy9hcnRpY2xlcy9yZXZkYmF5ZXMtYS12aWduZXR0ZS5odG1sKSB2aWduZXR0ZS4KCmBgYHtyIHBhY2thZ2VzLCBtZXNzYWdlPUZBTFNFfQojIFdlIG5lZWQgdGhlIGV2ZGJheWVzLCByZXZkYmF5ZXMsIGdncGxvdDIsIGJheWVzcGxvdCBhbmQgY29kYSBwYWNrYWdlcwpwa2cgPC0gYygiZXZkYmF5ZXMiLCAicmV2ZGJheWVzIiwgImdncGxvdDIiLCAiYmF5ZXNwbG90IiwgImNvZGEiKQpwa2dfbGlzdCA8LSBwa2dbIXBrZyAlaW4lIGluc3RhbGxlZC5wYWNrYWdlcygpWywgIlBhY2thZ2UiXV0KaW5zdGFsbC5wYWNrYWdlcyhwa2dfbGlzdCkKIyBMb2FkIGFsbCBwYWNrYWdlcwppbnZpc2libGUobGFwcGx5KHBrZywgbGlicmFyeSwgY2hhcmFjdGVyLm9ubHkgPSBUUlVFKSkKYGBgCgpgYGB7ciBzZXR1cH0KIyBTaW11bGF0aW9uIHNhbXBsZSBzaXplCm4gPC0gMTAwMDAKYGBgCgojIyBHUCBtb2RlbCBmb3IgdGhyZXNob2xkIGV4Y2Vzc2VzCgojIyMgR1AgcHJpb3JzCgpgYGB7ciBzZXRQcmlvcnN9CiMgSW5mb3JtYXRpb24gYWJvdXQgdGhlIHNldF9wcmlvcigpIGZ1bmN0aW9uCiMgWW91IGNhbiBjaG9vc2UgZnJvbSBhIHNldCBvZiBvcHRpb25zLCBvciBjcmVhdGUgeW91ciBvd24KP3NldF9wcmlvcgojIFNldCB0aGUgdGhyZXNob2xkCnUgPC0gcXVhbnRpbGUoZ29tLCBwcm9icyA9IDAuNjUpCiMgU2V0IGFuICd1bmluZm9ybWF0aXZlJyBwcmlvciBmb3IgdGhlIEdQIHBhcmFtZXRlcnMKZnAgPC0gc2V0X3ByaW9yKHByaW9yID0gImZsYXQiLCBtb2RlbCA9ICJncCIsIG1pbl94aSA9IC0xKQpgYGAKCiMjIyBHUCBwb3N0ZXJpb3JzCgpgYGB7ciBwb3N0ZXJpb3JTYW1wbGluZ30KIyBJbmZvcm1hdGlvbiBhYm91dCB0aGUgcnBvc3QgZnVuY3Rpb24KP3Jwb3N0CiMgSW5mb3JtYXRpb24gYWJvdXQgdGhlIGdvbSAoc2lnbmlmaWNhbnQgd2F2ZSBoZWlnaHRzKSBkYXRhCj9nb20KIyBTYW1wbGUgb24gKHNpZ21hX3UsIHhpKSBzY2FsZQpncDEgPC0gcnBvc3QobiA9IG4sIG1vZGVsID0gImdwIiwgcHJpb3IgPSBmcCwgdGhyZXNoID0gdSwgZGF0YSA9IGdvbSwKICAgICAgICAgICAgIHJvdGF0ZSA9IEZBTFNFKQojIFJvdGF0aW9uCmdwMiA8LSBycG9zdChuID0gbiwgbW9kZWwgPSAiZ3AiLCBwcmlvciA9IGZwLCB0aHJlc2ggPSB1LCBkYXRhID0gZ29tKQojIEJveC1Db3ggdHJhbnNmb3JtYXRpb24gKGFmdGVyIHRyYW5zZm9ybWF0aW9uIHRvIHBvc2l0aXZpdHkpCmdwMyA8LSBycG9zdChuID0gbiwgbW9kZWwgPSAiZ3AiLCBwcmlvciA9IGZwLCB0aHJlc2ggPSB1LCBkYXRhID0gZ29tLAogICAgICAgICAgICAgcm90YXRlID0gRkFMU0UsIHRyYW5zID0gIkJDIikKIyBCb3gtQ294IHRyYW5zZm9ybWF0aW9uIGFuZCB0aGVuIHJvdGF0aW9uCmdwNCA8LSBycG9zdChuID0gbiwgbW9kZWwgPSAiZ3AiLCBwcmlvciA9IGZwLCB0aHJlc2ggPSB1LCBkYXRhID0gZ29tLAogICAgICAgICAgICAgdHJhbnMgPSAiQkMiKQpgYGAKCiMjIyBDb21wYXJpbmcgYXBwcm9hY2hlcwoKYGBge3IgR1BwbG90c30KIyBTYW1wbGVzIGFuZCBwb3N0ZXJpb3IgZGVuc2l0eSBjb250b3VycwpwbG90KGdwMSwgbWFpbiA9IHBhc3RlKCJtb2RlIHJlbG9jYXRpb24gb25seSwgcGEgPSAiLCByb3VuZChncDEkcGEsIDMpKSkKcGxvdChncDIsIHJ1X3NjYWxlID0gVFJVRSwgbWFpbiA9IHBhc3RlKCJyb3RhdGlvbiwgcGEgPSAiLCByb3VuZChncDIkcGEsIDMpKSkKcGxvdChncDMsIHJ1X3NjYWxlID0gVFJVRSwgbWFpbiA9IHBhc3RlKCJCb3gtQ294LCBwYSA9ICIsIHJvdW5kKGdwMyRwYSwgMykpKQpwbG90KGdwNCwgcnVfc2NhbGUgPSBUUlVFLCBtYWluID0gcGFzdGUoIkJveC1Db3ggYW5kIHJvdGF0aW9uLCBwYSA9ICIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3VuZChncDQkcGEsIDMpKSkKYGBgCgpgYHJwb3N0X3JjcHAoKWBgIGlzIGZhc3RlciB0aGFuIGBgcnBvc3QoKWBgLiAgU2VlIHRoZSBbcnVzdGluZyBmYXN0ZXJdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZXZkYmF5ZXMvdmlnbmV0dGVzL3JldmRiYXllcy1iLXVzaW5nLXJjcHAtdmlnbmV0dGUuaHRtbCkgdmlnbmV0dGUuCgpgYGB7ciBmYXN0ZXJ9CmdwMiA8LSBycG9zdF9yY3BwKG4gPSBuLCBtb2RlbCA9ICJncCIsIHByaW9yID0gZnAsIHRocmVzaCA9IHUsIGRhdGEgPSBnb20pCmBgYAoKU3VnZ2VzdGlvbjogaW5jcmVhc2UgdGhlIHRocmVzaG9sZCBhbmQgc2VlIGhvdyB0aGUgYXBwZWFyYW5jZSBvZiB0aGUgcG9zdGVyaW9yIGNoYW5nZXMuCgojIyBQb3N0ZXJpb3IgcHJlZGljdGl2ZSBjaGVja2luZwoKVGhlcmUgaXMgZnVydGhlciBpbmZvcm1hdGlvbiBpbiB0aGUgW1Bvc3RlcmlvciBwcmVkaWN0aXZlIEVWIGluZmVyZW5jZV0oaHR0cHM6Ly9wYXVsbm9ydGhyb3AuZ2l0aHViLmlvL3JldmRiYXllcy9hcnRpY2xlcy9yZXZkYmF5ZXMtYy1wcmVkaWN0aXZlLXZpZ25ldHRlLmh0bWwpIHZpZ25ldHRlLgoKYGBge3IgR1BjaGVja30KIyBucmVwID0gNTAgYXNrcyBmb3IgNTAgZmFrZSByZXBsaWNhdGVzIG9mIHRoZSBvcmlnaW5hbCBkYXRhCiMgRm9yIGVhY2ggb2YgNTAgcG9zdGVyaW9yIHNhbXBsZXMgb2YgdGhlIHBhcmFtZXRlcnMgYSBkYXRhc2V0IGlzIHNpbXVsYXRlZCAKZ3BnIDwtIHJwb3N0KG4gPSBuLCBtb2RlbCA9ICJncCIsIHByaW9yID0gZnAsIHRocmVzaCA9IHUsIGRhdGEgPSBnb20sIAogICAgICAgICAgICAgbnJlcCA9IDUwKQojIEluZm9ybWF0aW9uIGFib3V0IHBwX2NoZWNrLmV2cG9zdAo/cHBfY2hlY2suZXZwb3N0CiMgQ29tcGFyZSByZWFsIGFuZCBmYWtlIGRhdGFzZXRzCnBwX2NoZWNrKGdwZywgdHlwZSA9ICJtdWx0aXBsZSIsIHN1YnR5cGUgPSAiZGVucyIpICsgZ2d0aXRsZSgiR1Aga2VybmVsIGRlbnNpdHkgZXN0aW1hdGVzIikKIyBDb21wYXJlIHJlYWwgYW5kIGZha2Ugc3VtbWFyeSBzdGF0aXN0aWNzCnBwX2NoZWNrKGdwZywgc3RhdCA9ICJtYXgiKQpgYGAKCiogV291bGQgeW91IGJlIGFibGUgdG8gc3BvdCB0aGUgcmVhbCBkYXRhc2V0IG9yIHN1bW1hcnkgc3RhdGlzdGljIGlmIGl0IHdhcyBub3QgaGlnaGxpZ2h0ZWQ/CiogT3B0aW9uOiB5b3UgY291bGQgcGxheSB3aXRoIHRoZSBhcmd1bWVudHMgCiAgICAtIGB0eXBlYCBhbmQvb3IgYHN1YnR5cGVgIGZvciB0aGUgZmlyc3QgcGxvdAogICAgLSBgc3RhdGAgZm9yIHRoZSBzZWNvbmQgcGxvdAoKIyMgUG9zdGVyaW9yIHByZWRpY3RpdmUgRVYgaW5mZXJlbmNlCgojIyMgQmlub21pYWwtR1AgbW9kZWwgZm9yIHRocmVzaG9sZCBleGNlZWRhbmNlcwoKTW9kZWxsaW5nIHRocmVzaG9sZCBleGNlc3NlcyBpcyBvbmx5IHBhcnQgb2YgdGhlIHN0b3J5LiAgV2UgYWxzbyBuZWVkIHRvIG1vZGVsIHRoZSBwcm9wb3J0aW9uIG9mIG9ic2VydmF0aW9ucyB0aGF0IGV4Y2VlZCB0aGUgdGhyZXNob2xkLgoKYGBge3IgQmluR1B9CmJwIDwtIHNldF9iaW5fcHJpb3IocHJpb3IgPSAiamVmZnJleXMiKQojIFdlIG5lZWQgdG8gcHJvdmlkZSB0aGUgbWVhbiBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zIHBlciB5ZWFyIAojIFRoZSBkYXRhIGNvdmVyIGEgcGVyaW9kIG9mIDEwNSB5ZWFycwpucHlfZ29tIDwtIGxlbmd0aChnb20pLzEwNQpiZ3BnIDwtIHJwb3N0KG4gPSAxMDAwLCBtb2RlbCA9ICJiaW5ncCIsIHByaW9yID0gZnAsIHRocmVzaCA9IHUsIGRhdGEgPSBnb20sCiAgICAgICAgICAgICAgYmluX3ByaW9yID0gYnAsIG5weSA9IG5weV9nb20sIG5yZXAgPSA1MCkKYGBgICAgICAgICAgICAgICAKCldlIGNhbiBtYWtlIHByZWRpY3RpdmUgaW5mZXJlbmNlcyBhYm91dCB0aGUgbGFyZ2VzdCB2YWx1ZSAkTV9OJCB0byBiZSBvYnNlcnZlZCBvdmVyIGEgdGltZSBob3Jpem9uIG9mICROJCB5ZWFycy4KCmBgYHtyIHByZWRCaW5HUH0KIyBJbmZvcm1hdGlvbiBhYm91dCBwcF9jaGVjay5ldnBvc3QKP3ByZWRpY3QuZXZwb3N0CiMgUHJlZGljdGl2ZSBkZW5zaXR5IG9mIHRoZSBsYXJnZXN0IHZhbHVlIGluIGBuX3llYXJzJyB5ZWFycwpwbG90KHByZWRpY3QoYmdwZywgdHlwZSA9ICJkIiwgbl95ZWFycyA9IDIwMCkpCiMgUHJlZGljdGl2ZSBpbnRlcnZhbHMgKGVxdWktdGFpbGVkIGFuZCBzaG9ydGVzdCBwb3NzaWJsZSkKaV9iZ3BwIDwtIHByZWRpY3QoYmdwZywgbl95ZWFycyA9IDIwMCwgbGV2ZWwgPSBjKDk1LCA5OSksIGhwZCA9IFRSVUUpCnBsb3QoaV9iZ3BwLCB3aGljaF9pbnQgPSAiYm90aCIpCmlfYmdwcCRzaG9ydCAKYGBgCgpgYGB7cn0KIyBUaGUgcHJlZGljdGl2ZSAxMDAsIDIwMCBhbmQgNTAwIHllYXIgcmV0dXJuIGxldmVscyAKcHJlZGljdChiZ3BnLCB0eXBlID0gInEiLCBuX3llYXJzID0gMSwgeCA9IGMoMC45OSwgMC45OTUsIDAuOTk4KSkkeQpgYGAKU2VlIFtOb3J0aHJvcCBhbmQgQXR0YWxpZGVzICgyMDE3KV0oaHR0cHM6Ly9kb2kub3JnLzEwLjExMTEvcnNzYy4xMjE1OSkgZm9yIGFuIGFuYWx5c2lzIG9mIHRoZXNlIGRhdGEgdXNpbmcgYW4gaW5mb3JtYXRpdmUgcHJpb3IuCgojIyBQUCBtb2RlbCBmb3IgdGhyZXNob2xkIGV4Y2VlZGFuY2VzCgpXZSBjb21wYXJlIHRocmVlIHdheXMgdG8gc2FtcGxlIGZyb20gYSBQUCBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uCgoxLiBQYXJhbWV0ZXJpc2UgaW4gdGVybXMgb2YgYW5udWFsIG1heGltYQoyLiBbV2Fkc3dvcnRoIGV0IGFsLiAoMjAxMCldKGh0dHBzOi8vZG9pLm9yZy8xMC4xMjE0LzEwLUFPQVMzMzMpOiBwYXJhbWV0ZXJpc2UgdG8gbWFrZSAkXG11JCBvcnRob2dvbmFsIHRvICQoXHNpZ21hLCBceGkpJCAKMy4gRW1waXJpY2FsIHJvdGF0aW9uIHRvIHJlZHVjZSBhc3NvY2lhdGlvbgoKYGBge3IgUFBzZXR1cH0KIyBJbmZvcm1hdGlvbiBhYm91dCB0aGUgcmFpbmZhbGwgZGF0YQo/cmV2ZGJheWVzOjpyYWluZmFsbAojIFNldCBhIHRocmVzaG9sZCBhbmQgdXNlIHRoZSBwcmlvciBmcm9tIHRoZSBldmRiYXllcyB1c2VyIGd1aWRlCnJ0aHJlc2ggPC0gNDAKcHJyYWluIDwtIGV2ZGJheWVzOjpwcmlvci5xdWFudChzaGFwZSA9IGMoMzguOSw3LjEsNDcpLCBzY2FsZSA9IGMoMS41LDYuMywyLjYpKQpgYGAKCmBgYHtyIFBQc2FtcGxpbmd9CiMgMS4gTnVtYmVyIG9mIGJsb2NrcyA9IG51bWJlciBvZiB5ZWFycyBvZiBkYXRhICg1NCkKcjEgPC0gcnBvc3QobiA9IG4sIG1vZGVsID0gInBwIiwgcHJpb3IgPSBwcnJhaW4sIGRhdGEgPSByYWluZmFsbCwKICAgICAgICAgICAgdGhyZXNoID0gcnRocmVzaCwgbm95ID0gNTQsIHJvdGF0ZSA9IEZBTFNFKQpwbG90KHIxKQojIDIuIE51bWJlciBvZiBibG9ja3MgPSBudW1iZXIgb2YgdGhyZXNob2xkIGV4Y2Vzc2VzICh1c2Vfbm95ID0gRkFMU0UpCm5fZXhjIDwtIHN1bShyYWluZmFsbCA+IHJ0aHJlc2gsIG5hLnJtID0gVFJVRSkKcjIgPC0gcnBvc3QobiA9IG4sIG1vZGVsID0gInBwIiwgcHJpb3IgPSBwcnJhaW4sIGRhdGEgPSByYWluZmFsbCwgCiAgICAgICAgICAgIHRocmVzaCA9IHJ0aHJlc2gsIG5veSA9IDU0LCB1c2Vfbm95ID0gRkFMU0UsIHJvdGF0ZSA9IEZBTFNFKQpwbG90KHIyLCBydV9zY2FsZSA9IFRSVUUpCiMgMy4gIyBSb3RhdGlvbiBhYm91dCBtYXhpbXVtIGEgcG9zdGVyaW9yaSBlc3RpbWF0ZSAoTUFQKQpyMyA8LSBycG9zdChuID0gbiwgbW9kZWwgPSAicHAiLCBwcmlvciA9IHBycmFpbiwgZGF0YSA9IHJhaW5mYWxsLCAKICAgICAgICAgICAgdGhyZXNoID0gcnRocmVzaCwgbm95ID0gNTQpCnBsb3QocjMsIHJ1X3NjYWxlID0gVFJVRSkKYyhyMSRwYSwgcjIkcGEsIHIzJHBhKQpgYGAKCiogQmFzZWQgb24gdGhlIHBsb3RzLCB3aGljaCBhcHByb2FjaCBkbyB5b3UgZXhwZWN0IHRvIGhhdmUgdGhlIGxhcmdlc3QgcHJvYmFiaWxpdHkgb2YgYWNjZXB0YW5jZT8KKiBJcyB0aGlzIHdoYXQgeW91IHNlZSBpbiB0aGUgdmFsdWVzIG9mIGByMSRwYWAsIGByMiRwYWAgYW5kIGByMyRwYWA/CgojIyBHRVYgbW9kZWwgZm9yIGJsb2NrIG1heGltYQoKYGBge3IgR0VWcHJpb3J9CiMgSW5mb3JtYXRpb24gYWJvdXQgdGhlIHBvcnRwaXJpZSBkYXRhCj9yZXZkYmF5ZXM6OnBvcnRwaXJpZQojIFVzZSB0aGUgcHJpb3IgZnJvbSB0aGUgZXZkYmF5ZXMgdXNlciBndWlkZQptYXQgPC0gZGlhZyhjKDEwMDAwLCAxMDAwMCwgMTAwKSkgICAgICAgICAKcG4gPC0gc2V0X3ByaW9yKHByaW9yID0gIm5vcm0iLCBtb2RlbCA9ICJnZXYiLCBtZWFuID0gYygwLCAwLCAwKSwgY292ID0gbWF0KQpgYGAKCiMjIyByZXZkYmF5ZXMKCmBgYHtyIHJldmRiYXllc30KbWF0IDwtIGRpYWcoYygxMDAwMCwgMTAwMDAsIDEwMCkpCmdldnAgIDwtIHJwb3N0X3JjcHAobiA9IG4sIG1vZGVsID0gImdldiIsIHByaW9yID0gcG4sIGRhdGEgPSBwb3J0cGlyaWUpCiMgSW5mb3JtYXRpb24gYWJvdXQgcGxvdC5ldnBvc3QKP3Bsb3QuZXZwb3N0CiMgQ2FuIHVzZSB0aGUgcGxvdHMgZnJvbSB0aGUgYmF5ZXNwbG90IHBhY2thZ2UKcGxvdChnZXZwLCB1c2VfYmF5ZXNwbG90ID0gVFJVRSwgZnVuX25hbWUgPSAiZGVucyIpCnBsb3QoZ2V2cCwgdXNlX2JheWVzcGxvdCA9IFRSVUUsIHBhcnMgPSAieGkiLCBwcm9iID0gMC45NSkKYGBgCgojIyMgZXZkYmF5ZXMKCmBgYHtyIGV2ZGJheWVzfQojIGV2ZGJheWVzIGhhcyBhIGZ1bmN0aW9uIGFyLmNob2ljZSB0byBoZWxwIHNldCB0aGUgcHJvcG9zYWwgU0RzCiMgSXQgZG9lcyB0aGlzIGJ5IHNlYXJjaGluZyBmb3IgdmFsdWVzIHRoYXQgYWNoaWV2ZSBhcHByb3hpbWF0ZWx5CiMgdGFyZ2V0IHZhbHVlcyBmb3IgdGhlIGFjY2VwdGFuY2UgcmF0ZXMgKGRlZmF1bHQgMC40IGZvciBhbGwgcGFyYW1ldGVycykKP2FyLmNob2ljZQojIEluaXRpYWxpc2UgZXZkYmF5ZXMnIE1hcmtvdiBjaGFpbiBhdCB0aGUgZXN0aW1hdGVkIHBvc3RlcmlvciBtZWFuCmluaXQgPC0gY29sTWVhbnMoZ2V2cCRzaW1fdmFscykKcHJvcC5zZC5hdXRvIDwtIGFyLmNob2ljZShpbml0ID0gaW5pdCwgcHJpb3IgPSBwbiwgbGggPSAiZ2V2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHBvcnRwaXJpZSwgcHNkID0gcmVwKDAuMDEsIDMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICB0b2wgPSByZXAoMC4wMiwgMykpJHBzZApwb3N0IDwtIHBvc3RlcmlvcihuLCBpbml0ID0gaW5pdCwgcHJpb3IgPSBwbiwgbGggPSAiZ2V2IiwgCiAgICAgICAgICAgICAgICAgIGRhdGEgPSBwb3J0cGlyaWUsIHBzZCA9IHByb3Auc2QuYXV0bykKZm9yIChpIGluIDE6MykgcGxvdChwb3N0WywgaV0sIHlsYWIgPSBjKCJtdSIsInNpZ21hIiwieGkiKVtpXSkgCmBgYAoKYGBge3IgY29kYX0KcG9zdF9mb3JfY29kYSA8LSBjb2RhOjptY21jKHBvc3QpCiMgQXNzdW1pbmcgbm8gYnVybi1pbiBwZXJpb2QKYnVybmluIDwtIDAgICAgICAgICAgICAgICAgIApwb3N0X2Zvcl9jb2RhIDwtIHdpbmRvdyhwb3N0X2Zvcl9jb2RhLCBzdGFydCA9IGJ1cm5pbiArIDEpCiMgVHJhY2UgcGxvdHMgYW5kIEtERXMKcGxvdChwb3N0X2Zvcl9jb2RhKQojIFRoZSBzYW1wbGVkIHZhbHVlcyBhcmUgYXV0b2NvcnJlbGF0ZWQKY29kYTo6YWNmcGxvdChwb3N0X2Zvcl9jb2RhKQojIEVmZmVjdGl2ZSBzYW1wbGUgc2l6ZXMgKDEwLDAwMCBmb3IgcmV2ZGJheWVzKQpjb2RhOjplZmZlY3RpdmVTaXplKHBvc3RfZm9yX2NvZGEpCmBgYAoKKiBJbiBwcmFjdGljZSBvbmUgd291bGQgcnVuIG11bHRpcGxlIGNoYWlucyBhbmQgdXNlIHRoZSBHZWxtYW4tUnViaW4gY29udmVyZ2VuY2UgZGlhZ25vc3RpYywgZS5nLiBgZ2VsbWFuLmRpYWdgIGluIHRoZSBgY29kYWAgcGFja2FnZS4gCiogVGhlIFtJbnRyb2R1Y3Rpb24gdG8gcmV2ZGJheWVzXShodHRwczovL3BhdWxub3J0aHJvcC5naXRodWIuaW8vcmV2ZGJheWVzL2FydGljbGVzL3JldmRiYXllcy1hLXZpZ25ldHRlLmh0bWwpIHNob3dzIHRoYXQgdGhlIHBvc3RlcmlvciBzYW1wbGVzIGZyb20gYGV2ZGJheWVzYCBhbmQgYHJldmRiYXllc2AgYXJlIGluIGFncmVlbWVudC4KCgo=