Introduction

Just last week, a paper by Verity and Nichols came up online early at Genetics. In this paper, they use a technique called thermodynamic integration to compute, apparently with quite good accuracy, the marginal likelihood for the structure model with different numbers of subpopulations (i.e., different \(K\) values). The method of thermodynamic integration has apparently been known for some time in statistical physics as an approximation method for normalizing constants; in the world of statistics it was described in Gelman and Meng (1998); but more recently it was detailed in an approachable fashion in reference to its use with the “power posterior” distribution by Friel and Pettitt (2008).

Thermodynamic integration looks like it would be a nice addition in anyone’s Monte Carlo toolbox, so this document gives a short tutorial about it. The first section provides some background on Bayesian model choice to remind the reader why we might be interested in estimating normalizing constants. The next section provides a (surprisingly simple, albeit rather long, now that I have written it all down) derivation that shows why thermodynamic integration can be used to approximate normalizing constants.

The third section introduces a toy problem and explores Bayesian model choice within it. The problem is simple enough that the marginal likelihoods can be computed exactly. Finally, we approximate the same marginal likelihoods using thermodynamic integration. We conclude with some thoughts on penalization for model complexity. (None of the sections described in this paragraph have been completed yet)

Quick Review of Bayesian Model Choice

Let \(M_i\) denote a model. Suppose we are interested in several different models under consideration. Each model describes a different set of circumstances and stochastic processes by which our data \(\mathbf{x}\) might have come to be observed. A model \(M_i\) tells us what the set of parameters is (hence it dicates the dimensionality of the parameter space), the probability distributions underlying observed and latent data (i.e., the likelihood), and the the prior distributions on the parameters.

Thus, when we write down the posterior probability, we could explicitly identify the model. For example: \[ P({\mathbf{\theta}}|{\mathbf{x}}, M_i) = \frac{P({\mathbf{x}}|{\mathbf{\theta}}, M_i)P({\mathbf{\theta}}| M_i)} {\int_{\mathbf{\theta}}P({\mathbf{x}}|{\mathbf{\theta}}, M_i)P({\mathbf{\theta}}| M_i) d\theta} \]

Now, if we want to be Bayesian about choosing among different models, we could express our uncertainty about models in terms of the posterior probability of a model. Or, if we just wanted to compare pairs of models, we might look at the Bayes Factor between two models, say, \(M_1\) and \(M_2\): \[ \mathrm{Bayes~Factor} = \frac{P({\mathbf{x}}|M_1)}{P({\mathbf{x}}|M_2)} \] Either way, we need to be able to compute \(P({\mathbf{x}}|M_i)\). Unfortunately, \[ P({\mathbf{x}}|M_i) = \int_{\mathbf{\theta}}P({\mathbf{x}}|{\mathbf{\theta}}, M_i)P({\mathbf{\theta}}| M_i) d\theta \] is the normalizing constant for the posterior from the model. Recall that the reason people rejoice about MCMC is that it provides a means of simulating from target distributions without having to compute the normalizing constant. Computing or even approximating normalizing constants is hard! But if we want to do Bayesian model choice, we will want to be able to compute (or accurately approximate) \(P({\mathbf{x}}|M_i)\), which is sometimes called the marginal likelihood or the model evidence.

Thermodynamic integration provides one computational approach to approximating the marginal likelihood.

Some preliminaries

There are a few mathematical/statistical things to familiarize ourselves with before proceeding to TI.

Something that we can compute during the course of MCMC

Though we can’t directly compute the marginal likelihood by Monte Carlo during our MCMC simulation we can compute log probability of the data given the current values of the parameters—\(\log[P({\mathbf{x}}|{\mathbf{\theta}}^{(j)}, M_i]\), where the superscript \((j)\) denotes the \(j\)-th iteration in the MCMC. If there are additional latent variables in the model, consider them as included in \({\mathbf{\theta}}\) (at least for now).

Averaging over the values of \(\log[P({\mathbf{x}}|{\mathbf{\theta}}^{(j)}, M_i]\) during MCMC gives a Monte Carlo estimate of the posterior mean of the log likelihood function: \[ \int_{\mathbf{\theta}}\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)] P({\mathbf{\theta}}| {\mathbf{x}}, M_i) d{\mathbf{\theta}}= \int_{\mathbf{\theta}}\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)] \biggl(\frac{P({\mathbf{x}}| {\mathbf{\theta}}, M_i) P({\mathbf{\theta}}| M_i)} {\int_{\mathbf{\theta}}P({\mathbf{x}}| {\mathbf{\theta}}, M_i) P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}}\biggr) d{\mathbf{\theta}}. \] This posterior mean is decidedly not the same as the log of the marginal likelihood. However your intuition might say that it should be related somehow to the log of the marginal likelihood. It turns out that it can be related, in an interesting fashion to the log marginal likelihood, and themodynamic integration exploits this relationship.

In order to make this work out, Friel and Pettitt (2008) considered a family of distributions called power posteriors.

Power posteriors

The power posterior with exponent \(\beta\) is simply a posterior distribution obtained by replacing the likelihood with the likelihood raised to the power of \(\beta\) (typically with \(\beta\) between 0 and 1, inclusive). That is, \[ P_\beta({\mathbf{\theta}}| {\mathbf{x}}, M_i) = \frac{[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)} {\int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}} \]

Note that if you can draw an MCMC sample from the posterior distribution (i.e. the power posterior with \(\beta = 1\)), then very likely you could modify your program easily to sample from the power posterior with any \(\beta\). For example, if you are doing Metropolis-Hasting updates, you need only raise the likelihood portions of the target density (that appear in the Hastings ratio) to the power of \(\beta\). Likewise, if you are doing Gibbs sampling on any variables, there is a good chance that the full conditional you are sampling from is of exponential family form, in which case, raising it to the power of \(\beta\) leads to a distribution in the same family.

If you can simulate via MCMC from the power posterior with exponent \(\beta\), then you could also compute an estimate of the posterior mean of \(\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]\) given \(\beta\). This, as before, is just the average of \(\log[P({\mathbf{x}}| {\mathbf{\theta}}^{(j)}, M_i)]\) over the course of the MCMC. It is a Monte Carlo approximation to \[ C(\beta; {\mathbf{x}}, M_i) = \int_{\mathbf{\theta}}\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)] P_\beta({\mathbf{\theta}}| {\mathbf{x}}, M_i) d{\mathbf{\theta}}= \int_{\mathbf{\theta}}\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)] \biggl(\frac{[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)} {\int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}}\biggr) d{\mathbf{\theta}}\] Note that \(\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]\), itself, is not raised to \(\beta\) (neither inside nor outside of the \(\log\) function).

In the next section, we will show how TI makes use of the fact that the log marginal likelihood can be written as an integral over values of \(\beta\) from 0 to 1 of \(C(\beta; {\mathbf{x}}, M_i)\).

The log marginal likelihood by integration over \(\beta\)

