1. INTRODUCTION

(Erp, Oberski, and Mulder 2018) provided an interesting comparison of different shrinkage priors in a regularized penalization task. The work visualized and described shrinkage priors well and compared them in a variety of conditions. However, the paper contained also some deficiencies regarding simulated data, convergence diagnostics and predictive performance presentation. The simulation conditions were not sparse enough to sufficiently investigate shrinkage abilities of the priors. Moreover, convergence problems were investigated only by investigating the trace plots and in some cases even by excluding simulation draws. The paper also used a large step size (1) and a low target acceptance rate (0.85). In addition, number of computed prediction mean square error (PMSE) values was inadequate in each simulation condition and their presentation difficult for a prior comparison.

The notebook presented here is a special assignment made under supervision of Prof. Aki Vehtari in Aalto university, aimed to provide tools and ideas to fix these shortcomings. The organization is as follows. Firstly, the data used is described in the section 2. The data is as presented in (Erp, Oberski, and Mulder 2018) but with more sparse representation and with a higher number of test samples. Secondly, the notebook describes how parallel coordinate and scatter plots can be used to diagnose convergence in section 3. The section concentrates on using Horseshoe and Regularized horseshoe priors as example models based on their convergence difficulties in (Erp, Oberski, and Mulder 2018). Moreover, statistics generated from multiple replications of the data is presented. In the section 4, model comparison is presented using PMSE and log pointwise predictive density (LPPD) values for test data. Originally, also the variable selection procedure described in (Erp, Oberski, and Mulder 2018) was planned to replace with projpred-package (Piironen and Vehtari 2017) but the high k-values prevented using it in this assignment. Finally, the conclusions of the assignment are discussed.

Another goal of the assignment is to provide a set of functions which can be utilized not only with the specific case described in this notebook, but also with a variety of different models and data sets by only renaming the directory paths. Moreover, the assignment details how Aalto-university students can utilize Triton in Stan model fittings in tasks which are practically infeasible with personal computers. The codes for Triton are not illustrated in the notebook but they can be attained from Triton folder along with usage instructions.

Next, let us start by including necessary libraries, functions and by choosing a working directory:

# Acquire packages
library(rstan)
library(gridExtra)
library(grid)
library(bayesplot)
library(knitr)
library(ggplot2)
library(parallel)
library("reshape2")
options(mc.cores = parallel::detectCores())
knitr::opts_knit$set(root.dir = normalizePath("~/Documents/Rbayes/Bayes_project_files/notebook"))
# Import from utilities folder
source("model_diagnostics.R")
source("data_generation.R")
source("model_generator.R")
source("choose_fits.R")

2. DATA

In (Erp, Oberski, and Mulder 2018) six different data sets, called as simulation conditions were illustrated. This notebook uses the first condition but with two modifications. Firstly, the number of coefficients is increased to \(38\) by padding \(30\) zeros in the end of the original coefficients. The reason for this is to improve the comparison of shrinkage abilities of the priors. In addition, the test set is enlarged to \(2000\) samples to attain more accurate distributions for PMSEs and LPPDs. From here on, the data set will be referred as modified simulation condition 1 and can be generated with the following code:

# Creates "project_data.RData"
data_generation()

3. STAN MODELS AND FITS

As discussed into the introduction, the special assignment has two main goals: Provide a convergence diagnosis for Horseshoe prior and to carry out a model comparison. The former is obtained by experimenting with three different parameterizations for Horseshoe prior and with Regularized Horseshoe. The parametrizations focus on reforming the Half-Cauchy distribution which is the main reason for convergence problems in Horseshoe prior. The latter is performed with the same 9 priors (including Horseshoe prior) as in (Erp, Oberski, and Mulder 2018) for simulation condition 1 with full Bayes approach. In total, 11 Stan models is created. The specifics of Horseshoe prior parametrizations are as follows:

Horseshoe 1: The same as given in (Erp, Oberski, and Mulder 2018) but with added prior for intercept \[\beta_0 \sim \mathcal{N}(0, 10) \] and with added generated quantity as test set log likelihood for LPPD computation. The original Stan code by Sara van Erp is slightly modified by using vectorized representations for speeding up computations and swapping the variable names of \(\tau\) and \(\lambda\).

Horseshoe 2. The same as Horseshoe 1 but with Tan-function parametrization for Half-Cauchy distribution as introduced by (Betancourt 2018).

Horseshoe 3. The same as Horseshoe 1 but with inverse-Gamma parametrization for Half-Cauchy distribution again described by (Betancourt 2018)

Other 8 models are otherwise the same as in (Erp, Oberski, and Mulder 2018) but as Horseshoe parametrizations, include computation of test set log-likelihoods and vectorized computing of \(y_{test}\) values. All the models can be created with following code block:

# Import from stan_files folder
stan_files <- list.files()[grep(".stan", list.files())]
model_generator(project_data, stan_files, 0)

Stan fits for all models are generated using \(sampling\) function with number of iterations as 8000, number of chains as 4, adapt_delta as 0.999 and max_treedepth ad 15. The high value of adaptation delta is necessary for not only Horseshoe prior which is prone to convergence problems but to also for the other models to ensure proper convergence. Number of iterations is higher than in (Erp, Oberski, and Mulder 2018) in order to prevent occurences of low effective sample size (\(N_{eff}\)) values. Fits can be generated exploiting again \(model.generator\) function. In this notebook, only fits for horseshoe parametrizations are necessary for divergent transition visualization and they are obtained as follows:

load("project_data.RData")
model_files <- c("horseshoe_1.SM", "horseshoe_2.SM", "horseshoe_3.SM")
model_generator(project_data, model_files, 1)

4. CONVERGENCE DIAGNOSTICS FOR HORSESHOE AND REGULARIZED HORSESHOE PRIORS

This section consists of two parts. The first demonstrates how parallel coordinate and scatter plots can be utilized in divergent transition visualization. In addition, Rhat and \(N_{eff}\) values extracted from the Stan fit are illustrated. The second part performs wider statistical diagnosis with multiple replications of the data. As previously discussed, all experiments are performed with Horseshoe prior and the main objective of the section is to used methods discussed to obtain optimal parametrization for the prior.

4.1 Experiments with 1 replication

Rhat and \(N_{eff}\) values are standard measures for convergence of Stan models (Gelman et al. 1995). However, in some cases the models may also suffer from divergent transitions which need to be examined with other tools. In (Erp, Oberski, and Mulder 2018), authors were investigating trace plots and in some cases dropping out simulations with high number of divergent transitions. This assignment proposes the use of parallel coordinate and scatter plots as suggested in (Gabry et al. 2017), in order to find out the nature of the transitions, that is, if they are false positives or not.

In parallel coordinate plots, the MCMC draws of Stan model are illustrated in two dimensions, which are parameters and their draw samples. The plots can be generated using \(mcmc.parcoord\) function and starting points of divergent transitions can be made visible using \(nuts \enspace parameters\). Generally, the parallel coordinates enable investigating divergent trajectories which are concentrated in the position of certain parameter and do not follow the same patterns as other draw trajectories. However, the parallel coordinates have trouble to visualize in the situations when the model has high number of parameters and the parameter values have high variance. Such is the case in this assignment, and in order to counter these problems, all draws in each chain are normalized between 0 and 1 and only 6 variables with lowest \(N_{eff}\) values are chosen for investigation. To ensure more clear visualization of trajectories, draw values are finally computed in logarithmic form with an added bias as 0.5 to ensure positivity. Non-divergent and divergent trajectories are plotted in black and green, respectively.

Other option for examining divergent transitions is to generate scatter plots for draw samples of two chosen parameters from distribution. As previously, \(nuts \enspace parameters\) can then be exploited to detect samples which are linked to divergent transitions. If these samples are concentrated in some location in scatter plot, model convergence could be questioned. Here, same draw values, parameters and coloration for divergent transitions as in parallel coordinate plots are presented in three different scatter plots for each Horseshoe parametrization.

fitfls <- list.files()[grep(".FIT", list.files())]
dt_visual(fitfls[1])
[1] "Model name: horseshoe_1 "
[1] "Number of RHAT values above 1.1: 0"
[1] "Number of divergent transitions: 325"
[1] "Minimum N_eff value and corresponding variable: 68, lambda[1]"

dt_visual(fitfls[2])
[1] "Model name: horseshoe_2 "
[1] "Number of RHAT values above 1.1: 0"
[1] "Number of divergent transitions: 31"
[1] "Minimum N_eff value and corresponding variable: 3875, lp__"

dt_visual(fitfls[3])
[1] "Model name: horseshoe_3 "
[1] "Number of RHAT values above 1.1: 0"
[1] "Number of divergent transitions: 16"
[1] "Minimum N_eff value and corresponding variable: 2168, tau"

The experiments on three different parametrizations show that in each case, divergent transitions are present and form concentrations in scatter plots to some extend. Therefore, the result clearly leaves out the discussion of false positives. Still, the visualizations illustrate that the results differ between parametrization. The first parametrization is clearly the worse, being the only one which exhibits clear divergent trajectories and concentrations and has lowest \(N_{eff}\) value over hundred times lower than number of iterations. The third parametrization performs the best, as it includes the lowest number of divergent transitions.

However, as all the used data is simulated, it might be the case that for this particular simulation the first parametrization happens to perform worse and the third parametrization better. In addition, only 1 replication of the data might be insufficient to give reliable convergence diagnostics. Consequently, in the setting of this assignment, parallel coordinate and scatter plots provide some insight to the problem but are insufficient for selecting optimal parametrization. Wider statistical analysis with multiple data replications is required and it is performed next.

