Most randomised controlled trials (RCTs) use non-probability samples and the goal is to estimate the sample average treatment effect (SATE). The sample is the finite population of interest and something else needs to be done to transfer or generalise the finding to other samples – ideally a few decades of substantive theory built on basic research.

There’s still an inferential problem, even with the finite sample. SATE is the average of each individual’s treatment effect (TEs), which is defined as the difference between the individual’s potential outcome following treatment and their potential outcome following control. However, only one of those two potential outcomes is realised for an individual, depending on whether they were randomised to treatment or control.

The standard ANCOVA-style way to estimate SATE is to regress the outcome on treatment group and covariates. This yields an unbiased estimate of the SATE; however, the standard error is a little too big, which means the confidence interval is a little too wide. The reason for this is that the correct standard error depends on the correlation between potential outcomes, but we cannot estimate this correlation since each trial participant only gives us one of the two values we wish to correlate.

Here’s the SE for a test without covariates (Reichardt & Gollob, 1999):

\[\sqrt{\frac{\sigma_X^2}{n_X} + \frac{\sigma_Y^2}{n_Y}-\left[ \frac{(\sigma_X-\sigma_Y)^2}{N} + \frac{2(1-\rho) \sigma_X \sigma_{Y}}{N} \right]}\]

where \(\sigma_X^2\) and \(\sigma_Y^2\) are the variances of the two groups, \(n_X\) and \(n_Y\) are the observed group sample sizes, and \(N\) is the total sample (the finite population) size. The problem is \(\rho\), the unobservable correlation between treat and control outcomes for each participant.

This problem was pointed out by Neyman (1923/1990). Reichardt and Gollob (1999) independently rediscovered the problem and suggested a way to get a less conservative standard error based on the reliability of the outcome measure, which gives an upper bound on the correlation. Aronow, Green, and Lee (2014) proved a result that puts bounds on the correlation based on the observed marginal distribution of outcomes. They also helpfully provided R code to do the sums; however, this approach only works for a model without any covariates.

I’m excited by a new preprint by Mikhaeil and Green (2024) that extends the approach to models with covariates and again provides R code, in the {sharpvar} package (currently on GitHub). Let’s give it a go.

Simulate data

#devtools::install_github("JonasMikhaeil/SharpVarianceBounds")
library(conflicted)
library(sharpvar)
library(tidyverse)
── Attaching core tidyverse packages ────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
library(broom)
library(tictoc)
conflicts_prefer(dplyr::filter)
[conflicted] Will prefer dplyr::filter over any other package.
set.seed(42)
theN <- 100

sim_dat <- tibble(latent_magic = 50 + rnorm(theN, 0, sqrt(.6)),
                  y0 = round(latent_magic + rnorm(theN, 0, sqrt(.4)), 1),
                  y1 = round(latent_magic + 0.2 + rnorm(theN, 0, sqrt(.4)), 1),
                  x  = latent_magic + rnorm(theN, mean = 0, sd = 1.5),
                  TE = y1 - y0) |>
  select(-latent_magic)
sim_dat
sim_dat |>
  select(-TE) |>
  cor() |>
  round(2)
     y0   y1    x
y0 1.00 0.64 0.47
y1 0.64 1.00 0.41
x  0.47 0.41 1.00

This is the true SATE for this finite population:

trueSATE <- mean(sim_dat$TE)
trueSATE
[1] 0.252

Simulate some efficacy trials

This is a slightly convoluted way to implement complete randomisation in which a fixed number of participants are randomised to treatment (compare with Bernoulli randomisation, where the proportion is a probability that may vary between trials).

completely_randomiser <- function(dat,
                                  treat_var_name = "treat",
                                  prop_treat = 0.5) {
  treat_n   <- ceiling(prop_treat * nrow(dat))
  control_n <- nrow(dat) - treat_n
  zero_ones <- c(rep(1, treat_n), rep(0, control_n))
  dat |>
    mutate(!!treat_var_name := sample(zero_ones))
}

This function will give us the realised potential outcome:

realise_potential <- function(dat, y_name = y, y0, y1, treat) {
  dat |>
    mutate(!!y_name := ifelse(treat == 1, y1, y0))
}