What we would like to know is \(P({\mathbf{x}}| M_i)\)—the marginal likelihood. It is just as good to know the log of that quantity, \(\log[P({\mathbf{x}}| M_i)]\), and so that is where we will start. The derivation here, as in a number of things in statistics, is going to involve writing down the quantity 1, dressed up in a tricky fashion, and then exploiting that expression with a fun trick. (This derivation proceeds in the opposite direction from most presentations in the literature and is a little longer, but I find it a little more illuminating.)

So, we start with what we would like to know (or, at least accurately approximate): \[ \log[P({\mathbf{x}}| M_i)] \] Obviously this is the same as \[ \log[P({\mathbf{x}}| M_i)] - 0, \] which is the same as \[ \log[P({\mathbf{x}}| M_i)] - \log(1). \] Now, we are going to write the \(1\) in \(\log(1)\) as the integral of the prior on \({\mathbf{\theta}}\) over all values of \({\mathbf{\theta}}\). (Clearly, since the prior on \({\mathbf{\theta}}\) is a distribution, it must integrate to 1…at least so long as it is a proper prior…). This gives us \[ \log[P({\mathbf{x}}| M_i)] - \log\biggl[ \int_{\mathbf{\theta}}P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr]. \] Now, we are just going to write \(\log[P({\mathbf{x}}| M_i)]\) out in its longer incarnation: \[ \log\biggl[ \int_{\mathbf{\theta}}P({\mathbf{x}}| {\mathbf{\theta}}, M_i) P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr] - \log\biggl[ \int_{\mathbf{\theta}}P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr] \] Now, we are going to include 1 in there again in a tricky fashion—this time as the likelihood, \(P({\mathbf{x}}| {\mathbf{\theta}}, M_i)\), raised to 0 in the right hand part. And we will also explicitly raise the likelihood where it appears in the left hand part to the power of 1. Obviously we still have the same thing as above: \[ \log\biggl[ \int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^1 P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr] - \log\biggl[ \int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^0 P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr] \] Notice that the only thing that is changing there is the exponent on the CDDL terms (i.e. in the left hand side it is 1 and in the right hand side it is 0). So, we could rewrite that as: \[ \biggl. \log\biggl[ \int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr] \biggr|_{\beta = 0}^{\beta = 1} \] The little vertical bar on the right is saying “evaluate the expression when \(\beta = 1\) and then subtract from that the expression evaluated with \(\beta = 0\).” If this notation is stirring deep memories within you of your high school calculus class, then, Congratulations! you are on the right track.

Recall from that calculus class that if you were evaluating the definite integral \(\int_a^b f(x)dx\), you would evaluate \(\bigl. g(x) \bigr|_a^b\) where \(g(x)\) was the indefinite integral or “anti-derivative” of \(f(x)\). Which is to say that \(\frac{d}{dx}g(x) = f(x)\).

