Introduction

Several readers of the discussion version of the fldgen paper have questioned whether fitting the mean field and variability models over the entire range of RCP scenarios introduces a form of bias. Here is one example of such a comment from Anonymous Reviewer #3:

I had similar thoughts as reviewer two re using different RCPs used to train the emulator, and I didn’t find the response fully convincing – some tests should be possible here? In particular, I found myself wondering whether EOF1 reflected responses to different RCPs. Did you check whether EOF1 was similar in an emulator trained on a few simulations with a single RCP (and didn’t disappear, as when you trained on a single simulation)? Why not compare the variance of the full emulator (i.e. trained on all 9 simulations) separately with the RCP2.6 simulations and with the RCP8.5 simulations to quantify any scenario bias? In any event, some discussion of this should be included in the text as I suspect many people will question it. Repeating from Reviewer Two “Section 4.2 got me thinking that as the model is trained on the RCP outputs, is there any difference in the results when taking just the set of realisations from RCP2.6 and RCP8.5? Certaintly across ESMs, the variance across models increases with increasing global mean temperature. It would therefore not be correct to use a variability model that is trained on RCP8.5 for low forcing scenarios or those with a peak and decline. I note the authors address this in section 4.3, but I wonder if they have tested this.”

We can break the reviewer’s conjecture down into several specific, testable claims.

  1. Is the mean field model fit to a single RCP significantly different to that fit to the ensemble of RCPs? Our experience with fitting more sophisticated pattern analysis algorithms suggests that it does not, but we have not formally tested that hypothesis with linear pattern scaling.
  2. Does the first EOF of the variability model represent an adjustment from compromise fit of the mean field to the specific behaviors of the individual warming scenarios? In other words, the claim here is that when we fit the mean field model to the entire collection of warming scenarios, we produce a mean field that is not exactly appropriate for any of the RCP warming scenarios, and that EOF-1 represents a correction field that brings the mean field into agreement with the individual RCP mean field behavior. If that conjecture is true, then it would be a mistake to randomize the phase of that component, as it is not truly representing random variation, but rather a component of the forced behavior that we are not capturing.
  3. Is the residual variance higher when fitting to a multi-scenario ensemble than when fitting to a single-scenario ensemble? This would be an indication that some of what we are describing as “variability” is actully forced variation not being captured by the mean field model.

I will refer to these claims collectively as the Compromise Conjecture (CC). If the CC is wholly or partly true, then our emulator is representing some of the forced variation as dynamical variability, which may require some sort of correction.

Of course, we already know that the CC is true to some extent. The assumption that the behavior of the ESMs can be cleanly separated into deterministic forcing and random variability was always an approximation; as we note in the main body of the paper. So, the real question here is, how big is the error created by that approximation? Is it large enough to require explicit correction?

Testing the Compromise Conjecture

Testing these claims is tricky for two reasons. First, the statistical properties of the ensemble depend on the number of scenarios in the ensemble, as well as on the mix or RCP pathways in the ensemble. Therefore, it would be very hard to get any interpretable result comparing the nine-run multi-rcp emulator to an emulator trained on two or three runs from a single rcp. Instead, we will have to investigate these questions by training an emulator on the three rcp8.5 scenarios that we have and comparing that to an emulator trained on three scenarios from across the rcps (I suggest 2.6, 6.0, and 8.5 as giving the most uniform coverage).

The second reason it is difficult to test these claims is that they hinge on the size of the effect. It may not be enough merely to test whether or not any effects are statistically significant because statistical significance is not the same as practical significance. If an effect is not statistically significant, then we can probably dismiss it on the grounds that we can’t even be sure it exists, let alone is important in practical applications. However, I am a bit concerned that on a large grid like we have (55,296 grid cells), even the tiny effects, which we know must be present as a consequence of our separability approximation, could be statistically detectable.

For claims where this happens, we need to define an effect size and a threshold of acceptability to compare it to. Further complicating this task is the quantitative results we are looking at are defined in individual grid cells, and the direction of the shift (if any) and scale of variability will be different between grid cells. We will have to find a way to aggregate any judgment of practical significance to the system as a whole.

Software version

These calculations were run with fldgen-v1.0.0

Simple tests evaluating the claims

library(fldgen)
library(dplyr)
library(ggplot2)
library(ggthemes)
set.seed(867-5309)
emulator_rcp85 <- train('data-rcp85', latvar='lat_2', lonvar='lon_2')
emulator_multi_rcp <- train('data-multi-rcp', latvar='lat_2', lonvar='lon_2')

Claim #1

The heart of this claim is that the mean field model for an ensemble of ESM runs from the same RCP will be different from the mean field model for an ensemble of runs covering a variety of RCP scenarios. We can examine the coefficients models directly to see how different the mean field models are.

ggplot(mapping=aes(x=as.vector(emulator_multi_rcp$pscl$w), 
                   y=as.vector(emulator_rcp85$pscl$w))) +
    geom_point(color='lightgrey', shape='.') +
    theme_solarized_2(light=FALSE, base_size=14) +
    xlab('MULTI coefficient') + ylab('RCP85 coefficient') +
    ggtitle('Comparison of linear coefficient (w)')

ggplot(mapping=aes(x=as.vector(emulator_multi_rcp$pscl$b), 
                   y=as.vector(emulator_rcp85$pscl$b))) +
    geom_point(color='lightgrey', shape='.') +
    theme_solarized_2(light=FALSE, base_size=14) +
    xlab('MULTI coefficient') + ylab('RCP85 coefficient') +
    ggtitle('Comparison of intercept coefficient (b)')

It is easy enough to see that those two models are extremely similar. We can quantify just how similar they are by fitting a linear model predicting the RCP85 coefficient from the corresponding multi-rcp coefficient.

lmw <- lm(emulator_rcp85$pscl$w~emulator_multi_rcp$pscl$w + 0)
lmb <- lm(emulator_rcp85$pscl$b~emulator_multi_rcp$pscl$b + 0)
summary(lmw)

Call:
lm(formula = emulator_rcp85$pscl$w ~ emulator_multi_rcp$pscl$w + 
    0)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.173075 -0.015505  0.003771  0.023052  0.183827 

Coefficients:
                           Estimate Std. Error t value Pr(>|t|)    
emulator_multi_rcp$pscl$w 0.9942681  0.0001213    8195   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.04184 on 55295 degrees of freedom
Multiple R-squared:  0.9992,    Adjusted R-squared:  0.9992 
F-statistic: 6.715e+07 on 1 and 55295 DF,  p-value: < 2.2e-16
summary(lmb)

Call:
lm(formula = emulator_rcp85$pscl$b ~ emulator_multi_rcp$pscl$b + 
    0)

Residuals:
    Min      1Q  Median      3Q     Max 
-55.504  -5.284   0.438   5.852  48.225 

Coefficients:
                           Estimate Std. Error t value Pr(>|t|)    
emulator_multi_rcp$pscl$b 0.9866313  0.0002057    4796   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 11.88 on 55295 degrees of freedom
Multiple R-squared:  0.9976,    Adjusted R-squared:  0.9976 
F-statistic: 2.3e+07 on 1 and 55295 DF,  p-value: < 2.2e-16