And a function to summarise the findings for the classic SE and the new sharp bound on the SE:

summarise_mod <- function(mod, dat, treat_var = "treat") {
  mod |>
    tidy() |>
    filter(term == treat_var) |>
    mutate(
      se_sharp = sharpvar(resid(mod), dat$treat, upper = TRUE) |> sqrt(),
      df = df.residual(mod)
    ) |>
    rename(se_classic = std.error) |>
    select(-c(statistic, p.value)) |>
    pivot_longer(
      cols = starts_with("se_"),
      names_prefix = "se_",
      names_to = "type",
      values_to = "se"
    ) |>
    mutate(ci_lower = estimate + qt(.05/2, df) * se,
           ci_upper = estimate + qt(1 - (.05/2), df) * se)
}

The pipeline we will replicate a few thousand times:

one_sim <- function(popn_dat) {
  one_trial <- popn_dat |>
    completely_randomiser() |>
    realise_potential("y", y0, y1, treat)
  
  the_mod <- lm(y ~ treat + x, data = one_trial)
  
  summarise_mod(the_mod, one_trial)
}

Off we go:

tic()
res <- replicate(10000, one_sim(sim_dat), simplify = FALSE) |> list_rbind()
toc()
102.51 sec elapsed

Now what’s the coverage like?

tallied_res <- res |>
  mutate(truth = trueSATE,
         covered = between(truth, ci_lower, ci_upper)) |>
  group_by(type) |>
  summarise(`proportion 95% CI coverage` = mean(covered))
tallied_res

We see that the classic (and conservative) 95% confidence interval covers the true SATE 97.58% of the time whereas Mikhaeil and Green’s improved interval gives us 97.15% coverage.

It worked, the interval is a tiny bit closer to the 95% target!

References

Aronow, P. M., Green, D. P., & Lee, D. K. K. (2014). Sharp bounds on the variance in randomized experiments. Annals of Statistics, 42, 850–871.

Mikhaeil, J. M., & Green, D. P. (2024). Sharp bounds on the variance of general regression adjustment in randomized experiments. arXiv preprint.

Neyman, J. (1923/1990). On the application of probability theory to agricultural experiments. Essay on principles. Section 9. Statistical Science, 5, 465–472.

Reichardt, C. S., & Gollob, H. F. (1999). Justifying the Use and Increasing the Power of a t Test for a Randomized Experiment With a Convenience Sample. Psychological Methods, 4, 117–128.