3.2 Experiments with 500 replications

To further compare the three prametrizations, a more statistical approach is proposed. In this approach, the models are each fitted for 500 different replications and for each fit, Rhat-values, minimum \(N_{eff}\) values and corresponding parameters and divergent transitions are collected. This time, also results for the Regularized Horseshoe are included. Furthermore, PMSE and LPPD values are also generated for each fit in order to study models predictive performance. All the values were computed with Triton and can be collected with loading following Gzip archive which also includes statistics for all the other 7 shrinkage priors mentioned in section 3.

load("fit_diagnostics")
chosen_fit_diagn <- choose_fits(fit_diagn, c("horseshoe_1.SM", "horseshoe_2.SM", "horseshoe_3.SM", "regularized_horseshoe.SM"), 500)
show_diagnostics(chosen_fit_diagn,0,show_neff = TRUE)

Number of RHAT values above 1.1
mean sd max min
horseshoe_1.SM 0.1 2.0 44 0
horseshoe_2.SM 0.5 8.3 163 0
horseshoe_3.SM 0.0 0.1 2 0
regularized_horseshoe.SM 0.0 0.0 0 0
Statistics of divergent transitions
mean sd max min
horseshoe_1.SM 52.6 66.2 984 10
horseshoe_2.SM 53.7 107.0 1607 10
horseshoe_3.SM 41.4 43.6 644 7
regularized_horseshoe.SM 0.0 0.1 1 0

Two main conclusions can be drawn from the statistics. Firstly, each Horseshoe parametrization suffers from convergence problems. Mean of divergent transitions is over 40 for each model, \(N_{eff}\) may have magnitudes even below 100 and in some fits, Rhat values may exceed threshold 1.1. Contrary to the results in previous section, parametrizations 1 and 2 have now equal performance. The outcome clearly emphasizes that parallel coordinate and scatter plots have limitations regarding convergence diagnosis. Considering the parametrization ranking, Horseshoe 3 has best statistics considering Rhat, \(N_{eff}\) value and divergent transition distributions. The result is as expected as the parametrization was suggested in (Piironen and Vehtari 2016) .

More importantly, the statistics show that in terms of convergence, none of the Horseshoe parametrizations can match the Regularized Horseshoe. In all replications, no Rhat values above 1.1 emerge, smallest N_{eff} values are all higher than 1000 and only one divergent transition is found. The result with divergent transitions is also better than in (Erp, Oberski, and Mulder 2018), which implies that high value of adapt delta and number of iterations are necessary for model convergence. However, it is also important to examine how models perform with unseen data. As previously discussed, this assignment uses PMSE and LPPD values for predictive performance comparison and their distribution are shown next.

show_diagnostics(chosen_fit_diagn,1,show_neff = FALSE)

Above distributions show that the models have very similar predictive performance. In the case of Horseshoe parametrizations, the distributions are almost identical which is as expected as all the parametrizations describe the same shrinkage prior. Similarity of distributions implies that if only predictive perfromance of the model is considered, the choice of model makes no drastic difference. Moreover, the similarity of predictive performances question also the effect of divergent transitions. One possible explanation is that mapping from the parameters to the predictive distributions is such that the bias in the parameter posterior indicated by the divergences does not have an effect. This can happen, for example if the unexplored part of the parameter posterior maps to very similar predictions to the other parts of the posterior.

4. MODEL COMPARISON

In (Erp, Oberski, and Mulder 2018) model comparisons were provided using mean and standard deviation values of PMSEs. As the mean values of different models were very close to each others, the comparison was slightly difficult. In addition, no further visualization was provided. This section aims to provide a tool for more clear comparison, using the PMSE and LPPD value distributions. Based on the experiments in previous section, the chosen parametrization for Horseshoe prior is the third parametrization. All results shown in this section are again computed from 500 simulation replications and with Triton. Let us start by visualizing the distributions:

# Creates fit_diagn file
chosen_fit_diagn <- choose_fits(fit_diagn, fit_diagn$models[c(1, 4:11)], 500)
show_diagnostics(chosen_fit_diagn,1,show_neff = FALSE)

As can be seen from above figures, predictive performance of the shrinkage priors do differ. Again, the outcome deviates from the results illustrated in (Erp, Oberski, and Mulder 2018). However, since so many models are involved, it is difficult to assess which performs best. In order to provide more informative model comparison, also statistics for rankings of PMSE and LPPD values are presented. In other words, ranking values 1 to 9 are assessed to each model in each replication in a such manner that value 1 is assigned to lowest PMSE value or absolute LPPD value and 9 to highest. Results are presented in two tables below:

show_diagnostics(chosen_fit_diagn,2,show_neff = FALSE)

Ranking values of PMSES (lower is better)
mean sd max min
elastic_net_cauchy.SM 8.2 1.2 9 1
horseshoe_3.SM 2.2 1.6 9 1
hyperlasso_cauchy.SM 4.7 1.3 7 1
lasso_cauchy.SM 5.3 1.1 9 1
normal_mixture_bernoulli.SM 3.8 1.7 9 1
normal_mixture_uniform.SM 3.9 1.6 9 1
regularized_horseshoe.SM 2.0 1.4 9 1
ridge_cauchy.SM 7.8 1.1 9 2
student_cauchy.SM 7.1 1.5 9 1
Ranking values of LPPDS (lower is better)
mean sd max min
elastic_net_cauchy.SM 8.4 1.1 9 2
horseshoe_3.SM 2.2 1.3 9 1
hyperlasso_cauchy.SM 4.6 1.3 8 1
lasso_cauchy.SM 5.3 1.1 9 1
normal_mixture_bernoulli.SM 3.8 1.7 9 1
normal_mixture_uniform.SM 3.9 1.6 9 1
regularized_horseshoe.SM 1.9 1.5 9 1
ridge_cauchy.SM 7.8 0.9 9 2
student_cauchy.SM 7.0 1.4 9 1

The tables depict that Horseshoe and Regularized Horseshoe have best predictive performance abilities. The success of Horseshoe priors is as expected since their shrinkage abilities have been previously well covered in literature (Carvalho, Polson, and Scott 2010, Piironen, Vehtari, and others (2017)). However, here it must be noted that just as in (Erp, Oberski, and Mulder 2018), sparsity parameter of the Regularized Horseshoe prior has a prior which is centered on the correct number of non-zero parameters in the model. The worst predictive performance is attained with Elastic Net and the second worst with Ridge Cauchy. All models are ranked in a similar order in both LPPD and PMSE cases. To ensure that results are valid, also Rhat values and divergent transitions are illustrated for each model:

show_diagnostics(chosen_fit_diagn,0,show_neff = FALSE)

Number of RHAT values above 1.1
mean sd max min
elastic_net_cauchy.SM 0 0.0 0 0
horseshoe_3.SM 0 0.1 2 0
hyperlasso_cauchy.SM 0 0.0 0 0
lasso_cauchy.SM 0 0.0 0 0
normal_mixture_bernoulli.SM 0 0.0 0 0
normal_mixture_uniform.SM 0 0.0 0 0
regularized_horseshoe.SM 0 0.0 0 0
ridge_cauchy.SM 0 0.0 0 0
student_cauchy.SM 0 0.0 0 0
Statistics of divergent transitions
mean sd max min
elastic_net_cauchy.SM 0.0 0.2 4 0
horseshoe_3.SM 41.4 43.6 644 7
hyperlasso_cauchy.SM 0.4 4.3 86 0
lasso_cauchy.SM 0.0 0.0 0 0
normal_mixture_bernoulli.SM 0.0 0.0 0 0
normal_mixture_uniform.SM 0.0 0.0 0 0
regularized_horseshoe.SM 0.0 0.1 1 0
ridge_cauchy.SM 0.0 0.0 0 0
student_cauchy.SM 0.0 0.2 3 0

5. CONCLUSIONS

The conclusions of the assignment can be briefly summarized as follows:

1: When model is suffering from the convergence difficulties and includes divergent transitions, the adaptation delta should be assessed as high as possible (0.999), number of iterations as 8000 and if the transitions still exist, scatter and parallel coordinate plots used. However, using only plots may be insufficient and therefore also wider statistics for the transitions and also for Rhat and \(N_{eff}\) values are required.

2: Using the modified simulation condition 1, best parametrization for Horseshoe prior is by reforming Half-Cauchy distribution with Inverse_Gamma parametrization. However, Regularized Horseshoe prior is still a better choice of parametrization as it includes virtually no divergent transitions in the setting of this assignment. The predictive performance of the priors are still very close to each other.

3: When comparing different shrinkage priors with modified simulation condition 1, the differences in model performance can be seen visually from PMSE and LPPD distributions and the best model can be determined based on their values. Horseshoe and Regularized Horseshoe were found to be the top shrinkage priors for the task.

REFERENCES

Betancourt, Michael. 2018. “Fitting the Cauchy Distribution.” https://betanalpha.github.io/assets/case_studies/fitting_the_cauchy.html.

Carvalho, Carlos M, Nicholas G Polson, and James G Scott. 2010. “The Horseshoe Estimator for Sparse Signals.” Biometrika 97 (2). Oxford University Press: 465–80.

Erp, Sara van, Daniel L Oberski, and Joris Mulder. 2018. “Shrinkage Priors for Bayesian Penalized Regression.” Open Science Framework.

Gabry, Jonah, Daniel Simpson, Aki Vehtari, Michael Betancourt, and Andrew Gelman. 2017. “Visualization in Bayesian Workflow.” arXiv Preprint arXiv:1709.01449.