So, the average ratio between the RCP85 and multi-rcp linear coefficients (\(w\)) is 0.994. The \(R^2\) on this relationship is 0.999. Most of the residuals are within +/- 0.02 of 0 (for a coefficient that ranges approximately from 0-3).

For the intercept coefficient (\(b\)), the relationship is ever so slightly rougher; the coefficient ratio is 0.987, with an \(R^2\) of “only” 0.998. Most of the residuals are between -5 and +6 (the scale of this variable is considerably larger: -650 - +300.)

The mean field models are virtually indistinguishable, whether fit on a single RCP or a selection of RCPs; therefore, although the long-period EOFs are telling us something about the differences between individual runs, there doesn’t seem to be any evidence that these differences are a systematic function of RCP.

To me, these results alone vitiate the Compromise Conjecture. Without any significant difference in the mean response under different climate change pathways, there is no real motivation for the other claims.

Claim #2

The second claim in the CC is that the long-period EOFs are a representation of the mismatch between the mean field model and the RCP outputs from which the residuals are calculated. If this were true, then we would expect that for emulators fit to runs representing a single rcp, there should not be a long-period mode. We can check this hypothesis by plotting the power spectrum for EOF-1 for the single-rcp emulator.

psd_rcp85_eof1 <- emulator_rcp85$fx$mag[1:47 ,2]^2
rpsd_rcp85_eof1 <- psd_rcp85_eof1 / max(psd_rcp85_eof1)
psd_freq <- (seq_along(rpsd_rcp85_eof1)-1)/95
ggplot(mapping=aes(x=psd_freq, y=rpsd_rcp85_eof1)) + geom_smooth(se=FALSE, color='lightgrey') +
    xlab('Frequency') + ylab('EOF-1 Power Spectral Density') + 
    ggtitle('RCP85 residuals with RCP85 mean field') +
    theme_solarized_2(light=FALSE, base_size = 14)

psd_multi_eof1 <- emulator_multi_rcp$fx$mag[1:47 ,2]^2
rpsd_multi_eof1 <- psd_multi_eof1 / max(psd_multi_eof1)
ggplot(mapping=aes(x=psd_freq, y=rpsd_multi_eof1)) + geom_smooth(se=FALSE, color='lightgrey') +
    xlab('Frequency') + ylab('EOF-1 Power Spectral Density') + 
    ggtitle('MULTI residuals with MULTI mean field') +
    theme_solarized_2(light=FALSE, base_size = 14)

The single-rcp power spectrum looks very similar to the corresponding figure from the paper. It is actually slightly more concentrated at low frequencies than the corresponding power spectrum for the emulator trained on all 9 ESM runs. The result of the multi-rcp fit is qualitatively similar, though with rather more relative power at higher frequencies.

Based on these results, it seems clear that the long-period EOF is not the result of anything related to the CC, as it occurs even when the entire model is fit on a single rcp.

Claim #3

This claim posits that the residuals for the ESMs in the multi-rcp emulator have a variance that is inflated relative to the corresponding residuals for the single-rcp emulator, due to the mismatch in the mean field model. In light of the results for Claim #1, this claim seems hard to support. Nevertheless, it’s worth going through how we might test a claim like this.

What makes this claim tricky to adjudicate is that although we have a sample of residuals in each grid cell, we generally expect the variance of those values to be grid cell dependent. Therefore, we cannot readily combine all of these residuals into a single statistical test. What we can do is to employ something like our statistical analysis from the paper, where we perform the F-test on a grid cell by grid cell basis and then compare the number of failures to the expected number of failures under the null hypothesis and under an alternate hypothesis of a de minimis change in variance.

Alternatively, we could apply the F-test individually in each grid cell using the Holm-Bonferroni correction. (Holm 1979). This correction adjusts for the fact that when running many independent, but related tests, some (many, in the case of the large number of tests we will be performing) will have low p-values just due to random variation. For the sake of variety, we will take the latter approach in this analysis.

## Residuals for the rcp85 model are stored in the emulator
resid85 <- emulator_rcp85$pscl$r
## To calculate the residuals for the multi-rcp model we have to apply that mean field
## model manually
calc_resid <- function(pscl, tgav, griddata) {
    tmean <- fldgen::pscl_apply(pscl, tgav)
    griddata$tas - tmean
}
residmulti <- calc_resid(emulator_multi_rcp$pscl, emulator_rcp85$tgav, emulator_rcp85$griddata)
getpval <- function(i) {
    rmulti <- residmulti[ , i]
    r85 <- resid85[ , i]
    ## Test that the ratio of var(rmulti)/var(r85) is _greater_ than 1
    var.test(rmulti, r85, alternative='greater')$p.value
}
pvals <- sapply(seq(1,ncol(resid85)), getpval)
## Accept or reject using the Holm-Bonferroni procedure.
pvals_srt <- sort(pvals)
holm_fac <- rev(seq_along(pvals_srt))
pvals_holm <- pmin(pvals_srt * holm_fac, 1.0)
## Find the number of null hypotheses to reject.  The rule is find the first one that
## _doesn't_ reject; reject all the ones before that
base_pval <- 0.05
n_null_reject <- min(which(pvals_holm > base_pval)) - 1
n_null_reject
[1] 0

From this calculation we see that none of the grid cells show evidence of a larger variance when using the multi-rcp mean field model. In fact, this test is not even close. Even without the Holm-Bonferroni correction, only 6 grid cells show a statistically significant difference in variance. Given the tiny difference in the mean field models in question, this is to be expected.

Conclusion

It turns out that we never ended up needing to worry about effect sizes or the like. The mean field models are practically identical for the two ensembles. As a result, the three claims in the CC don’t even rise to the level of statistical significance. Given the amount of data here, that would indicate that the effect sizes involved are truly tiny. Therefore, the CC, though plausible a priori, appears not to be a factor in the results presented in the paper.

References

Holm, S. (1979), “A Simple Sequentially Rejective Multiple Test Procedure”, Scandinavian Journal of Statistics, 6(2), pp. 65-70.