LS0tDQp0aXRsZTogIlNoYXJwIHZhcmlhbmNlIGJvdW5kcyBmb3IgU0FURTogZ2l2aW5nIE1pa2hhZWlsIGFuZCBHcmVlbidzICgyMDI0KSB3b3JrIGEgdGVzdCBkcml2ZSINCmF1dGhvcjogQW5kaSBGdWdhcmQNCmRhdGU6IDkgTm92IDIwMjQNCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KICAgIGNvZGVfZm9sZGluZzogbm9uZQ0KLS0tDQoNCg0KTW9zdCByYW5kb21pc2VkIGNvbnRyb2xsZWQgdHJpYWxzIChSQ1RzKSB1c2Ugbm9uLXByb2JhYmlsaXR5IHNhbXBsZXMgYW5kIHRoZSBnb2FsIGlzIHRvIGVzdGltYXRlIHRoZSBzYW1wbGUgYXZlcmFnZSB0cmVhdG1lbnQgZWZmZWN0IChTQVRFKS4gVGhlIHNhbXBsZSBpcyB0aGUgZmluaXRlIHBvcHVsYXRpb24gb2YgaW50ZXJlc3QgYW5kIHNvbWV0aGluZyBlbHNlIG5lZWRzIHRvIGJlIGRvbmUgdG8gdHJhbnNmZXIgb3IgZ2VuZXJhbGlzZSB0aGUgZmluZGluZyB0byBvdGhlciBzYW1wbGVzIC0tIGlkZWFsbHkgYSBmZXcgZGVjYWRlcyBvZiBzdWJzdGFudGl2ZSB0aGVvcnkgYnVpbHQgb24gYmFzaWMgcmVzZWFyY2guDQoNClRoZXJlJ3Mgc3RpbGwgYW4gaW5mZXJlbnRpYWwgcHJvYmxlbSwgZXZlbiB3aXRoIHRoZSBmaW5pdGUgc2FtcGxlLiBTQVRFIGlzIHRoZSBhdmVyYWdlIG9mIGVhY2ggaW5kaXZpZHVhbCdzIHRyZWF0bWVudCBlZmZlY3QgKFRFcyksIHdoaWNoIGlzIGRlZmluZWQgYXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgaW5kaXZpZHVhbCdzIHBvdGVudGlhbCBvdXRjb21lIGZvbGxvd2luZyB0cmVhdG1lbnQgYW5kIHRoZWlyIHBvdGVudGlhbCBvdXRjb21lIGZvbGxvd2luZyBjb250cm9sLiBIb3dldmVyLCBvbmx5IG9uZSBvZiB0aG9zZSB0d28gcG90ZW50aWFsIG91dGNvbWVzIGlzIHJlYWxpc2VkIGZvciBhbiBpbmRpdmlkdWFsLCBkZXBlbmRpbmcgb24gd2hldGhlciB0aGV5IHdlcmUgcmFuZG9taXNlZCB0byB0cmVhdG1lbnQgb3IgY29udHJvbC4NCg0KVGhlIHN0YW5kYXJkIEFOQ09WQS1zdHlsZSB3YXkgdG8gZXN0aW1hdGUgU0FURSBpcyB0byByZWdyZXNzIHRoZSBvdXRjb21lIG9uIHRyZWF0bWVudCBncm91cCBhbmQgY292YXJpYXRlcy4gVGhpcyB5aWVsZHMgYW4gdW5iaWFzZWQgZXN0aW1hdGUgb2YgdGhlIFNBVEU7IGhvd2V2ZXIsIHRoZSBzdGFuZGFyZCBlcnJvciBpcyBhIGxpdHRsZSB0b28gYmlnLCB3aGljaCBtZWFucyB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCBpcyBhIGxpdHRsZSB0b28gd2lkZS4gVGhlIHJlYXNvbiBmb3IgdGhpcyBpcyB0aGF0IHRoZSBjb3JyZWN0IHN0YW5kYXJkIGVycm9yIGRlcGVuZHMgb24gdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gcG90ZW50aWFsIG91dGNvbWVzLCBidXQgd2UgY2Fubm90IGVzdGltYXRlIHRoaXMgY29ycmVsYXRpb24gc2luY2UgZWFjaCB0cmlhbCBwYXJ0aWNpcGFudCBvbmx5IGdpdmVzIHVzIG9uZSBvZiB0aGUgdHdvIHZhbHVlcyB3ZSB3aXNoIHRvIGNvcnJlbGF0ZS4NCg0KSGVyZSdzIHRoZSBTRSBmb3IgYSB0ZXN0IHdpdGhvdXQgY292YXJpYXRlcyAoUmVpY2hhcmR0ICYgR29sbG9iLCAxOTk5KToNCg0KJCRcc3FydHtcZnJhY3tcc2lnbWFfWF4yfXtuX1h9ICsgXGZyYWN7XHNpZ21hX1leMn17bl9ZfS1cbGVmdFsgXGZyYWN7KFxzaWdtYV9YLVxzaWdtYV9ZKV4yfXtOfSArIFxmcmFjezIoMS1ccmhvKSBcc2lnbWFfWCBcc2lnbWFfe1l9fXtOfSBccmlnaHRdfSQkDQoNCndoZXJlICRcc2lnbWFfWF4yJCBhbmQgJFxzaWdtYV9ZXjIkIGFyZSB0aGUgdmFyaWFuY2VzIG9mIHRoZSB0d28gZ3JvdXBzLCAkbl9YJCBhbmQgJG5fWSQgYXJlIHRoZSBvYnNlcnZlZCBncm91cCBzYW1wbGUgc2l6ZXMsIGFuZCAkTiQgaXMgdGhlIHRvdGFsIHNhbXBsZSAodGhlIGZpbml0ZSBwb3B1bGF0aW9uKSBzaXplLiBUaGUgcHJvYmxlbSBpcyAkXHJobyQsIHRoZSB1bm9ic2VydmFibGUgY29ycmVsYXRpb24gYmV0d2VlbiB0cmVhdCBhbmQgY29udHJvbCBvdXRjb21lcyBmb3IgZWFjaCBwYXJ0aWNpcGFudC4NCg0KVGhpcyBwcm9ibGVtIHdhcyBwb2ludGVkIG91dCBieSBOZXltYW4gKDE5MjMvMTk5MCkuIFJlaWNoYXJkdCBhbmQgR29sbG9iICgxOTk5KSBpbmRlcGVuZGVudGx5IHJlZGlzY292ZXJlZCB0aGUgcHJvYmxlbSBhbmQgc3VnZ2VzdGVkIGEgd2F5IHRvIGdldCBhIGxlc3MgY29uc2VydmF0aXZlIHN0YW5kYXJkIGVycm9yIGJhc2VkIG9uIHRoZSByZWxpYWJpbGl0eSBvZiB0aGUgb3V0Y29tZSBtZWFzdXJlLCB3aGljaCBnaXZlcyBhbiB1cHBlciBib3VuZCBvbiB0aGUgY29ycmVsYXRpb24uICBBcm9ub3csIEdyZWVuLCBhbmQgTGVlICgyMDE0KSBwcm92ZWQgYSByZXN1bHQgdGhhdCBwdXRzIGJvdW5kcyBvbiB0aGUgY29ycmVsYXRpb24gYmFzZWQgb24gdGhlIG9ic2VydmVkIG1hcmdpbmFsIGRpc3RyaWJ1dGlvbiBvZiBvdXRjb21lcy4gVGhleSBhbHNvIGhlbHBmdWxseSBwcm92aWRlZCBSIGNvZGUgdG8gZG8gdGhlIHN1bXM7IGhvd2V2ZXIsIHRoaXMgYXBwcm9hY2ggb25seSB3b3JrcyBmb3IgYSBtb2RlbCB3aXRob3V0IGFueSBjb3ZhcmlhdGVzLg0KDQpJJ20gZXhjaXRlZCBieSBhIG5ldyBwcmVwcmludCBieSBNaWtoYWVpbCBhbmQgR3JlZW4gKDIwMjQpIHRoYXQgZXh0ZW5kcyB0aGUgYXBwcm9hY2ggdG8gbW9kZWxzIHdpdGggY292YXJpYXRlcyBhbmQgYWdhaW4gcHJvdmlkZXMgUiBjb2RlLCBpbiB0aGUge1tzaGFycHZhcl0oaHR0cHM6Ly9naXRodWIuY29tL0pvbmFzTWlraGFlaWwvU2hhcnBWYXJpYW5jZUJvdW5kcyl9IHBhY2thZ2UgKGN1cnJlbnRseSBvbiBHaXRIdWIpLiBMZXQncyBnaXZlIGl0IGEgZ28uDQoNCiMjIFNpbXVsYXRlIGRhdGENCg0KYGBge3J9DQojZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJKb25hc01pa2hhZWlsL1NoYXJwVmFyaWFuY2VCb3VuZHMiKQ0KbGlicmFyeShjb25mbGljdGVkKQ0KbGlicmFyeShzaGFycHZhcikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkodGljdG9jKQ0KY29uZmxpY3RzX3ByZWZlcihkcGx5cjo6ZmlsdGVyKQ0KYGBgDQoNCg0KYGBge3J9DQpzZXQuc2VlZCg0MikNCnRoZU4gPC0gMTAwDQoNCnNpbV9kYXQgPC0gdGliYmxlKGxhdGVudF9tYWdpYyA9IDUwICsgcm5vcm0odGhlTiwgMCwgc3FydCguNikpLA0KICAgICAgICAgICAgICAgICAgeTAgPSByb3VuZChsYXRlbnRfbWFnaWMgKyBybm9ybSh0aGVOLCAwLCBzcXJ0KC40KSksIDEpLA0KICAgICAgICAgICAgICAgICAgeTEgPSByb3VuZChsYXRlbnRfbWFnaWMgKyAwLjIgKyBybm9ybSh0aGVOLCAwLCBzcXJ0KC40KSksIDEpLA0KICAgICAgICAgICAgICAgICAgeCAgPSBsYXRlbnRfbWFnaWMgKyBybm9ybSh0aGVOLCBtZWFuID0gMCwgc2QgPSAxLjUpLA0KICAgICAgICAgICAgICAgICAgVEUgPSB5MSAtIHkwKSB8Pg0KICBzZWxlY3QoLWxhdGVudF9tYWdpYykNCmBgYA0KDQoNCmBgYHtyfQ0Kc2ltX2RhdA0KYGBgDQoNCmBgYHtyfQ0Kc2ltX2RhdCB8Pg0KICBzZWxlY3QoLVRFKSB8Pg0KICBjb3IoKSB8Pg0KICByb3VuZCgyKQ0KYGBgDQoNClRoaXMgaXMgdGhlIHRydWUgU0FURSBmb3IgdGhpcyBmaW5pdGUgcG9wdWxhdGlvbjoNCg0KYGBge3J9DQp0cnVlU0FURSA8LSBtZWFuKHNpbV9kYXQkVEUpDQp0cnVlU0FURQ0KYGBgDQoNCg0KIyMgU2ltdWxhdGUgc29tZSBlZmZpY2FjeSB0cmlhbHMNCg0KVGhpcyBpcyBhIHNsaWdodGx5IGNvbnZvbHV0ZWQgd2F5IHRvIGltcGxlbWVudCBjb21wbGV0ZSByYW5kb21pc2F0aW9uIGluIHdoaWNoIGEgZml4ZWQgbnVtYmVyIG9mIHBhcnRpY2lwYW50cyBhcmUgcmFuZG9taXNlZCB0byB0cmVhdG1lbnQgKGNvbXBhcmUgd2l0aCBCZXJub3VsbGkgcmFuZG9taXNhdGlvbiwgd2hlcmUgdGhlIHByb3BvcnRpb24gaXMgYSBwcm9iYWJpbGl0eSB0aGF0IG1heSB2YXJ5IGJldHdlZW4gdHJpYWxzKS4NCg0KYGBge3J9DQpjb21wbGV0ZWx5X3JhbmRvbWlzZXIgPC0gZnVuY3Rpb24oZGF0LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyZWF0X3Zhcl9uYW1lID0gInRyZWF0IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wX3RyZWF0ID0gMC41KSB7DQogIHRyZWF0X24gICA8LSBjZWlsaW5nKHByb3BfdHJlYXQgKiBucm93KGRhdCkpDQogIGNvbnRyb2xfbiA8LSBucm93KGRhdCkgLSB0cmVhdF9uDQogIHplcm9fb25lcyA8LSBjKHJlcCgxLCB0cmVhdF9uKSwgcmVwKDAsIGNvbnRyb2xfbikpDQogIGRhdCB8Pg0KICAgIG11dGF0ZSghIXRyZWF0X3Zhcl9uYW1lIDo9IHNhbXBsZSh6ZXJvX29uZXMpKQ0KfQ0KYGBgDQoNClRoaXMgZnVuY3Rpb24gd2lsbCBnaXZlIHVzIHRoZSByZWFsaXNlZCBwb3RlbnRpYWwgb3V0Y29tZToNCg0KYGBge3J9DQpyZWFsaXNlX3BvdGVudGlhbCA8LSBmdW5jdGlvbihkYXQsIHlfbmFtZSA9IHksIHkwLCB5MSwgdHJlYXQpIHsNCiAgZGF0IHw+DQogICAgbXV0YXRlKCEheV9uYW1lIDo9IGlmZWxzZSh0cmVhdCA9PSAxLCB5MSwgeTApKQ0KfQ0KYGBgDQoNCkFuZCBhIGZ1bmN0aW9uIHRvIHN1bW1hcmlzZSB0aGUgZmluZGluZ3MgZm9yIHRoZSBjbGFzc2ljIFNFIGFuZCB0aGUgbmV3IHNoYXJwIGJvdW5kIG9uIHRoZSBTRToNCg0KYGBge3J9DQpzdW1tYXJpc2VfbW9kIDwtIGZ1bmN0aW9uKG1vZCwgZGF0LCB0cmVhdF92YXIgPSAidHJlYXQiKSB7DQogIG1vZCB8Pg0KICAgIHRpZHkoKSB8Pg0KICAgIGZpbHRlcih0ZXJtID09IHRyZWF0X3ZhcikgfD4NCiAgICBtdXRhdGUoDQogICAgICBzZV9zaGFycCA9IHNoYXJwdmFyKHJlc2lkKG1vZCksIGRhdCR0cmVhdCwgdXBwZXIgPSBUUlVFKSB8PiBzcXJ0KCksDQogICAgICBkZiA9IGRmLnJlc2lkdWFsKG1vZCkNCiAgICApIHw+DQogICAgcmVuYW1lKHNlX2NsYXNzaWMgPSBzdGQuZXJyb3IpIHw+DQogICAgc2VsZWN0KC1jKHN0YXRpc3RpYywgcC52YWx1ZSkpIHw+DQogICAgcGl2b3RfbG9uZ2VyKA0KICAgICAgY29scyA9IHN0YXJ0c193aXRoKCJzZV8iKSwNCiAgICAgIG5hbWVzX3ByZWZpeCA9ICJzZV8iLA0KICAgICAgbmFtZXNfdG8gPSAidHlwZSIsDQogICAgICB2YWx1ZXNfdG8gPSAic2UiDQogICAgKSB8Pg0KICAgIG11dGF0ZShjaV9sb3dlciA9IGVzdGltYXRlICsgcXQoLjA1LzIsIGRmKSAqIHNlLA0KICAgICAgICAgICBjaV91cHBlciA9IGVzdGltYXRlICsgcXQoMSAtICguMDUvMiksIGRmKSAqIHNlKQ0KfQ0KYGBgDQoNCg0KVGhlIHBpcGVsaW5lIHdlIHdpbGwgcmVwbGljYXRlIGEgZmV3IHRob3VzYW5kIHRpbWVzOg0KDQpgYGB7cn0NCm9uZV9zaW0gPC0gZnVuY3Rpb24ocG9wbl9kYXQpIHsNCiAgb25lX3RyaWFsIDwtIHBvcG5fZGF0IHw+DQogICAgY29tcGxldGVseV9yYW5kb21pc2VyKCkgfD4NCiAgICByZWFsaXNlX3BvdGVudGlhbCgieSIsIHkwLCB5MSwgdHJlYXQpDQogIA0KICB0aGVfbW9kIDwtIGxtKHkgfiB0cmVhdCArIHgsIGRhdGEgPSBvbmVfdHJpYWwpDQogIA0KICBzdW1tYXJpc2VfbW9kKHRoZV9tb2QsIG9uZV90cmlhbCkNCn0NCmBgYA0KDQoNCg0KT2ZmIHdlIGdvOg0KDQpgYGB7cn0NCnRpYygpDQpyZXMgPC0gcmVwbGljYXRlKDEwMDAwLCBvbmVfc2ltKHNpbV9kYXQpLCBzaW1wbGlmeSA9IEZBTFNFKSB8PiBsaXN0X3JiaW5kKCkNCnRvYygpDQpgYGANCg0KTm93IHdoYXQncyB0aGUgY292ZXJhZ2UgbGlrZT8NCg0KDQpgYGB7cn0NCnRhbGxpZWRfcmVzIDwtIHJlcyB8Pg0KICBtdXRhdGUodHJ1dGggPSB0cnVlU0FURSwNCiAgICAgICAgIGNvdmVyZWQgPSBiZXR3ZWVuKHRydXRoLCBjaV9sb3dlciwgY2lfdXBwZXIpKSB8Pg0KICBncm91cF9ieSh0eXBlKSB8Pg0KICBzdW1tYXJpc2UoYHByb3BvcnRpb24gOTUlIENJIGNvdmVyYWdlYCA9IG1lYW4oY292ZXJlZCkpDQp0YWxsaWVkX3Jlcw0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpnaW1tZV9yZXMgPC0gZnVuY3Rpb24od2hpY2gpIHsNCiAgdGhlX3Byb3AgPC0gdGFsbGllZF9yZXMgfD4gZmlsdGVyKHR5cGUgPT0gd2hpY2gpIHw+IHB1bGwoMikNCiAgcm91bmQoMTAwICogdGhlX3Byb3AsMikNCn0NCmBgYA0KDQpXZSBzZWUgdGhhdCB0aGUgY2xhc3NpYyAoYW5kIGNvbnNlcnZhdGl2ZSkgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWwgY292ZXJzIHRoZSB0cnVlIFNBVEUgYHIgZ2ltbWVfcmVzKCJjbGFzc2ljIilgJSBvZiB0aGUgdGltZSB3aGVyZWFzIE1pa2hhZWlsIGFuZCBHcmVlbidzIGltcHJvdmVkIGludGVydmFsIGdpdmVzIHVzIGByIGdpbW1lX3Jlcygic2hhcnAiKWAlIGNvdmVyYWdlLg0KDQpJdCB3b3JrZWQsIHRoZSBpbnRlcnZhbCBpcyBhIHRpbnkgYml0IGNsb3NlciB0byB0aGUgOTUlIHRhcmdldCENCg0KDQojIyBSZWZlcmVuY2VzDQoNCkFyb25vdywgUC4gTS4sIEdyZWVuLCBELiBQLiwgJiBMZWUsIEQuIEsuIEsuICgyMDE0KS4gW1NoYXJwIGJvdW5kcyBvbiB0aGUgdmFyaWFuY2UgaW4gcmFuZG9taXplZCBleHBlcmltZW50c10oaHR0cHM6Ly93d3cuanN0b3Iub3JnL3N0YWJsZS80MzU1NjMwOCkuIEFubmFscyBvZiBTdGF0aXN0aWNzLCA0MiwgODUwLS04NzEuDQoNCk1pa2hhZWlsLCBKLiBNLiwgJiBHcmVlbiwgRC4gUC4gKDIwMjQpLiBbU2hhcnAgYm91bmRzIG9uIHRoZSB2YXJpYW5jZSBvZiBnZW5lcmFsIHJlZ3Jlc3Npb24gYWRqdXN0bWVudCBpbiByYW5kb21pemVkIGV4cGVyaW1lbnRzXShodHRwczovL2FyeGl2Lm9yZy9hYnMvMjQxMS4wMDE5MSkuIGFyWGl2IHByZXByaW50Lg0KDQpOZXltYW4sIEouICgxOTIzLzE5OTApLiBbT24gdGhlIGFwcGxpY2F0aW9uIG9mIHByb2JhYmlsaXR5IHRoZW9yeSB0byBhZ3JpY3VsdHVyYWwgZXhwZXJpbWVudHMuIEVzc2F5IG9uIHByaW5jaXBsZXMuIFNlY3Rpb24gOS5dKGh0dHBzOi8vd3d3LmpzdG9yLm9yZy9zdGFibGUvMjI0NTM4MikgX1N0YXRpc3RpY2FsIFNjaWVuY2VfLCBfNV8sIDQ2NS0tNDcyLg0KDQpSZWljaGFyZHQsIEMuIFMuLCAmIEdvbGxvYiwgSC4gRi4gKDE5OTkpLiBbSnVzdGlmeWluZyB0aGUgVXNlIGFuZCBJbmNyZWFzaW5nIHRoZSBQb3dlciBvZiBhIF90XyBUZXN0IGZvciBhIFJhbmRvbWl6ZWQgRXhwZXJpbWVudCBXaXRoIGEgQ29udmVuaWVuY2UgU2FtcGxlXShodHRwczovL3BzeWNuZXQuYXBhLm9yZy9kb2kvMTAuMTAzNy8xMDgyLTk4OVguNC4xLjExNykuIF9Qc3ljaG9sb2dpY2FsIE1ldGhvZHNfLCBfNF8sIDExNy0tMTI4Lg0KDQo=