Gelman, Andrew, John B Carlin, Hal S Stern, and Donald B Rubin. 1995. Bayesian Data Analysis. Chapman; Hall/CRC.

Piironen, Juho, and Aki Vehtari. 2016. “On the Hyperprior Choice for the Global Shrinkage Parameter in the Horseshoe Prior.” arXiv Preprint arXiv:1610.05559.

———. 2017. “Comparison of Bayesian Predictive Methods for Model Selection.” Statistics and Computing 27 (3). Springer: 711–35.

Piironen, Juho, Aki Vehtari, and others. 2017. “Sparsity Information and Regularization in the Horseshoe and Other Shrinkage Priors.” Electronic Journal of Statistics 11 (2). The Institute of Mathematical Statistics; the Bernoulli Society: 5018–51.

LS0tCnRpdGxlOiAiQ09OVkVSR0VOQ0UgRElBR05PU0lTIEFORCBDT01QQVJJU09OIE9GIFNIUklOS0FHRSBQUklPUlMiCm91dHB1dDogaHRtbF9ub3RlYm9vawpiaWJsaW9ncmFwaHk6IHJlZi5iaWIKYXV0aG9yOiBUdW9tYXMgS2FzZXZhCmRhdGU6IDE0LjEwLjIwMTgKLS0tCgojIDEuIElOVFJPRFVDVElPTgoKW0B2YW4yMDE4c2hyaW5rYWdlXSBwcm92aWRlZCBhbiBpbnRlcmVzdGluZyBjb21wYXJpc29uIG9mIGRpZmZlcmVudCBzaHJpbmthZ2UgcHJpb3JzIGluIGEgcmVndWxhcml6ZWQgcGVuYWxpemF0aW9uIHRhc2suIFRoZSB3b3JrIHZpc3VhbGl6ZWQgYW5kIGRlc2NyaWJlZCBzaHJpbmthZ2UgcHJpb3JzIHdlbGwgYW5kIGNvbXBhcmVkIHRoZW0gaW4gYSB2YXJpZXR5IG9mIGNvbmRpdGlvbnMuIEhvd2V2ZXIsIHRoZSBwYXBlciBjb250YWluZWQgYWxzbyBzb21lIGRlZmljaWVuY2llcyByZWdhcmRpbmcgc2ltdWxhdGVkIGRhdGEsIGNvbnZlcmdlbmNlIGRpYWdub3N0aWNzIGFuZCBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlIHByZXNlbnRhdGlvbi4gVGhlIHNpbXVsYXRpb24gY29uZGl0aW9ucyB3ZXJlIG5vdCBzcGFyc2UgZW5vdWdoIHRvIHN1ZmZpY2llbnRseSBpbnZlc3RpZ2F0ZSBzaHJpbmthZ2UgYWJpbGl0aWVzIG9mIHRoZSBwcmlvcnMuIE1vcmVvdmVyLCBjb252ZXJnZW5jZSBwcm9ibGVtcyB3ZXJlIGludmVzdGlnYXRlZCBvbmx5IGJ5IGludmVzdGlnYXRpbmcgdGhlIHRyYWNlIHBsb3RzIGFuZCBpbiBzb21lIGNhc2VzIGV2ZW4gYnkgZXhjbHVkaW5nIHNpbXVsYXRpb24gZHJhd3MuIFRoZSBwYXBlciBhbHNvIHVzZWQgYSBsYXJnZSBzdGVwIHNpemUgKDEpIGFuZCBhIGxvdyB0YXJnZXQgYWNjZXB0YW5jZSByYXRlICgwLjg1KS4gSW4gYWRkaXRpb24sIG51bWJlciBvZiBjb21wdXRlZCBwcmVkaWN0aW9uIG1lYW4gc3F1YXJlIGVycm9yIChQTVNFKSB2YWx1ZXMgd2FzIGluYWRlcXVhdGUgaW4gZWFjaCBzaW11bGF0aW9uIGNvbmRpdGlvbiBhbmQgdGhlaXIgcHJlc2VudGF0aW9uIGRpZmZpY3VsdCBmb3IgYSBwcmlvciBjb21wYXJpc29uLgoKVGhlIG5vdGVib29rIHByZXNlbnRlZCBoZXJlIGlzIGEgc3BlY2lhbCBhc3NpZ25tZW50IG1hZGUgdW5kZXIgc3VwZXJ2aXNpb24gb2YgKipQcm9mLiBBa2kgVmVodGFyaSoqIGluIEFhbHRvIHVuaXZlcnNpdHksIGFpbWVkIHRvIHByb3ZpZGUgdG9vbHMgYW5kIGlkZWFzIHRvIGZpeCB0aGVzZSBzaG9ydGNvbWluZ3MuIFRoZSBvcmdhbml6YXRpb24gaXMgYXMgZm9sbG93cy4gRmlyc3RseSwgdGhlIGRhdGEgdXNlZCBpcyBkZXNjcmliZWQgaW4gdGhlIHNlY3Rpb24gMi4gVGhlIGRhdGEgaXMgYXMgcHJlc2VudGVkIGluIFtAdmFuMjAxOHNocmlua2FnZV0gYnV0IHdpdGggbW9yZSBzcGFyc2UgcmVwcmVzZW50YXRpb24gYW5kIHdpdGggYSBoaWdoZXIgbnVtYmVyIG9mIHRlc3Qgc2FtcGxlcy4KU2Vjb25kbHksIHRoZSBub3RlYm9vayBkZXNjcmliZXMgaG93IHBhcmFsbGVsIGNvb3JkaW5hdGUgYW5kIHNjYXR0ZXIgcGxvdHMgY2FuIGJlIHVzZWQgdG8gZGlhZ25vc2UgY29udmVyZ2VuY2UgaW4gc2VjdGlvbiAzLiAgVGhlIHNlY3Rpb24gY29uY2VudHJhdGVzIG9uIHVzaW5nIEhvcnNlc2hvZSBhbmQgUmVndWxhcml6ZWQgaG9yc2VzaG9lIHByaW9ycyBhcyBleGFtcGxlIG1vZGVscyBiYXNlZCBvbiB0aGVpciBjb252ZXJnZW5jZSBkaWZmaWN1bHRpZXMgaW4gIFtAdmFuMjAxOHNocmlua2FnZV0uIE1vcmVvdmVyLCBzdGF0aXN0aWNzIGdlbmVyYXRlZCBmcm9tIG11bHRpcGxlIHJlcGxpY2F0aW9ucyBvZiB0aGUgZGF0YSBpcyBwcmVzZW50ZWQuICBJbiB0aGUgc2VjdGlvbiA0LCBtb2RlbCBjb21wYXJpc29uIGlzIHByZXNlbnRlZCB1c2luZyBQTVNFIGFuZCBsb2cgcG9pbnR3aXNlIHByZWRpY3RpdmUgZGVuc2l0eSAoTFBQRCkgdmFsdWVzIGZvciB0ZXN0IGRhdGEuIE9yaWdpbmFsbHksIGFsc28gdGhlIHZhcmlhYmxlIHNlbGVjdGlvbiBwcm9jZWR1cmUgZGVzY3JpYmVkIGluIFtAdmFuMjAxOHNocmlua2FnZV0gd2FzIHBsYW5uZWQgdG8gcmVwbGFjZSB3aXRoIHByb2pwcmVkLXBhY2thZ2UgW0BwaWlyb25lbjIwMTdjb21wYXJpc29uXSBidXQgdGhlIGhpZ2ggay12YWx1ZXMgcHJldmVudGVkIHVzaW5nIGl0IGluIHRoaXMgYXNzaWdubWVudC4gRmluYWxseSwgdGhlIGNvbmNsdXNpb25zIG9mIHRoZSBhc3NpZ25tZW50IGFyZSBkaXNjdXNzZWQuCgpBbm90aGVyIGdvYWwgb2YgdGhlIGFzc2lnbm1lbnQgaXMgdG8gcHJvdmlkZSBhIHNldCBvZiBmdW5jdGlvbnMgd2hpY2ggY2FuIGJlIHV0aWxpemVkIG5vdCBvbmx5IHdpdGggdGhlIHNwZWNpZmljIGNhc2UgZGVzY3JpYmVkIGluIHRoaXMgbm90ZWJvb2ssIGJ1dCBhbHNvIHdpdGggYSB2YXJpZXR5IG9mIGRpZmZlcmVudCBtb2RlbHMgYW5kIGRhdGEgc2V0cyBieSBvbmx5IHJlbmFtaW5nIHRoZSBkaXJlY3RvcnkgcGF0aHMuIE1vcmVvdmVyLCB0aGUgYXNzaWdubWVudCBkZXRhaWxzIGhvdyBBYWx0by11bml2ZXJzaXR5IHN0dWRlbnRzIGNhbiB1dGlsaXplIFRyaXRvbiBpbiBTdGFuIG1vZGVsIGZpdHRpbmdzIGluIHRhc2tzIHdoaWNoIGFyZSBwcmFjdGljYWxseSBpbmZlYXNpYmxlIHdpdGggcGVyc29uYWwgY29tcHV0ZXJzLiBUaGUgY29kZXMgZm9yIFRyaXRvbiBhcmUgbm90IGlsbHVzdHJhdGVkIGluIHRoZSBub3RlYm9vayBidXQgdGhleSBjYW4gYmUgYXR0YWluZWQgZnJvbSBUcml0b24gZm9sZGVyIGFsb25nIHdpdGggdXNhZ2UgaW5zdHJ1Y3Rpb25zLiAKCk5leHQsIGxldCB1cyBzdGFydCBieSBpbmNsdWRpbmcgbmVjZXNzYXJ5IGxpYnJhcmllcywgZnVuY3Rpb25zIGFuZCBieSBjaG9vc2luZyBhIHdvcmtpbmcgZGlyZWN0b3J5OiAKCmBgYHtyfQojIEFjcXVpcmUgcGFja2FnZXMKbGlicmFyeShyc3RhbikKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoZ3JpZCkKbGlicmFyeShiYXllc3Bsb3QpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwYXJhbGxlbCkKbGlicmFyeSgicmVzaGFwZTIiKQpvcHRpb25zKG1jLmNvcmVzID0gcGFyYWxsZWw6OmRldGVjdENvcmVzKCkpCmBgYAoKYGBge3Igc2V0dXB9CmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gbm9ybWFsaXplUGF0aCgifi9Eb2N1bWVudHMvUmJheWVzL0JheWVzX3Byb2plY3RfZmlsZXMvbm90ZWJvb2siKSkKYGBgCgoKYGBge3J9CiMgSW1wb3J0IGZyb20gdXRpbGl0aWVzIGZvbGRlcgpzb3VyY2UoIm1vZGVsX2RpYWdub3N0aWNzLlIiKQpzb3VyY2UoImRhdGFfZ2VuZXJhdGlvbi5SIikKc291cmNlKCJtb2RlbF9nZW5lcmF0b3IuUiIpCnNvdXJjZSgiY2hvb3NlX2ZpdHMuUiIpCgpgYGAKCiMgMi4gREFUQQoKSW4gW0B2YW4yMDE4c2hyaW5rYWdlXSBzaXggZGlmZmVyZW50IGRhdGEgc2V0cywgY2FsbGVkIGFzIHNpbXVsYXRpb24gY29uZGl0aW9ucyB3ZXJlIGlsbHVzdHJhdGVkLiBUaGlzIG5vdGVib29rIHVzZXMgdGhlIGZpcnN0IGNvbmRpdGlvbiBidXQgd2l0aCB0d28gbW9kaWZpY2F0aW9ucy4gRmlyc3RseSwgdGhlIG51bWJlciBvZiBjb2VmZmljaWVudHMgaXMgaW5jcmVhc2VkIHRvICQzOCQgYnkgcGFkZGluZyAkMzAkIHplcm9zIGluIHRoZSBlbmQgb2YgdGhlIG9yaWdpbmFsIGNvZWZmaWNpZW50cy4gVGhlIHJlYXNvbiBmb3IgdGhpcyBpcyB0byBpbXByb3ZlIHRoZSBjb21wYXJpc29uIG9mIHNocmlua2FnZSBhYmlsaXRpZXMgb2YgdGhlIHByaW9ycy4gSW4gYWRkaXRpb24sIHRoZSB0ZXN0IHNldCBpcyBlbmxhcmdlZCB0byAkMjAwMCQgc2FtcGxlcyB0byBhdHRhaW4gbW9yZSBhY2N1cmF0ZSBkaXN0cmlidXRpb25zIGZvciBQTVNFcyBhbmQgTFBQRHMuIEZyb20gaGVyZSBvbiwgdGhlIGRhdGEgc2V0IHdpbGwgYmUgcmVmZXJyZWQgYXMgKiptb2RpZmllZCBzaW11bGF0aW9uIGNvbmRpdGlvbiAxKiogYW5kIGNhbiBiZSBnZW5lcmF0ZWQgd2l0aCB0aGUgZm9sbG93aW5nIGNvZGU6CgpgYGB7cn0KIyBDcmVhdGVzICJwcm9qZWN0X2RhdGEuUkRhdGEiCmRhdGFfZ2VuZXJhdGlvbigpCmBgYAoKIyAzLiBTVEFOIE1PREVMUyBBTkQgRklUUwoKQXMgZGlzY3Vzc2VkIGludG8gdGhlIGludHJvZHVjdGlvbiwgdGhlIHNwZWNpYWwgYXNzaWdubWVudCBoYXMgdHdvIG1haW4gZ29hbHM6IFByb3ZpZGUgYSBjb252ZXJnZW5jZSBkaWFnbm9zaXMgZm9yIEhvcnNlc2hvZSBwcmlvciBhbmQgdG8gY2Fycnkgb3V0IGEgbW9kZWwgY29tcGFyaXNvbi4gVGhlIGZvcm1lciBpcyBvYnRhaW5lZCBieSBleHBlcmltZW50aW5nIHdpdGggdGhyZWUgZGlmZmVyZW50IHBhcmFtZXRlcml6YXRpb25zIGZvciBIb3JzZXNob2UgcHJpb3IgYW5kIHdpdGggUmVndWxhcml6ZWQgSG9yc2VzaG9lLiBUaGUgcGFyYW1ldHJpemF0aW9ucyBmb2N1cyBvbiByZWZvcm1pbmcgdGhlIEhhbGYtQ2F1Y2h5IGRpc3RyaWJ1dGlvbiB3aGljaCBpcyB0aGUgbWFpbiByZWFzb24gZm9yIGNvbnZlcmdlbmNlIHByb2JsZW1zIGluIEhvcnNlc2hvZSBwcmlvci4gVGhlIGxhdHRlciBpcyBwZXJmb3JtZWQgd2l0aCB0aGUgc2FtZSA5IHByaW9ycyAoaW5jbHVkaW5nIEhvcnNlc2hvZSBwcmlvcikgYXMgaW4gW0B2YW4yMDE4c2hyaW5rYWdlXSBmb3Igc2ltdWxhdGlvbiBjb25kaXRpb24gMSB3aXRoIGZ1bGwgQmF5ZXMgYXBwcm9hY2guIEluIHRvdGFsLCAxMSBTdGFuIG1vZGVscyBpcyBjcmVhdGVkLiBUaGUgc3BlY2lmaWNzIG9mIEhvcnNlc2hvZSBwcmlvciBwYXJhbWV0cml6YXRpb25zIGFyZSBhcyBmb2xsb3dzOgoKKipIb3JzZXNob2UgMToqKiBUaGUgc2FtZSBhcyBnaXZlbiBpbiBbQHZhbjIwMThzaHJpbmthZ2VdIGJ1dCB3aXRoIGFkZGVkIHByaW9yIGZvciBpbnRlcmNlcHQgJCRcYmV0YV8wIFxzaW0gIFxtYXRoY2Fse059KDAsIDEwKSAkJAphbmQgd2l0aCBhZGRlZCBnZW5lcmF0ZWQgcXVhbnRpdHkgYXMgdGVzdCBzZXQgbG9nIGxpa2VsaWhvb2QgZm9yIExQUEQgY29tcHV0YXRpb24uIFRoZSBvcmlnaW5hbCBTdGFuIGNvZGUgYnkgU2FyYSB2YW4gRXJwIGlzIHNsaWdodGx5IG1vZGlmaWVkIGJ5IHVzaW5nIHZlY3Rvcml6ZWQgcmVwcmVzZW50YXRpb25zIGZvciBzcGVlZGluZyB1cCBjb21wdXRhdGlvbnMgYW5kIHN3YXBwaW5nIHRoZSB2YXJpYWJsZSBuYW1lcyBvZiAkXHRhdSQgYW5kICRcbGFtYmRhJC4gCgoqKkhvcnNlc2hvZSAyLioqIFRoZSBzYW1lIGFzIEhvcnNlc2hvZSAxIGJ1dCB3aXRoIFRhbi1mdW5jdGlvbiBwYXJhbWV0cml6YXRpb24gZm9yIEhhbGYtQ2F1Y2h5IGRpc3RyaWJ1dGlvbiBhcyBpbnRyb2R1Y2VkIGJ5IFtAQmV0YW5jb3VydF0uICAKCioqSG9yc2VzaG9lIDMuKiogVGhlIHNhbWUgYXMgSG9yc2VzaG9lIDEgYnV0IHdpdGggaW52ZXJzZS1HYW1tYSBwYXJhbWV0cml6YXRpb24gZm9yIEhhbGYtQ2F1Y2h5IGRpc3RyaWJ1dGlvbiBhZ2FpbiBkZXNjcmliZWQgYnkgW0BCZXRhbmNvdXJ0XQoKCioqT3RoZXIgOCBtb2RlbHMqKiBhcmUgb3RoZXJ3aXNlIHRoZSBzYW1lIGFzIGluIFtAdmFuMjAxOHNocmlua2FnZV0gYnV0IGFzIEhvcnNlc2hvZSBwYXJhbWV0cml6YXRpb25zLCBpbmNsdWRlIGNvbXB1dGF0aW9uIG9mIHRlc3Qgc2V0IGxvZy1saWtlbGlob29kcyBhbmQgdmVjdG9yaXplZCBjb21wdXRpbmcgb2YgJHlfe3Rlc3R9JCB2YWx1ZXMuIEFsbCB0aGUgbW9kZWxzIGNhbiBiZSBjcmVhdGVkIHdpdGggZm9sbG93aW5nIGNvZGUgYmxvY2s6CgpgYGB7cn0KIyBJbXBvcnQgZnJvbSBzdGFuX2ZpbGVzIGZvbGRlcgpzdGFuX2ZpbGVzIDwtIGxpc3QuZmlsZXMoKVtncmVwKCIuc3RhbiIsIGxpc3QuZmlsZXMoKSldCm1vZGVsX2dlbmVyYXRvcihwcm9qZWN0X2RhdGEsIHN0YW5fZmlsZXMsIDApCmBgYAoKKipTdGFuIGZpdHMqKiBmb3IgYWxsIG1vZGVscyBhcmUgZ2VuZXJhdGVkIHVzaW5nICRzYW1wbGluZyQgZnVuY3Rpb24gd2l0aCBudW1iZXIgb2YgaXRlcmF0aW9ucyBhcyA4MDAwLCBudW1iZXIgb2YgY2hhaW5zIGFzIDQsIGFkYXB0X2RlbHRhIGFzIDAuOTk5IGFuZCBtYXhfdHJlZWRlcHRoIGFkIDE1LiBUaGUgaGlnaCB2YWx1ZSBvZiBhZGFwdGF0aW9uIGRlbHRhIGlzIG5lY2Vzc2FyeSBmb3Igbm90IG9ubHkgSG9yc2VzaG9lIHByaW9yIHdoaWNoIGlzIHByb25lIHRvIGNvbnZlcmdlbmNlIHByb2JsZW1zIGJ1dCB0byBhbHNvIGZvciB0aGUgb3RoZXIgbW9kZWxzIHRvIGVuc3VyZSBwcm9wZXIgY29udmVyZ2VuY2UuIE51bWJlciBvZiBpdGVyYXRpb25zIGlzIGhpZ2hlciB0aGFuIGluIFtAdmFuMjAxOHNocmlua2FnZV0gaW4gb3JkZXIgdG8gcHJldmVudCBvY2N1cmVuY2VzIG9mIGxvdyBlZmZlY3RpdmUgc2FtcGxlIHNpemUgKCROX3tlZmZ9JCkgdmFsdWVzLiBGaXRzIGNhbiBiZSBnZW5lcmF0ZWQgZXhwbG9pdGluZyBhZ2FpbiAkbW9kZWwuZ2VuZXJhdG9yJCBmdW5jdGlvbi4gSW4gdGhpcyBub3RlYm9vaywgb25seSBmaXRzIGZvciBob3JzZXNob2UgcGFyYW1ldHJpemF0aW9ucyBhcmUgbmVjZXNzYXJ5IGZvciBkaXZlcmdlbnQgdHJhbnNpdGlvbiB2aXN1YWxpemF0aW9uIGFuZCB0aGV5IGFyZSBvYnRhaW5lZCBhcyBmb2xsb3dzOgoKYGBge3J9CmxvYWQoInByb2plY3RfZGF0YS5SRGF0YSIpCm1vZGVsX2ZpbGVzIDwtIGMoImhvcnNlc2hvZV8xLlNNIiwgImhvcnNlc2hvZV8yLlNNIiwgImhvcnNlc2hvZV8zLlNNIikKbW9kZWxfZ2VuZXJhdG9yKHByb2plY3RfZGF0YSwgbW9kZWxfZmlsZXMsIDEpCmBgYAoKCgojIDQuIENPTlZFUkdFTkNFIERJQUdOT1NUSUNTIEZPUiBIT1JTRVNIT0UgQU5EIFJFR1VMQVJJWkVEIEhPUlNFU0hPRSBQUklPUlMKClRoaXMgc2VjdGlvbiBjb25zaXN0cyBvZiB0d28gcGFydHMuIFRoZSBmaXJzdCBkZW1vbnN0cmF0ZXMgaG93IHBhcmFsbGVsIGNvb3JkaW5hdGUgYW5kIHNjYXR0ZXIgcGxvdHMgY2FuIGJlIHV0aWxpemVkIGluIGRpdmVyZ2VudCB0cmFuc2l0aW9uIHZpc3VhbGl6YXRpb24uIEluIGFkZGl0aW9uLCBSaGF0IGFuZCAkTl97ZWZmfSQgdmFsdWVzIGV4dHJhY3RlZCBmcm9tIHRoZSBTdGFuIGZpdCBhcmUgaWxsdXN0cmF0ZWQuIFRoZSBzZWNvbmQgcGFydCBwZXJmb3JtcyB3aWRlciBzdGF0aXN0aWNhbCBkaWFnbm9zaXMgd2l0aCBtdWx0aXBsZSByZXBsaWNhdGlvbnMgb2YgdGhlIGRhdGEuIEFzIHByZXZpb3VzbHkgZGlzY3Vzc2VkLCBhbGwgZXhwZXJpbWVudHMgYXJlIHBlcmZvcm1lZCB3aXRoIEhvcnNlc2hvZSBwcmlvciBhbmQgdGhlIG1haW4gb2JqZWN0aXZlIG9mIHRoZSBzZWN0aW9uIGlzIHRvIHVzZWQgbWV0aG9kcyBkaXNjdXNzZWQgdG8gb2J0YWluIG9wdGltYWwgcGFyYW1ldHJpemF0aW9uIGZvciB0aGUgcHJpb3IuCgojIyA0LjEgRXhwZXJpbWVudHMgd2l0aCAxIHJlcGxpY2F0aW9uCgpSaGF0IGFuZCAkTl97ZWZmfSQgdmFsdWVzIGFyZSBzdGFuZGFyZCBtZWFzdXJlcyBmb3IgY29udmVyZ2VuY2Ugb2YgU3RhbiBtb2RlbHMgW0BnZWxtYW4xOTk1YmF5ZXNpYW5dLiBIb3dldmVyLCBpbiBzb21lIGNhc2VzIHRoZSBtb2RlbHMgbWF5IGFsc28gc3VmZmVyIGZyb20gZGl2ZXJnZW50IHRyYW5zaXRpb25zIHdoaWNoIG5lZWQgdG8gYmUgZXhhbWluZWQgd2l0aCBvdGhlciB0b29scy4gSW4gW0B2YW4yMDE4c2hyaW5rYWdlXSwgYXV0aG9ycyB3ZXJlIGludmVzdGlnYXRpbmcgdHJhY2UgcGxvdHMgYW5kIGluIHNvbWUgY2FzZXMgZHJvcHBpbmcgb3V0IHNpbXVsYXRpb25zIHdpdGggaGlnaCBudW1iZXIgb2YgZGl2ZXJnZW50IHRyYW5zaXRpb25zLiBUaGlzIGFzc2lnbm1lbnQgcHJvcG9zZXMgdGhlIHVzZSBvZiBwYXJhbGxlbCBjb29yZGluYXRlIGFuZCBzY2F0dGVyIHBsb3RzIGFzIHN1Z2dlc3RlZCBpbiBbQGdhYnJ5MjAxN3Zpc3VhbGl6YXRpb25dLCBpbiAgb3JkZXIgdG8gZmluZCBvdXQgdGhlIG5hdHVyZSBvZiB0aGUgdHJhbnNpdGlvbnMsIHRoYXQgaXMsIGlmIHRoZXkgYXJlIGZhbHNlIHBvc2l0aXZlcyBvciBub3QuIAoKSW4gKipwYXJhbGxlbCBjb29yZGluYXRlIHBsb3RzKiosIHRoZSBNQ01DIGRyYXdzIG9mIFN0YW4gbW9kZWwgYXJlIGlsbHVzdHJhdGVkIGluIHR3byBkaW1lbnNpb25zLCB3aGljaCBhcmUgcGFyYW1ldGVycyBhbmQgdGhlaXIgZHJhdyBzYW1wbGVzLiBUaGUgcGxvdHMgY2FuIGJlIGdlbmVyYXRlZCB1c2luZyAkbWNtYy5wYXJjb29yZCQgZnVuY3Rpb24gYW5kIHN0YXJ0aW5nIHBvaW50cyBvZiBkaXZlcmdlbnQgdHJhbnNpdGlvbnMgY2FuIGJlIG1hZGUgdmlzaWJsZSB1c2luZyAkbnV0cyBcZW5zcGFjZSBwYXJhbWV0ZXJzJC4gR2VuZXJhbGx5LCB0aGUgcGFyYWxsZWwgY29vcmRpbmF0ZXMgZW5hYmxlIGludmVzdGlnYXRpbmcgZGl2ZXJnZW50IHRyYWplY3RvcmllcyB3aGljaCBhcmUgY29uY2VudHJhdGVkIGluIHRoZSBwb3NpdGlvbiBvZiBjZXJ0YWluIHBhcmFtZXRlciBhbmQgZG8gbm90IGZvbGxvdyB0aGUgc2FtZSBwYXR0ZXJucyBhcyBvdGhlciBkcmF3IHRyYWplY3Rvcmllcy4gSG93ZXZlciwgdGhlIHBhcmFsbGVsIGNvb3JkaW5hdGVzIGhhdmUgdHJvdWJsZSB0byB2aXN1YWxpemUgaW4gdGhlIHNpdHVhdGlvbnMgd2hlbiB0aGUgbW9kZWwgaGFzIGhpZ2ggbnVtYmVyIG9mIHBhcmFtZXRlcnMgYW5kIHRoZSBwYXJhbWV0ZXIgdmFsdWVzIGhhdmUgaGlnaCB2YXJpYW5jZS4gU3VjaCBpcyB0aGUgY2FzZSBpbiB0aGlzIGFzc2lnbm1lbnQsIGFuZCBpbiBvcmRlciB0byBjb3VudGVyIHRoZXNlIHByb2JsZW1zLCBhbGwgZHJhd3MgaW4gZWFjaCBjaGFpbiBhcmUgbm9ybWFsaXplZCBiZXR3ZWVuIDAgYW5kIDEgYW5kIG9ubHkgNiB2YXJpYWJsZXMgd2l0aCBsb3dlc3QgJE5fe2VmZn0kIHZhbHVlcyBhcmUgY2hvc2VuIGZvciBpbnZlc3RpZ2F0aW9uLiBUbyBlbnN1cmUgbW9yZSBjbGVhciB2aXN1YWxpemF0aW9uIG9mIHRyYWplY3RvcmllcywgZHJhdyB2YWx1ZXMgYXJlIGZpbmFsbHkgY29tcHV0ZWQgaW4gbG9nYXJpdGhtaWMgZm9ybSB3aXRoIGFuIGFkZGVkIGJpYXMgYXMgMC41IHRvIGVuc3VyZSBwb3NpdGl2aXR5LiBOb24tZGl2ZXJnZW50IGFuZCBkaXZlcmdlbnQgdHJhamVjdG9yaWVzIGFyZSBwbG90dGVkIGluIGJsYWNrIGFuZCBncmVlbiwgcmVzcGVjdGl2ZWx5LgoKT3RoZXIgb3B0aW9uIGZvciBleGFtaW5pbmcgZGl2ZXJnZW50IHRyYW5zaXRpb25zIGlzIHRvIGdlbmVyYXRlICoqc2NhdHRlciBwbG90cyoqIGZvciBkcmF3IHNhbXBsZXMgb2YgdHdvIGNob3NlbiBwYXJhbWV0ZXJzIGZyb20gZGlzdHJpYnV0aW9uLiBBcyBwcmV2aW91c2x5LCAkbnV0cyBcZW5zcGFjZSBwYXJhbWV0ZXJzJCBjYW4gdGhlbiBiZSBleHBsb2l0ZWQgdG8gZGV0ZWN0IHNhbXBsZXMgd2hpY2ggYXJlIGxpbmtlZCB0byBkaXZlcmdlbnQgdHJhbnNpdGlvbnMuIElmIHRoZXNlIHNhbXBsZXMgYXJlIGNvbmNlbnRyYXRlZCBpbiBzb21lIGxvY2F0aW9uIGluIHNjYXR0ZXIgcGxvdCwgbW9kZWwgY29udmVyZ2VuY2UgY291bGQgYmUgcXVlc3Rpb25lZC4gSGVyZSwgc2FtZSBkcmF3IHZhbHVlcywgcGFyYW1ldGVycyBhbmQgY29sb3JhdGlvbiBmb3IgZGl2ZXJnZW50IHRyYW5zaXRpb25zIGFzIGluIHBhcmFsbGVsIGNvb3JkaW5hdGUgcGxvdHMgYXJlIHByZXNlbnRlZCBpbiB0aHJlZSBkaWZmZXJlbnQgc2NhdHRlciBwbG90cyBmb3IgZWFjaCBIb3JzZXNob2UgcGFyYW1ldHJpemF0aW9uLgoKCmBgYHtyfQpmaXRmbHMgPC0gbGlzdC5maWxlcygpW2dyZXAoIi5GSVQiLCBsaXN0LmZpbGVzKCkpXQpkdF92aXN1YWwoZml0ZmxzWzFdKQpgYGAKCmBgYHtyfQpkdF92aXN1YWwoZml0ZmxzWzJdKQpgYGAKCmBgYHtyfQpkdF92aXN1YWwoZml0ZmxzWzNdKQpgYGAKClRoZSBleHBlcmltZW50cyBvbiB0aHJlZSBkaWZmZXJlbnQgcGFyYW1ldHJpemF0aW9ucyBzaG93IHRoYXQgaW4gZWFjaCBjYXNlLCBkaXZlcmdlbnQgdHJhbnNpdGlvbnMgYXJlIHByZXNlbnQgYW5kIGZvcm0gY29uY2VudHJhdGlvbnMgaW4gc2NhdHRlciBwbG90cyB0byBzb21lIGV4dGVuZC4gVGhlcmVmb3JlLCB0aGUgcmVzdWx0IGNsZWFybHkgbGVhdmVzIG91dCB0aGUgZGlzY3Vzc2lvbiBvZiBmYWxzZSBwb3NpdGl2ZXMuIFN0aWxsLCB0aGUgdmlzdWFsaXphdGlvbnMgaWxsdXN0cmF0ZSB0aGF0IHRoZSByZXN1bHRzIGRpZmZlciBiZXR3ZWVuIHBhcmFtZXRyaXphdGlvbi4gVGhlIGZpcnN0IHBhcmFtZXRyaXphdGlvbiBpcyBjbGVhcmx5IHRoZSB3b3JzZSwgYmVpbmcgdGhlIG9ubHkgb25lIHdoaWNoIGV4aGliaXRzIGNsZWFyIGRpdmVyZ2VudCB0cmFqZWN0b3JpZXMgYW5kIGNvbmNlbnRyYXRpb25zIGFuZCBoYXMgbG93ZXN0ICROX3tlZmZ9JCB2YWx1ZSBvdmVyIGh1bmRyZWQgdGltZXMgbG93ZXIgdGhhbiBudW1iZXIgb2YgaXRlcmF0aW9ucy4gVGhlIHRoaXJkIHBhcmFtZXRyaXphdGlvbiBwZXJmb3JtcyB0aGUgYmVzdCwgYXMgaXQgaW5jbHVkZXMgdGhlIGxvd2VzdCBudW1iZXIgb2YgZGl2ZXJnZW50IHRyYW5zaXRpb25zLiAKCkhvd2V2ZXIsIGFzIGFsbCB0aGUgdXNlZCBkYXRhIGlzIHNpbXVsYXRlZCwgaXQgbWlnaHQgYmUgdGhlIGNhc2UgdGhhdCBmb3IgdGhpcyBwYXJ0aWN1bGFyIHNpbXVsYXRpb24gdGhlIGZpcnN0IHBhcmFtZXRyaXphdGlvbiBoYXBwZW5zIHRvIHBlcmZvcm0gd29yc2UgYW5kIHRoZSB0aGlyZCBwYXJhbWV0cml6YXRpb24gYmV0dGVyLiBJbiBhZGRpdGlvbiwgb25seSAxIHJlcGxpY2F0aW9uIG9mIHRoZSBkYXRhIG1pZ2h0IGJlIGluc3VmZmljaWVudCB0byBnaXZlIHJlbGlhYmxlIGNvbnZlcmdlbmNlIGRpYWdub3N0aWNzLiAgQ29uc2VxdWVudGx5LCBpbiB0aGUgc2V0dGluZyBvZiB0aGlzIGFzc2lnbm1lbnQsICoqcGFyYWxsZWwgY29vcmRpbmF0ZSBhbmQgc2NhdHRlciBwbG90cyBwcm92aWRlIHNvbWUgaW5zaWdodCB0byB0aGUgcHJvYmxlbSBidXQgYXJlIGluc3VmZmljaWVudCBmb3Igc2VsZWN0aW5nIG9wdGltYWwgcGFyYW1ldHJpemF0aW9uKiouIFdpZGVyIHN0YXRpc3RpY2FsIGFuYWx5c2lzIHdpdGggbXVsdGlwbGUgZGF0YSByZXBsaWNhdGlvbnMgaXMgcmVxdWlyZWQgYW5kIGl0IGlzIHBlcmZvcm1lZCBuZXh0LgoKIyMgMy4yIEV4cGVyaW1lbnRzIHdpdGggNTAwIHJlcGxpY2F0aW9ucwoKVG8gZnVydGhlciBjb21wYXJlIHRoZSB0aHJlZSBwcmFtZXRyaXphdGlvbnMsIGEgbW9yZSBzdGF0aXN0aWNhbCBhcHByb2FjaCBpcyBwcm9wb3NlZC4gSW4gdGhpcyBhcHByb2FjaCwgdGhlIG1vZGVscyBhcmUgZWFjaCBmaXR0ZWQgZm9yIDUwMCBkaWZmZXJlbnQgcmVwbGljYXRpb25zIGFuZCBmb3IgZWFjaCBmaXQsIFJoYXQtdmFsdWVzLCBtaW5pbXVtICROX3tlZmZ9JCB2YWx1ZXMgYW5kIGNvcnJlc3BvbmRpbmcgcGFyYW1ldGVycyBhbmQgZGl2ZXJnZW50IHRyYW5zaXRpb25zIGFyZSBjb2xsZWN0ZWQuIFRoaXMgdGltZSwgYWxzbyByZXN1bHRzIGZvciB0aGUgUmVndWxhcml6ZWQgSG9yc2VzaG9lIGFyZSBpbmNsdWRlZC4gRnVydGhlcm1vcmUsIFBNU0UgYW5kIExQUEQgdmFsdWVzIGFyZSBhbHNvIGdlbmVyYXRlZCBmb3IgZWFjaCBmaXQgaW4gb3JkZXIgdG8gc3R1ZHkgbW9kZWxzIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UuIEFsbCB0aGUgdmFsdWVzIHdlcmUgY29tcHV0ZWQgd2l0aCBUcml0b24gYW5kIGNhbiBiZSBjb2xsZWN0ZWQgd2l0aCBsb2FkaW5nIGZvbGxvd2luZyBHemlwIGFyY2hpdmUgd2hpY2ggYWxzbyBpbmNsdWRlcyBzdGF0aXN0aWNzIGZvciBhbGwgdGhlIG90aGVyIDcgc2hyaW5rYWdlIHByaW9ycyBtZW50aW9uZWQgaW4gc2VjdGlvbiAzLgpgYGB7cn0KbG9hZCgiZml0X2RpYWdub3N0aWNzIikKYGBgCgpgYGB7cn0KY2hvc2VuX2ZpdF9kaWFnbiA8LSBjaG9vc2VfZml0cyhmaXRfZGlhZ24sIGMoImhvcnNlc2hvZV8xLlNNIiwgImhvcnNlc2hvZV8yLlNNIiwgImhvcnNlc2hvZV8zLlNNIiwgInJlZ3VsYXJpemVkX2hvcnNlc2hvZS5TTSIpLCA1MDApCnNob3dfZGlhZ25vc3RpY3MoY2hvc2VuX2ZpdF9kaWFnbiwwLHNob3dfbmVmZiA9IFRSVUUpCgoKYGBgClR3byBtYWluIGNvbmNsdXNpb25zIGNhbiBiZSBkcmF3biBmcm9tIHRoZSBzdGF0aXN0aWNzLiBGaXJzdGx5LCBlYWNoIEhvcnNlc2hvZSBwYXJhbWV0cml6YXRpb24gc3VmZmVycyBmcm9tIGNvbnZlcmdlbmNlIHByb2JsZW1zLiBNZWFuIG9mIGRpdmVyZ2VudCB0cmFuc2l0aW9ucyBpcyBvdmVyIDQwIGZvciBlYWNoIG1vZGVsLCAkTl97ZWZmfSQgbWF5IGhhdmUgbWFnbml0dWRlcyBldmVuIGJlbG93IDEwMCBhbmQgaW4gc29tZSBmaXRzLCBSaGF0IHZhbHVlcyBtYXkgZXhjZWVkIHRocmVzaG9sZCAxLjEuIENvbnRyYXJ5IHRvIHRoZSByZXN1bHRzIGluIHByZXZpb3VzIHNlY3Rpb24sIHBhcmFtZXRyaXphdGlvbnMgMSBhbmQgMiBoYXZlIG5vdyBlcXVhbCBwZXJmb3JtYW5jZS4gVGhlIG91dGNvbWUgY2xlYXJseSBlbXBoYXNpemVzIHRoYXQgcGFyYWxsZWwgY29vcmRpbmF0ZSBhbmQgc2NhdHRlciBwbG90cyBoYXZlIGxpbWl0YXRpb25zIHJlZ2FyZGluZyBjb252ZXJnZW5jZSBkaWFnbm9zaXMuIENvbnNpZGVyaW5nIHRoZSBwYXJhbWV0cml6YXRpb24gcmFua2luZywgIEhvcnNlc2hvZSAzIGhhcyBiZXN0IHN0YXRpc3RpY3MgY29uc2lkZXJpbmcgUmhhdCwgICROX3tlZmZ9JCB2YWx1ZSBhbmQgZGl2ZXJnZW50IHRyYW5zaXRpb24gZGlzdHJpYnV0aW9ucy4gIFRoZSByZXN1bHQgaXMgYXMgZXhwZWN0ZWQgYXMgdGhlIHBhcmFtZXRyaXphdGlvbiB3YXMgc3VnZ2VzdGVkIGluIFtAcGlpcm9uZW4yMDE2aHlwZXJwcmlvcl0gLgoKTW9yZSBpbXBvcnRhbnRseSwgdGhlIHN0YXRpc3RpY3Mgc2hvdyB0aGF0IGluIHRlcm1zIG9mIGNvbnZlcmdlbmNlLCAqKm5vbmUgb2YgdGhlIEhvcnNlc2hvZSBwYXJhbWV0cml6YXRpb25zIGNhbiBtYXRjaCB0aGUgUmVndWxhcml6ZWQgSG9yc2VzaG9lKiouIEluIGFsbCByZXBsaWNhdGlvbnMsIG5vIFJoYXQgdmFsdWVzIGFib3ZlIDEuMSBlbWVyZ2UsIHNtYWxsZXN0IE5fe2VmZn0gdmFsdWVzIGFyZSBhbGwgaGlnaGVyIHRoYW4gMTAwMCBhbmQgb25seSBvbmUgZGl2ZXJnZW50IHRyYW5zaXRpb24gaXMgZm91bmQuIFRoZSByZXN1bHQgd2l0aCBkaXZlcmdlbnQgdHJhbnNpdGlvbnMgaXMgYWxzbyBiZXR0ZXIgdGhhbiBpbiBbQHZhbjIwMThzaHJpbmthZ2VdLCB3aGljaCBpbXBsaWVzIHRoYXQgaGlnaCB2YWx1ZSBvZiBhZGFwdCBkZWx0YSBhbmQgbnVtYmVyIG9mIGl0ZXJhdGlvbnMgYXJlIG5lY2Vzc2FyeSBmb3IgbW9kZWwgY29udmVyZ2VuY2UuIEhvd2V2ZXIsIGl0IGlzIGFsc28gaW1wb3J0YW50IHRvIGV4YW1pbmUgaG93IG1vZGVscyBwZXJmb3JtIHdpdGggdW5zZWVuIGRhdGEuIEFzIHByZXZpb3VzbHkgZGlzY3Vzc2VkLCB0aGlzIGFzc2lnbm1lbnQgdXNlcyBQTVNFIGFuZCBMUFBEIHZhbHVlcyBmb3IgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSBjb21wYXJpc29uIGFuZCB0aGVpciBkaXN0cmlidXRpb24gYXJlIHNob3duIG5leHQuCmBgYHtyfQpzaG93X2RpYWdub3N0aWNzKGNob3Nlbl9maXRfZGlhZ24sMSxzaG93X25lZmYgPSBGQUxTRSkKYGBgCkFib3ZlIGRpc3RyaWJ1dGlvbnMgc2hvdyB0aGF0ICoqdGhlIG1vZGVscyBoYXZlIHZlcnkgc2ltaWxhciBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlLioqIEluIHRoZSBjYXNlIG9mIEhvcnNlc2hvZSBwYXJhbWV0cml6YXRpb25zLCB0aGUgZGlzdHJpYnV0aW9ucyBhcmUgYWxtb3N0IGlkZW50aWNhbCB3aGljaCBpcyBhcyBleHBlY3RlZCBhcyBhbGwgdGhlIHBhcmFtZXRyaXphdGlvbnMgZGVzY3JpYmUgdGhlIHNhbWUgc2hyaW5rYWdlIHByaW9yLiBTaW1pbGFyaXR5IG9mIGRpc3RyaWJ1dGlvbnMgaW1wbGllcyB0aGF0IGlmIG9ubHkgcHJlZGljdGl2ZSBwZXJmcm9tYW5jZSBvZiB0aGUgbW9kZWwgaXMgY29uc2lkZXJlZCwgdGhlIGNob2ljZSBvZiBtb2RlbCBtYWtlcyBubyBkcmFzdGljIGRpZmZlcmVuY2UuIE1vcmVvdmVyLCB0aGUgc2ltaWxhcml0eSBvZiBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlcyBxdWVzdGlvbiBhbHNvIHRoZSBlZmZlY3Qgb2YgZGl2ZXJnZW50IHRyYW5zaXRpb25zLiBPbmUgcG9zc2libGUgZXhwbGFuYXRpb24gaXMgdGhhdCBtYXBwaW5nIGZyb20gdGhlIHBhcmFtZXRlcnMgdG8gdGhlIHByZWRpY3RpdmUgCmRpc3RyaWJ1dGlvbnMgaXMgc3VjaCB0aGF0IHRoZSBiaWFzIGluIHRoZSBwYXJhbWV0ZXIgcG9zdGVyaW9yIGluZGljYXRlZCBieSB0aGUgCmRpdmVyZ2VuY2VzIGRvZXMgbm90IGhhdmUgYW4gZWZmZWN0LiBUaGlzIGNhbiBoYXBwZW4sIGZvciBleGFtcGxlIGlmIHRoZSAKdW5leHBsb3JlZCBwYXJ0IG9mIHRoZSBwYXJhbWV0ZXIgcG9zdGVyaW9yIG1hcHMgdG8gdmVyeSBzaW1pbGFyIHByZWRpY3Rpb25zIHRvIAp0aGUgb3RoZXIgcGFydHMgb2YgdGhlIHBvc3Rlcmlvci4KCiMjIDQuIE1PREVMIENPTVBBUklTT04KCkluIFtAdmFuMjAxOHNocmlua2FnZV0gbW9kZWwgY29tcGFyaXNvbnMgd2VyZSBwcm92aWRlZCB1c2luZyBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24gdmFsdWVzIG9mIFBNU0VzLiBBcyB0aGUgbWVhbiB2YWx1ZXMgb2YgZGlmZmVyZW50IG1vZGVscyB3ZXJlIHZlcnkgY2xvc2UgdG8gZWFjaCBvdGhlcnMsIHRoZSBjb21wYXJpc29uIHdhcyBzbGlnaHRseSBkaWZmaWN1bHQuIEluIGFkZGl0aW9uLCBubyBmdXJ0aGVyIHZpc3VhbGl6YXRpb24gd2FzIHByb3ZpZGVkLiBUaGlzIHNlY3Rpb24gYWltcyB0byBwcm92aWRlIGEgdG9vbCBmb3IgbW9yZSBjbGVhciBjb21wYXJpc29uLCB1c2luZyB0aGUgUE1TRSBhbmQgTFBQRCB2YWx1ZSBkaXN0cmlidXRpb25zLiBCYXNlZCBvbiB0aGUgZXhwZXJpbWVudHMgaW4gcHJldmlvdXMgc2VjdGlvbiwgdGhlIGNob3NlbiBwYXJhbWV0cml6YXRpb24gZm9yIEhvcnNlc2hvZSBwcmlvciBpcyB0aGUgdGhpcmQgcGFyYW1ldHJpemF0aW9uLiBBbGwgcmVzdWx0cyBzaG93biBpbiB0aGlzIHNlY3Rpb24gYXJlIGFnYWluIGNvbXB1dGVkIGZyb20gNTAwIHNpbXVsYXRpb24gcmVwbGljYXRpb25zIGFuZCB3aXRoIFRyaXRvbi4gIExldCB1cyBzdGFydCBieSB2aXN1YWxpemluZyB0aGUgZGlzdHJpYnV0aW9uczoKCmBgYHtyfQojIENyZWF0ZXMgZml0X2RpYWduIGZpbGUKY2hvc2VuX2ZpdF9kaWFnbiA8LSBjaG9vc2VfZml0cyhmaXRfZGlhZ24sIGZpdF9kaWFnbiRtb2RlbHNbYygxLCA0OjExKV0sIDUwMCkKc2hvd19kaWFnbm9zdGljcyhjaG9zZW5fZml0X2RpYWduLDEsc2hvd19uZWZmID0gRkFMU0UpCmBgYApBcyBjYW4gYmUgc2VlbiBmcm9tIGFib3ZlIGZpZ3VyZXMsICoqcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSBvZiB0aGUgc2hyaW5rYWdlIHByaW9ycyBkbyBkaWZmZXIqKi4gQWdhaW4sIHRoZSBvdXRjb21lIGRldmlhdGVzIGZyb20gdGhlIHJlc3VsdHMgaWxsdXN0cmF0ZWQgaW4gW0B2YW4yMDE4c2hyaW5rYWdlXS4gIEhvd2V2ZXIsIHNpbmNlIHNvIG1hbnkgbW9kZWxzIGFyZSBpbnZvbHZlZCwgaXQgaXMgZGlmZmljdWx0IHRvIGFzc2VzcyB3aGljaCBwZXJmb3JtcyBiZXN0LiBJbiBvcmRlciB0byBwcm92aWRlIG1vcmUgaW5mb3JtYXRpdmUgbW9kZWwgY29tcGFyaXNvbiwgYWxzbyBzdGF0aXN0aWNzIGZvciByYW5raW5ncyBvZiBQTVNFIGFuZCBMUFBEIHZhbHVlcyBhcmUgcHJlc2VudGVkLiBJbiBvdGhlciB3b3JkcywgcmFua2luZyB2YWx1ZXMgMSB0byA5IGFyZSBhc3Nlc3NlZCB0byBlYWNoIG1vZGVsIGluIGVhY2ggcmVwbGljYXRpb24gaW4gYSBzdWNoIG1hbm5lciB0aGF0IHZhbHVlIDEgaXMgYXNzaWduZWQgdG8gbG93ZXN0IFBNU0UgdmFsdWUgb3IgYWJzb2x1dGUgTFBQRCB2YWx1ZSBhbmQgOSB0byBoaWdoZXN0LiBSZXN1bHRzIGFyZSBwcmVzZW50ZWQgaW4gdHdvIHRhYmxlcyBiZWxvdzoKCgpgYGB7cn0Kc2hvd19kaWFnbm9zdGljcyhjaG9zZW5fZml0X2RpYWduLDIsc2hvd19uZWZmID0gRkFMU0UpCmBgYApUaGUgdGFibGVzIGRlcGljdCB0aGF0ICoqSG9yc2VzaG9lIGFuZCBSZWd1bGFyaXplZCBIb3JzZXNob2UgaGF2ZSBiZXN0IHByZWRpY3RpdmUgcGVyZm9ybWFuY2UgYWJpbGl0aWVzKiouICBUaGUgc3VjY2VzcyBvZiBIb3JzZXNob2UgcHJpb3JzIGlzIGFzIGV4cGVjdGVkIHNpbmNlIHRoZWlyIHNocmlua2FnZSBhYmlsaXRpZXMgaGF2ZSBiZWVuIHByZXZpb3VzbHkgd2VsbCBjb3ZlcmVkIGluIGxpdGVyYXR1cmUgW0BjYXJ2YWxobzIwMTBob3JzZXNob2UsIEBwaWlyb25lbjIwMTdzcGFyc2l0eV0uIEhvd2V2ZXIsIGhlcmUgaXQgbXVzdCBiZSBub3RlZCB0aGF0IGp1c3QgYXMgaW4gW0B2YW4yMDE4c2hyaW5rYWdlXSwgc3BhcnNpdHkgcGFyYW1ldGVyIG9mIHRoZSBSZWd1bGFyaXplZCBIb3JzZXNob2UgcHJpb3IgaGFzIGEgcHJpb3Igd2hpY2ggaXMgY2VudGVyZWQgb24gdGhlIGNvcnJlY3QgbnVtYmVyIG9mIG5vbi16ZXJvIHBhcmFtZXRlcnMgaW4gdGhlIG1vZGVsLiBUaGUgd29yc3QgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZSBpcyBhdHRhaW5lZCB3aXRoIEVsYXN0aWMgTmV0IGFuZCB0aGUgc2Vjb25kIHdvcnN0IHdpdGggUmlkZ2UgQ2F1Y2h5LiBBbGwgbW9kZWxzIGFyZSByYW5rZWQgaW4gYSBzaW1pbGFyIG9yZGVyIGluIGJvdGggTFBQRCBhbmQgUE1TRSBjYXNlcy4gVG8gZW5zdXJlIHRoYXQgcmVzdWx0cyBhcmUgdmFsaWQsIGFsc28gUmhhdCB2YWx1ZXMgYW5kIGRpdmVyZ2VudCB0cmFuc2l0aW9ucyBhcmUgaWxsdXN0cmF0ZWQgZm9yIGVhY2ggbW9kZWw6CgpgYGB7cn0Kc2hvd19kaWFnbm9zdGljcyhjaG9zZW5fZml0X2RpYWduLDAsc2hvd19uZWZmID0gRkFMU0UpCmBgYAoKCiMjIDUuIENPTkNMVVNJT05TCgpUaGUgY29uY2x1c2lvbnMgb2YgdGhlIGFzc2lnbm1lbnQgY2FuIGJlIGJyaWVmbHkgc3VtbWFyaXplZCBhcyBmb2xsb3dzOgoKKioxOioqIFdoZW4gbW9kZWwgaXMgc3VmZmVyaW5nIGZyb20gdGhlIGNvbnZlcmdlbmNlIGRpZmZpY3VsdGllcyBhbmQgaW5jbHVkZXMgZGl2ZXJnZW50IHRyYW5zaXRpb25zLCB0aGUgYWRhcHRhdGlvbiBkZWx0YSBzaG91bGQgYmUgYXNzZXNzZWQgYXMgaGlnaCBhcyBwb3NzaWJsZSAoMC45OTkpLCBudW1iZXIgb2YgaXRlcmF0aW9ucyBhcyA4MDAwIGFuZCBpZiB0aGUgdHJhbnNpdGlvbnMgc3RpbGwgZXhpc3QsIHNjYXR0ZXIgYW5kIHBhcmFsbGVsIGNvb3JkaW5hdGUgcGxvdHMgdXNlZC4gSG93ZXZlciwgdXNpbmcgb25seSBwbG90cyBtYXkgYmUgaW5zdWZmaWNpZW50IGFuZCB0aGVyZWZvcmUgYWxzbyB3aWRlciBzdGF0aXN0aWNzIGZvciB0aGUgdHJhbnNpdGlvbnMgYW5kIGFsc28gZm9yIFJoYXQgYW5kICROX3tlZmZ9JCB2YWx1ZXMgYXJlIHJlcXVpcmVkLgoKKioyOioqIFVzaW5nIHRoZSBtb2RpZmllZCBzaW11bGF0aW9uIGNvbmRpdGlvbiAxLCBiZXN0IHBhcmFtZXRyaXphdGlvbiBmb3IgSG9yc2VzaG9lIHByaW9yIGlzIGJ5IHJlZm9ybWluZyBIYWxmLUNhdWNoeSBkaXN0cmlidXRpb24gd2l0aCBJbnZlcnNlX0dhbW1hIHBhcmFtZXRyaXphdGlvbi4gSG93ZXZlciwgUmVndWxhcml6ZWQgSG9yc2VzaG9lIHByaW9yIGlzIHN0aWxsIGEgYmV0dGVyIGNob2ljZSBvZiBwYXJhbWV0cml6YXRpb24gYXMgaXQgaW5jbHVkZXMgdmlydHVhbGx5IG5vIGRpdmVyZ2VudCB0cmFuc2l0aW9ucyBpbiB0aGUgc2V0dGluZyBvZiB0aGlzIGFzc2lnbm1lbnQuIFRoZSBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlIG9mIHRoZSBwcmlvcnMgYXJlIHN0aWxsIHZlcnkgY2xvc2UgdG8gZWFjaCBvdGhlci4KCioqMzoqKiBXaGVuIGNvbXBhcmluZyBkaWZmZXJlbnQgc2hyaW5rYWdlIHByaW9ycyB3aXRoIG1vZGlmaWVkIHNpbXVsYXRpb24gY29uZGl0aW9uIDEsIHRoZSBkaWZmZXJlbmNlcyBpbiBtb2RlbCBwZXJmb3JtYW5jZSBjYW4gYmUgc2VlbiB2aXN1YWxseSBmcm9tIFBNU0UgYW5kIExQUEQgZGlzdHJpYnV0aW9ucyBhbmQgdGhlIGJlc3QgbW9kZWwgY2FuIGJlIGRldGVybWluZWQgYmFzZWQgb24gdGhlaXIgdmFsdWVzLiBIb3JzZXNob2UgYW5kIFJlZ3VsYXJpemVkIEhvcnNlc2hvZSB3ZXJlIGZvdW5kIHRvIGJlIHRoZSB0b3Agc2hyaW5rYWdlIHByaW9ycyBmb3IgdGhlIHRhc2suCgojIyBSRUZFUkVOQ0VT