So, as you might have guessed, our next step is going to be to express the equation above, that we have been working through, as a definite integral over \(\beta\) from 0 to 1. If we do that, then from our foregoing excursion back to our calculus class, the integrand must clearly be the derivative (with respect to \(\beta\)) of \[ \log\biggl[ \int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr] \] Remember, as well, that \(\frac{d}{dx}\log u(x) = \frac{1}{u(x)}\frac{d}{dx}u(x)\) so that \[ \frac{\partial}{\partial \beta} \log\biggl[ \int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr] = \frac{1}{\int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}} \frac{\partial}{\partial \beta} \int_{\mathbf{\theta}}[P(x | {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}. \] We can change the order of differentiation and integration in the term on the right after the partial derivative sign, and thus simplify that term to: \[ \begin{aligned} \frac{\partial}{\partial \beta} \int_{\mathbf{\theta}}[P(x | {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}&= \int_{\mathbf{\theta}}\frac{\partial}{\partial \beta}[P(x | {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\\ &= \int_{\mathbf{\theta}}\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)] [P(x | {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}, \end{aligned} \] making use of the fact that \(\frac{d}{dx}a^x = [\log a] a^x\).

Putting this together we can write \[ \begin{aligned} \frac{\partial}{\partial \beta} \log\biggl[ \int_{\mathbf{\theta}}[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}\biggr] &= \int_{\mathbf{\theta}}\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)] \frac{[P(x | {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)} {\int_{\mathbf{\theta}}[P(x | {\mathbf{\theta}}, M_i)]^\beta P({\mathbf{\theta}}| M_i)d{\mathbf{\theta}}} d{\mathbf{\theta}}\\ &= \int_{\mathbf{\theta}}\log[P({\mathbf{x}}| {\mathbf{\theta}}, M_i)] P_\beta({\mathbf{\theta}}| {\mathbf{x}}, M_i) \\ &= C(\beta; {\mathbf{x}}, M_i) \end{aligned} \]

Remember that this derivative is what we were going to integrate over from \(\beta = 0\) to \(\beta = 1\), which means that \[ \log[P({\mathbf{x}}| M_i)] = \int_{\beta = 0}^{\beta = 1} C(\beta; {\mathbf{x}}, M_i) d\beta \] Now, we typically are not going to be able to analytically evaluate that integral, but that is OK because:

  1. that is just a simple one-dimensional integral, and
  2. in the previous section we saw that we can approximate \(C(\beta; {\mathbf{x}}, M_i)\) for any \(\beta\) by running MCMC and sampling from the power posterior with exponent \(\beta\).

Therefore, we can just form MCMC approximations of \(C(\beta; {\mathbf{x}}, M_i)\) at many values of \(\beta\) between 0 and 1, and then approximate the integral by the trapezoidal rule or Simpson’s method for approximating integrals. Both of which are straightforward. Holy Cow! That is pretty cool.

I currently don’t know how workable this scheme is in practice. One big question is “how much Monte Carlo variance does one find when \(\beta\) is small? Enough that it is very hard to estimate the mean log likelihood accurately when \(\beta\) is small?” Some further work has been done on reducing the discretization error. See Friel, Hurn, and Wyse (2014).

References

Friel, Nial, and Anthony N Pettitt. 2008. “Marginal Likelihood Estimation via Power Posteriors.” Journal of the Royal Statistical Society: Series B (Statistical Methodology) 70: 589–607.

Friel, Nial, Merrilee Hurn, and Jason Wyse. 2014. “Improving Power Posterior Estimation of Statistical Evidence.” Statistics and Computing 24: 709–23. doi:10.1007/s11222-013-9397-1.

Gelman, Andrew, and Xiao-Li Meng. 1998. “Simulating Normalizing Constants: From Importance Sampling to Bridge Sampling to Path Sampling.” Statistical Science 13: 163–85.

LS0tCnRpdGxlOiAiQW4gRXhwbG9yYXRpb24gb2YgVGhlcm1vZHluYW1pYyBJbnRlZ3JhdGlvbiIKYXV0aG9yOiAiRXJpYyBDLiBBbmRlcnNvbiIKZGF0ZTogIkp1bHkgMjQsIDIwMTYiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQpiaWJsaW9ncmFwaHk6IHRpLmJpYgotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYAoKXG5ld2NvbW1hbmR7XGJ0aGV0YX17XG1hdGhiZntcdGhldGF9fQpcbmV3Y29tbWFuZHtcYnh9e1xtYXRoYmZ7eH19ClxuZXdjb21tYW5ke1xien17XG1hdGhiZnt6fX0KCgojIyBJbnRyb2R1Y3Rpb24KCkp1c3QgbGFzdCB3ZWVrLCBhIHBhcGVyIGJ5IFZlcml0eSBhbmQgTmljaG9scyBjYW1lIHVwIG9ubGluZSBlYXJseSBhdCAqR2VuZXRpY3MqLiAgSW4gdGhpcyBwYXBlciwKdGhleSB1c2UgYSB0ZWNobmlxdWUgY2FsbGVkICp0aGVybW9keW5hbWljIGludGVncmF0aW9uKiB0byBjb21wdXRlLCBhcHBhcmVudGx5IHdpdGggcXVpdGUgZ29vZAphY2N1cmFjeSwgdGhlIG1hcmdpbmFsIGxpa2VsaWhvb2QgZm9yIHRoZSAqc3RydWN0dXJlKiAgbW9kZWwgd2l0aCBkaWZmZXJlbnQgbnVtYmVycyBvZiBzdWJwb3B1bGF0aW9ucwooaS5lLiwgZGlmZmVyZW50ICRLJCB2YWx1ZXMpLiAgVGhlIG1ldGhvZCBvZiB0aGVybW9keW5hbWljIGludGVncmF0aW9uIGhhcyBhcHBhcmVudGx5IGJlZW4ga25vd24gZm9yIHNvbWUgdGltZQppbiBzdGF0aXN0aWNhbCBwaHlzaWNzIGFzIGFuIGFwcHJveGltYXRpb24gbWV0aG9kIGZvciBub3JtYWxpemluZyBjb25zdGFudHM7IGluIHRoZSB3b3JsZCBvZiBzdGF0aXN0aWNzIGl0IHdhcyBkZXNjcmliZWQKaW4gQGdlbG1hbjE5OThzaW11bGF0aW5nOyBidXQgbW9yZSByZWNlbnRseSBpdCB3YXMgZGV0YWlsZWQgaW4gYW4gYXBwcm9hY2hhYmxlIGZhc2hpb24gaW4gcmVmZXJlbmNlIHRvIGl0cyB1c2Ugd2l0aCB0aGUgCiJwb3dlciBwb3N0ZXJpb3IiIGRpc3RyaWJ1dGlvbiBieSAgQGZyaWVsMjAwOG1hcmdpbmFsLiAgCgpUaGVybW9keW5hbWljIGludGVncmF0aW9uIGxvb2tzIGxpa2UgaXQgd291bGQgYmUgYSBuaWNlIGFkZGl0aW9uIGluIGFueW9uZSdzIE1vbnRlIENhcmxvIAp0b29sYm94LCBzbyB0aGlzIGRvY3VtZW50IGdpdmVzIGEgc2hvcnQgdHV0b3JpYWwgYWJvdXQgaXQuICBUaGUgZmlyc3Qgc2VjdGlvbiBwcm92aWRlcyBzb21lCmJhY2tncm91bmQgb24gQmF5ZXNpYW4gbW9kZWwgY2hvaWNlIHRvIHJlbWluZCB0aGUgcmVhZGVyIHdoeSB3ZSBtaWdodCBiZSBpbnRlcmVzdGVkIGluIGVzdGltYXRpbmcKbm9ybWFsaXppbmcgY29uc3RhbnRzLiAgVGhlIG5leHQgc2VjdGlvbiBwcm92aWRlcyBhIChzdXJwcmlzaW5nbHkgc2ltcGxlLCBhbGJlaXQgcmF0aGVyIGxvbmcsCm5vdyB0aGF0IEkgaGF2ZSB3cml0dGVuIGl0IGFsbCBkb3duKSBkZXJpdmF0aW9uCnRoYXQgc2hvd3Mgd2h5IHRoZXJtb2R5bmFtaWMgaW50ZWdyYXRpb24gY2FuIGJlIHVzZWQgdG8gYXBwcm94aW1hdGUgbm9ybWFsaXppbmcgY29uc3RhbnRzLgoKClRoZSB0aGlyZCBzZWN0aW9uIGludHJvZHVjZXMgYSB0b3kgcHJvYmxlbSBhbmQgZXhwbG9yZXMgQmF5ZXNpYW4gbW9kZWwgY2hvaWNlIHdpdGhpbiBpdC4gIFRoZQpwcm9ibGVtIGlzIHNpbXBsZSBlbm91Z2ggdGhhdCB0aGUgbWFyZ2luYWwgbGlrZWxpaG9vZHMgY2FuIGJlIGNvbXB1dGVkIGV4YWN0bHkuICBGaW5hbGx5LCB3ZSAKYXBwcm94aW1hdGUgdGhlIHNhbWUgbWFyZ2luYWwgbGlrZWxpaG9vZHMgdXNpbmcgdGhlcm1vZHluYW1pYyBpbnRlZ3JhdGlvbi4gIFdlIGNvbmNsdWRlIHdpdGggc29tZQp0aG91Z2h0cyBvbiBwZW5hbGl6YXRpb24gZm9yIG1vZGVsIGNvbXBsZXhpdHkuICAoKk5vbmUgb2YgdGhlIHNlY3Rpb25zIGRlc2NyaWJlZCBpbiB0aGlzIHBhcmFncmFwaCBoYXZlIGJlZW4gY29tcGxldGVkIHlldCopCgoKCiMjIFF1aWNrIFJldmlldyBvZiBCYXllc2lhbiBNb2RlbCBDaG9pY2UKCkxldCAkTV9pJCBkZW5vdGUgYSBtb2RlbC4gIFN1cHBvc2Ugd2UgYXJlIGludGVyZXN0ZWQgaW4gc2V2ZXJhbCBkaWZmZXJlbnQgbW9kZWxzIHVuZGVyIGNvbnNpZGVyYXRpb24uCkVhY2ggbW9kZWwgZGVzY3JpYmVzIGEgZGlmZmVyZW50CnNldCBvZiBjaXJjdW1zdGFuY2VzIGFuZCBzdG9jaGFzdGljIHByb2Nlc3NlcyBieSB3aGljaCBvdXIgZGF0YSAkXG1hdGhiZnt4fSQgbWlnaHQgaGF2ZSAKY29tZSB0byBiZSBvYnNlcnZlZC4gIEEgbW9kZWwgJE1faSQgdGVsbHMgdXMgd2hhdCB0aGUgc2V0IG9mIHBhcmFtZXRlcnMgaXMgKGhlbmNlIGl0IGRpY2F0ZXMKdGhlIGRpbWVuc2lvbmFsaXR5IG9mIHRoZSBwYXJhbWV0ZXIgc3BhY2UpLCB0aGUgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9ucyB1bmRlcmx5aW5nIG9ic2VydmVkCmFuZCBsYXRlbnQgZGF0YSAoaS5lLiwgdGhlIGxpa2VsaWhvb2QpLCBhbmQgdGhlIHRoZSBwcmlvciBkaXN0cmlidXRpb25zIG9uIHRoZSBwYXJhbWV0ZXJzLgoKVGh1cywgd2hlbiB3ZSB3cml0ZSBkb3duIHRoZSBwb3N0ZXJpb3IgcHJvYmFiaWxpdHksIHdlIGNvdWxkIGV4cGxpY2l0bHkgaWRlbnRpZnkgdGhlCm1vZGVsLiBGb3IgZXhhbXBsZToKJCQKUChcYnRoZXRhfFxieCwgTV9pKSA9IFxmcmFje1AoXGJ4fFxidGhldGEsIE1faSlQKFxidGhldGEgfCBNX2kpfQp7XGludF9cYnRoZXRhIFAoXGJ4fFxidGhldGEsIE1faSlQKFxidGhldGEgfCBNX2kpIGRcdGhldGF9CiQkCgpOb3csIGlmIHdlIHdhbnQgdG8gYmUgQmF5ZXNpYW4gYWJvdXQgY2hvb3NpbmcgYW1vbmcgZGlmZmVyZW50IG1vZGVscywgd2UgY291bGQKZXhwcmVzcyBvdXIgdW5jZXJ0YWludHkgYWJvdXQgbW9kZWxzIGluIHRlcm1zIG9mIHRoZSBwb3N0ZXJpb3IgcHJvYmFiaWxpdHkgb2YgCmEgbW9kZWwuICBPciwgaWYgd2UganVzdCB3YW50ZWQgdG8gY29tcGFyZSBwYWlycyBvZiBtb2RlbHMsIHdlIG1pZ2h0IGxvb2sgYXQgdGhlCkJheWVzIEZhY3RvciBiZXR3ZWVuIHR3byBtb2RlbHMsIHNheSwgJE1fMSQgYW5kICRNXzIkOgokJApcbWF0aHJte0JheWVzfkZhY3Rvcn0gPSBcZnJhY3tQKFxieHxNXzEpfXtQKFxieHxNXzIpfQokJApFaXRoZXIgd2F5LCB3ZSBuZWVkIHRvIGJlIGFibGUgdG8gY29tcHV0ZSAkUChcYnh8TV9pKSQuICBVbmZvcnR1bmF0ZWx5LCAKJCQKUChcYnh8TV9pKSA9ICBcaW50X1xidGhldGEgUChcYnh8XGJ0aGV0YSwgTV9pKVAoXGJ0aGV0YSB8IE1faSkgZFx0aGV0YQokJAppcyB0aGUgbm9ybWFsaXppbmcgY29uc3RhbnQgZm9yIHRoZSBwb3N0ZXJpb3IgZnJvbSB0aGUgbW9kZWwuICBSZWNhbGwgdGhhdCB0aGUgcmVhc29uIHBlb3BsZSAKcmVqb2ljZSBhYm91dCBNQ01DIGlzIHRoYXQgaXQgcHJvdmlkZXMgYSBtZWFucyBvZiBzaW11bGF0aW5nIGZyb20gdGFyZ2V0IApkaXN0cmlidXRpb25zIHdpdGhvdXQgaGF2aW5nIHRvIGNvbXB1dGUgdGhlIG5vcm1hbGl6aW5nIGNvbnN0YW50LiAgQ29tcHV0aW5nCm9yIGV2ZW4gYXBwcm94aW1hdGluZyBub3JtYWxpemluZyBjb25zdGFudHMgaXMgaGFyZCEgQnV0IGlmIHdlIHdhbnQgdG8gZG8gQmF5ZXNpYW4KbW9kZWwgY2hvaWNlLCB3ZSB3aWxsIHdhbnQgdG8gYmUgYWJsZSB0byBjb21wdXRlIChvciBhY2N1cmF0ZWx5IGFwcHJveGltYXRlKQokUChcYnh8TV9pKSQsIHdoaWNoIGlzIHNvbWV0aW1lcyBjYWxsZWQgdGhlICptYXJnaW5hbCBsaWtlbGlob29kKiBvciB0aGUgCiptb2RlbCBldmlkZW5jZSouCgpUaGVybW9keW5hbWljIGludGVncmF0aW9uIHByb3ZpZGVzIG9uZSBjb21wdXRhdGlvbmFsIGFwcHJvYWNoIHRvIGFwcHJveGltYXRpbmcKdGhlIG1hcmdpbmFsIGxpa2VsaWhvb2QuCgojIyBTb21lIHByZWxpbWluYXJpZXMKClRoZXJlIGFyZSBhIGZldyBtYXRoZW1hdGljYWwvc3RhdGlzdGljYWwgdGhpbmdzIHRvIGZhbWlsaWFyaXplIG91cnNlbHZlcyB3aXRoCmJlZm9yZSBwcm9jZWVkaW5nIHRvIFRJLiAgCgoKIyMjIFNvbWV0aGluZyB0aGF0IHdlICpjYW4qIGNvbXB1dGUgZHVyaW5nIHRoZSBjb3Vyc2Ugb2YgTUNNQwoKVGhvdWdoIHdlIGNhbid0IGRpcmVjdGx5IGNvbXB1dGUgdGhlIG1hcmdpbmFsIGxpa2VsaWhvb2QgYnkgTW9udGUgQ2FybG8gZHVyaW5nCm91ciBNQ01DIHNpbXVsYXRpb24gd2UgY2FuIGNvbXB1dGUgbG9nIHByb2JhYmlsaXR5IG9mIHRoZSBkYXRhIGdpdmVuIHRoZQpjdXJyZW50IHZhbHVlcyBvZiB0aGUgcGFyYW1ldGVycy0tLSRcbG9nW1AoXGJ4fFxidGhldGFeeyhqKX0sIE1faV0kLCB3aGVyZSB0aGUgCnN1cGVyc2NyaXB0ICQoaikkIGRlbm90ZXMgdGhlICRqJC10aCBpdGVyYXRpb24gaW4gdGhlIE1DTUMuICBJZiB0aGVyZSBhcmUgYWRkaXRpb25hbCBsYXRlbnQgdmFyaWFibGVzIGluIHRoZQptb2RlbCwgY29uc2lkZXIgdGhlbSBhcyBpbmNsdWRlZCBpbiAkXGJ0aGV0YSQgKGF0IGxlYXN0IGZvciBub3cpLgoKCkF2ZXJhZ2luZyBvdmVyIHRoZSB2YWx1ZXMgb2YgJFxsb2dbUChcYnh8XGJ0aGV0YV57KGopfSwgTV9pXSQgZHVyaW5nIE1DTUMgZ2l2ZXMgYSBNb250ZSBDYXJsbyBlc3RpbWF0ZQpvZiB0aGUgcG9zdGVyaW9yIG1lYW4gb2YgdGhlIGxvZyBsaWtlbGlob29kIGZ1bmN0aW9uOgokJApcaW50X1xidGhldGEgXGxvZ1tQKFxieCB8IFxidGhldGEsIE1faSldIFAoXGJ0aGV0YSB8IFxieCwgTV9pKSBkXGJ0aGV0YSAgPSAKXGludF9cYnRoZXRhIFxsb2dbUChcYnggfCBcYnRoZXRhLCBNX2kpXSBcYmlnZ2woXGZyYWN7UChcYnggfCBcYnRoZXRhLCBNX2kpIFAoXGJ0aGV0YSB8IE1faSl9CntcaW50X1xidGhldGEgUChcYnggfCBcYnRoZXRhLCBNX2kpIFAoXGJ0aGV0YSB8IE1faSlkXGJ0aGV0YX1cYmlnZ3IpCmRcYnRoZXRhLgokJApUaGlzIHBvc3RlcmlvciBtZWFuIGlzIGRlY2lkZWRseSAqbm90KiB0aGUgc2FtZSBhcyB0aGUgbG9nIG9mIHRoZSBtYXJnaW5hbCBsaWtlbGlob29kLgpIb3dldmVyIHlvdXIgaW50dWl0aW9uIG1pZ2h0IHNheSB0aGF0IGl0IHNob3VsZCBiZSByZWxhdGVkIHNvbWVob3cgdG8gdGhlIGxvZyBvZiAKdGhlIG1hcmdpbmFsIGxpa2VsaWhvb2QuIEl0IHR1cm5zIG91dCB0aGF0IGl0IGNhbiBiZSByZWxhdGVkLCBpbiBhbiBpbnRlcmVzdGluZwpmYXNoaW9uIHRvIHRoZSBsb2cgbWFyZ2luYWwgbGlrZWxpaG9vZCwgYW5kIHRoZW1vZHluYW1pYyBpbnRlZ3JhdGlvbiBleHBsb2l0cyB0aGlzCnJlbGF0aW9uc2hpcC4gCgpJbiBvcmRlciB0byBtYWtlIHRoaXMgd29yayBvdXQsIEBmcmllbDIwMDhtYXJnaW5hbCBjb25zaWRlcmVkIGEgZmFtaWx5IG9mIGRpc3RyaWJ1dGlvbnMgCmNhbGxlZCAqcG93ZXIgcG9zdGVyaW9ycyouICAKCiMjIyBQb3dlciBwb3N0ZXJpb3JzCgpUaGUgcG93ZXIgcG9zdGVyaW9yIHdpdGggZXhwb25lbnQgJFxiZXRhJCBpcyBzaW1wbHkgYSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIApvYnRhaW5lZCBieSByZXBsYWNpbmcgdGhlIGxpa2VsaWhvb2Qgd2l0aCB0aGUgbGlrZWxpaG9vZCByYWlzZWQgdG8gdGhlIHBvd2VyCm9mICRcYmV0YSQgKHR5cGljYWxseSB3aXRoICRcYmV0YSQgYmV0d2VlbiAwIGFuZCAxLCBpbmNsdXNpdmUpLiBUaGF0IGlzLAokJApQX1xiZXRhKFxidGhldGEgfCBcYngsIE1faSkgPSBcZnJhY3tbUChcYnggfCBcYnRoZXRhLCBNX2kpXV5cYmV0YSBQKFxidGhldGEgfCBNX2kpfQp7XGludF9cYnRoZXRhIFtQKFxieCB8IFxidGhldGEsIE1faSldXlxiZXRhIFAoXGJ0aGV0YSB8IE1faSlkXGJ0aGV0YX0KJCQKCk5vdGUgdGhhdCBpZiB5b3UgY2FuIGRyYXcgYW4gTUNNQyBzYW1wbGUgZnJvbSB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiAoaS5lLiB0aGUgCnBvd2VyIHBvc3RlcmlvciB3aXRoICRcYmV0YSA9IDEkKSwgdGhlbiB2ZXJ5IGxpa2VseSB5b3UgY291bGQgbW9kaWZ5IHlvdXIgcHJvZ3JhbSAKZWFzaWx5IHRvIHNhbXBsZSBmcm9tIHRoZSBwb3dlciBwb3N0ZXJpb3Igd2l0aCBhbnkgJFxiZXRhJC4gIEZvciBleGFtcGxlLCBpZiB5b3UgYXJlIGRvaW5nCk1ldHJvcG9saXMtSGFzdGluZyB1cGRhdGVzLCB5b3UgbmVlZCBvbmx5IHJhaXNlIHRoZSBsaWtlbGlob29kIHBvcnRpb25zIG9mIHRoZSAKdGFyZ2V0IGRlbnNpdHkgKHRoYXQgYXBwZWFyIGluIHRoZSBIYXN0aW5ncyByYXRpbykgdG8gdGhlIHBvd2VyIG9mICRcYmV0YSQuCkxpa2V3aXNlLCBpZiB5b3UgYXJlIGRvaW5nIEdpYmJzIHNhbXBsaW5nIG9uIGFueSB2YXJpYWJsZXMsCnRoZXJlIGlzIGEgZ29vZCBjaGFuY2UgdGhhdCB0aGUgZnVsbCBjb25kaXRpb25hbCB5b3UgYXJlIHNhbXBsaW5nIGZyb20gaXMgb2YKZXhwb25lbnRpYWwgZmFtaWx5IGZvcm0sIGluIHdoaWNoIGNhc2UsIHJhaXNpbmcgaXQgdG8gdGhlIHBvd2VyIG9mICRcYmV0YSQgbGVhZHMgdG8gYSAKZGlzdHJpYnV0aW9uIGluIHRoZSBzYW1lIGZhbWlseS4gIAoKSWYgeW91IGNhbiBzaW11bGF0ZSB2aWEgTUNNQyBmcm9tIHRoZSBwb3dlciBwb3N0ZXJpb3Igd2l0aCBleHBvbmVudCAkXGJldGEkLAp0aGVuIHlvdSBjb3VsZCBhbHNvIGNvbXB1dGUgYW4gZXN0aW1hdGUgb2YgdGhlIHBvc3RlcmlvciBtZWFuIG9mICRcbG9nW1AoXGJ4IHwgXGJ0aGV0YSwgTV9pKV0kCmdpdmVuICRcYmV0YSQuICBUaGlzLCBhcyBiZWZvcmUsIGlzIGp1c3QgdGhlIGF2ZXJhZ2Ugb2YgCiRcbG9nW1AoXGJ4IHwgXGJ0aGV0YV57KGopfSwgTV9pKV0kIG92ZXIgdGhlIGNvdXJzZSBvZiB0aGUgTUNNQy4gIEl0IGlzIGEgTW9udGUgQ2FybG8gYXBwcm94aW1hdGlvbiB0bwokJApDKFxiZXRhOyBcYngsIE1faSkgPSBcaW50X1xidGhldGEgXGxvZ1tQKFxieCB8IFxidGhldGEsIE1faSldIFBfXGJldGEoXGJ0aGV0YSB8IFxieCwgTV9pKSBkXGJ0aGV0YSAgPSAKXGludF9cYnRoZXRhIFxsb2dbUChcYnggfCBcYnRoZXRhLCBNX2kpXSBcYmlnZ2woXGZyYWN7W1AoXGJ4IHwgXGJ0aGV0YSwgTV9pKV1eXGJldGEgUChcYnRoZXRhIHwgTV9pKX0Ke1xpbnRfXGJ0aGV0YSBbUChcYnggfCBcYnRoZXRhLCBNX2kpXV5cYmV0YSBQKFxidGhldGEgfCBNX2kpZFxidGhldGF9XGJpZ2dyKQpkXGJ0aGV0YQokJApOb3RlIHRoYXQgJFxsb2dbUChcYnggfCBcYnRoZXRhLCBNX2kpXSQsIGl0c2VsZiwgaXMgKm5vdCogcmFpc2VkIHRvICRcYmV0YSQgCihuZWl0aGVyIGluc2lkZSBub3Igb3V0c2lkZSBvZiB0aGUgJFxsb2ckIGZ1bmN0aW9uKS4KCkluIHRoZSBuZXh0IHNlY3Rpb24sIHdlIHdpbGwgc2hvdyBob3cgVEkgbWFrZXMgdXNlIG9mIHRoZSBmYWN0IHRoYXQgdGhlIGxvZyBtYXJnaW5hbCBsaWtlbGlob29kCmNhbiBiZSB3cml0dGVuIGFzIGFuIGludGVncmFsIG92ZXIgdmFsdWVzIG9mICRcYmV0YSQgZnJvbSAwIHRvIDEgb2YgJEMoXGJldGE7IFxieCwgTV9pKSQuICAKCiMjIFRoZSBsb2cgbWFyZ2luYWwgbGlrZWxpaG9vZCBieSBpbnRlZ3JhdGlvbiBvdmVyICRcYmV0YSQKCldoYXQgd2Ugd291bGQgbGlrZSB0byBrbm93IGlzICRQKFxieCB8IE1faSkkLS0tdGhlIG1hcmdpbmFsIGxpa2VsaWhvb2QuICBJdCBpcyBqdXN0IGFzIGdvb2QgdG8ga25vdyB0aGUgbG9nIG9mIHRoYXQKcXVhbnRpdHksICRcbG9nW1AoXGJ4IHwgTV9pKV0kLCBhbmQgc28gdGhhdCBpcyB3aGVyZSB3ZSB3aWxsIHN0YXJ0LiAgVGhlIGRlcml2YXRpb24gaGVyZSwgYXMgaW4gYSBudW1iZXIgb2YgdGhpbmdzIAppbiBzdGF0aXN0aWNzLCBpcyBnb2luZyB0byBpbnZvbHZlIHdyaXRpbmcgZG93biB0aGUgcXVhbnRpdHkgMSwgZHJlc3NlZCB1cCBpbiBhIHRyaWNreSBmYXNoaW9uLCBhbmQgdGhlbiBleHBsb2l0aW5nIHRoYXQgCmV4cHJlc3Npb24gd2l0aCBhIGZ1biB0cmljay4gIChUaGlzIGRlcml2YXRpb24gcHJvY2VlZHMgaW4gdGhlIG9wcG9zaXRlIGRpcmVjdGlvbiBmcm9tIG1vc3QgcHJlc2VudGF0aW9ucyBpbiB0aGUgCmxpdGVyYXR1cmUgYW5kIGlzIGEgbGl0dGxlIGxvbmdlciwgYnV0IEkgZmluZCBpdCBhIGxpdHRsZSBtb3JlIGlsbHVtaW5hdGluZy4pCgpTbywgd2Ugc3RhcnQgd2l0aCB3aGF0IHdlIHdvdWxkIGxpa2UgdG8ga25vdyAob3IsIGF0IGxlYXN0IGFjY3VyYXRlbHkgYXBwcm94aW1hdGUpOgokJApcbG9nW1AoXGJ4fCBNX2kpXQokJApPYnZpb3VzbHkgdGhpcyBpcyB0aGUgc2FtZSBhcyAKJCQKXGxvZ1tQKFxieCB8IE1faSldIC0gMCwgCiQkCndoaWNoIGlzIHRoZSBzYW1lIGFzCiQkClxsb2dbUChcYnggfCBNX2kpXSAtIFxsb2coMSkuCiQkCk5vdywgd2UgYXJlIGdvaW5nIHRvIHdyaXRlIHRoZSAkMSQgaW4gJFxsb2coMSkkIGFzIHRoZSBpbnRlZ3JhbCBvZiB0aGUgcHJpb3Igb24gJFxidGhldGEkIApvdmVyIGFsbCB2YWx1ZXMgb2YgJFxidGhldGEkLiAgKENsZWFybHksIHNpbmNlIHRoZSBwcmlvciBvbiAkXGJ0aGV0YSQgaXMgYSBkaXN0cmlidXRpb24sIGl0Cm11c3QgaW50ZWdyYXRlIHRvIDEuLi5hdCBsZWFzdCBzbyBsb25nIGFzIGl0IGlzIGEgcHJvcGVyIHByaW9yLi4uKS4gIFRoaXMgZ2l2ZXMgdXMKJCQKXGxvZ1tQKFxieCB8IE1faSldIC0gXGxvZ1xiaWdnbFsgIApcaW50X1xidGhldGEgUChcYnRoZXRhIHwgTV9pKWRcYnRoZXRhClxiaWdncl0uCiQkCk5vdywgd2UgYXJlIGp1c3QgZ29pbmcgdG8gd3JpdGUgJFxsb2dbUChcYnggfCBNX2kpXSQgb3V0IGluIGl0cyBsb25nZXIgaW5jYXJuYXRpb246CiQkClxsb2dcYmlnZ2xbIApcaW50X1xidGhldGEgUChcYnggfCBcYnRoZXRhLCBNX2kpIFAoXGJ0aGV0YSB8IE1faSlkXGJ0aGV0YQpcYmlnZ3JdIAotIApcbG9nXGJpZ2dsWyAgClxpbnRfXGJ0aGV0YSBQKFxidGhldGEgfCBNX2kpZFxidGhldGEKXGJpZ2dyXQokJApOb3csIHdlIGFyZSBnb2luZyB0byBpbmNsdWRlIDEgaW4gdGhlcmUgYWdhaW4gaW4gYSB0cmlja3kgZmFzaGlvbi0tLXRoaXMgdGltZQphcyB0aGUgbGlrZWxpaG9vZCwgJFAoXGJ4IHwgXGJ0aGV0YSwgTV9pKSQsIHJhaXNlZCB0byAwIGluIHRoZSByaWdodCBoYW5kIHBhcnQuIEFuZCB3ZSB3aWxsIGFsc28gZXhwbGljaXRseSAKcmFpc2UgdGhlIGxpa2VsaWhvb2Qgd2hlcmUgaXQgYXBwZWFycyBpbiB0aGUgbGVmdCBoYW5kIHBhcnQgdG8gdGhlIHBvd2VyIG9mIDEuICBPYnZpb3VzbHkgd2Ugc3RpbGwgaGF2ZSB0aGUKc2FtZSB0aGluZyBhcyBhYm92ZToKJCQKXGxvZ1xiaWdnbFsgClxpbnRfXGJ0aGV0YSBbUChcYnggfCBcYnRoZXRhLCBNX2kpXV4xIFAoXGJ0aGV0YSB8IE1faSlkXGJ0aGV0YQpcYmlnZ3JdIAotIApcbG9nXGJpZ2dsWyAgClxpbnRfXGJ0aGV0YSAKW1AoXGJ4IHwgXGJ0aGV0YSwgTV9pKV1eMApQKFxidGhldGEgfCBNX2kpZFxidGhldGEKXGJpZ2dyXQokJApOb3RpY2UgdGhhdCB0aGUgb25seSB0aGluZyB0aGF0IGlzIGNoYW5naW5nIHRoZXJlIGlzIHRoZSBleHBvbmVudCBvbiB0aGUgQ0RETCB0ZXJtcwooaS5lLiBpbiB0aGUgbGVmdCBoYW5kIHNpZGUgaXQgaXMgMSBhbmQgaW4gdGhlIHJpZ2h0IGhhbmQgc2lkZSBpdCBpcyAwKS4gIFNvLCB3ZSBjb3VsZApyZXdyaXRlIHRoYXQgYXM6CiQkClxiaWdnbC4KXGxvZ1xiaWdnbFsgClxpbnRfXGJ0aGV0YSBbUChcYnggfCBcYnRoZXRhLCBNX2kpXV5cYmV0YSBQKFxidGhldGEgfCBNX2kpZFxidGhldGEKXGJpZ2dyXSAKXGJpZ2dyfF97XGJldGEgPSAwfV57XGJldGEgPSAxfQokJApUaGUgbGl0dGxlIHZlcnRpY2FsIGJhciBvbiB0aGUgcmlnaHQgaXMgc2F5aW5nICJldmFsdWF0ZSB0aGUgZXhwcmVzc2lvbiB3aGVuICRcYmV0YSA9IDEkIGFuZCB0aGVuIHN1YnRyYWN0IApmcm9tIHRoYXQgdGhlIGV4cHJlc3Npb24gZXZhbHVhdGVkIHdpdGggJFxiZXRhID0gMCQuIiAgSWYgdGhpcyBub3RhdGlvbiBpcyBzdGlycmluZyBkZWVwIG1lbW9yaWVzIHdpdGhpbgp5b3Ugb2YgeW91ciBoaWdoIHNjaG9vbCBjYWxjdWx1cyBjbGFzcywgdGhlbiwgQ29uZ3JhdHVsYXRpb25zISB5b3UgYXJlIG9uIHRoZSByaWdodCB0cmFjay4KClJlY2FsbCBmcm9tIHRoYXQgY2FsY3VsdXMgY2xhc3MgdGhhdCBpZiB5b3Ugd2VyZSBldmFsdWF0aW5nIHRoZSBkZWZpbml0ZSBpbnRlZ3JhbCAKJFxpbnRfYV5iIGYoeClkeCQsIHlvdSB3b3VsZCBldmFsdWF0ZSAkXGJpZ2wuIGcoeCkgXGJpZ3J8X2FeYiQgd2hlcmUgJGcoeCkkIHdhcyB0aGUgaW5kZWZpbml0ZQppbnRlZ3JhbCBvciAiYW50aS1kZXJpdmF0aXZlIiBvZiAkZih4KSQuICBXaGljaCBpcyB0byBzYXkgdGhhdCAkXGZyYWN7ZH17ZHh9Zyh4KSA9IGYoeCkkLgoKU28sIGFzIHlvdSBtaWdodCBoYXZlIGd1ZXNzZWQsIG91ciBuZXh0IHN0ZXAgaXMgZ29pbmcgdG8gYmUgdG8gZXhwcmVzcyB0aGUgZXF1YXRpb24gYWJvdmUsIHRoYXQKd2UgaGF2ZSBiZWVuIHdvcmtpbmcgdGhyb3VnaCwgYXMgYSBkZWZpbml0ZSBpbnRlZ3JhbCBvdmVyICRcYmV0YSQgZnJvbSAwIHRvIDEuICBJZiB3ZSBkbyB0aGF0LAp0aGVuIGZyb20gb3VyIGZvcmVnb2luZyBleGN1cnNpb24gYmFjayB0byBvdXIgY2FsY3VsdXMgY2xhc3MsIHRoZSBpbnRlZ3JhbmQgbXVzdCBjbGVhcmx5IGJlIHRoZQpkZXJpdmF0aXZlICh3aXRoIHJlc3BlY3QgdG8gJFxiZXRhJCkgb2YgCiQkClxsb2dcYmlnZ2xbIApcaW50X1xidGhldGEgW1AoXGJ4IHwgXGJ0aGV0YSwgTV9pKV1eXGJldGEgUChcYnRoZXRhIHwgTV9pKWRcYnRoZXRhClxiaWdncl0KJCQKUmVtZW1iZXIsIGFzIHdlbGwsIHRoYXQgJFxmcmFje2R9e2R4fVxsb2cgdSh4KSA9IFxmcmFjezF9e3UoeCl9XGZyYWN7ZH17ZHh9dSh4KSQgc28gdGhhdAokJApcZnJhY3tccGFydGlhbH17XHBhcnRpYWwgXGJldGF9IApcbG9nXGJpZ2dsWyAKXGludF9cYnRoZXRhIFtQKFxieCB8IFxidGhldGEsIE1faSldXlxiZXRhIFAoXGJ0aGV0YSB8IE1faSlkXGJ0aGV0YQpcYmlnZ3JdCj0KXGZyYWN7MX17XGludF9cYnRoZXRhIFtQKFxieCB8IFxidGhldGEsIE1faSldXlxiZXRhIFAoXGJ0aGV0YSB8IE1faSlkXGJ0aGV0YX0KXGZyYWN7XHBhcnRpYWx9e1xwYXJ0aWFsIFxiZXRhfQpcaW50X1xidGhldGEgW1AoeCB8IFxidGhldGEsIE1faSldXlxiZXRhIFAoXGJ0aGV0YSB8IE1faSlkXGJ0aGV0YS4KJCQKV2UgY2FuIGNoYW5nZSB0aGUgb3JkZXIgb2YgZGlmZmVyZW50aWF0aW9uIGFuZCBpbnRlZ3JhdGlvbiBpbiB0aGUgdGVybSBvbiB0aGUgcmlnaHQKYWZ0ZXIgdGhlIHBhcnRpYWwgZGVyaXZhdGl2ZSBzaWduLCBhbmQgdGh1cwpzaW1wbGlmeSB0aGF0IHRlcm0gdG86CiQkClxiZWdpbnthbGlnbmVkfQpcZnJhY3tccGFydGlhbH17XHBhcnRpYWwgXGJldGF9IFxpbnRfXGJ0aGV0YSBbUCh4IHwgXGJ0aGV0YSwgTV9pKV1eXGJldGEgUChcYnRoZXRhIHwgTV9pKWRcYnRoZXRhICY9CiBcaW50X1xidGhldGEgXGZyYWN7XHBhcnRpYWx9e1xwYXJ0aWFsIFxiZXRhfVtQKHggfCBcYnRoZXRhLCBNX2kpXV5cYmV0YSBQKFxidGhldGEgfCBNX2kpZFxidGhldGEgXFwKICY9CiBcaW50X1xidGhldGEgXGxvZ1tQKFxieCB8IFxidGhldGEsIE1faSldIFtQKHggfCBcYnRoZXRhLCBNX2kpXV5cYmV0YSBQKFxidGhldGEgfCBNX2kpZFxidGhldGEsClxlbmR7YWxpZ25lZH0KJCQKbWFraW5nIHVzZSBvZiB0aGUgZmFjdCB0aGF0ICRcZnJhY3tkfXtkeH1hXnggPSBbXGxvZyBhXSBhXngkLgoKUHV0dGluZyB0aGlzIHRvZ2V0aGVyIHdlIGNhbiB3cml0ZSAKJCQKXGJlZ2lue2FsaWduZWR9ClxmcmFje1xwYXJ0aWFsfXtccGFydGlhbCBcYmV0YX0gClxsb2dcYmlnZ2xbIApcaW50X1xidGhldGEgW1AoXGJ4IHwgXGJ0aGV0YSwgTV9pKV1eXGJldGEgUChcYnRoZXRhIHwgTV9pKWRcYnRoZXRhClxiaWdncl0KJj0KXGludF9cYnRoZXRhIFxsb2dbUChcYnggfCBcYnRoZXRhLCBNX2kpXSBcZnJhY3tbUCh4IHwgXGJ0aGV0YSwgTV9pKV1eXGJldGEgUChcYnRoZXRhIHwgTV9pKX0Ke1xpbnRfXGJ0aGV0YSBbUCh4IHwgXGJ0aGV0YSwgTV9pKV1eXGJldGEgUChcYnRoZXRhIHwgTV9pKWRcYnRoZXRhfSAKZFxidGhldGEgXFwKJj0gClxpbnRfXGJ0aGV0YSBcbG9nW1AoXGJ4IHwgXGJ0aGV0YSwgTV9pKV0gUF9cYmV0YShcYnRoZXRhIHwgXGJ4LCBNX2kpIFxcCiY9IEMoXGJldGE7IFxieCwgTV9pKQpcZW5ke2FsaWduZWR9CiQkCgpSZW1lbWJlciB0aGF0IHRoaXMgZGVyaXZhdGl2ZSBpcyB3aGF0IHdlIHdlcmUgZ29pbmcgdG8gaW50ZWdyYXRlIG92ZXIgZnJvbSAkXGJldGEgID0gMCQgdG8gJFxiZXRhID0gMSQsIHdoaWNoIG1lYW5zIHRoYXQgCiQkClxsb2dbUChcYnggfCBNX2kpXSA9IFxpbnRfe1xiZXRhID0gMH1ee1xiZXRhID0gMX0gQyhcYmV0YTsgXGJ4LCBNX2kpIGRcYmV0YQokJApOb3csIHdlIHR5cGljYWxseSBhcmUgbm90IGdvaW5nIHRvIGJlIGFibGUgdG8gYW5hbHl0aWNhbGx5IGV2YWx1YXRlIHRoYXQgaW50ZWdyYWwsIGJ1dCB0aGF0IGlzIE9LIGJlY2F1c2U6CgoxLiB0aGF0IGlzIGp1c3QgYSBzaW1wbGUgb25lLWRpbWVuc2lvbmFsIGludGVncmFsLCBhbmQKMi4gaW4gdGhlIHByZXZpb3VzIHNlY3Rpb24gd2Ugc2F3IHRoYXQgd2UgY2FuIGFwcHJveGltYXRlICRDKFxiZXRhOyBcYngsIE1faSkkIGZvciBhbnkgJFxiZXRhJCBieSBydW5uaW5nIAogICAgTUNNQyBhbmQgc2FtcGxpbmcgZnJvbSB0aGUgcG93ZXIgcG9zdGVyaW9yIHdpdGggZXhwb25lbnQgJFxiZXRhJC4gIAoKVGhlcmVmb3JlLCB3ZSBjYW4ganVzdCBmb3JtIE1DTUMgYXBwcm94aW1hdGlvbnMgb2YgJEMoXGJldGE7IFxieCwgTV9pKSQgYXQgbWFueSB2YWx1ZXMgb2YgJFxiZXRhJCBiZXR3ZWVuCjAgYW5kIDEsIGFuZCB0aGVuIGFwcHJveGltYXRlIHRoZSBpbnRlZ3JhbCBieSB0aGUgdHJhcGV6b2lkYWwgcnVsZSBvciBTaW1wc29uJ3MgbWV0aG9kIGZvciBhcHByb3hpbWF0aW5nIAppbnRlZ3JhbHMuICBCb3RoIG9mIHdoaWNoIGFyZSBzdHJhaWdodGZvcndhcmQuICBIb2x5IENvdyEgVGhhdCBpcyBwcmV0dHkgY29vbC4KCkkgY3VycmVudGx5IGRvbid0IGtub3cgaG93IHdvcmthYmxlIHRoaXMgc2NoZW1lIGlzIGluIHByYWN0aWNlLiBPbmUgYmlnIHF1ZXN0aW9uIGlzICJob3cgbXVjaCBNb250ZSBDYXJsbyB2YXJpYW5jZQpkb2VzIG9uZSBmaW5kIHdoZW4gJFxiZXRhJCBpcyBzbWFsbD8gRW5vdWdoIHRoYXQgaXQgaXMgdmVyeSBoYXJkIHRvIGVzdGltYXRlIHRoZSBtZWFuIGxvZyBsaWtlbGlob29kIGFjY3VyYXRlbHkgd2hlbiAKJFxiZXRhJCBpcyBzbWFsbD8iICBTb21lIGZ1cnRoZXIgd29yayBoYXMgYmVlbiBkb25lIG9uIHJlZHVjaW5nIHRoZSBkaXNjcmV0aXphdGlvbiBlcnJvci4gU2VlIEBmcmllbDIwMTQuCgoKIyMgUmVmZXJlbmNlcwoK