LS0tCnRpdGxlOiAnRmxkZ2VuIHYxLjA6IEFuYWx5c2lzIG9mIHRoZSBDb21wcm9taXNlIENvbmplY3R1cmUnCmF1dGhvcjogIlJvYmVydCBMaW5rIgpkYXRlOiAnMjAxOS0wMy0wMycKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKLS0tCgojIyBJbnRyb2R1Y3Rpb24KClNldmVyYWwgcmVhZGVycyBvZiB0aGUgZGlzY3Vzc2lvbiB2ZXJzaW9uIG9mIHRoZSBmbGRnZW4gcGFwZXIgaGF2ZSBxdWVzdGlvbmVkCndoZXRoZXIgZml0dGluZyB0aGUgbWVhbiBmaWVsZCBhbmQgdmFyaWFiaWxpdHkgbW9kZWxzIG92ZXIgdGhlIGVudGlyZSByYW5nZSBvZgpSQ1Agc2NlbmFyaW9zIGludHJvZHVjZXMgYSBmb3JtIG9mIGJpYXMuICBIZXJlIGlzIG9uZSBleGFtcGxlIG9mIHN1Y2ggYSBjb21tZW50CmZyb20gQW5vbnltb3VzIFJldmlld2VyIFwjMzoKCj4gSSBoYWQgc2ltaWxhciB0aG91Z2h0cyBhcyByZXZpZXdlciB0d28gcmUgdXNpbmcgZGlmZmVyZW50IFJDUHMgdXNlZCB0byB0cmFpbgp0aGUgZW11bGF0b3IsIGFuZCBJIGRpZG7igJl0IGZpbmQgdGhlIHJlc3BvbnNlIGZ1bGx5IGNvbnZpbmNpbmcg4oCTIHNvbWUgdGVzdHMKc2hvdWxkIGJlIHBvc3NpYmxlIGhlcmU/IEluIHBhcnRpY3VsYXIsIEkgZm91bmQgbXlzZWxmIHdvbmRlcmluZyB3aGV0aGVyIEVPRjEKcmVmbGVjdGVkIHJlc3BvbnNlcyB0byBkaWZmZXJlbnQgUkNQcy4gRGlkIHlvdSBjaGVjayB3aGV0aGVyIEVPRjEgd2FzIHNpbWlsYXIgaW4KYW4gZW11bGF0b3IgdHJhaW5lZCBvbiBhIGZldyBzaW11bGF0aW9ucyB3aXRoIGEgc2luZ2xlIFJDUCAoYW5kIGRpZG7igJl0CmRpc2FwcGVhciwgYXMgd2hlbiB5b3UgdHJhaW5lZCBvbiBhIHNpbmdsZSBzaW11bGF0aW9uKT8gV2h5IG5vdCBjb21wYXJlIHRoZQp2YXJpYW5jZSBvZiB0aGUgZnVsbCBlbXVsYXRvciAoaS5lLiB0cmFpbmVkIG9uIGFsbCA5IHNpbXVsYXRpb25zKSBzZXBhcmF0ZWx5CndpdGggdGhlIFJDUDIuNiBzaW11bGF0aW9ucyBhbmQgd2l0aCB0aGUgUkNQOC41IHNpbXVsYXRpb25zIHRvIHF1YW50aWZ5IGFueQpzY2VuYXJpbyBiaWFzPyBJbiBhbnkgZXZlbnQsIHNvbWUgZGlzY3Vzc2lvbiBvZiB0aGlzIHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGUKdGV4dCBhcyBJIHN1c3BlY3QgbWFueSBwZW9wbGUgd2lsbCBxdWVzdGlvbiBpdC4gUmVwZWF0aW5nIGZyb20gUmV2aWV3ZXIgVHdvCuKAnFNlY3Rpb24gNC4yIGdvdCBtZSB0aGlua2luZyB0aGF0IGFzIHRoZSBtb2RlbCBpcyB0cmFpbmVkIG9uIHRoZSBSQ1Agb3V0cHV0cywgaXMKdGhlcmUgYW55IGRpZmZlcmVuY2UgaW4gdGhlIHJlc3VsdHMgd2hlbiB0YWtpbmcganVzdCB0aGUgc2V0IG9mIHJlYWxpc2F0aW9ucwpmcm9tIFJDUDIuNiBhbmQgUkNQOC41PyBDZXJ0YWludGx5IGFjcm9zcyBFU01zLCB0aGUgdmFyaWFuY2UgYWNyb3NzIG1vZGVscwppbmNyZWFzZXMgd2l0aCBpbmNyZWFzaW5nIGdsb2JhbCBtZWFuIHRlbXBlcmF0dXJlLiBJdCB3b3VsZCB0aGVyZWZvcmUgbm90IGJlCmNvcnJlY3QgdG8gdXNlIGEgdmFyaWFiaWxpdHkgbW9kZWwgdGhhdCBpcyB0cmFpbmVkIG9uIFJDUDguNSBmb3IgbG93IGZvcmNpbmcKc2NlbmFyaW9zIG9yIHRob3NlIHdpdGggYSBwZWFrIGFuZCBkZWNsaW5lLiBJIG5vdGUgdGhlIGF1dGhvcnMgYWRkcmVzcyB0aGlzIGluCnNlY3Rpb24gNC4zLCBidXQgSSB3b25kZXIgaWYgdGhleSBoYXZlIHRlc3RlZCB0aGlzLuKAnQoKV2UgY2FuIGJyZWFrIHRoZSByZXZpZXdlcidzIGNvbmplY3R1cmUgZG93biBpbnRvIHNldmVyYWwgc3BlY2lmaWMsIHRlc3RhYmxlIApjbGFpbXMuCgoxLiAqKklzIHRoZSBtZWFuIGZpZWxkIG1vZGVsIGZpdCB0byBhIHNpbmdsZSBSQ1Agc2lnbmlmaWNhbnRseSBkaWZmZXJlbnQgdG8gdGhhdApmaXQgdG8gdGhlIGVuc2VtYmxlIG9mIFJDUHM/KiogIE91ciBleHBlcmllbmNlIHdpdGggZml0dGluZyBtb3JlIHNvcGhpc3RpY2F0ZWQKcGF0dGVybiBhbmFseXNpcyBhbGdvcml0aG1zIHN1Z2dlc3RzIHRoYXQgaXQgZG9lcyBub3QsIGJ1dCB3ZSBoYXZlIG5vdCBmb3JtYWxseQp0ZXN0ZWQgdGhhdCBoeXBvdGhlc2lzIHdpdGggbGluZWFyIHBhdHRlcm4gc2NhbGluZy4KMy4gKipEb2VzIHRoZSBmaXJzdCBFT0Ygb2YgdGhlIHZhcmlhYmlsaXR5IG1vZGVsIHJlcHJlc2VudCBhbiBhZGp1c3RtZW50IGZyb20KY29tcHJvbWlzZSBmaXQgb2YgdGhlIG1lYW4gZmllbGQgdG8gdGhlIHNwZWNpZmljIGJlaGF2aW9ycyBvZiB0aGUgaW5kaXZpZHVhbCAKd2FybWluZyBzY2VuYXJpb3M/KiogIEluIG90aGVyIHdvcmRzLCB0aGUgY2xhaW0gaGVyZSBpcyB0aGF0IHdoZW4gd2UgZml0IHRoZSAKbWVhbiBmaWVsZCBtb2RlbCB0byB0aGUgZW50aXJlIGNvbGxlY3Rpb24gb2Ygd2FybWluZyBzY2VuYXJpb3MsIHdlIHByb2R1Y2UgYQptZWFuIGZpZWxkIHRoYXQgaXMgbm90IGV4YWN0bHkgYXBwcm9wcmlhdGUgZm9yIGFueSBvZiB0aGUgUkNQIHdhcm1pbmcgc2NlbmFyaW9zLAphbmQgdGhhdCBFT0YtMSByZXByZXNlbnRzIGEgY29ycmVjdGlvbiBmaWVsZCB0aGF0IGJyaW5ncyB0aGUgbWVhbiBmaWVsZCBpbnRvIAphZ3JlZW1lbnQgd2l0aCB0aGUgaW5kaXZpZHVhbCBSQ1AgbWVhbiBmaWVsZCBiZWhhdmlvci4gIF9JZl8gdGhhdCBjb25qZWN0dXJlIGlzCnRydWUsIHRoZW4gaXQgd291bGQgYmUgYSBtaXN0YWtlIHRvIHJhbmRvbWl6ZSB0aGUgcGhhc2Ugb2YgdGhhdCBjb21wb25lbnQsIGFzCml0IGlzIG5vdCB0cnVseSByZXByZXNlbnRpbmcgcmFuZG9tIHZhcmlhdGlvbiwgYnV0IHJhdGhlciBhIGNvbXBvbmVudCBvZiB0aGUgCmZvcmNlZCBiZWhhdmlvciB0aGF0IHdlIGFyZSBub3QgY2FwdHVyaW5nLgoyLiAqKklzIHRoZSByZXNpZHVhbCB2YXJpYW5jZSBoaWdoZXIgd2hlbiBmaXR0aW5nIHRvIGEgbXVsdGktc2NlbmFyaW8gZW5zZW1ibGUKdGhhbiB3aGVuIGZpdHRpbmcgdG8gYSBzaW5nbGUtc2NlbmFyaW8gZW5zZW1ibGU/KiogIFRoaXMgd291bGQgYmUgYW4gaW5kaWNhdGlvbgp0aGF0IHNvbWUgb2Ygd2hhdCB3ZSBhcmUgZGVzY3JpYmluZyBhcyAidmFyaWFiaWxpdHkiIGlzIGFjdHVsbHkgZm9yY2VkIHZhcmlhdGlvbgpub3QgYmVpbmcgY2FwdHVyZWQgYnkgdGhlIG1lYW4gZmllbGQgbW9kZWwuCgoKSSB3aWxsIHJlZmVyIHRvIHRoZXNlIGNsYWltcyBjb2xsZWN0aXZlbHkgYXMgdGhlIF9Db21wcm9taXNlIENvbmplY3R1cmVfIChDQykuCklmIHRoZSBDQyBpcyB3aG9sbHkgb3IgcGFydGx5IHRydWUsIHRoZW4gb3VyIGVtdWxhdG9yIGlzIHJlcHJlc2VudGluZyBzb21lIG9mCnRoZSBmb3JjZWQgdmFyaWF0aW9uIGFzIGR5bmFtaWNhbCB2YXJpYWJpbGl0eSwgd2hpY2ggbWF5IHJlcXVpcmUgc29tZSBzb3J0IG9mCmNvcnJlY3Rpb24uCgpPZiBjb3Vyc2UsIHdlIGFscmVhZHkgX2tub3dfIHRoYXQgdGhlIENDIGlzIHRydWUgdG8gc29tZSBleHRlbnQuICBUaGUgYXNzdW1wdGlvbgp0aGF0IHRoZSBiZWhhdmlvciBvZiB0aGUgRVNNcyBjYW4gYmUgY2xlYW5seSBzZXBhcmF0ZWQgaW50byBkZXRlcm1pbmlzdGljIGZvcmNpbmcKYW5kIHJhbmRvbSB2YXJpYWJpbGl0eSB3YXMgYWx3YXlzIGFuIGFwcHJveGltYXRpb247IGFzIHdlIG5vdGUgaW4gdGhlIG1haW4gYm9keSBvZiB0aGUgcGFwZXIuClNvLCB0aGUgcmVhbCBxdWVzdGlvbiBoZXJlIGlzLCBob3cgYmlnIGlzIHRoZSBlcnJvciBjcmVhdGVkIGJ5IHRoYXQgYXBwcm94aW1hdGlvbj8KSXMgaXQgbGFyZ2UgZW5vdWdoIHRvIHJlcXVpcmUgZXhwbGljaXQgY29ycmVjdGlvbj8KCiMjIFRlc3RpbmcgdGhlIENvbXByb21pc2UgQ29uamVjdHVyZQoKVGVzdGluZyB0aGVzZSBjbGFpbXMgaXMgdHJpY2t5IGZvciB0d28gcmVhc29ucy4gIEZpcnN0LCB0aGUgc3RhdGlzdGljYWwKcHJvcGVydGllcyBvZiB0aGUgZW5zZW1ibGUgZGVwZW5kIG9uIHRoZSBudW1iZXIgb2Ygc2NlbmFyaW9zIGluIHRoZSBlbnNlbWJsZSwgYXMKd2VsbCBhcyBvbiB0aGUgbWl4IG9yIFJDUCBwYXRod2F5cyBpbiB0aGUgZW5zZW1ibGUuICBUaGVyZWZvcmUsIGl0IHdvdWxkIGJlIHZlcnkKaGFyZCB0byBnZXQgYW55IGludGVycHJldGFibGUgcmVzdWx0IGNvbXBhcmluZyB0aGUgbmluZS1ydW4gbXVsdGktcmNwIGVtdWxhdG9yIAp0byBhbiBlbXVsYXRvciB0cmFpbmVkIG9uIHR3byBvciB0aHJlZSBydW5zIGZyb20gYSBzaW5nbGUgcmNwLiAgSW5zdGVhZCwgd2Ugd2lsbApoYXZlIHRvIGludmVzdGlnYXRlIHRoZXNlIHF1ZXN0aW9ucyBieSB0cmFpbmluZyBhbiBlbXVsYXRvciBvbiB0aGUgdGhyZWUgcmNwOC41CnNjZW5hcmlvcyB0aGF0IHdlIGhhdmUgYW5kIGNvbXBhcmluZyB0aGF0IHRvIGFuIGVtdWxhdG9yIHRyYWluZWQgb24gdGhyZWUgCnNjZW5hcmlvcyBmcm9tIGFjcm9zcyB0aGUgcmNwcyAoSSBzdWdnZXN0IDIuNiwgNi4wLCBhbmQgOC41IGFzIGdpdmluZyB0aGUgbW9zdCAKdW5pZm9ybSBjb3ZlcmFnZSkuICAKClRoZSBzZWNvbmQgcmVhc29uIGl0IGlzIGRpZmZpY3VsdCB0byB0ZXN0IHRoZXNlIGNsYWltcyBpcyB0aGF0IHRoZXkgaGluZ2Ugb24KdGhlIHNpemUgb2YgdGhlIGVmZmVjdC4gIEl0IG1heSBub3QgYmUgZW5vdWdoIG1lcmVseSB0byB0ZXN0IHdoZXRoZXIgCm9yIG5vdCBhbnkgZWZmZWN0cyBhcmUgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBiZWNhdXNlIHN0YXRpc3RpY2FsIHNpZ25pZmljYW5jZQppcyBub3QgdGhlIHNhbWUgYXMgX3ByYWN0aWNhbF8gc2lnbmlmaWNhbmNlLiAgSWYgYW4gZWZmZWN0IGlzIG5vdCBzdGF0aXN0aWNhbGx5CnNpZ25pZmljYW50LCB0aGVuIHdlIGNhbiBwcm9iYWJseSBkaXNtaXNzIGl0IG9uIHRoZSBncm91bmRzIHRoYXQgd2UgY2FuJ3QgZXZlbgpiZSBzdXJlIGl0IGV4aXN0cywgbGV0IGFsb25lIGlzIGltcG9ydGFudCBpbiBwcmFjdGljYWwgYXBwbGljYXRpb25zLiAgSG93ZXZlciwKSSBhbSBhIGJpdCBjb25jZXJuZWQgdGhhdCBvbiBhIGxhcmdlIGdyaWQgbGlrZSB3ZSBoYXZlICg1NSwyOTYgZ3JpZCBjZWxscyksIGV2ZW4KdGhlIHRpbnkgZWZmZWN0cywgd2hpY2ggd2Uga25vdyBtdXN0IGJlIHByZXNlbnQgYXMgYSBjb25zZXF1ZW5jZSBvZiBvdXIgc2VwYXJhYmlsaXR5CmFwcHJveGltYXRpb24sIGNvdWxkIGJlIHN0YXRpc3RpY2FsbHkgZGV0ZWN0YWJsZS4gIAoKRm9yIGNsYWltcyB3aGVyZSB0aGlzIGhhcHBlbnMsIHdlIG5lZWQgdG8gZGVmaW5lIGFuIGVmZmVjdCBzaXplIGFuZCBhIHRocmVzaG9sZApvZiBhY2NlcHRhYmlsaXR5IHRvIGNvbXBhcmUgaXQgdG8uICBGdXJ0aGVyIGNvbXBsaWNhdGluZyB0aGlzIHRhc2sgaXMgdGhlCnF1YW50aXRhdGl2ZSByZXN1bHRzIHdlIGFyZSBsb29raW5nIGF0IGFyZSBkZWZpbmVkIGluIGluZGl2aWR1YWwgZ3JpZCBjZWxscywgYW5kCnRoZSBkaXJlY3Rpb24gb2YgdGhlIHNoaWZ0IChpZiBhbnkpIGFuZCBzY2FsZSBvZiB2YXJpYWJpbGl0eSB3aWxsIGJlIGRpZmZlcmVudApiZXR3ZWVuIGdyaWQgY2VsbHMuICBXZSB3aWxsIGhhdmUgdG8gZmluZCBhIHdheSB0byBhZ2dyZWdhdGUgYW55IGp1ZGdtZW50IG9mCnByYWN0aWNhbCBzaWduaWZpY2FuY2UgdG8gdGhlIHN5c3RlbSBhcyBhIHdob2xlLgoKCiMjIFNvZnR3YXJlIHZlcnNpb24KClRoZXNlIGNhbGN1bGF0aW9ucyB3ZXJlIHJ1biB3aXRoIGByIHBhc3RlMCgnZmxkZ2VuLXYnLHBhY2thZ2VWZXJzaW9uKCdmbGRnZW4nKSlgCgojIyBTaW1wbGUgdGVzdHMgZXZhbHVhdGluZyB0aGUgY2xhaW1zCgpgYGB7ciBzZXR1cH0KbGlicmFyeShmbGRnZW4pCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3RoZW1lcykKCnNldC5zZWVkKDg2Ny01MzA5KQpgYGAKCmBgYHtyIGxvYWRkYXRhfQplbXVsYXRvcl9yY3A4NSA8LSB0cmFpbignZGF0YS1yY3A4NScsIGxhdHZhcj0nbGF0XzInLCBsb252YXI9J2xvbl8yJykKZW11bGF0b3JfbXVsdGlfcmNwIDwtIHRyYWluKCdkYXRhLW11bHRpLXJjcCcsIGxhdHZhcj0nbGF0XzInLCBsb252YXI9J2xvbl8yJykKYGBgCgojIyBDbGFpbSBcIzEKClRoZSBoZWFydCBvZiB0aGlzIGNsYWltIGlzIHRoYXQgdGhlIG1lYW4gZmllbGQgbW9kZWwgZm9yIGFuIGVuc2VtYmxlIG9mIApFU00gcnVucyBmcm9tIHRoZSBzYW1lIFJDUCB3aWxsIGJlIGRpZmZlcmVudCBmcm9tIHRoZSBtZWFuIGZpZWxkIG1vZGVsIGZvcgphbiBlbnNlbWJsZSBvZiBydW5zIGNvdmVyaW5nIGEgdmFyaWV0eSBvZiBSQ1Agc2NlbmFyaW9zLiAgV2UgY2FuIGV4YW1pbmUKdGhlIGNvZWZmaWNpZW50cyBtb2RlbHMgZGlyZWN0bHkgdG8gc2VlIGhvdyBkaWZmZXJlbnQgdGhlIG1lYW4gZmllbGQgbW9kZWxzCmFyZS4KYGBge3IgcGxvdGNvZWZzfQpnZ3Bsb3QobWFwcGluZz1hZXMoeD1hcy52ZWN0b3IoZW11bGF0b3JfbXVsdGlfcmNwJHBzY2wkdyksIAogICAgICAgICAgICAgICAgICAgeT1hcy52ZWN0b3IoZW11bGF0b3JfcmNwODUkcHNjbCR3KSkpICsKICAgIGdlb21fcG9pbnQoY29sb3I9J2xpZ2h0Z3JleScsIHNoYXBlPScuJykgKwogICAgdGhlbWVfc29sYXJpemVkXzIobGlnaHQ9RkFMU0UsIGJhc2Vfc2l6ZT0xNCkgKwogICAgeGxhYignTVVMVEkgY29lZmZpY2llbnQnKSArIHlsYWIoJ1JDUDg1IGNvZWZmaWNpZW50JykgKwogICAgZ2d0aXRsZSgnQ29tcGFyaXNvbiBvZiBsaW5lYXIgY29lZmZpY2llbnQgKHcpJykKCmdncGxvdChtYXBwaW5nPWFlcyh4PWFzLnZlY3RvcihlbXVsYXRvcl9tdWx0aV9yY3AkcHNjbCRiKSwgCiAgICAgICAgICAgICAgICAgICB5PWFzLnZlY3RvcihlbXVsYXRvcl9yY3A4NSRwc2NsJGIpKSkgKwogICAgZ2VvbV9wb2ludChjb2xvcj0nbGlnaHRncmV5Jywgc2hhcGU9Jy4nKSArCiAgICB0aGVtZV9zb2xhcml6ZWRfMihsaWdodD1GQUxTRSwgYmFzZV9zaXplPTE0KSArCiAgICB4bGFiKCdNVUxUSSBjb2VmZmljaWVudCcpICsgeWxhYignUkNQODUgY29lZmZpY2llbnQnKSArCiAgICBnZ3RpdGxlKCdDb21wYXJpc29uIG9mIGludGVyY2VwdCBjb2VmZmljaWVudCAoYiknKQpgYGAKCkl0IGlzIGVhc3kgZW5vdWdoIHRvIHNlZSB0aGF0IHRob3NlIHR3byBtb2RlbHMgYXJlIF9leHRyZW1lbHlfIHNpbWlsYXIuICBXZSBjYW4KcXVhbnRpZnkganVzdCBob3cgc2ltaWxhciB0aGV5IGFyZSBieSBmaXR0aW5nIGEgbGluZWFyIG1vZGVsIHByZWRpY3RpbmcgdGhlIFJDUDg1CmNvZWZmaWNpZW50IGZyb20gdGhlIGNvcnJlc3BvbmRpbmcgbXVsdGktcmNwIGNvZWZmaWNpZW50LgoKYGBge3IgY29lZm1vZGVsc30KbG13IDwtIGxtKGVtdWxhdG9yX3JjcDg1JHBzY2wkd35lbXVsYXRvcl9tdWx0aV9yY3AkcHNjbCR3ICsgMCkKbG1iIDwtIGxtKGVtdWxhdG9yX3JjcDg1JHBzY2wkYn5lbXVsYXRvcl9tdWx0aV9yY3AkcHNjbCRiICsgMCkKCnN1bW1hcnkobG13KQpzdW1tYXJ5KGxtYikKYGBgCgpTbywgdGhlIGF2ZXJhZ2UgcmF0aW8gYmV0d2VlbiB0aGUgUkNQODUgYW5kIG11bHRpLXJjcCBsaW5lYXIgY29lZmZpY2llbnRzICgkdyQpIGlzCjAuOTk0LiAgVGhlICRSXjIkIG9uIHRoaXMgcmVsYXRpb25zaGlwIGlzIDAuOTk5LiAgTW9zdCBvZiB0aGUgcmVzaWR1YWxzIGFyZSB3aXRoaW4KKy8tIDAuMDIgb2YgMCAoZm9yIGEgY29lZmZpY2llbnQgdGhhdCByYW5nZXMgYXBwcm94aW1hdGVseSBmcm9tIDAtMykuCgpGb3IgdGhlIGludGVyY2VwdCBjb2VmZmljaWVudCAoJGIkKSwgdGhlIHJlbGF0aW9uc2hpcCBpcyBldmVyIHNvIHNsaWdodGx5IHJvdWdoZXI7CnRoZSBjb2VmZmljaWVudCByYXRpbyBpcyAwLjk4Nywgd2l0aCBhbiAkUl4yJCBvZiAib25seSIgMC45OTguICBNb3N0IG9mIHRoZSByZXNpZHVhbHMKYXJlIGJldHdlZW4gLTUgYW5kICs2ICh0aGUgc2NhbGUgb2YgdGhpcyB2YXJpYWJsZSBpcyBjb25zaWRlcmFibHkgbGFyZ2VyOiAtNjUwIC0gKzMwMC4pCgpUaGUgbWVhbiBmaWVsZCBtb2RlbHMgYXJlIHZpcnR1YWxseSBpbmRpc3Rpbmd1aXNoYWJsZSwgd2hldGhlciBmaXQgb24gYSBzaW5nbGUKUkNQIG9yIGEgc2VsZWN0aW9uIG9mIFJDUHM7IHRoZXJlZm9yZSwgYWx0aG91Z2ggdGhlIGxvbmctcGVyaW9kIEVPRnMgYXJlIHRlbGxpbmcKdXMgX3NvbWV0aGluZ18gYWJvdXQgdGhlIGRpZmZlcmVuY2VzIGJldHdlZW4gaW5kaXZpZHVhbCBydW5zLCB0aGVyZSBkb2Vzbid0IHNlZW0KdG8gYmUgYW55IGV2aWRlbmNlIHRoYXQgdGhlc2UgZGlmZmVyZW5jZXMgYXJlIGEgc3lzdGVtYXRpYyBmdW5jdGlvbiBvZiBSQ1AuCgpUbyBtZSwgdGhlc2UgcmVzdWx0cyBhbG9uZSB2aXRpYXRlIHRoZSBDb21wcm9taXNlIENvbmplY3R1cmUuICBXaXRob3V0IGFueQpzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHRoZSBtZWFuIHJlc3BvbnNlIHVuZGVyIGRpZmZlcmVudCBjbGltYXRlIGNoYW5nZQpwYXRod2F5cywgdGhlcmUgaXMgbm8gcmVhbCBtb3RpdmF0aW9uIGZvciB0aGUgb3RoZXIgY2xhaW1zLgoKIyMgQ2xhaW0gXCMyCgpUaGUgc2Vjb25kIGNsYWltIGluIHRoZSBDQyBpcyB0aGF0IHRoZSBsb25nLXBlcmlvZCBFT0ZzIGFyZSBhIHJlcHJlc2VudGF0aW9uIG9mIHRoZSAKbWlzbWF0Y2ggYmV0d2VlbiB0aGUgbWVhbiBmaWVsZCBtb2RlbCBhbmQgdGhlIFJDUCBvdXRwdXRzIGZyb20gd2hpY2ggdGhlIHJlc2lkdWFscyAKYXJlIGNhbGN1bGF0ZWQuICBJZiB0aGlzIHdlcmUgdHJ1ZSwgdGhlbiB3ZSB3b3VsZCBleHBlY3QgdGhhdCBmb3IgZW11bGF0b3JzIGZpdCB0byAKcnVucyByZXByZXNlbnRpbmcgYSBfc2luZ2xlXyByY3AsIHRoZXJlIHNob3VsZCBub3QgYmUgYSBsb25nLXBlcmlvZCBtb2RlLiAgV2UgY2FuCmNoZWNrIHRoaXMgaHlwb3RoZXNpcyBieSBwbG90dGluZyB0aGUgcG93ZXIgc3BlY3RydW0gZm9yIEVPRi0xIGZvciB0aGUgc2luZ2xlLXJjcAplbXVsYXRvci4KCmBgYHtyIGxwZW9mfQpwc2RfcmNwODVfZW9mMSA8LSBlbXVsYXRvcl9yY3A4NSRmeCRtYWdbMTo0NyAsMl1eMgpycHNkX3JjcDg1X2VvZjEgPC0gcHNkX3JjcDg1X2VvZjEgLyBtYXgocHNkX3JjcDg1X2VvZjEpCnBzZF9mcmVxIDwtIChzZXFfYWxvbmcocnBzZF9yY3A4NV9lb2YxKS0xKS85NQpnZ3Bsb3QobWFwcGluZz1hZXMoeD1wc2RfZnJlcSwgeT1ycHNkX3JjcDg1X2VvZjEpKSArIGdlb21fc21vb3RoKHNlPUZBTFNFLCBjb2xvcj0nbGlnaHRncmV5JykgKwogICAgeGxhYignRnJlcXVlbmN5JykgKyB5bGFiKCdFT0YtMSBQb3dlciBTcGVjdHJhbCBEZW5zaXR5JykgKyAKICAgIGdndGl0bGUoJ1JDUDg1IHJlc2lkdWFscyB3aXRoIFJDUDg1IG1lYW4gZmllbGQnKSArCiAgICB0aGVtZV9zb2xhcml6ZWRfMihsaWdodD1GQUxTRSwgYmFzZV9zaXplID0gMTQpCgpwc2RfbXVsdGlfZW9mMSA8LSBlbXVsYXRvcl9tdWx0aV9yY3AkZngkbWFnWzE6NDcgLDJdXjIKcnBzZF9tdWx0aV9lb2YxIDwtIHBzZF9tdWx0aV9lb2YxIC8gbWF4KHBzZF9tdWx0aV9lb2YxKQpnZ3Bsb3QobWFwcGluZz1hZXMoeD1wc2RfZnJlcSwgeT1ycHNkX211bHRpX2VvZjEpKSArIGdlb21fc21vb3RoKHNlPUZBTFNFLCBjb2xvcj0nbGlnaHRncmV5JykgKwogICAgeGxhYignRnJlcXVlbmN5JykgKyB5bGFiKCdFT0YtMSBQb3dlciBTcGVjdHJhbCBEZW5zaXR5JykgKyAKICAgIGdndGl0bGUoJ01VTFRJIHJlc2lkdWFscyB3aXRoIE1VTFRJIG1lYW4gZmllbGQnKSArCiAgICB0aGVtZV9zb2xhcml6ZWRfMihsaWdodD1GQUxTRSwgYmFzZV9zaXplID0gMTQpCmBgYAoKVGhlIHNpbmdsZS1yY3AgcG93ZXIgc3BlY3RydW0gbG9va3MgX3ZlcnlfIHNpbWlsYXIgdG8gdGhlIGNvcnJlc3BvbmRpbmcgZmlndXJlCmZyb20gdGhlIHBhcGVyLiAgSXQgaXMgYWN0dWFsbHkgc2xpZ2h0bHkgX21vcmVfIGNvbmNlbnRyYXRlZCBhdCBsb3cgZnJlcXVlbmNpZXMKdGhhbiB0aGUgY29ycmVzcG9uZGluZyBwb3dlciBzcGVjdHJ1bSBmb3IgdGhlIGVtdWxhdG9yIHRyYWluZWQgb24gYWxsIDkgRVNNCnJ1bnMuICBUaGUgcmVzdWx0IG9mIHRoZSBtdWx0aS1yY3AgZml0IGlzIHF1YWxpdGF0aXZlbHkgc2ltaWxhciwgdGhvdWdoIHdpdGgKcmF0aGVyIG1vcmUgcmVsYXRpdmUgcG93ZXIgYXQgaGlnaGVyIGZyZXF1ZW5jaWVzLgoKQmFzZWQgb24gdGhlc2UgcmVzdWx0cywgaXQgc2VlbXMgY2xlYXIgdGhhdCB0aGUgbG9uZy1wZXJpb2QgRU9GIGlzIF9ub3RfIHRoZSAKcmVzdWx0IG9mIGFueXRoaW5nIHJlbGF0ZWQgdG8gdGhlIENDLCBhcyBpdCBvY2N1cnMgZXZlbiB3aGVuIHRoZSBlbnRpcmUgbW9kZWwKaXMgZml0IG9uIGEgc2luZ2xlIHJjcC4KCiMjIENsYWltIFwjMwoKVGhpcyBjbGFpbSBwb3NpdHMgdGhhdCB0aGUgcmVzaWR1YWxzIGZvciB0aGUgRVNNcyBpbiB0aGUgbXVsdGktcmNwIGVtdWxhdG9yCmhhdmUgYSB2YXJpYW5jZSB0aGF0IGlzIGluZmxhdGVkIHJlbGF0aXZlIHRvIHRoZSBjb3JyZXNwb25kaW5nIHJlc2lkdWFscyAKZm9yIHRoZSBzaW5nbGUtcmNwIGVtdWxhdG9yLCBkdWUgdG8gdGhlIG1pc21hdGNoIGluIHRoZSBtZWFuIGZpZWxkIG1vZGVsLgpJbiBsaWdodCBvZiB0aGUgcmVzdWx0cyBmb3IgQ2xhaW0gXCMxLCB0aGlzIGNsYWltIHNlZW1zIGhhcmQgdG8gc3VwcG9ydC4KTmV2ZXJ0aGVsZXNzLCBpdCdzIHdvcnRoIGdvaW5nIHRocm91Z2ggaG93IHdlIG1pZ2h0IHRlc3QgYSBjbGFpbSBsaWtlIHRoaXMuCgpXaGF0IG1ha2VzIHRoaXMgY2xhaW0gdHJpY2t5IHRvIGFkanVkaWNhdGUgaXMgdGhhdCBhbHRob3VnaCB3ZSBoYXZlIGEgc2FtcGxlIG9mCnJlc2lkdWFscyBpbiBlYWNoIGdyaWQgY2VsbCwgd2UgZ2VuZXJhbGx5IGV4cGVjdCB0aGUgdmFyaWFuY2Ugb2YgdGhvc2UgdmFsdWVzIHRvCmJlIGdyaWQgY2VsbCBkZXBlbmRlbnQuICBUaGVyZWZvcmUsIHdlIGNhbm5vdCByZWFkaWx5IGNvbWJpbmUgYWxsIG9mIHRoZXNlCnJlc2lkdWFscyBpbnRvIGEgc2luZ2xlIHN0YXRpc3RpY2FsIHRlc3QuICBXaGF0IHdlIGNhbiBkbyBpcyB0byBlbXBsb3kgc29tZXRoaW5nCmxpa2Ugb3VyIHN0YXRpc3RpY2FsIGFuYWx5c2lzIGZyb20gdGhlIHBhcGVyLCB3aGVyZSB3ZSBwZXJmb3JtIHRoZSBGLXRlc3Qgb24gYQpncmlkIGNlbGwgYnkgZ3JpZCBjZWxsIGJhc2lzIGFuZCB0aGVuIGNvbXBhcmUgdGhlIG51bWJlciBvZiBmYWlsdXJlcyB0byB0aGUKZXhwZWN0ZWQgbnVtYmVyIG9mIGZhaWx1cmVzIHVuZGVyIHRoZSBudWxsIGh5cG90aGVzaXMgYW5kIHVuZGVyIGFuIGFsdGVybmF0ZQpoeXBvdGhlc2lzIG9mIGEgX2RlIG1pbmltaXNfIGNoYW5nZSBpbiB2YXJpYW5jZS4KCkFsdGVybmF0aXZlbHksIHdlIGNvdWxkIGFwcGx5IHRoZSBGLXRlc3QgaW5kaXZpZHVhbGx5IGluIGVhY2ggZ3JpZCBjZWxsIHVzaW5nCnRoZSBIb2xtLUJvbmZlcnJvbmkgY29ycmVjdGlvbi4gKEhvbG0gMTk3OSkuICBUaGlzIGNvcnJlY3Rpb24gYWRqdXN0cyBmb3IgdGhlCmZhY3QgdGhhdCB3aGVuIHJ1bm5pbmcgbWFueSBpbmRlcGVuZGVudCwgYnV0IHJlbGF0ZWQgdGVzdHMsIHNvbWUgKG1hbnksIGluIHRoZQpjYXNlIG9mIHRoZSBsYXJnZSBudW1iZXIgb2YgdGVzdHMgd2Ugd2lsbCBiZSBwZXJmb3JtaW5nKSB3aWxsIGhhdmUgbG93IHAtdmFsdWVzCmp1c3QgZHVlIHRvIHJhbmRvbSB2YXJpYXRpb24uICBGb3IgdGhlIHNha2Ugb2YgdmFyaWV0eSwgd2Ugd2lsbCB0YWtlIHRoZSBsYXR0ZXIKYXBwcm9hY2ggaW4gdGhpcyBhbmFseXNpcy4KCmBgYHtyIHJlc2lkdWFsX2FuYWx5c2lzfQojIyBSZXNpZHVhbHMgZm9yIHRoZSByY3A4NSBtb2RlbCBhcmUgc3RvcmVkIGluIHRoZSBlbXVsYXRvcgpyZXNpZDg1IDwtIGVtdWxhdG9yX3JjcDg1JHBzY2wkcgojIyBUbyBjYWxjdWxhdGUgdGhlIHJlc2lkdWFscyBmb3IgdGhlIG11bHRpLXJjcCBtb2RlbCB3ZSBoYXZlIHRvIGFwcGx5IHRoYXQgbWVhbiBmaWVsZAojIyBtb2RlbCBtYW51YWxseQpjYWxjX3Jlc2lkIDwtIGZ1bmN0aW9uKHBzY2wsIHRnYXYsIGdyaWRkYXRhKSB7CiAgICB0bWVhbiA8LSBmbGRnZW46OnBzY2xfYXBwbHkocHNjbCwgdGdhdikKICAgIGdyaWRkYXRhJHRhcyAtIHRtZWFuCn0KcmVzaWRtdWx0aSA8LSBjYWxjX3Jlc2lkKGVtdWxhdG9yX211bHRpX3JjcCRwc2NsLCBlbXVsYXRvcl9yY3A4NSR0Z2F2LCBlbXVsYXRvcl9yY3A4NSRncmlkZGF0YSkKCmdldHB2YWwgPC0gZnVuY3Rpb24oaSkgewogICAgcm11bHRpIDwtIHJlc2lkbXVsdGlbICwgaV0KICAgIHI4NSA8LSByZXNpZDg1WyAsIGldCiAgICAjIyBUZXN0IHRoYXQgdGhlIHJhdGlvIG9mIHZhcihybXVsdGkpL3ZhcihyODUpIGlzIF9ncmVhdGVyXyB0aGFuIDEKICAgIHZhci50ZXN0KHJtdWx0aSwgcjg1LCBhbHRlcm5hdGl2ZT0nZ3JlYXRlcicpJHAudmFsdWUKfQpwdmFscyA8LSBzYXBwbHkoc2VxKDEsbmNvbChyZXNpZDg1KSksIGdldHB2YWwpCmBgYAoKYGBge3IgaG9sbV9ib25mZXJyb25pfQojIyBBY2NlcHQgb3IgcmVqZWN0IHVzaW5nIHRoZSBIb2xtLUJvbmZlcnJvbmkgcHJvY2VkdXJlLgpwdmFsc19zcnQgPC0gc29ydChwdmFscykKaG9sbV9mYWMgPC0gcmV2KHNlcV9hbG9uZyhwdmFsc19zcnQpKQpwdmFsc19ob2xtIDwtIHBtaW4ocHZhbHNfc3J0ICogaG9sbV9mYWMsIDEuMCkKIyMgRmluZCB0aGUgbnVtYmVyIG9mIG51bGwgaHlwb3RoZXNlcyB0byByZWplY3QuICBUaGUgcnVsZSBpcyBmaW5kIHRoZSBmaXJzdCBvbmUgdGhhdAojIyBfZG9lc24ndF8gcmVqZWN0OyByZWplY3QgYWxsIHRoZSBvbmVzIGJlZm9yZSB0aGF0CmJhc2VfcHZhbCA8LSAwLjA1Cm5fbnVsbF9yZWplY3QgPC0gbWluKHdoaWNoKHB2YWxzX2hvbG0gPiBiYXNlX3B2YWwpKSAtIDEKbl9udWxsX3JlamVjdApgYGAKCkZyb20gdGhpcyBjYWxjdWxhdGlvbiB3ZSBzZWUgdGhhdCBub25lIG9mIHRoZSBncmlkIGNlbGxzIHNob3cgZXZpZGVuY2Ugb2YgYSBsYXJnZXIgdmFyaWFuY2Ugd2hlbiB1c2luZyB0aGUgbXVsdGktcmNwCm1lYW4gZmllbGQgbW9kZWwuICBJbiBmYWN0LCB0aGlzIHRlc3QgaXMgbm90IGV2ZW4gY2xvc2UuICBFdmVuIHdpdGhvdXQgdGhlIEhvbG0tQm9uZmVycm9uaSBjb3JyZWN0aW9uLApvbmx5IGByIHN1bShwdmFscyA8PSAwLjA1KWAgZ3JpZCBjZWxscyBzaG93IGEgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGluIHZhcmlhbmNlLiAgR2l2ZW4gCnRoZSB0aW55IGRpZmZlcmVuY2UgaW4gdGhlIG1lYW4gZmllbGQgbW9kZWxzIGluIHF1ZXN0aW9uLCB0aGlzIGlzIHRvIGJlIGV4cGVjdGVkLgoKIyMgQ29uY2x1c2lvbgoKSXQgdHVybnMgb3V0IHRoYXQgd2UgbmV2ZXIgZW5kZWQgdXAgbmVlZGluZyB0byB3b3JyeSBhYm91dCBlZmZlY3Qgc2l6ZXMgb3IgdGhlIGxpa2UuICBUaGUgbWVhbiBmaWVsZAptb2RlbHMgYXJlIHByYWN0aWNhbGx5IGlkZW50aWNhbCBmb3IgdGhlIHR3byBlbnNlbWJsZXMuICBBcyBhIHJlc3VsdCwgdGhlIHRocmVlIGNsYWltcyBpbiB0aGUgQ0MgZG9uJ3QKZXZlbiByaXNlIHRvIHRoZSBsZXZlbCBvZiBzdGF0aXN0aWNhbCBzaWduaWZpY2FuY2UuICBHaXZlbiB0aGUgYW1vdW50IG9mIGRhdGEgaGVyZSwgdGhhdCB3b3VsZCBpbmRpY2F0ZQp0aGF0IHRoZSBlZmZlY3Qgc2l6ZXMgaW52b2x2ZWQgYXJlIHRydWx5IHRpbnkuICBUaGVyZWZvcmUsIHRoZSBDQywgdGhvdWdoIHBsYXVzaWJsZSBhIHByaW9yaSwgYXBwZWFycwpub3QgdG8gYmUgYSBmYWN0b3IgaW4gdGhlIHJlc3VsdHMgcHJlc2VudGVkIGluIHRoZSBwYXBlci4KCgojIyBSZWZlcmVuY2VzCgpIb2xtLCBTLiAoMTk3OSksICJBIFNpbXBsZSBTZXF1ZW50aWFsbHkgUmVqZWN0aXZlIE11bHRpcGxlIFRlc3QgUHJvY2VkdXJlIiwKX1NjYW5kaW5hdmlhbiBKb3VybmFsIG9mIFN0YXRpc3RpY3NfLCA2KDIpLCBwcC4gNjUtNzAu