library(tidyverse)
Loading tidyverse: ggplot2
Loading tidyverse: tibble
Loading tidyverse: tidyr
Loading tidyverse: readr
Loading tidyverse: purrr
Loading tidyverse: dplyr
Conflicts with tidy packages ------------------------------------------------------------------------------------------------
filter(): dplyr, stats
lag():    dplyr, stats
library(DiagrammeR)

Bayesian Inference

Personal Probability

To understand the Bayesian paradigm, it is useful to start with the awareness that everyone has their own probabilities for events or outcomes, and these probabilities are informed by each person’s experience, their prior beliefs, the data that they have access to, and the inferential perspectives or models that they can bring to the task of understanding and incorporating the information that they have available.

Wait! What kind of crazy notion of probability is this? Many of us might be familiar with the idea of probability being interpretable as the long-run average frequency of outcomes if a particular event is repeated many times. But this “personal probability” paradigm sounds quite different…

A good way to approach this is with some simple card play. If I hand out cards from a shuffled deck to five people in the room and tell them not to look at the cards, and then ask everyone what the probability is that the next card on the deck is the ace of spades, most everyone will have the same probability for that. But if we let the 5 people look at their cards and then ask each, in turn, what they now think is the probability that the top card is the ace of spades, they will likely update their beliefs based on the card that they possess, as well as the responses of any cardholders before them.

There a lot of assumptions that go into these calculations. What are they?

At any rate, it is easy to see that people have different probabilities for the top card being an ace of spades depending on how much information they have.

Probability as a “Measuring Stick” for Uncertainty

A big switch being made here is that we are now using probability as a way of expressing or measuring each person’s “uncertainty” about an event. This is quite a departure from thinking about probability only as a property that can be discussed in connection with events that we can envision happening multiple time (so that we might derive a notion of probability as the average frequency of occurrence over very many trials.)

This interpretation of probability is considerably more flexible than the “frequentist” interpretation, and it is also already familiar to most of us: we are already quite comfortable with being told that the probability it is going to rain today is 30%, even though there will only ever be one today. With probability as a measure of uncertainty, you can use probabilities to talk about things that will only happen once. What is the probability that:

  • there will be three more category 5 hurricanes this season?
  • the Republicans in Congress will succeed in repealing Obamacare before Sept 30, 2017?

Not only that, but now we can use probability to make statements about how uncertain we are about things that are deterministic. For example:

  • What is your probability that Monrovia is the capital of Liberia?

So, if we are trying to measure:

  • height, then we use centimeters,
  • mass, then we use kilograms,
  • electrical resistance, we use Ohms
  • uncertainty?…we use probability…

An interesting digression

Probability as a field of mathematical study did not necessarily “grow up” with the intent to be a way to measure uncertainty. (It partly grew out of contemplation of “Borel subsets” and many much more esoteric concepts.) But the way that it was developed as a mathematical construct turns out to be precisely what is required if we desired to extend the system of logic in which 1 means “absolutely true” and 0 means “absolutely false” to a logical system in which there could be degrees of uncertainly between 0 and 1.

Updating Beliefs

A characteristic feature that we saw playing our card game is that when new information arrives, people update their beliefs, and hence they update their degree of undertainty (their probabilites…).

Clearly, if we want to be Bayesians and use probability to express uncertainty about things, we need a coherent, reasonable way to update our beliefs. This is done using basic principles from probability, which were described (for inferential purposes) by the Reverend Thomas Bayes (born 1702), and is hence known as Bayes’ Law, or Bayes Theorem.

Bayes Theorem is typically expressed in an equation that probably feels pretty opaque to most people (it certainly did to me when I was a young biology graduate student.) I remembered seeing it something like this: suppose that you have observed some data \(D\), and that you have \(k\) different hypotheses for its occurrence, and for each hypothesis, \(i\), you can compute \(P(D|H_i)\) the probability of observing D given that hypothesis \(i\) is true.

The posterior probability of a certain hypothesis \(H_i\) given \(D\) is then: \[ P(H_i|D) = \frac{P(D|H_i)P(H_i)}{\sum_{j = 1}^k P(D|H_j)P(H_j)} \] Yack! Let’s see if we can find an easier way to talk about this!

We will (at least I hope it will be easier) and we will do so while talking about a simple problem that we can build upon to make more complex models: estimating the frequency of an allele in a population.

A Simple Conditional Probability and DAGs

Almost all of the probabilities that we talk about routinely are conditional probabilities. That is, they are probabilities that are expressed conditional on some other variable or thing taking a certain value.

Here we will start beating to death an example that involves genotype and allele frequencies, but bear with us, because we will end up using what we learn from this example—and building upon it—throughout this lecture.

If we ask about the probability that an individual is homozygous for the \(A\) allele, we might first have to make an assumption that the population is in Hardy-Weinberg equilibrium, and then we also need to assess this probability conditional on the frequency of the \(A\) allele being \(p_A\) in the population.

So, we could write: \[ P(\mbox{Individual is AA}~|~p_A) = p_A^2 \] If we knew the value of \(p_A\), then it would be easy to do this calculation. This is an example of probability “running forward”. We will see later that when we want to do inference we need to “run probability backward” (which is what Bayes’ Theorem lets us do.)

Recall that HWE means that the allelic type of the two gene copies carried in an individual are conditionally independent given the allele frequency. Hence, the probability of drawing the first gene copy as an A is \(p_A\), and the probability that the second gene copy is drawn as an A (given that the first was an \(A\)), is also \(p_A\). So the probability that the individual is \(AA\) is the product of those: \(p_A^2\).

We can draw a diagram of that called an acyclic directed graph (or DAG). These are very helpful for visualizing models as they become more complex.

The key thing to know about DAGs is that they express the factorization of the joint probability of the variables into a product of conditional probabilities. (Specifically a product over nodes of the probability of each node conditional on its parents.)

From the way the DAG is drawn above, it is clear that we can say: \[ P(\mbox{Individual is AA}~|~p_A) = P(Y_1 = A~|~p_A) P(Y_2 = A~|~p_A) = p_A \cdot p_A = p_A^2 \]

Here is a quick summary of DAGs:

A Picture of Inference of Allele Frequencies From a Sample of Genotypes

The previous discussion assumed that the allele frequency was known, and we wanted to compute the probability of an individual’s (unknown) genotype. For that exercise, we were running from an observed node in the graph (\(p_A\)) to two unobserved ones. This is a straightforward calculation of probabilities.

Much of the time in science, we are able to observe the variables at the end of the arrows in a DAG, and we want to make inferences about the variables that are “upstream” of them in a DAG. For an example, let us consider the situation in which we sample \(N\) diploids and observe their genotypes, and from that we want to infer the allele frequency \(p_A\).

The DAG for this situation looks like this:

From which it is immediately apparent that the probability of all the data, say \(\boldsymbol{Y} = (Y_{1,1}, Y_{1,2}, Y_{2,1}, \ldots, Y_{N,1}, Y_{N,2})\) is just a simple product of Bernoulli random variables: \[ P(\boldsymbol{Y}~|~p_A) = \prod_{i=1}^N P(Y_{i,1}~|~p_A)P(Y_{i,2}~|~p_A) \] In fact, if we define each \(Y\) to be 0 or 1 as follows: \[ \begin{align} Y = 0 & ~~~~~\mbox{with probability} ~~~ 1 - p_A & ~~\mbox{(i.e., it's an}~a) \\ Y = 1 & ~~~~~\mbox{with probability} ~~~ p_A & ~~\mbox{(i.e., it's an}~A) \end{align} \] Then it is not too hard to see that \[ P(\boldsymbol{Y}~|~p_A) = p_A^{\sum Y_{i,j}} (1- p_A)^{2N - \sum Y_{i,j}} \] This is a probability function. But if you consider this as a function of \(p_A\) with \(\boldsymbol{Y}\) considered as fixed, then it is often referred to as the likelihood function.

Methods of Inference

We see that we are trying to learn something (make inference) about \(p_A\) (an unshaded/unobserved variable) that is upstream of our observed data. This is inference.

To put some concrete numbers on this. Let’s say that \(N = 100\) diploids, and out of the 200 gene copies, 73 of them were \(A\) alleles.

There are lots of ways that you might do inference. Here are a few:

  • Method of the Eyeball: Look at your sample and surmise that the fraction of A alleles in the sample is a good estimate of the fraction of \(A\) alleles in the population.
  • Method of Moments: This formalizes the “Method of the Eyeball” by equating the sample mean with the population mean.
  • Method of Maximum Likelihood: Find the value of \(p_A\) that maximizes the probability of observing your sample. In other words, consider the probability \(P(\boldsymbol{Y}~|~p_A)\) as a function of \(p_A\), where the data, \(\boldsymbol{Y}\), are fixed, and then find the value of \(p_A\) that maximises that likelihood function.

All of those methods give you a point estimate for \(p_A\). An alternative to these methods is to be Bayesian and find the posterior distribution for \(p_A\) conditional on the data, \(\boldsymbol{Y}\).

Before we do this, we are going to want to review a view simple facts about marginal, conditional, and joint probabilities.

Some important probability rules

If you have two different events \(A\) (no relation, necessarily, to the big-A allele ) and \(B\), and we use \(A\) and \(B\) to refer to the outcome of each, then here are some things that are always true:

  • \(P(A)\) and \(P(B)\) are referred to as marginal probabilities.
  • The joint probability of \(A\) and \(B\) is the probability that those two outcomes occurred, and it can be computed as the product of a marginal probability and a conditional probability, in two different ways: \[ P(A,B) = P(A)P(B~|~A) = P(B)P(A~|~B) \]
  • This means that conditional probabilities can be computed from the joint probability: \[ P(A~|~B) = \frac{P(A,B)}{P(B)}~~~~~~~~~~~~~~~~~~~~~~~~ P(B~|~A) = \frac{P(A,B)}{P(A)} \]

And that leads us to an expression for Bayes Theorem that I find easier to grok out: \[ P(A~|~B) \propto P(A, B) \] where we are thinking of \(P(A|B)\) as a function of \(A\) with \(B\) fixed. It is typically easy to compute the joint probability, \(P(A,B)\), and then you just have to remember that \(P(A~|~B)\), since it is a probability on \(A\), must sum to one over all possible values of \(A\).

The same is true for: \[ P(B~|~A) \propto P(A, B) \]

Bayesian Inference for \(p_A\)

Back to our simple example. If we want to do Bayesian inference for \(p_A\) we see that we will want to compute the posterior probability: \[ P(p_A|\boldsymbol{Y}) \] which we now know is going to be proportional to the joint probability: \[ P(p_A,\boldsymbol{Y}) \] and what we currently have at our disposal is the likelihood: \[ P(\boldsymbol{Y}~|~p_A) \] We could get the joint probability by using the likelihood in the product: \[ P(p_A,\boldsymbol{Y}) = P(\boldsymbol{Y}~|~p_A) P(p_A) \] But what is this \(P(p_A)\)?!

It is the prior distribution for \(p_A\). It is a necessary ingredient to be able to use the likelihood to compute the joint probability (and, hence, the posterior probability), and we envision it as a probability distribution that expresses our degree of belief about \(p_A\) before we look at the data.

Note that this all boils down verbally to: The posterior distribution is proportional to the prior times the likelihood.

A family of priors for \(p_A\)

Since \(p_A\) is a proportion, an obvious choice for prior would be a beta distribution. The beta distribution gives a continuous prior distribution on a value that is between 0 and 1. It has two parameters, often called \(\alpha_1\) and \(\alpha_2\). Here are some examples:

The beta density for a random variable \(X\) has the form: \[ p(x | \alpha_1, \alpha_2) = \frac{\Gamma(\alpha_1 + \alpha_2)}{\Gamma(\alpha_1)\Gamma(\alpha_2)} x^{\alpha_1 - 1}(1-x)^{\alpha_2 - 1} \] The part that looks hairy is a few Gamma functions. Don’t worry about those—it is a constant. The important part (the “kernel”, as they say…) is: \[ x^{\alpha_1 - 1}(1-x)^{\alpha_2 - 1} \] Or, if we wanted this to a be a prior on \(p_A\), the prior would be proportional to: \[ {p_A}^{\alpha_1 - 1}(1-p_A)^{\alpha_2 - 1} \] And, if we wanted to be even more specific, we could choose \(\alpha_1 = \alpha_2 = 1\) to give ourselves a uniform prior which is proportional to 1: \[ P(p_A) \propto {p_A}^{1 - 1}(1-p_A)^{1 - 1} = {p_A}^{0}(1-p_A)^{0} = 1 \]

A Graphical Aside

Just wanting to point out that if you want to be a Bayesian, you can’t have any unobserved nodes on your DAG that don’t have any parents. Those priors that you use/accept/assume are always the uppermost nodes in a DAG. I usually use gray nodes to denote them. For example, here is the DAG for the Bayesian version of the previously shown DAG:

The posterior for \(p_A\)

Now that we have a choice for our prior, \(P(p_A)\), we can easily find something that is proportional to the posterior distribution. What is proportional to the posterior distribution? Remember, The posterior distribution is proportional to the prior times the likelihood (which, don’t forget, is the joint probability). Remember that the likelihood looks like: \[ P(\boldsymbol{Y}~|~p_A) = p_A^{\sum Y_{i,j}} (1- p_A)^{2N - \sum Y_{i,j}} \] And, in our example, the number of \(A\) alleles is 73 (out of 200), so \(\sum Y_{i,j} = 73\) and \(2N - \sum Y_{i,j} = 127\).

Since we are only going to worry about finding something that the posterior probability is proportional to, we can drop any constants and we get this for the prior times the likelihood: \[ \begin{align} P(p_A~|~\boldsymbol{Y}) &\propto {p_A}^{0}(1-p_A)^{0} \times p_A^{73}(1-p_A)^{127} \\ & \propto p_A^{73}(1-p_A)^{127} \\ & \propto p_A^{74 - 1}(1-p_A)^{128 - 1} \\ \end{align} \] which is precisely the kernel of a beta distribution with parameters 74 and 128.

Aha! So, the posterior here is a beta distribution with \(\alpha_1 = 74\) and \(\alpha_2 = 128\). We can plot that if we want:

To the Bayesian, the posterior distribution is everything

To the Bayesian, the posterior distribution contains all the information that the data has about the parameter to be estimated—in this case, \(p_A\). And, the full posterior distribution, unsummarized, expresses that all that information as fully as can be done.

However, sometimes you don’t want to carry around a full posterior distribution, especially if it is a distribution on multiple variables (multidimensional).

Often you will want to summarise the posterior distribution.

Some standard ways of summarizing the posterior

  1. The posterior mean. Gives a point estimate that minimizes squared error posterior loss.
  2. The posterior median. Gives a point estimate that minimizes absolute posterior loss.
  3. The posterior mode. Gives a point estimate that minimizes 0-1 posterior loss.
  4. The Bayesian Credible Interval: provides an interval estimator. Like a confidence interval, but infinitely easier to intepret correctly…

Monte Carlo and Markov Chain Monte Carlo

In the above segment, we obtained a posterior distribution analytically. That is not the way things typically work out. It is more common that one is not able to obtain the posterior analytically, but, rather, can only obtain a sample from the posterior distribution. With a sample from the posterior, however, it is possible to use Monte Carlo to approximate virtually any quantity that might be of interest. Let’s look at that with our simple example.

A “vanilla” Monte Carlo sample from the posterior for \(p_A\)

Even though we can compute the posterior analytically, it can still be convenient to obtain a sample from it. We can sample 1 million values from the posterior for \(p_A\) like this:

pA <- rbeta(n = 10^6, 74, 128)

The first 10 values of that sample look like:

pA[1:10]
 [1] 0.3433463 0.3250922 0.3296478 0.4008230 0.3619769 0.3038206 0.3374032 0.3873018 0.3780296 0.3635428

We call this is a “vanilla” Monte Carlo sample because every member of the sample was independent—this is not Markov chain Monte Carlo.

If we wanted to use the sample to approximate the full posterior, we could do that with a histogram:

hist(pA, breaks = 100)

Let’s watch this in action: COMPUTER DEMO beta_dens

If we want the posterior mean, that is easy, too:

mean(pA)
[1] 0.3663259

as is the posterior median:

median(pA)
[1] 0.365903

Or the standard deviation of the posterior distribution:

sd(pA)
[1] 0.03382594

Or, the 90%-equal-tail Credible Interval

quantile(pA, probs = c(0.05, 0.95))
       5%       95% 
0.3114611 0.4227772 

All of those quantities could have been obtained analytically in this case, but it is a lot simpler to just work with a Monte Carlo sample because the operations are the same with every Monte Carlo sample (which is not necessarily true of every analytical distribution…).

Transformations are simple with a Monte Carlo sample

Imagine for a moment that what you really wanted to estimate was the probability that, if you sampled three individuals, in sequence, from the population, the first one would be homozygous \(AA\), the second one would be heterozygous \(Aa\) and the third one would be homozygous \(aa\). Since we are being Bayesians here, we will want to compute the posterior distribution of that probability given the observed data. This is something that would be quite messy to do analytically, but it is easy to use the Monte Carlo sample to do it. Clearly, for a given \(p_A\), the probability of the sequence (\(AA\), \(Aa\), \(aa\)) is \(p_A^2\times 2 p_A (1-p_A) \times (1-p)^2\). So, the posterior distribution of that quantity is simply:

three_geno_seq_posterior <- pA^2 * 2 * pA * (1 - pA) * (1 - pA)^2

And we can look at it:

hist(three_geno_seq_posterior, breaks = 100)

What is the Markov Chain part of MCMC?

We’ve seent that Monte Carlo in this Bayesian context is all about basing one’s inference on a samples from the posterior distribution. However, it turns out that you often can’t obtain independent samples from posterior. In high dimensions that is just not possible. But, it is possible to construct an ergodic Markov chain that has as its limiting distribution the posterior distribution you want to be sampling from.

What?!

OK, we will talk briefly about Markov chains. Basically a Markov chain is a stochastic process (like a random walk) in which the probability of ending up in some place after the next step depends only on where it currently is—not on how it got there…

A classic example is a random walk, we will consider one with scattering boundaries:

The important take-home message from the tpm Computer Demo is that if you run a Markov chain long enough, it spends time in different states with a predictable pattern called the limiting distribution. In other words, you can take a sample of the states visited by the chain and use that as a Monte Carlo sample. That is Markov chain Monte Carlo.

Let’s see what it looks like for \(p_A\)

Computer Demo beta_dens with MCMC.

Why MCMC is so great for Bayesians

Via MCMC, it is possible to obtain samples from the posterior distribution even if the posterior distribution is highly-multidimensional and complicated.

There are two main reasons for this:

  1. A Markov chain can be devised to sample from the posterior distribution without knowing the normalizing constant. In other words, if you can compute the joint probability (prior times likelihood) for a fully-observed version of your model, that is all you need. (Note that you can pretty much always compute the joint probability for a fully-observed model.)
  2. The Markov chain so devised can be constructed by proposing changes only to small parts of the model, which makes it possible to break down complex distributions in ways that make it manageable to sample from them.

The details of this are beyond the scope of a 1.25 hour lecture.

Why MCMC can be not-so-great

  1. It can be computationally expensive and take a long time.
  2. It can mix poorly, i.e. it might not sample reliably from all areas of the distribution in proportion to (or even approximately in proportion to) their posterior probability.
  3. It can appear to be mixing well, but actually not be mixing well. It is important to perform multiple runs from different starting values to assess convergence.
  4. Especially in “canned packages” it can let you do “black-boxy” inference in models that are so complicated that it is hard to have proper intuition about how they behave or perform given the vararies of your own data.

Again, these topics are beyond the scope of this presentation. But grab me sometime during the week if you want to talk about it.

Probabilistic Genotype Calling / Allele frequency estimation

We are now going to expand our allele frequency model just a little bit, to get a taste for how we might infer both allele frequencies and genotypes given short read data.

Let’s consider this setup: we are trying to infer genotypes in individuals and estimate the allele frequencies in a population at a SNP in which the variants are the two different bases, \(C\) or \(T\). We know where the SNP occurs (we are disregarding the problem of inferring whether a SNP is there) but we do not know its frequency in the population. We have sequenced \(N\) individuals at this SNP. We don’t know the genotype of any of these individuals, but we get to observe the number of sequencing reads on each individual, \(i\), that contain a \(C\), and the number of reads that contain a \(T\) at the site. We call that observed variable \(\boldsymbol{R}_i = (R_{i,C}, R_{i,T})\), a two-vector. We include in our model a sequencing error rate \(\mu\) which, for simplicity here, we will assume is known. With probability \(\mu\) a read from a chromosome that really contains a \(C\) at the site will report a \(T\), while with probability \(1 - \mu\) the base at the site is correctly reported as a \(C\). Similarly for chromosomes that contain a \(T\) at the site, with probability \(\mu\) a read will report a \(C\) and with probability \(1 - \mu\) it will correctly report a \(T\).

Here is a DAG for the model:

All right. This is fun. Now there are two layers of unknown variables (the \(Y\)’s and \(p_C\) that we will try to infer together, at the same time).

Conditional probabilities in the model

Most of these we have seen before:

  • \(P(p_C | \alpha_C, \alpha_T)\) is just a beta prior on \(p_C\).
  • \(Y_{i,1}\) is a Bernoulli trial with success probability (i.e. probability of getting a \(C\) of \(p_C\).)
  • The only new one is the probability distribution of read counts given the genotype and the genotyping error rate: \(P(\boldsymbol{R}_i~|~Y_{i,1}, Y_{i,2}, \mu)\)

The conditional probability \(P(\boldsymbol{R}_i~|~Y_{i,1}, Y_{i,2}, \mu)\)

This thing turns out to be pretty easy. It can be broken down into cases:

  1. \(i\) is homozygous for \(C\) (i.e., \(Y_{i,1} = Y_{i,2} = C\)): In this case, the only way to get a read with a \(T\) at the site is by a sequencing error, which happens with probability \(\mu\). Thus, it is akin to drawing \(M = R_{i,C} + R_{i,T}\) balls out of an urn (with replacement), a fraction \(\mu\) of which say \(T\) on them, the rest which say \(C\) on them. In such a case \(R_{i,C}\) is binomially distributed, \(M\) draws with success probability \(1-\mu\).
  2. \(i\) is homozygous for \(T\) (i.e., \(Y_{i,1} = Y_{i,2} = T\)): Same argument as above, \(R_{i,C}\) is binomially distributed, \(M\) draws with success probability \(\mu\) this time, rather than \(\mu\).
  3. \(i\) is homozygous for \(T\) (i.e., \((Y_{i,1} = C, Y_{i,2} = T)\) or \((Y_{i,1} = T, Y_{i,2} = C)\)): Because we have assumed sequencing error rates are symmetrical between different bases, this is easily figured out—the reads are like balls you are sampling (with replacement) from an Urn in which half of the balls are \(T\)’s and half of them are \(C\)’s.

A little flavor of how MCMC proceeds

The unobserved genotypes of the individuals in the above model are what are sometimes called “missing data”. They are not missing data in the sense of small holes in your data set that resulted from some data-collection failure. They are missing in the sense of “What is missing here is something that would make this whole problem easier”. Clearly, as we showed in an earlier section, if we knew these genotypes exactly, doing Bayesian inference for \(p_C\) is pretty darn easy.

Another name for this “missing data” is “latent variables.” Many formulations of MCMC are developed with these types of latent variables. In our case, a brief sketch of how MCMC would proceed starts with a bit of wishful thinking. We say, “Wouldn’t it be great if we actually knew the value of \(p_C\)…Hey! We don’t, but let’s just start with a guess and pretend it is true.” So, we would start by initializing the model and setting \(p_C\) to some random value, let us call that value \(p_C^{(0)}\).

Now, if we know the value of \(p_C\), then the only thing that would be left unknown in the model would be the genotypes of the individuals. But looking at the graph it is clear that they are all conditionally indendent given \(p_C^{(0)}\) and the the observed read depths. So, pretending that \(p_C^{(0)}\) is the truth, we could compute, for each individual $i, the posterior probabilities of \(i\)’s genotype (the three cases, 1–3 above). (By the way, this distribution is often called the “full conditional distribution”).

Then we would simulate values of the genotypes from those posterior distributions. Aha! once we have those simulated, we can pretend that they are real and use them to come up with a new estimate of \(p_C\) by compute the posterior distribution (full conditional) for \(p_C\) given the current values of the genotypes and then simulating a value from that distribution. Call that \(p_C^{(1)}\), and then go back to simulating new values for the genotypes.

Doing that over and over again creates a Markov chain that does a random walk over the space of all possible genotypes of the \(i\) individuals and the unknown allele frequency \(p_C\), with the amount of time the chain spends in any state being proportional to the posterior probability of that state!.

Some of the assumptions in the above model…

There are quite a few but the biggest is that each read is independent of the others. That assumption would be violated if:

  • the sequences upon which the \(C\) (or the \(T\)) occurred were somehow subject to greater amplification during any PCR steps, or were more likely to attach to “the lawn” on an Illumina machine.
  • there are PCR duplicates. This can be a really big issue for RAD methods that don’t have a good mechanism for filtering PCR duplicates.

Why is this a good idea?

Because the allele frequency estimate is there to inform the inference of genotypes.

If the frequency of the \(C\) allele is quite low, that will provide a lot of evidence in the model against inferring someone to be homozygous for the \(C\) allele.

And this would be a good thing, because after a little bit of looking at published data sets of genotypes called by traditional means (i.e. apparently without considering allele frequencies), it appears there is a bit of an epidemic of genotyping error in RAD sequenced data.

Estimating Genotyping Error Rates in some RAD datasets

I became interested in widespread departures from Hardy-Weinberg equilibrium in called genotypes from RAD seq data, and investigated it a little bit.

It is important to recognize in this section that we are dealing only with called genotypes and have not retained any of the read depth information, etc. We are just looking at called genotypes!

Looking at Willow Flycatchers

My wife, Kristen Ruegg, does a lot of RAD seq on birds. She is a stickler for high-quality DNA and high read depths, and she works with some very good technicians at UCLA. Below is a plot I made of some of her (as yet unpublished) data from Willow Flycatchers. They called 105,000 SNPs in almost 200 individuals, and shown here are 47 individuals from the imperiled population of the extimus subspecies in Arizona. It is a plot of the expected frequency of each genotype (0 = homozygous for the reference allele, 1 = heterozygote, 2 = homozygous for the alternate allele) on the \(x\)-axis against the observed frequency of each genotype, across all loci polymorphic amongst those 47 individuals.

These data were obtained by alignment to a de-novo assembled genome with SNPs calling using GATK, with light filtering (read depths > 6 or 10, and Phred-scaled genotype likelihoods > 30, I think).

Note numbers up there:

  • n is the number of individuals in the population.
  • n_f is the number left after tossing out anyone with more than 90% missing data.
  • L is the number of loci in the whole data set.
  • L_f is the number of loci remaining after removing those that are monomorphic in the focal population, or which are missing data from more than 70% of the individuals.

It looks reasonably good—you want the observed to fall along the expected line—apart from some obvious outliers that are all heterozygotes: clearly more than one genomic region aligning to the same spot in the assembled genome.

What should these plots look like?

It is easy to see what these plots should look like under Hardy-Weinberg equilibrium by simulating it. Here are results of simulations with sample sizes of 20 and 40 individuals.

Also, if you do a little thinking and some algebra you can see that, because the expected genotype frequencies are computed from the allele frequencies estimated from the observed genotypes, there are some bounds on where the points can go. Those are indicated by dashed lines above.

What about some published data sets?

I went through Molecular Ecology and Dryad and found about 12 data sets created by some version of RAD (RAD, RAD-PE, ddRAD, etc.) that were in a format that was not too hard to wrangle into an 012 matrix. For each data set, I focused on the single sampling location with the largest sample size and made similar plots for them. Here are two:

Wow! Those are some data sets that are, in the aggregate, showing severe departures from Hardy-Weinberg equilibrium.

I think in one of them the authors said that they filtered out loci that were significantly out of HWE. So, it might be that with small samples, and focusing only on a single marker at a time, it is hard to detect these distortions. But they are quite evident when viewed like this. The main point: there are far more homozygotes than you would expect under HWE.

A Simple Model of Genotyping Errors

When I look at these pictures, I think, “Let’s make a super simple model of genotyping error and estimate what the genotyping error rates must be to get things that look this distorted.”

Obviously, there are some heterozygotes that are being called as homozygotes. So, let’s propose this: all individuals that are truly homozygotes get correctly called as homozygotes, but individuals that are truly heterozygous have a probability \(m\) of being miscalled as a homozygote. If the individual is miscalled, then it has an equal chance of being called as either homozygote.

We can draw a DAG for this model, but let’s establish a convention, first: rather than naming alleles by the bases that they carry, we will just let the alleles be labelled 0 and 1. Then the possible genotypes, \(G\) are denoted 0, 1, or 2, according to the number of 1 alleles in the diploid genotype.

\(p_1\) is the frequency of the “1” allele.

We don’t have time to go over the details of the model, but they are straightforward and trivial. It takes just a few lines of R code to implement MCMC for it. It mixes well, and even on large data sets it doesn’t take too long to get an estimate of that heterozygote miscall rate parameter \(m\).

ANGSD and Low Coverage RAD Data

We just saw evidence of widespread genotyping error in some RAD datasets. What should be clear is that not all RAD data sets have inaccurate genotype calls. But some of them have really inaccurate genotype calls. We haven’t had time to do a proper analysis of correlations of the genotyping error rates with sequencing methods and protocols, so we won’t investigate that, here.

However, it is natural to ask whether it seems likely that a program like ANGSD, (which calls genotypes probabilistically using a model not unlike the one that we developed in an earlier section) will be able to ameliorate the genotyping error situation we have encountered.

I don’t have a whole lot of experience using ANGSD, but I’ve been involved in checking some results from a recent paper (Prince et al.) out of Mike Miller’s group. They used ANGSD for most of their analyses, so we can use their data to see how ANGSD handles things.

The chinook_gatk data set above is actually the Chinook data from Prince et al. that I ran through the GATK pipeline used for the wifl data set. It is obvious that the data do not carry as much information about genotype as the wifl data.

Alongside the Chinook data, the Prince et al. paper also analyzed (in a very similar fashion) a data set from steelhead trout. We can show some ANGSD results from that.

Forcing ANGSD to Call Genotypes

ANGSD does not like to call genotypes. It prefers to compute genotype posteriors and then carry those to the downstream analyses. However, you can force it to call genotypes and then submit those to an analysis to estimate \(m\) like we did above.

I’ve done that for the steelhead data, using parameter settings identical to those used by Prince et al. for their PCA analysis.

Here is what it looks like when we do that:

The two populations above had the highest average number of individuals with called genotypes out of all the sampling locations.

When we throw these data into our \(m\)-estimation function we get:

Population Estimated \(m\)
Eel Premature 0.66
Umpqua Mature 0.69

That is quite poor. But note that for the PCA, Prince et al used a uniform prior on genotypes (meaning that, a priori, each of the three genotypes has the same probability). This type of model in ANGSD does not use the estimated allele frequency to provide a model for genotype frequencies. So, we should not be surprised that it performed so poorly in providing inferred genotypes.

However, it is worth noting that if you are inferring a lot of genotypes from a lot of different populations, this prior makes more sense than the allele frequency prior.

ANGSD with the Allele Freq Prior for Genotypes

We get a very different picture when we apply a model for the genotypes that makes use of the allele frequencies and assumes that genotypes should occur in Hardy-Weinberg proportions. In that case, here are what the observed versus expected genotype frequencies plot looks like:

Umpqua Mature

Eel Premature

That looks better than it does with the uniform prior, but it doesn’t really look that good. It certainly doesn’t look like what you would expect.

What are the consequences of this? It seems reasonable that there are a number of analyses that might be affected by unreliable inference of genotypes…and some that probably are not. That would be a good discussion item…

Subsampling Reads to Before Feeding them into ANGSD?

Disclaimer here: I am not an expert at using ANGSD, but I have applied it a few times. Most recently I used it to reproduce a lot of the work in the recent Prince et al. paper. One of the things that intrigued me (as a statistician) was their practice of randomly subsampling aligned, filtered reads out of their BAM files for each individual before analyzing the data with ANGSD. This was done, apparently, “To remove variation associated with variable sequencing depth.”" (I’m not sure how that is supposed to work. The models are such that even if you have a lot of reads from one individual, that individual will never be granted more than one genotypes’ worth of information at a locus).

For most of their analyses, they only used 60,000 alignments from Chinook and 120,000 from mykiss. Here is a plot that shows where those numbers are relative to the distribution of number of reads across individuals. The black vertical lines are at 60K and 120K for Chinook and Steelhead, respectively.

Holy Moly! That is a lot of data that is getting thrown away. (By subsampling these BAMs, they are effectively tossing out $$70% of the total number of alignmnents).

That can’t be good, can it?

A PCA of Willow Flycatchers

I was able to assess this (a little bit) by using Kristen’s Willow Flycatcher data. When I perform a PCA using her data run through her GATK pipeline (using all the reads left after alignment and filtering of PCR duplicates) we get quite strong separation between the different subspecies of WIFLs and also some evidence of geographic structuring within the subspecies:

A PCA when We Subsample to 120K Reads and Use ANGSD/ngsTools

However, we can take the same data set and ask, “What would this look like if Kristen were not super diligent in getting high read depths from high quality DNA, and so, instead, she got much lower read depths and chose to run her data through ANGSD while subsampling her BAMs to 120K reads?”

This is done by simply subsampling the BAMs to 120K reads and using ngsCovar to perform the PCA. Here is what that looks like:

Hmm…the trailii subspecies shows up as a clearly distinct cluster, but there is only limited separation between the remaining subspecies. The picture is not quite so clear as it is with all the data, it doesn’t accord well with subspecies designations and geographic structuring, and it is much harder to identify misidentified samples, etc.

Given this, I think that a good discussion topic for the week might be to explore how far one ought (or oughtn’t) go in targeting low numbers of reads, subsampling them even further, and then believing that it should all be OK because one is going to call genotypes probabilistically.

Wrap Up

Key Take Home Messages:

  1. To the Bayesian, probability is how we measure uncertainty.
  2. The posterior is proportional to the prior times the likelihood.
  3. Monte Carlo sampling from a posterior distribution makes it very easy to assess the posterior distribution of any function of the samples.
  4. MCMC is useful to Bayesians because it can simulate from the posterior without needing to compute the normalizing constant.
  5. MCMC is great, but should be used with care.
  6. In their essence, models for calling genotypes probabilistically while estimating and accounting for allele frequencies are quite simple, and make a lot of sense.
  7. There are a lot of RAD/GBS-derived data sets of genotypes that show evidence of profoundly high rates of heterozygotes being miscalled as homozygotes. It doesn’t seem out of the question that such error rates could influence downstream inferences.
  8. However, not all studies show very high genotyping error rates—high read depths and intelligent/stringent filtering can prevail.
  9. Probabilistic genotype calling is certainly a principled way to address these issues, but it is not a panacea. It still adheres to the principles of GIGO and can’t make something from nothing.
  10. Don’t fool yourself into thinking that by using probabilistic genotype calling you won’t lose anything when you shave sequencing effort down to as little as possible.
    It looks like it is possible to lose a fair bit when you go down to low read depth / coverage. Doing so in the context of whole-genome sequencing makes sense, it is worth discussing whether doing RAD seq and then throwing away a lot of your reads and read depth makes much sense.
LS0tCnRpdGxlOiAiQmF5ZXNpYW4gSW5mZXJlbmNlLCBNQ01DLCBhbmQgR2Vub3R5cGUgQ2FsbGluZzogQSBOYXJyYXRpdmUgT3V0bGluZSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKLS0tCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKIyMgQmF5ZXNpYW4gSW5mZXJlbmNlCgojIyMgUGVyc29uYWwgUHJvYmFiaWxpdHkKClRvIHVuZGVyc3RhbmQgdGhlIEJheWVzaWFuIHBhcmFkaWdtLCBpdCBpcyB1c2VmdWwgdG8gc3RhcnQgd2l0aCB0aGUgYXdhcmVuZXNzCnRoYXQgZXZlcnlvbmUgaGFzIHRoZWlyIG93biBwcm9iYWJpbGl0aWVzIGZvciBldmVudHMgb3Igb3V0Y29tZXMsIGFuZCB0aGVzZSAKcHJvYmFiaWxpdGllcyBhcmUgaW5mb3JtZWQgYnkgZWFjaCBwZXJzb24ncyBleHBlcmllbmNlLCB0aGVpciBwcmlvciBiZWxpZWZzLAp0aGUgZGF0YSB0aGF0IHRoZXkgaGF2ZSBhY2Nlc3MgdG8sIGFuZCB0aGUgaW5mZXJlbnRpYWwgcGVyc3BlY3RpdmVzIG9yIF9tb2RlbHNfCnRoYXQgdGhleSBjYW4gYnJpbmcgdG8gdGhlIHRhc2sgb2YgdW5kZXJzdGFuZGluZyBhbmQgaW5jb3Jwb3JhdGluZyB0aGUgaW5mb3JtYXRpb24gdGhhdCB0aGV5CmhhdmUgYXZhaWxhYmxlLgoKV2FpdCEgV2hhdCBraW5kIG9mIGNyYXp5IG5vdGlvbiBvZiBwcm9iYWJpbGl0eSBpcyB0aGlzPyAgTWFueSBvZiB1cyBtaWdodCBiZSAKZmFtaWxpYXIgd2l0aCB0aGUgaWRlYSBvZiBwcm9iYWJpbGl0eSBiZWluZyBpbnRlcnByZXRhYmxlIGFzIHRoZSBsb25nLXJ1biBhdmVyYWdlCmZyZXF1ZW5jeSBvZiBvdXRjb21lcyBpZiBhIHBhcnRpY3VsYXIgZXZlbnQgaXMgcmVwZWF0ZWQgbWFueSB0aW1lcy4gIEJ1dCB0aGlzIAoicGVyc29uYWwgcHJvYmFiaWxpdHkiIHBhcmFkaWdtIHNvdW5kcyBxdWl0ZSBkaWZmZXJlbnQuLi4KCkEgZ29vZCB3YXkgdG8gYXBwcm9hY2ggdGhpcyBpcyB3aXRoIHNvbWUgc2ltcGxlIGNhcmQgcGxheS4gIElmIEkgaGFuZCBvdXQKY2FyZHMgZnJvbSBhIHNodWZmbGVkIGRlY2sgdG8gZml2ZSBwZW9wbGUgaW4gdGhlIHJvb20gYW5kIHRlbGwgdGhlbSBub3QgdG8gCmxvb2sgYXQgdGhlIGNhcmRzLCBhbmQgdGhlbiBhc2sgZXZlcnlvbmUgd2hhdCB0aGUgcHJvYmFiaWxpdHkgaXMgdGhhdCB0aGUgCm5leHQgY2FyZCBvbiB0aGUgZGVjayBpcyB0aGUgYWNlIG9mIHNwYWRlcywgbW9zdCBldmVyeW9uZSB3aWxsIGhhdmUgdGhlIApzYW1lIHByb2JhYmlsaXR5IGZvciB0aGF0LiAgQnV0IGlmIHdlIGxldCB0aGUgNSBwZW9wbGUgbG9vayBhdCB0aGVpciBjYXJkcyAKYW5kIHRoZW4gYXNrIGVhY2gsIGluIHR1cm4sIHdoYXQgdGhleSBub3cgdGhpbmsgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQgdGhlCnRvcCBjYXJkIGlzIHRoZSBhY2Ugb2Ygc3BhZGVzLCB0aGV5IHdpbGwgbGlrZWx5IHVwZGF0ZSB0aGVpciBiZWxpZWZzIGJhc2VkCm9uIHRoZSBjYXJkIHRoYXQgdGhleSBwb3NzZXNzLCBhcyB3ZWxsIGFzIHRoZSByZXNwb25zZXMgb2YgYW55IGNhcmRob2xkZXJzCmJlZm9yZSB0aGVtLgoKVGhlcmUgYSBsb3Qgb2YgYXNzdW1wdGlvbnMgdGhhdCBnbyBpbnRvIHRoZXNlIGNhbGN1bGF0aW9ucy4gIFdoYXQgYXJlIHRoZXk/CgpBdCBhbnkgcmF0ZSwgaXQgaXMgZWFzeSB0byBzZWUgdGhhdCBwZW9wbGUgaGF2ZSBkaWZmZXJlbnQgcHJvYmFiaWxpdGllcyBmb3IgdGhlCnRvcCBjYXJkIGJlaW5nIGFuIGFjZSBvZiBzcGFkZXMgZGVwZW5kaW5nIG9uIGhvdyBtdWNoIGluZm9ybWF0aW9uIHRoZXkgaGF2ZS4KCiMjIyBQcm9iYWJpbGl0eSBhcyBhICJNZWFzdXJpbmcgU3RpY2siIGZvciBVbmNlcnRhaW50eQoKQSBiaWcgc3dpdGNoIGJlaW5nIG1hZGUgaGVyZSBpcyB0aGF0IHdlIGFyZSBub3cgdXNpbmcgcHJvYmFiaWxpdHkgYXMgYSB3YXkgCm9mIGV4cHJlc3Npbmcgb3IgbWVhc3VyaW5nIGVhY2ggcGVyc29uJ3MgInVuY2VydGFpbnR5IiBhYm91dCBhbiBldmVudC4gIFRoaXMKaXMgcXVpdGUgYSBkZXBhcnR1cmUgZnJvbSB0aGlua2luZyBhYm91dCBwcm9iYWJpbGl0eSBvbmx5IGFzIGEgcHJvcGVydHkgdGhhdApjYW4gYmUgZGlzY3Vzc2VkIGluIGNvbm5lY3Rpb24gd2l0aCBldmVudHMgdGhhdCB3ZSBjYW4gZW52aXNpb24gaGFwcGVuaW5nCm11bHRpcGxlIHRpbWUgKHNvIHRoYXQgd2UgbWlnaHQgZGVyaXZlIGEgbm90aW9uIG9mIHByb2JhYmlsaXR5IGFzIHRoZSBhdmVyYWdlCmZyZXF1ZW5jeSBvZiBvY2N1cnJlbmNlIG92ZXIgdmVyeSBtYW55IHRyaWFscy4pCgpUaGlzIGludGVycHJldGF0aW9uIG9mIHByb2JhYmlsaXR5IGlzIGNvbnNpZGVyYWJseSBtb3JlIGZsZXhpYmxlIHRoYW4gdGhlCiJmcmVxdWVudGlzdCIgaW50ZXJwcmV0YXRpb24sIGFuZCBpdCBpcyBhbHNvIGFscmVhZHkgZmFtaWxpYXIgdG8gbW9zdCBvZiB1czoKd2UgYXJlIGFscmVhZHkgcXVpdGUgY29tZm9ydGFibGUgd2l0aCBiZWluZyB0b2xkIHRoYXQgdGhlIHByb2JhYmlsaXR5IGl0IGlzIApnb2luZyB0byByYWluIHRvZGF5IGlzIDMwJSwgZXZlbiB0aG91Z2ggdGhlcmUgd2lsbCBvbmx5IGV2ZXIgYmUgb25lIHRvZGF5LiBXaXRoIApwcm9iYWJpbGl0eSBhcyBhIG1lYXN1cmUgb2YgdW5jZXJ0YWludHksIHlvdSBjYW4gdXNlIHByb2JhYmlsaXRpZXMgdG8gdGFsayBhYm91dAp0aGluZ3MgdGhhdCB3aWxsIG9ubHkgaGFwcGVuIG9uY2UuIFdoYXQgaXMgdGhlIHByb2JhYmlsaXR5IHRoYXQ6CgotIHRoZXJlIHdpbGwgYmUgdGhyZWUgbW9yZSBjYXRlZ29yeSA1IGh1cnJpY2FuZXMgdGhpcyBzZWFzb24/Ci0gdGhlIFJlcHVibGljYW5zIGluIENvbmdyZXNzIHdpbGwgc3VjY2VlZCBpbiByZXBlYWxpbmcgT2JhbWFjYXJlIGJlZm9yZSBTZXB0IDMwLCAyMDE3PwoKTm90IG9ubHkgdGhhdCwgYnV0IG5vdyB3ZSBjYW4gdXNlIHByb2JhYmlsaXR5IHRvIG1ha2Ugc3RhdGVtZW50cyBhYm91dCBob3cKdW5jZXJ0YWluIHdlIGFyZSBhYm91dCB0aGluZ3MgdGhhdCBhcmUgZGV0ZXJtaW5pc3RpYy4gIEZvciBleGFtcGxlOgoKKiBXaGF0IGlzIHlvdXIgcHJvYmFiaWxpdHkgdGhhdCBNb25yb3ZpYSBpcyB0aGUgY2FwaXRhbCBvZiBMaWJlcmlhPyAKClNvLCBpZiB3ZSBhcmUgdHJ5aW5nIHRvIG1lYXN1cmU6CgotIGhlaWdodCwgdGhlbiB3ZSB1c2UgY2VudGltZXRlcnMsCi0gbWFzcywgdGhlbiB3ZSB1c2Uga2lsb2dyYW1zLAotIGVsZWN0cmljYWwgcmVzaXN0YW5jZSwgd2UgdXNlIE9obXMKLSB1bmNlcnRhaW50eT8uLi53ZSB1c2UgcHJvYmFiaWxpdHkuLi4KCiMjIyBBbiBpbnRlcmVzdGluZyBkaWdyZXNzaW9uCgpQcm9iYWJpbGl0eSBhcyBhIGZpZWxkIG9mIG1hdGhlbWF0aWNhbCBzdHVkeSBkaWQgbm90IG5lY2Vzc2FyaWx5ICJncm93IHVwIiB3aXRoIHRoZQppbnRlbnQgdG8gYmUgYSB3YXkgdG8gbWVhc3VyZSB1bmNlcnRhaW50eS4gIChJdCBwYXJ0bHkgZ3JldyBvdXQgb2YgY29udGVtcGxhdGlvbgpvZiAiQm9yZWwgc3Vic2V0cyIgYW5kIG1hbnkgbXVjaCBtb3JlIGVzb3RlcmljIGNvbmNlcHRzLikgQnV0IHRoZSB3YXkgdGhhdAppdCB3YXMgZGV2ZWxvcGVkIGFzIGEgbWF0aGVtYXRpY2FsIGNvbnN0cnVjdCB0dXJucyBvdXQgdG8gYmUgcHJlY2lzZWx5IHdoYXQgCmlzIHJlcXVpcmVkIGlmIHdlIGRlc2lyZWQgdG8gZXh0ZW5kIHRoZSBzeXN0ZW0gb2YgbG9naWMgaW4gd2hpY2ggMSBtZWFucwoiYWJzb2x1dGVseSB0cnVlIiBhbmQgMCBtZWFucyAiYWJzb2x1dGVseSBmYWxzZSIgdG8gYSBsb2dpY2FsIHN5c3RlbSBpbiB3aGljaAp0aGVyZSBjb3VsZCBiZSBkZWdyZWVzIG9mIHVuY2VydGFpbmx5IGJldHdlZW4gMCBhbmQgMS4KCgojIyMgVXBkYXRpbmcgQmVsaWVmcwoKQSBjaGFyYWN0ZXJpc3RpYyBmZWF0dXJlIHRoYXQgd2Ugc2F3IHBsYXlpbmcgb3VyIGNhcmQgZ2FtZSBpcyB0aGF0IHdoZW4gbmV3CmluZm9ybWF0aW9uIGFycml2ZXMsIHBlb3BsZSB1cGRhdGUgdGhlaXIgYmVsaWVmcywgYW5kIGhlbmNlIHRoZXkgdXBkYXRlCnRoZWlyIGRlZ3JlZSBvZiB1bmRlcnRhaW50eSAodGhlaXIgcHJvYmFiaWxpdGVzLi4uKS4KCkNsZWFybHksIGlmIHdlIHdhbnQgdG8gYmUgQmF5ZXNpYW5zIGFuZCB1c2UgcHJvYmFiaWxpdHkgdG8gZXhwcmVzcyB1bmNlcnRhaW50eQphYm91dCB0aGluZ3MsIHdlIG5lZWQgYSBjb2hlcmVudCwgcmVhc29uYWJsZSB3YXkgdG8gdXBkYXRlIG91ciBiZWxpZWZzLiAgVGhpcyBpcwpkb25lIHVzaW5nIGJhc2ljIHByaW5jaXBsZXMgZnJvbSBwcm9iYWJpbGl0eSwgd2hpY2ggd2VyZSBkZXNjcmliZWQgKGZvciBpbmZlcmVudGlhbApwdXJwb3NlcykgYnkgdGhlIFJldmVyZW5kIFRob21hcyBCYXllcyAoYm9ybiAxNzAyKSwgYW5kIGlzIGhlbmNlIGtub3duIGFzIApCYXllcycgTGF3LCBvciBCYXllcyBUaGVvcmVtLiAgCgpCYXllcyBUaGVvcmVtIGlzIHR5cGljYWxseSBleHByZXNzZWQgaW4gYW4gZXF1YXRpb24gdGhhdCBwcm9iYWJseSBmZWVscwpwcmV0dHkgb3BhcXVlIHRvIG1vc3QgcGVvcGxlIChpdCBjZXJ0YWlubHkgZGlkIHRvIG1lIHdoZW4gSSB3YXMgYSB5b3VuZwpiaW9sb2d5IGdyYWR1YXRlIHN0dWRlbnQuKSAgSSByZW1lbWJlcmVkIHNlZWluZyBpdCBzb21ldGhpbmcgbGlrZSB0aGlzOgpzdXBwb3NlIHRoYXQgeW91IGhhdmUgb2JzZXJ2ZWQgc29tZSBkYXRhICREJCwgYW5kIHRoYXQgeW91IGhhdmUgJGskIGRpZmZlcmVudApoeXBvdGhlc2VzIGZvciBpdHMgb2NjdXJyZW5jZSwgYW5kIGZvciBlYWNoIGh5cG90aGVzaXMsICRpJCwgIHlvdSBjYW4gY29tcHV0ZQokUChEfEhfaSkkIHRoZSBwcm9iYWJpbGl0eSBvZiBvYnNlcnZpbmcgRCBnaXZlbiB0aGF0IGh5cG90aGVzaXMgJGkkIGlzIHRydWUuCgpUaGUgcG9zdGVyaW9yIHByb2JhYmlsaXR5IG9mIGEgY2VydGFpbiBoeXBvdGhlc2lzICRIX2kkIGdpdmVuICREJCBpcyB0aGVuOgokJApQKEhfaXxEKSA9IFxmcmFje1AoRHxIX2kpUChIX2kpfXtcc3VtX3tqID0gMX1eayBQKER8SF9qKVAoSF9qKX0KJCQKWWFjayEgIExldCdzIHNlZSBpZiB3ZSBjYW4gZmluZCBhbiBlYXNpZXIgd2F5IHRvIHRhbGsgYWJvdXQgdGhpcyEKCldlIHdpbGwgKGF0IGxlYXN0IEkgaG9wZSBpdCB3aWxsIGJlIGVhc2llcikgYW5kIHdlIHdpbGwgZG8gc28gd2hpbGUgdGFsa2luZwphYm91dCBhIHNpbXBsZSBwcm9ibGVtIHRoYXQgd2UgY2FuIGJ1aWxkIHVwb24gdG8gbWFrZSBtb3JlIGNvbXBsZXggbW9kZWxzOgplc3RpbWF0aW5nIHRoZSBmcmVxdWVuY3kgb2YgYW4gYWxsZWxlIGluIGEgcG9wdWxhdGlvbi4KCiMjIyBBIFNpbXBsZSBDb25kaXRpb25hbCBQcm9iYWJpbGl0eSBhbmQgREFHcwoKQWxtb3N0IGFsbCBvZiB0aGUgcHJvYmFiaWxpdGllcyB0aGF0IHdlIHRhbGsgYWJvdXQgcm91dGluZWx5IGFyZQpfY29uZGl0aW9uYWwgcHJvYmFiaWxpdGllc18uICBUaGF0IGlzLCB0aGV5IGFyZSBwcm9iYWJpbGl0aWVzIHRoYXQgYXJlCmV4cHJlc3NlZCBjb25kaXRpb25hbCBvbiBzb21lIG90aGVyIHZhcmlhYmxlIG9yIHRoaW5nIHRha2luZyBhIGNlcnRhaW4gdmFsdWUuIAoKSGVyZSB3ZSB3aWxsIHN0YXJ0IGJlYXRpbmcgdG8gZGVhdGggYW4gZXhhbXBsZSB0aGF0IGludm9sdmVzIGdlbm90eXBlIGFuZCAKYWxsZWxlIGZyZXF1ZW5jaWVzLCBidXQgYmVhciB3aXRoIHVzLCBiZWNhdXNlIHdlIHdpbGwgZW5kIHVwIHVzaW5nIHdoYXQgd2UKbGVhcm4gZnJvbSB0aGlzIGV4YW1wbGUtLS1hbmQgYnVpbGRpbmcgdXBvbiBpdC0tLXRocm91Z2hvdXQgdGhpcwpsZWN0dXJlLiAKCklmIHdlIGFzayBhYm91dCB0aGUgcHJvYmFiaWxpdHkgdGhhdCBhbiBpbmRpdmlkdWFsIGlzIGhvbW96eWdvdXMKZm9yIHRoZSAkQSQgYWxsZWxlLCB3ZSBtaWdodCBmaXJzdCBoYXZlIHRvIG1ha2UgYW4gYXNzdW1wdGlvbiB0aGF0IHRoZSBwb3B1bGF0aW9uCmlzIGluIEhhcmR5LVdlaW5iZXJnIGVxdWlsaWJyaXVtLCBhbmQgdGhlbiB3ZSBhbHNvIG5lZWQgdG8gYXNzZXNzIHRoaXMgcHJvYmFiaWxpdHkKX2NvbmRpdGlvbmFsIG9uXyB0aGUgZnJlcXVlbmN5IG9mIHRoZSAkQSQgYWxsZWxlIGJlaW5nICRwX0EkIGluIHRoZSBwb3B1bGF0aW9uLgoKU28sIHdlIGNvdWxkIHdyaXRlOgokJApQKFxtYm94e0luZGl2aWR1YWwgaXMgQUF9fnx+cF9BKSA9IHBfQV4yCiQkCklmIHdlIGtuZXcgdGhlIHZhbHVlIG9mICRwX0EkLCB0aGVuIGl0IHdvdWxkIGJlIGVhc3kgdG8gZG8gdGhpcyBjYWxjdWxhdGlvbi4gIFRoaXMgaXMKYW4gZXhhbXBsZSBvZiBwcm9iYWJpbGl0eSAicnVubmluZyBmb3J3YXJkIi4gIFdlIHdpbGwgc2VlIGxhdGVyIHRoYXQgd2hlbgp3ZSB3YW50IHRvIGRvIGluZmVyZW5jZSB3ZSBuZWVkIHRvICJydW4gcHJvYmFiaWxpdHkgYmFja3dhcmQiICh3aGljaCBpcyB3aGF0IApCYXllcycgVGhlb3JlbSBsZXRzIHVzIGRvLikgCgpSZWNhbGwgdGhhdCBIV0UgbWVhbnMgdGhhdCB0aGUgYWxsZWxpYyB0eXBlIG9mIHRoZSB0d28gZ2VuZSBjb3BpZXMgY2FycmllZCBpbiAKYW4gaW5kaXZpZHVhbCBhcmUgY29uZGl0aW9uYWxseSBpbmRlcGVuZGVudCBnaXZlbiB0aGUgYWxsZWxlIGZyZXF1ZW5jeS4gIEhlbmNlLCAKdGhlIHByb2JhYmlsaXR5IG9mIGRyYXdpbmcgdGhlIGZpcnN0IGdlbmUgY29weSBhcyBhbiBBIGlzICRwX0EkLCBhbmQgdGhlIHByb2JhYmlsaXR5CnRoYXQgdGhlIHNlY29uZCBnZW5lIGNvcHkgaXMgZHJhd24gYXMgYW4gQSAoZ2l2ZW4gdGhhdCB0aGUgZmlyc3Qgd2FzIGFuICRBJCksIGlzIGFsc28gJHBfQSQuClNvIHRoZSBwcm9iYWJpbGl0eSB0aGF0IHRoZSBpbmRpdmlkdWFsIGlzICRBQSQgaXMgdGhlIHByb2R1Y3Qgb2YgdGhvc2U6ICRwX0FeMiQuCgpXZSBjYW4gZHJhdyBhIGRpYWdyYW0gb2YgdGhhdCBjYWxsZWQgYW4gYWN5Y2xpYyBkaXJlY3RlZCBncmFwaCAob3IgREFHKS4gIFRoZXNlIGFyZQp2ZXJ5IGhlbHBmdWwgZm9yIHZpc3VhbGl6aW5nIG1vZGVscyBhcyB0aGV5IGJlY29tZSBtb3JlIGNvbXBsZXguICAKCiFbXShkaWFncmFtcy9zaW1wbGUxLnBuZykKClRoZSBrZXkgdGhpbmcgdG8ga25vdyBhYm91dCBEQUdzIGlzIHRoYXQgdGhleSBleHByZXNzIHRoZSBmYWN0b3JpemF0aW9uIG9mIAp0aGUgam9pbnQgcHJvYmFiaWxpdHkgb2YgdGhlIHZhcmlhYmxlcyBpbnRvIGEgcHJvZHVjdCBvZiBjb25kaXRpb25hbApwcm9iYWJpbGl0aWVzLiAoU3BlY2lmaWNhbGx5IGEgcHJvZHVjdCBvdmVyIG5vZGVzIG9mIHRoZSBwcm9iYWJpbGl0eSBvZgplYWNoIG5vZGUgY29uZGl0aW9uYWwgb24gaXRzIHBhcmVudHMuKSAgCgpGcm9tIHRoZSB3YXkgCnRoZSBEQUcgaXMgZHJhd24gYWJvdmUsIGl0IGlzIGNsZWFyIHRoYXQgd2UgY2FuIHNheToKJCQKUChcbWJveHtJbmRpdmlkdWFsIGlzIEFBfX58fnBfQSkgPSBQKFlfMSA9IEF+fH5wX0EpIFAoWV8yID0gQX58fnBfQSkgPSBwX0EgXGNkb3QgcF9BID0gIHBfQV4yCiQkCgpIZXJlIGlzIGEgcXVpY2sgc3VtbWFyeSBvZiBEQUdzOgoKIVtdKHNsaWRlX2dyYWJzL2RhZy1ub3Rlcy5wbmcpCgoKCiMjIyBBIFBpY3R1cmUgb2YgSW5mZXJlbmNlIG9mIEFsbGVsZSBGcmVxdWVuY2llcyBGcm9tIGEgU2FtcGxlIG9mIEdlbm90eXBlcwoKVGhlIHByZXZpb3VzIGRpc2N1c3Npb24gYXNzdW1lZCB0aGF0IHRoZSBhbGxlbGUgZnJlcXVlbmN5IHdhcyBrbm93biwgYW5kIHdlIHdhbnRlZAp0byBjb21wdXRlIHRoZSBwcm9iYWJpbGl0eSBvZiBhbiBpbmRpdmlkdWFsJ3MgKHVua25vd24pIGdlbm90eXBlLiAgRm9yIHRoYXQgZXhlcmNpc2UsCndlIHdlcmUgcnVubmluZyBmcm9tIGFuIG9ic2VydmVkIG5vZGUgaW4gdGhlIGdyYXBoICgkcF9BJCkgdG8gdHdvIHVub2JzZXJ2ZWQgb25lcy4gIFRoaXMgCmlzIGEgc3RyYWlnaHRmb3J3YXJkIGNhbGN1bGF0aW9uIG9mIHByb2JhYmlsaXRpZXMuCgpNdWNoIG9mIHRoZSB0aW1lIGluIHNjaWVuY2UsIHdlIGFyZSBhYmxlIHRvIG9ic2VydmUgdGhlIHZhcmlhYmxlcyBhdCB0aGUgZW5kIG9mIHRoZSAKYXJyb3dzIGluIGEgREFHLCBhbmQgd2Ugd2FudCB0byBtYWtlIGluZmVyZW5jZXMgYWJvdXQgdGhlIHZhcmlhYmxlcyB0aGF0IGFyZSAidXBzdHJlYW0iCm9mIHRoZW0gaW4gYSBEQUcuIEZvciBhbiBleGFtcGxlLCBsZXQgdXMgY29uc2lkZXIgdGhlIHNpdHVhdGlvbiBpbiB3aGljaCB3ZSBzYW1wbGUgJE4kCmRpcGxvaWRzIGFuZCBvYnNlcnZlIHRoZWlyIGdlbm90eXBlcywgYW5kIGZyb20gdGhhdCB3ZSB3YW50IHRvIGluZmVyIHRoZSBhbGxlbGUgZnJlcXVlbmN5CiRwX0EkLiAgCgpUaGUgREFHIGZvciB0aGlzIHNpdHVhdGlvbiBsb29rcyBsaWtlIHRoaXM6CgohW10oZGlhZ3JhbXMvaW5mZXIxLnBuZykKCkZyb20gd2hpY2ggaXQgaXMgaW1tZWRpYXRlbHkgYXBwYXJlbnQgdGhhdCB0aGUgcHJvYmFiaWxpdHkgb2YgYWxsIHRoZSAKZGF0YSwgc2F5ICRcYm9sZHN5bWJvbHtZfSA9IChZX3sxLDF9LCBZX3sxLDJ9LCBZX3syLDF9LCBcbGRvdHMsIFlfe04sMX0sIFlfe04sMn0pJAppcyBqdXN0IGEgc2ltcGxlIHByb2R1Y3Qgb2YgQmVybm91bGxpIHJhbmRvbSB2YXJpYWJsZXM6CiQkClAoXGJvbGRzeW1ib2x7WX1+fH5wX0EpID0gXHByb2Rfe2k9MX1eTiBQKFlfe2ksMX1+fH5wX0EpUChZX3tpLDJ9fnx+cF9BKSAKJCQKSW4gZmFjdCwgaWYgd2UgZGVmaW5lIGVhY2ggJFkkIHRvIGJlIDAgb3IgMSBhcyBmb2xsb3dzOgokJApcYmVnaW57YWxpZ259ClkgPSAwICYgfn5+fn5cbWJveHt3aXRoIHByb2JhYmlsaXR5fSB+fn4gMSAtIHBfQSAmIH5+XG1ib3h7KGkuZS4sIGl0J3MgYW59fmEpIFxcClkgPSAxICYgfn5+fn5cbWJveHt3aXRoIHByb2JhYmlsaXR5fSB+fn4gcF9BICYgfn5cbWJveHsoaS5lLiwgaXQncyBhbn1+QSkKXGVuZHthbGlnbn0KJCQKVGhlbiBpdCBpcyBub3QgdG9vIGhhcmQgdG8gc2VlIHRoYXQKJCQKUChcYm9sZHN5bWJvbHtZfX58fnBfQSkgPSBwX0Fee1xzdW0gWV97aSxqfX0gKDEtIHBfQSleezJOIC0gXHN1bSBZX3tpLGp9fQokJApUaGlzIGlzIGEgcHJvYmFiaWxpdHkgZnVuY3Rpb24uICBCdXQgaWYgeW91IGNvbnNpZGVyIHRoaXMgYXMgYSBmdW5jdGlvbiBvZiAkcF9BJCB3aXRoIAokXGJvbGRzeW1ib2x7WX0kIGNvbnNpZGVyZWQgYXMgZml4ZWQsIHRoZW4gaXQgaXMgb2Z0ZW4gcmVmZXJyZWQgdG8gYXMgdGhlIApfbGlrZWxpaG9vZCBmdW5jdGlvbl8uCgoKIyMjIE1ldGhvZHMgb2YgSW5mZXJlbmNlCgpXZSBzZWUgdGhhdCB3ZSBhcmUgdHJ5aW5nIHRvIGxlYXJuIHNvbWV0aGluZyAobWFrZSBpbmZlcmVuY2UpIGFib3V0IAokcF9BJCAoYW4gdW5zaGFkZWQvdW5vYnNlcnZlZCB2YXJpYWJsZSkgdGhhdCBpcyB1cHN0cmVhbSBvZiBvdXIgb2JzZXJ2ZWQKZGF0YS4gIFRoaXMgaXMgaW5mZXJlbmNlLiAgCgpUbyBwdXQgc29tZSBjb25jcmV0ZSBudW1iZXJzIG9uIHRoaXMuICBMZXQncyBzYXkgdGhhdCAkTiA9IDEwMCQgZGlwbG9pZHMsIGFuZCAKb3V0IG9mIHRoZSAyMDAgZ2VuZSBjb3BpZXMsIDczIG9mIHRoZW0gd2VyZSAkQSQgYWxsZWxlcy4KClRoZXJlIGFyZSBsb3RzIG9mIHdheXMgdGhhdCB5b3UgbWlnaHQgZG8gaW5mZXJlbmNlLiAgSGVyZSBhcmUgYSBmZXc6CgotIF9NZXRob2Qgb2YgdGhlIEV5ZWJhbGxfOiBMb29rIGF0IHlvdXIgc2FtcGxlIGFuZCBzdXJtaXNlIHRoYXQgdGhlIGZyYWN0aW9uIG9mIEEgYWxsZWxlcwppbiB0aGUgc2FtcGxlIGlzIGEgZ29vZCBlc3RpbWF0ZSBvZiB0aGUgZnJhY3Rpb24gb2YgJEEkIGFsbGVsZXMgaW4gdGhlIHBvcHVsYXRpb24uCi0gX01ldGhvZCBvZiBNb21lbnRzXzogVGhpcyBmb3JtYWxpemVzIHRoZSAiTWV0aG9kIG9mIHRoZSBFeWViYWxsIiBieSBlcXVhdGluZyB0aGUgc2FtcGxlIG1lYW4Kd2l0aCB0aGUgcG9wdWxhdGlvbiBtZWFuLgotIF9NZXRob2Qgb2YgTWF4aW11bSBMaWtlbGlob29kXzogRmluZCB0aGUgdmFsdWUgb2YgJHBfQSQgdGhhdCBtYXhpbWl6ZXMgdGhlIHByb2JhYmlsaXR5IG9mCm9ic2VydmluZyB5b3VyIHNhbXBsZS4gIEluIG90aGVyIHdvcmRzLCBjb25zaWRlciB0aGUgcHJvYmFiaWxpdHkKJFAoXGJvbGRzeW1ib2x7WX1+fH5wX0EpJCBhcyBhIGZ1bmN0aW9uIG9mICRwX0EkLCB3aGVyZSB0aGUgZGF0YSwKJFxib2xkc3ltYm9se1l9JCwgYXJlIGZpeGVkLCBhbmQgdGhlbiBmaW5kIHRoZSB2YWx1ZSBvZiAkcF9BJCB0aGF0IG1heGltaXNlcyB0aGF0IF9saWtlbGlob29kXyAKZnVuY3Rpb24uCgpBbGwgb2YgdGhvc2UgbWV0aG9kcyBnaXZlIHlvdSBhIF9wb2ludCBlc3RpbWF0ZV8gZm9yICRwX0EkLiAgQW4gYWx0ZXJuYXRpdmUgdG8KdGhlc2UgbWV0aG9kcyBpcyB0byBiZSBCYXllc2lhbiBhbmQgZmluZCB0aGUgX3Bvc3RlcmlvciBkaXN0cmlidXRpb25fIGZvciAkcF9BJApjb25kaXRpb25hbCBvbiB0aGUgZGF0YSwgJFxib2xkc3ltYm9se1l9JC4gCgpCZWZvcmUgd2UgZG8gdGhpcywgd2UgYXJlIGdvaW5nIHRvIHdhbnQgdG8gcmV2aWV3IGEgdmlldyBzaW1wbGUgZmFjdHMgYWJvdXQKbWFyZ2luYWwsIGNvbmRpdGlvbmFsLCBhbmQgam9pbnQgcHJvYmFiaWxpdGllcy4KCiMjIyBTb21lIGltcG9ydGFudCBwcm9iYWJpbGl0eSBydWxlcwoKSWYgeW91IGhhdmUgdHdvIGRpZmZlcmVudCBldmVudHMgJEEkIChubyByZWxhdGlvbiwgbmVjZXNzYXJpbHksIHRvIHRoZSBiaWctQSBhbGxlbGUgKSBhbmQgJEIkLAphbmQgd2UgdXNlICRBJCBhbmQgJEIkIHRvIHJlZmVyIHRvIHRoZSBvdXRjb21lIG9mIGVhY2gsIHRoZW4gaGVyZSBhcmUgc29tZSB0aGluZ3MKdGhhdCBhcmUgYWx3YXlzIHRydWU6CgotICRQKEEpJCBhbmQgJFAoQikkIGFyZSByZWZlcnJlZCB0byBhcyBtYXJnaW5hbCBwcm9iYWJpbGl0aWVzLgotIFRoZSBqb2ludCBwcm9iYWJpbGl0eSBvZiAkQSQgYW5kICRCJCBpcyB0aGUgcHJvYmFiaWxpdHkgdGhhdCB0aG9zZSB0d28gb3V0Y29tZXMKb2NjdXJyZWQsIGFuZCBpdCBjYW4gYmUgY29tcHV0ZWQgYXMgdGhlIHByb2R1Y3Qgb2YgYSBtYXJnaW5hbCBwcm9iYWJpbGl0eSBhbmQgYSBjb25kaXRpb25hbApwcm9iYWJpbGl0eSwgaW4gdHdvIGRpZmZlcmVudCB3YXlzOgokJApQKEEsQikgPSBQKEEpUChCfnx+QSkgPSBQKEIpUChBfnx+QikKJCQKLSBUaGlzIG1lYW5zIHRoYXQgY29uZGl0aW9uYWwgcHJvYmFiaWxpdGllcyBjYW4gYmUgY29tcHV0ZWQgZnJvbSB0aGUgam9pbnQgcHJvYmFiaWxpdHk6CiQkClAoQX58fkIpID0gXGZyYWN7UChBLEIpfXtQKEIpfX5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fgpQKEJ+fH5BKSA9IFxmcmFje1AoQSxCKX17UChBKX0KJCQKCkFuZCB0aGF0IGxlYWRzIHVzIHRvIGFuIGV4cHJlc3Npb24gZm9yIEJheWVzIFRoZW9yZW0gdGhhdCBJIGZpbmQgZWFzaWVyIHRvIGdyb2sgb3V0OgokJApQKEF+fH5CKSBccHJvcHRvIFAoQSwgQikKJCQKd2hlcmUgd2UgYXJlIHRoaW5raW5nIG9mICRQKEF8QikkIGFzIGEgZnVuY3Rpb24gb2YgJEEkIHdpdGggJEIkIGZpeGVkLiAgSXQgaXMgdHlwaWNhbGx5CmVhc3kgdG8gY29tcHV0ZSB0aGUgam9pbnQgcHJvYmFiaWxpdHksICRQKEEsQikkLCBhbmQgdGhlbiB5b3UganVzdCBoYXZlIHRvIHJlbWVtYmVyIHRoYXQKJFAoQX58fkIpJCwgc2luY2UgaXQgaXMgYSBwcm9iYWJpbGl0eSBvbiAkQSQsIG11c3Qgc3VtIHRvIG9uZSBvdmVyIGFsbCBwb3NzaWJsZSB2YWx1ZXMgb2YgJEEkLgoKVGhlIHNhbWUgaXMgdHJ1ZSBmb3I6CiQkClAoQn58fkEpIFxwcm9wdG8gUChBLCBCKQokJAoKIyMjIEJheWVzaWFuIEluZmVyZW5jZSBmb3IgJHBfQSQKCkJhY2sgdG8gb3VyIHNpbXBsZSBleGFtcGxlLiAgSWYgd2Ugd2FudCB0byBkbyBCYXllc2lhbiBpbmZlcmVuY2UgZm9yICRwX0EkIHdlIApzZWUgdGhhdCB3ZSB3aWxsIHdhbnQgdG8gY29tcHV0ZSB0aGUgX3Bvc3RlcmlvciBwcm9iYWJpbGl0eV86CiQkClAocF9BfFxib2xkc3ltYm9se1l9KQokJAp3aGljaCAgd2Ugbm93IGtub3cgaXMgZ29pbmcgdG8gYmUgcHJvcG9ydGlvbmFsIHRvIHRoZSBfam9pbnQgcHJvYmFiaWxpdHlfOgokJApQKHBfQSxcYm9sZHN5bWJvbHtZfSkKJCQKYW5kIHdoYXQgd2UgY3VycmVudGx5IGhhdmUgYXQgb3VyIGRpc3Bvc2FsIGlzIHRoZSBfbGlrZWxpaG9vZF86CiQkClAoXGJvbGRzeW1ib2x7WX1+fH5wX0EpCiQkCldlIGNvdWxkIGdldCB0aGUgam9pbnQgcHJvYmFiaWxpdHkgYnkgdXNpbmcgdGhlIGxpa2VsaWhvb2QgaW4gdGhlIHByb2R1Y3Q6CiQkClAocF9BLFxib2xkc3ltYm9se1l9KSA9IFAoXGJvbGRzeW1ib2x7WX1+fH5wX0EpIFAocF9BKQokJApCdXQgd2hhdCBpcyB0aGlzICRQKHBfQSkkPyEKCkl0IGlzIHRoZSBfcHJpb3IgZGlzdHJpYnV0aW9uXyBmb3IgJHBfQSQuICBJdCBpcyBhCm5lY2Vzc2FyeSBpbmdyZWRpZW50IHRvIGJlIGFibGUgdG8gdXNlIHRoZSBsaWtlbGlob29kIHRvIGNvbXB1dGUgdGhlCmpvaW50IHByb2JhYmlsaXR5IChhbmQsIGhlbmNlLCB0aGUgcG9zdGVyaW9yIHByb2JhYmlsaXR5KSwgYW5kIHdlIGVudmlzaW9uCml0IGFzIGEgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uIHRoYXQKZXhwcmVzc2VzIG91ciBkZWdyZWUgb2YgYmVsaWVmIGFib3V0ICRwX0EkIF9iZWZvcmUgd2UgbG9vayBhdCB0aGUgZGF0YV8uCgpOb3RlIHRoYXQgdGhpcyBhbGwgYm9pbHMgZG93biB2ZXJiYWxseSB0bzogKipUaGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBpcyAKcHJvcG9ydGlvbmFsIHRvIHRoZSBwcmlvciB0aW1lcyB0aGUgbGlrZWxpaG9vZCoqLiAKCgojIyMgQSBmYW1pbHkgb2YgcHJpb3JzIGZvciAkcF9BJAoKU2luY2UgJHBfQSQgaXMgYSBwcm9wb3J0aW9uLCBhbiBvYnZpb3VzIGNob2ljZSBmb3IgcHJpb3Igd291bGQKYmUgYSBiZXRhIGRpc3RyaWJ1dGlvbi4gIFRoZSBiZXRhIGRpc3RyaWJ1dGlvbiBnaXZlcyBhIGNvbnRpbnVvdXMgcHJpb3IKZGlzdHJpYnV0aW9uIG9uIGEgdmFsdWUgdGhhdCBpcyBiZXR3ZWVuIDAgYW5kIDEuICBJdCBoYXMgdHdvIHBhcmFtZXRlcnMsCm9mdGVuIGNhbGxlZCAkXGFscGhhXzEkIGFuZCAkXGFscGhhXzIkLiAgSGVyZSBhcmUgc29tZSBleGFtcGxlczoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQp4cyA8LSBzZXEoMCwxLCBieSA9IDAuMDAxKQphdGliIDwtIGxpc3QoCiAgYGExID0gMS8xMDsgIGEyID0gMS8xMGAgPSB0aWJibGUocF9BID0geHMsIGRlbnNpdHkgPSBkYmV0YSh4cywgMC4xLCAwLjEpKSwKICBgYTEgPSAxLzI7ICBhMiA9IDEvMmAgPSB0aWJibGUocF9BID0geHMsIGRlbnNpdHkgPSBkYmV0YSh4cywgMC41LCAwLjUpKSwKICBgYTEgPSAxOyAgYTIgPSAxYCA9IHRpYmJsZShwX0EgPSB4cywgZGVuc2l0eSA9IGRiZXRhKHhzLCAxLCAxKSksCiAgYGExID0gNTsgIGEyID0gNWAgPSB0aWJibGUocF9BID0geHMsIGRlbnNpdHkgPSBkYmV0YSh4cywgNSwgNSkpLAogIGBhMSA9IDEwOyAgYTIgPSAyYCA9IHRpYmJsZShwX0EgPSB4cywgZGVuc2l0eSA9IGRiZXRhKHhzLCAxMCwgMikpCikgJT4lCiAgYmluZF9yb3dzKC5pZCA9ICJwYXJhbWV0ZXJzIikKCmcgPC0gZ2dwbG90KGF0aWIsIGFlcyh4ID0gcF9BLCB5ID0gZGVuc2l0eSwgY29sb3VyID0gcGFyYW1ldGVycykpICsKICBnZW9tX2xpbmUoKSArCiAgeWxpbSgwLCA0LjMpCgoKZ2dzYXZlKGcsIGZpbGVuYW1lID0gImZpZ3VyZXMvYmV0YV9kZW5zaXRpZXMucGRmIiwgd2lkdGggPSA3LCBoZWlnaHQgPSA1KQoKZwpgYGAKClRoZSBiZXRhIGRlbnNpdHkgZm9yIGEgcmFuZG9tIHZhcmlhYmxlICRYJCBoYXMgdGhlIGZvcm06CiQkCnAoeCB8IFxhbHBoYV8xLCBcYWxwaGFfMikgPSBcZnJhY3tcR2FtbWEoXGFscGhhXzEgKyBcYWxwaGFfMil9e1xHYW1tYShcYWxwaGFfMSlcR2FtbWEoXGFscGhhXzIpfQp4XntcYWxwaGFfMSAtIDF9KDEteClee1xhbHBoYV8yIC0gMX0KJCQKVGhlIHBhcnQgdGhhdCBsb29rcyBoYWlyeSBpcyBhIGZldyBHYW1tYSBmdW5jdGlvbnMuICBEb24ndCB3b3JyeSBhYm91dCB0aG9zZS0tLWl0CmlzIGEgY29uc3RhbnQuICBUaGUgaW1wb3J0YW50IHBhcnQgKHRoZSAia2VybmVsIiwgYXMgdGhleSBzYXkuLi4pIGlzOgokJAp4XntcYWxwaGFfMSAtIDF9KDEteClee1xhbHBoYV8yIC0gMX0KJCQKT3IsIGlmIHdlIHdhbnRlZCB0aGlzIHRvIGEgYmUgYSBwcmlvciBvbiAkcF9BJCwgdGhlIHByaW9yIHdvdWxkIGJlIHByb3BvcnRpb25hbCB0bzoKJCQKe3BfQX1ee1xhbHBoYV8xIC0gMX0oMS1wX0EpXntcYWxwaGFfMiAtIDF9CiQkCkFuZCwgaWYgd2Ugd2FudGVkIHRvIGJlIGV2ZW4gbW9yZSBzcGVjaWZpYywgd2UgY291bGQgY2hvb3NlICRcYWxwaGFfMSA9IFxhbHBoYV8yID0gMSQgdG8KZ2l2ZSBvdXJzZWx2ZXMgYSB1bmlmb3JtIHByaW9yIHdoaWNoIGlzIHByb3BvcnRpb25hbCB0byAxOgokJApQKHBfQSkgXHByb3B0byB7cF9BfV57MSAtIDF9KDEtcF9BKV57MSAtIDF9ID0ge3BfQX1eezB9KDEtcF9BKV57MH0gPSAxCiQkCgoKIyMjIEEgR3JhcGhpY2FsIEFzaWRlCgpKdXN0IHdhbnRpbmcgdG8gcG9pbnQgb3V0IHRoYXQgaWYgeW91IHdhbnQgdG8gYmUgYSBCYXllc2lhbiwgeW91IApjYW4ndCBoYXZlIGFueSB1bm9ic2VydmVkIG5vZGVzIG9uIHlvdXIgREFHIHRoYXQgZG9uJ3QgaGF2ZSBhbnkgcGFyZW50cy4KVGhvc2UgcHJpb3JzIHRoYXQgeW91IHVzZS9hY2NlcHQvYXNzdW1lIGFyZSBhbHdheXMgdGhlIHVwcGVybW9zdCBub2RlcwppbiBhIERBRy4gIEkgdXN1YWxseSB1c2UgZ3JheSBub2RlcyB0byBkZW5vdGUgdGhlbS4gRm9yIGV4YW1wbGUsIGhlcmUgaXMgdGhlCkRBRyBmb3IgdGhlIEJheWVzaWFuIHZlcnNpb24gb2YgdGhlIHByZXZpb3VzbHkgc2hvd24gREFHOgoKIVtdKGRpYWdyYW1zL2luZmVyMS13aXRoLXByaW9yLnBuZykKCgoKIyMjIFRoZSBwb3N0ZXJpb3IgZm9yICRwX0EkCgpOb3cgdGhhdCB3ZSBoYXZlIGEgY2hvaWNlIGZvciBvdXIgcHJpb3IsICRQKHBfQSkkLCB3ZSBjYW4gZWFzaWx5IGZpbmQgc29tZXRoaW5nIHRoYXQKaXMgcHJvcG9ydGlvbmFsIHRvIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uLiAgV2hhdCBpcyBwcm9wb3J0aW9uYWwgdG8gdGhlIHBvc3RlcmlvcgpkaXN0cmlidXRpb24/IFJlbWVtYmVyLCAqKlRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIGlzIApwcm9wb3J0aW9uYWwgdG8gdGhlIHByaW9yIHRpbWVzIHRoZSBsaWtlbGlob29kKiogKHdoaWNoLCBkb24ndCBmb3JnZXQsIGlzIHRoZQpfam9pbnRfIHByb2JhYmlsaXR5KS4gIFJlbWVtYmVyIHRoYXQgdGhlIGxpa2VsaWhvb2QgbG9va3MgbGlrZToKJCQKUChcYm9sZHN5bWJvbHtZfX58fnBfQSkgPSBwX0Fee1xzdW0gWV97aSxqfX0gKDEtIHBfQSleezJOIC0gXHN1bSBZX3tpLGp9fQokJApBbmQsIGluIG91ciBleGFtcGxlLCB0aGUgbnVtYmVyIG9mICRBJCBhbGxlbGVzIGlzIDczIChvdXQgb2YgMjAwKSwgc28KJFxzdW0gWV97aSxqfSA9IDczJCBhbmQgJDJOIC0gXHN1bSBZX3tpLGp9ID0gIDEyNyQuCgpTaW5jZSB3ZSBhcmUgb25seSBnb2luZyB0byB3b3JyeSBhYm91dCBmaW5kaW5nIHNvbWV0aGluZyB0aGF0IHRoZQpwb3N0ZXJpb3IgcHJvYmFiaWxpdHkgaXMgcHJvcG9ydGlvbmFsIHRvLCB3ZSBjYW4gZHJvcCBhbnkgY29uc3RhbnRzIGFuZCAKd2UgZ2V0IHRoaXMgZm9yIHRoZSBwcmlvciB0aW1lcyB0aGUgbGlrZWxpaG9vZDoKJCQKXGJlZ2lue2FsaWdufQpQKHBfQX58flxib2xkc3ltYm9se1l9KSAmXHByb3B0byB7cF9BfV57MH0oMS1wX0EpXnswfSBcdGltZXMgcF9BXns3M30oMS1wX0EpXnsxMjd9IFxcCiAgJiBccHJvcHRvIHBfQV57NzN9KDEtcF9BKV57MTI3fSBcXAogICYgXHByb3B0byBwX0Feezc0IC0gMX0oMS1wX0EpXnsxMjggLSAxfSBcXApcZW5ke2FsaWdufQokJAp3aGljaCBpcyBwcmVjaXNlbHkgdGhlIGtlcm5lbCBvZiBhIGJldGEgZGlzdHJpYnV0aW9uIHdpdGggcGFyYW1ldGVycyAKNzQgYW5kIDEyOC4gIAoKQWhhISBTbywgdGhlIHBvc3RlcmlvciBoZXJlIGlzIGEgYmV0YSBkaXN0cmlidXRpb24gd2l0aCAkXGFscGhhXzEgPSA3NCQKYW5kICRcYWxwaGFfMiA9IDEyOCQuICBXZSBjYW4gcGxvdCB0aGF0IGlmIHdlIHdhbnQ6CmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp4cyA8LSBzZXEoMCwgMSwgYnkgPSAwLjAwMSkKYnRpYiA8LSB0aWJibGUocF9BID0geHMsCiAgICAgICAgICAgICAgIGRlbnNpdHkgPSBkYmV0YSh4cywgNzQsIDEyOCkpCmcgPC0gZ2dwbG90KGJ0aWIsIGFlcyh4ID0gcF9BLCB5ID0gZGVuc2l0eSkpICsKICBnZW9tX2xpbmUoKSArCiAgZ2d0aXRsZSgiUG9zdGVyaW9yIERpc3RyaWJ1dGlvbiBvZiBwX0EiKQoKCmdnc2F2ZShnLCBmaWxlbmFtZSA9ICJmaWd1cmVzL3BhX3Bvc3Rlcmlvci5wZGYiLCB3aWR0aCA9IDcsIGhlaWdodCA9IDUpCgpnCmBgYAoKIyMjIFRvIHRoZSBCYXllc2lhbiwgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24gaXMgZXZlcnl0aGluZwoKVG8gdGhlIEJheWVzaWFuLCB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBjb250YWlucyBhbGwgdGhlIGluZm9ybWF0aW9uCnRoYXQgdGhlIGRhdGEgaGFzIGFib3V0IHRoZSBwYXJhbWV0ZXIgdG8gYmUgZXN0aW1hdGVkLS0taW4gdGhpcyBjYXNlLCAkcF9BJC4KQW5kLCB0aGUgZnVsbCBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uLCB1bnN1bW1hcml6ZWQsIGV4cHJlc3NlcyB0aGF0IGFsbCB0aGF0IGluZm9ybWF0aW9uCmFzIGZ1bGx5IGFzIGNhbiBiZSBkb25lLiAgCgpIb3dldmVyLCBzb21ldGltZXMgeW91IGRvbid0IHdhbnQgdG8gY2FycnkgYXJvdW5kIGEgZnVsbCBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uLCAKZXNwZWNpYWxseSBpZiBpdCBpcyBhIGRpc3RyaWJ1dGlvbiBvbiBtdWx0aXBsZSB2YXJpYWJsZXMgKG11bHRpZGltZW5zaW9uYWwpLgoKT2Z0ZW4geW91IHdpbGwgd2FudCB0byBzdW1tYXJpc2UgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24uCgojIyMgU29tZSBzdGFuZGFyZCB3YXlzIG9mIHN1bW1hcml6aW5nIHRoZSBwb3N0ZXJpb3IKCjEuIFRoZSBwb3N0ZXJpb3IgbWVhbi4gIEdpdmVzIGEgcG9pbnQgZXN0aW1hdGUgdGhhdCBtaW5pbWl6ZXMgc3F1YXJlZCBlcnJvciBwb3N0ZXJpb3IgbG9zcy4KMi4gVGhlIHBvc3RlcmlvciBtZWRpYW4uICBHaXZlcyBhIHBvaW50IGVzdGltYXRlIHRoYXQgbWluaW1pemVzIGFic29sdXRlIHBvc3RlcmlvciBsb3NzLgozLiBUaGUgcG9zdGVyaW9yIG1vZGUuIEdpdmVzIGEgcG9pbnQgZXN0aW1hdGUgdGhhdCBtaW5pbWl6ZXMgMC0xIHBvc3RlcmlvciBsb3NzLgo0LiBUaGUgQmF5ZXNpYW4gQ3JlZGlibGUgSW50ZXJ2YWw6IHByb3ZpZGVzIGFuIGludGVydmFsIGVzdGltYXRvci4gTGlrZSBhIGNvbmZpZGVuY2UgaW50ZXJ2YWwsIGJ1dCBpbmZpbml0ZWx5IGVhc2llciB0byBpbnRlcHJldCBjb3JyZWN0bHkuLi4KCgoKCiMjIE1vbnRlIENhcmxvIGFuZCBNYXJrb3YgQ2hhaW4gTW9udGUgQ2FybG8KCkluIHRoZSBhYm92ZSBzZWdtZW50LCB3ZSBvYnRhaW5lZCBhIHBvc3RlcmlvciBkaXN0cmlidXRpb24gYW5hbHl0aWNhbGx5LiAgVGhhdAppcyBub3QgdGhlIHdheSB0aGluZ3MgdHlwaWNhbGx5IHdvcmsgb3V0LiAgSXQgaXMgbW9yZSBjb21tb24gdGhhdApvbmUgaXMgbm90IGFibGUgdG8gb2J0YWluIHRoZSBwb3N0ZXJpb3IgYW5hbHl0aWNhbGx5LCBidXQsIHJhdGhlciwgY2FuIG9ubHkKb2J0YWluIGEgX3NhbXBsZV8gZnJvbSB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbi4gIFdpdGggYSBzYW1wbGUgZnJvbSB0aGUgcG9zdGVyaW9yLApob3dldmVyLCBpdCBpcyBwb3NzaWJsZSB0byB1c2UgTW9udGUgQ2FybG8gdG8gYXBwcm94aW1hdGUgdmlydHVhbGx5IGFueSBxdWFudGl0eQp0aGF0IG1pZ2h0IGJlIG9mIGludGVyZXN0LiAgTGV0J3MgbG9vayBhdCB0aGF0IHdpdGggb3VyIHNpbXBsZSBleGFtcGxlLgoKIyMjIEEgInZhbmlsbGEiIE1vbnRlIENhcmxvIHNhbXBsZSBmcm9tIHRoZSBwb3N0ZXJpb3IgZm9yICRwX0EkIAoKRXZlbiB0aG91Z2ggd2UgY2FuIGNvbXB1dGUgdGhlIHBvc3RlcmlvciBhbmFseXRpY2FsbHksIGl0IGNhbiBzdGlsbApiZSBjb252ZW5pZW50IHRvIG9idGFpbiBhIHNhbXBsZSBmcm9tIGl0LiAgV2UgY2FuIHNhbXBsZSAxIG1pbGxpb24gdmFsdWVzCmZyb20gdGhlIHBvc3RlcmlvciBmb3IgJHBfQSQgbGlrZSB0aGlzOgpgYGB7cn0KcEEgPC0gcmJldGEobiA9IDEwXjYsIDc0LCAxMjgpCmBgYApUaGUgZmlyc3QgMTAgdmFsdWVzIG9mIHRoYXQgc2FtcGxlIGxvb2sgbGlrZToKYGBge3J9CnBBWzE6MTBdCmBgYAoKV2UgY2FsbCB0aGlzIGlzIGEgInZhbmlsbGEiIE1vbnRlIENhcmxvIHNhbXBsZSBiZWNhdXNlIGV2ZXJ5IG1lbWJlciBvZiB0aGUgc2FtcGxlCndhcyBpbmRlcGVuZGVudC0tLXRoaXMgaXMgbm90IF9NYXJrb3YgY2hhaW5fIE1vbnRlIENhcmxvLgoKSWYgd2Ugd2FudGVkIHRvIHVzZSB0aGUgc2FtcGxlIHRvIGFwcHJveGltYXRlIHRoZSBmdWxsIHBvc3Rlcmlvciwgd2UgY291bGQgZG8gCnRoYXQgd2l0aCBhIGhpc3RvZ3JhbToKYGBge3J9Cmhpc3QocEEsIGJyZWFrcyA9IDEwMCkKYGBgCgpMZXQncyB3YXRjaCB0aGlzIGluIGFjdGlvbjogICoqQ09NUFVURVIgREVNTyBiZXRhX2RlbnMqKgoKSWYgd2Ugd2FudCB0aGUgcG9zdGVyaW9yIG1lYW4sIHRoYXQgaXMgZWFzeSwgdG9vOgpgYGB7cn0KbWVhbihwQSkKYGBgCmFzIGlzIHRoZSBwb3N0ZXJpb3IgbWVkaWFuOgpgYGB7cn0KbWVkaWFuKHBBKQpgYGAKT3IgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbjoKYGBge3J9CnNkKHBBKQpgYGAKT3IsIHRoZSA5MCUtZXF1YWwtdGFpbCBDcmVkaWJsZSBJbnRlcnZhbApgYGB7cn0KcXVhbnRpbGUocEEsIHByb2JzID0gYygwLjA1LCAwLjk1KSkKYGBgCkFsbCBvZiB0aG9zZSBxdWFudGl0aWVzIGNvdWxkIGhhdmUgYmVlbiBvYnRhaW5lZCBhbmFseXRpY2FsbHkgaW4gdGhpcyBjYXNlLApidXQgaXQgaXMgYSBsb3Qgc2ltcGxlciB0byBqdXN0IHdvcmsgd2l0aCBhIE1vbnRlIENhcmxvIHNhbXBsZSBiZWNhdXNlIHRoZSAKb3BlcmF0aW9ucyBhcmUgdGhlIHNhbWUgd2l0aCBldmVyeSBNb250ZSBDYXJsbyBzYW1wbGUgKHdoaWNoIGlzIG5vdCBuZWNlc3NhcmlseQp0cnVlIG9mIGV2ZXJ5IGFuYWx5dGljYWwgZGlzdHJpYnV0aW9uLi4uKS4KCiMjIyBUcmFuc2Zvcm1hdGlvbnMgYXJlIHNpbXBsZSB3aXRoIGEgTW9udGUgQ2FybG8gc2FtcGxlCgpJbWFnaW5lIGZvciBhIG1vbWVudCB0aGF0IHdoYXQgeW91IHJlYWxseSB3YW50ZWQgdG8gZXN0aW1hdGUgd2FzIHRoZSAKcHJvYmFiaWxpdHkgdGhhdCwgaWYgeW91IHNhbXBsZWQgdGhyZWUgaW5kaXZpZHVhbHMsIGluIHNlcXVlbmNlLCBmcm9tIHRoZSBwb3B1bGF0aW9uLAp0aGUgZmlyc3Qgb25lIHdvdWxkIGJlIGhvbW96eWdvdXMgJEFBJCwgdGhlIHNlY29uZCBvbmUgd291bGQgYmUgaGV0ZXJvenlnb3VzICRBYSQKYW5kIHRoZSB0aGlyZCBvbmUgd291bGQgYmUgaG9tb3p5Z291cyAkYWEkLiBTaW5jZSB3ZSBhcmUgYmVpbmcgQmF5ZXNpYW5zIGhlcmUsIAp3ZSB3aWxsIHdhbnQgdG8gY29tcHV0ZSB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBvZiB0aGF0IHByb2JhYmlsaXR5IGdpdmVuIHRoZSAKb2JzZXJ2ZWQgZGF0YS4gIFRoaXMgaXMgc29tZXRoaW5nIHRoYXQgd291bGQgYmUgcXVpdGUgbWVzc3kgdG8gZG8gYW5hbHl0aWNhbGx5LApidXQgaXQgaXMgZWFzeSB0byB1c2UgdGhlIE1vbnRlIENhcmxvIHNhbXBsZSB0byBkbyBpdC4gIENsZWFybHksIGZvciBhIGdpdmVuICRwX0EkLCAKdGhlIHByb2JhYmlsaXR5IG9mIHRoZSBzZXF1ZW5jZSAoJEFBJCwgJEFhJCwgJGFhJCkgaXMKJHBfQV4yXHRpbWVzIDIgcF9BICgxLXBfQSkgXHRpbWVzICgxLXApXjIkLiAgU28sIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIG9mIHRoYXQKcXVhbnRpdHkgaXMgc2ltcGx5OiAKYGBge3J9CnRocmVlX2dlbm9fc2VxX3Bvc3RlcmlvciA8LSBwQV4yICogMiAqIHBBICogKDEgLSBwQSkgKiAoMSAtIHBBKV4yCmBgYApBbmQgd2UgY2FuIGxvb2sgYXQgaXQ6CmBgYHtyfQpoaXN0KHRocmVlX2dlbm9fc2VxX3Bvc3RlcmlvciwgYnJlYWtzID0gMTAwKQpgYGAKCgojIyMgV2hhdCBpcyB0aGUgTWFya292IENoYWluIHBhcnQgb2YgTUNNQz8KCldlJ3ZlIHNlZW50IHRoYXQgTW9udGUgQ2FybG8gaW4gdGhpcyBCYXllc2lhbiBjb250ZXh0IGlzIGFsbCBhYm91dCBiYXNpbmcKb25lJ3MgaW5mZXJlbmNlIG9uIGEgX3NhbXBsZXNfIGZyb20gdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24uICBIb3dldmVyLCBpdCB0dXJucwpvdXQgdGhhdCB5b3Ugb2Z0ZW4gY2FuJ3Qgb2J0YWluIF9pbmRlcGVuZGVudF8gc2FtcGxlcyBmcm9tIHBvc3Rlcmlvci4gIEluIGhpZ2ggZGltZW5zaW9ucwp0aGF0IGlzIGp1c3Qgbm90IHBvc3NpYmxlLiAgQnV0LCBpdCBfaXNfIHBvc3NpYmxlIHRvIGNvbnN0cnVjdCBhbiBlcmdvZGljIE1hcmtvdiBjaGFpbiB0aGF0CmhhcyBhcyBpdHMgbGltaXRpbmcgZGlzdHJpYnV0aW9uIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIHlvdSB3YW50IHRvIGJlIHNhbXBsaW5nIGZyb20uCgpXaGF0PyEKCk9LLCB3ZSB3aWxsIHRhbGsgYnJpZWZseSBhYm91dCBNYXJrb3YgY2hhaW5zLiAgQmFzaWNhbGx5IGEgTWFya292IGNoYWluIGlzIGEKc3RvY2hhc3RpYyBwcm9jZXNzIChsaWtlIGEgcmFuZG9tIHdhbGspIGluIHdoaWNoIHRoZSBwcm9iYWJpbGl0eSBvZiBlbmRpbmcgdXAgCmluIHNvbWUgcGxhY2UgYWZ0ZXIgdGhlIG5leHQgc3RlcCBkZXBlbmRzIG9ubHkgb24gd2hlcmUgaXQgY3VycmVudGx5IGlzLS0tbm90Cm9uIGhvdyBpdCBnb3QgdGhlcmUuLi4KCkEgY2xhc3NpYyBleGFtcGxlIGlzIGEgcmFuZG9tIHdhbGssIHdlIHdpbGwgY29uc2lkZXIgb25lIHdpdGggc2NhdHRlcmluZyBib3VuZGFyaWVzOgoKIVtdKHNsaWRlX2dyYWJzL3JhbmRvbS13YWxrLnBuZykKClRoZSBpbXBvcnRhbnQgdGFrZS1ob21lIG1lc3NhZ2UgZnJvbSB0aGUgYHRwbWAgQ29tcHV0ZXIgRGVtbyBpcyB0aGF0IGlmIHlvdSBydW4gYSBNYXJrb3YgY2hhaW4KbG9uZyBlbm91Z2gsIGl0IHNwZW5kcyB0aW1lIGluIGRpZmZlcmVudCBzdGF0ZXMgd2l0aCBhIHByZWRpY3RhYmxlIHBhdHRlcm4gY2FsbGVkIHRoZSAKbGltaXRpbmcgZGlzdHJpYnV0aW9uLiAgSW4gb3RoZXIgd29yZHMsIHlvdSBjYW4gdGFrZSBhIHNhbXBsZSBvZiB0aGUgc3RhdGVzIHZpc2l0ZWQgYnkgdGhlCmNoYWluIGFuZCB1c2UgdGhhdCBhcyBhIE1vbnRlIENhcmxvIHNhbXBsZS4gIFRoYXQgaXMgTWFya292IGNoYWluIE1vbnRlIENhcmxvLgoKIyMjIExldCdzIHNlZSB3aGF0IGl0IGxvb2tzIGxpa2UgZm9yICRwX0EkCgpDb21wdXRlciBEZW1vIGJldGFfZGVucyB3aXRoIE1DTUMuCgojIyMgV2h5IE1DTUMgaXMgc28gZ3JlYXQgZm9yIEJheWVzaWFucwoKVmlhIE1DTUMsIGl0IGlzIHBvc3NpYmxlIHRvIG9idGFpbiBzYW1wbGVzIGZyb20gdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24KZXZlbiBpZiB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBpcyBoaWdobHktbXVsdGlkaW1lbnNpb25hbCBhbmQgY29tcGxpY2F0ZWQuCgpUaGVyZSBhcmUgdHdvIG1haW4gcmVhc29ucyBmb3IgdGhpczoKCjEuIEEgTWFya292IGNoYWluIGNhbiBiZSBkZXZpc2VkIHRvIHNhbXBsZSBmcm9tIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uCndpdGhvdXQga25vd2luZyB0aGUgbm9ybWFsaXppbmcgY29uc3RhbnQuICBJbiBvdGhlciB3b3JkcywgaWYgeW91IGNhbiBjb21wdXRlIHRoZQpqb2ludCBwcm9iYWJpbGl0eSAocHJpb3IgdGltZXMgbGlrZWxpaG9vZCkgZm9yIGEgZnVsbHktb2JzZXJ2ZWQgdmVyc2lvbiBvZiB5b3VyIG1vZGVsLAp0aGF0IGlzIGFsbCB5b3UgbmVlZC4gKE5vdGUgdGhhdCB5b3UgY2FuIHByZXR0eSBtdWNoIGFsd2F5cyBjb21wdXRlIHRoZSBqb2ludCBwcm9iYWJpbGl0eSAKZm9yIGEgZnVsbHktb2JzZXJ2ZWQgbW9kZWwuKQoyLiBUaGUgTWFya292IGNoYWluIHNvIGRldmlzZWQgY2FuIGJlIGNvbnN0cnVjdGVkIGJ5IHByb3Bvc2luZyBjaGFuZ2VzIG9ubHkgdG8gc21hbGwKcGFydHMgb2YgdGhlIG1vZGVsLCB3aGljaCBtYWtlcyBpdCBwb3NzaWJsZSB0byBicmVhayBkb3duIGNvbXBsZXggZGlzdHJpYnV0aW9ucyBpbgp3YXlzIHRoYXQgbWFrZSBpdCBtYW5hZ2VhYmxlIHRvIHNhbXBsZSBmcm9tIHRoZW0uCgpUaGUgZGV0YWlscyBvZiB0aGlzIGFyZSBiZXlvbmQgdGhlIHNjb3BlIG9mIGEgMS4yNSBob3VyIGxlY3R1cmUuCgojIyMgV2h5IE1DTUMgY2FuIGJlIG5vdC1zby1ncmVhdAoKMS4gSXQgY2FuIGJlIGNvbXB1dGF0aW9uYWxseSBleHBlbnNpdmUgYW5kIHRha2UgYSBsb25nIHRpbWUuCjIuIEl0IGNhbiBtaXggcG9vcmx5LCBpLmUuIGl0IG1pZ2h0IG5vdCBzYW1wbGUgcmVsaWFibHkgZnJvbSBhbGwgYXJlYXMKb2YgdGhlIGRpc3RyaWJ1dGlvbiBpbiBwcm9wb3J0aW9uIHRvIChvciBldmVuIGFwcHJveGltYXRlbHkgaW4gcHJvcG9ydGlvbiB0bykgdGhlaXIKcG9zdGVyaW9yIHByb2JhYmlsaXR5LgozLiBJdCBjYW4gYXBwZWFyIHRvIGJlIG1peGluZyB3ZWxsLCBidXQgYWN0dWFsbHkgbm90IGJlIG1peGluZyB3ZWxsLiAgSXQgaXMgaW1wb3J0YW50IHRvCnBlcmZvcm0gbXVsdGlwbGUgcnVucyBmcm9tIGRpZmZlcmVudCBzdGFydGluZyB2YWx1ZXMgdG8gYXNzZXNzIGNvbnZlcmdlbmNlLgo0LiBFc3BlY2lhbGx5IGluICJjYW5uZWQgcGFja2FnZXMiIGl0IGNhbiBsZXQgeW91IGRvICJibGFjay1ib3h5IiBpbmZlcmVuY2UgaW4gbW9kZWxzIHRoYXQgYXJlIApzbyBjb21wbGljYXRlZCB0aGF0IGl0IGlzIGhhcmQgdG8gaGF2ZSBwcm9wZXIgaW50dWl0aW9uIGFib3V0IGhvdyB0aGV5IGJlaGF2ZSBvciBwZXJmb3JtIGdpdmVuCnRoZSB2YXJhcmllcyBvZiB5b3VyIG93biBkYXRhLgoKQWdhaW4sIHRoZXNlIHRvcGljcyBhcmUgYmV5b25kIHRoZSBzY29wZSBvZiB0aGlzIHByZXNlbnRhdGlvbi4gIEJ1dCBncmFiIG1lIHNvbWV0aW1lIGR1cmluZyB0aGUgd2VlayBpZiB5b3Ugd2FudCB0byB0YWxrIGFib3V0IGl0LgoKCgojIyBQcm9iYWJpbGlzdGljIEdlbm90eXBlIENhbGxpbmcgLyBBbGxlbGUgZnJlcXVlbmN5IGVzdGltYXRpb24geyNwcm9iY2FsbH0KCldlIGFyZSBub3cgZ29pbmcgdG8gZXhwYW5kIG91ciBhbGxlbGUgZnJlcXVlbmN5IG1vZGVsIGp1c3QgYSBsaXR0bGUgYml0LCB0byBnZXQgYSB0YXN0ZSBmb3IgCmhvdyB3ZSBtaWdodCBpbmZlciBib3RoIGFsbGVsZSBmcmVxdWVuY2llcyBhbmQgZ2Vub3R5cGVzIGdpdmVuIHNob3J0IHJlYWQgZGF0YS4KCkxldCdzIGNvbnNpZGVyIHRoaXMgc2V0dXA6IHdlIGFyZSB0cnlpbmcgdG8gaW5mZXIgZ2Vub3R5cGVzIGluIGluZGl2aWR1YWxzIGFuZCBlc3RpbWF0ZQp0aGUgYWxsZWxlIGZyZXF1ZW5jaWVzIGluIGEgcG9wdWxhdGlvbiBhdCBhIFNOUCBpbiB3aGljaCB0aGUgdmFyaWFudHMgYXJlIHRoZSB0d28KZGlmZmVyZW50IGJhc2VzLCAgJEMkIG9yICRUJC4gIFdlIGtub3cgd2hlcmUgdGhlIFNOUCBvY2N1cnMgKHdlIGFyZSBkaXNyZWdhcmRpbmcgdGhlIHByb2JsZW0Kb2YgaW5mZXJyaW5nIHdoZXRoZXIgYSBTTlAgaXMgdGhlcmUpIGJ1dCB3ZSBkbyBub3Qga25vdyBpdHMgZnJlcXVlbmN5IGluIHRoZSBwb3B1bGF0aW9uLgpXZSBoYXZlIHNlcXVlbmNlZCAkTiQgaW5kaXZpZHVhbHMgYXQgdGhpcyBTTlAuICBXZSBkb24ndCBrbm93IHRoZSBnZW5vdHlwZSBvZiBhbnkgb2YgdGhlc2UKaW5kaXZpZHVhbHMsIGJ1dCB3ZSBnZXQgdG8gb2JzZXJ2ZSB0aGUgbnVtYmVyIG9mIHNlcXVlbmNpbmcgcmVhZHMgb24gZWFjaCBpbmRpdmlkdWFsLCAkaSQsCnRoYXQgY29udGFpbiBhICRDJCwgYW5kIHRoZSBudW1iZXIgb2YgcmVhZHMgdGhhdCBjb250YWluIGEgJFQkIGF0IHRoZSBzaXRlLiAgV2UgY2FsbCB0aGF0Cm9ic2VydmVkIHZhcmlhYmxlICRcYm9sZHN5bWJvbHtSfV9pID0gKFJfe2ksQ30sIFJfe2ksVH0pJCwgYSB0d28tdmVjdG9yLiAgV2UgaW5jbHVkZSBpbiBvdXIgbW9kZWwgCmEgc2VxdWVuY2luZyBlcnJvciByYXRlICRcbXUkIHdoaWNoLCBmb3Igc2ltcGxpY2l0eSBoZXJlLCB3ZSB3aWxsIGFzc3VtZSBpcyBrbm93bi4KV2l0aCBwcm9iYWJpbGl0eSAkXG11JCBhIHJlYWQgZnJvbSBhIGNocm9tb3NvbWUgdGhhdCByZWFsbHkgY29udGFpbnMgYSAkQyQgYXQgdGhlIHNpdGUgd2lsbApyZXBvcnQgYSAkVCQsIHdoaWxlIHdpdGggcHJvYmFiaWxpdHkgJDEgLSBcbXUkIHRoZSBiYXNlIGF0IHRoZSBzaXRlIGlzIGNvcnJlY3RseSByZXBvcnRlZCBhcyBhICRDJC4gIFNpbWlsYXJseSBmb3IgY2hyb21vc29tZXMgdGhhdCBjb250YWluIGEgJFQkIGF0IHRoZSBzaXRlLCB3aXRoIHByb2JhYmlsaXR5ICRcbXUkIGEgcmVhZAp3aWxsIHJlcG9ydCBhICRDJCBhbmQgd2l0aCBwcm9iYWJpbGl0eSAkMSAtIFxtdSQgaXQgd2lsbCBjb3JyZWN0bHkgcmVwb3J0IGEgJFQkLiAgCgpIZXJlIGlzIGEgREFHIGZvciB0aGUgbW9kZWw6CgohW10oZGlhZ3JhbXMvZ2Vub3MtYW5kLXJlYWRzLWRhZy5wbmcpCgogIAogIApBbGwgcmlnaHQuICBUaGlzIGlzIGZ1bi4gIE5vdyB0aGVyZSBhcmUgX3R3b18gbGF5ZXJzIG9mIHVua25vd24gdmFyaWFibGVzICh0aGUgJFkkJ3MgYW5kICRwX0MkIAp0aGF0IHdlIHdpbGwgdHJ5IHRvIGluZmVyIHRvZ2V0aGVyLCBhdCB0aGUgc2FtZSB0aW1lKS4KCgojIyMgQ29uZGl0aW9uYWwgcHJvYmFiaWxpdGllcyBpbiB0aGUgbW9kZWwKCk1vc3Qgb2YgdGhlc2Ugd2UgaGF2ZSBzZWVuIGJlZm9yZToKCi0gJFAocF9DIHwgXGFscGhhX0MsIFxhbHBoYV9UKSQgaXMganVzdCBhIGJldGEgcHJpb3Igb24gJHBfQyQuCi0gJFlfe2ksMX0kIGlzIGEgQmVybm91bGxpIHRyaWFsIHdpdGggc3VjY2VzcyBwcm9iYWJpbGl0eSAoaS5lLiBwcm9iYWJpbGl0eSBvZgpnZXR0aW5nIGEgJEMkIG9mICRwX0MkLikKLSBUaGUgb25seSBuZXcgb25lIGlzIHRoZSBwcm9iYWJpbGl0eSBkaXN0cmlidXRpb24gb2YgcmVhZCBjb3VudHMgZ2l2ZW4gdGhlIGdlbm90eXBlIGFuZAp0aGUgZ2Vub3R5cGluZyBlcnJvciByYXRlOiAkUChcYm9sZHN5bWJvbHtSfV9pfnx+WV97aSwxfSwgWV97aSwyfSwgXG11KSQKCiMjIyBUaGUgY29uZGl0aW9uYWwgcHJvYmFiaWxpdHkgJFAoXGJvbGRzeW1ib2x7Un1faX58fllfe2ksMX0sIFlfe2ksMn0sIFxtdSkkCgpUaGlzIHRoaW5nIHR1cm5zIG91dCB0byBiZSBwcmV0dHkgZWFzeS4gIEl0IGNhbiBiZSBicm9rZW4gZG93biBpbnRvIGNhc2VzOgoKMS4gKiokaSQgaXMgaG9tb3p5Z291cyBmb3IgJEMkIChpLmUuLCAkWV97aSwxfSA9IFlfe2ksMn0gPSBDJCk6KiogSW4gdGhpcyBjYXNlLAp0aGUgb25seSB3YXkgdG8gZ2V0IGEgcmVhZCB3aXRoIGEgJFQkIGF0IHRoZSBzaXRlIGlzIGJ5IGEgc2VxdWVuY2luZyBlcnJvciwgd2hpY2ggCmhhcHBlbnMgd2l0aCBwcm9iYWJpbGl0eSAkXG11JC4gIFRodXMsIGl0IGlzIGFraW4gdG8gZHJhd2luZyAkTSA9IFJfe2ksQ30gKyBSX3tpLFR9JApiYWxscyBvdXQgb2YgYW4gdXJuICh3aXRoIHJlcGxhY2VtZW50KSwgYSBmcmFjdGlvbiAkXG11JCBvZiB3aGljaApzYXkgJFQkIG9uIHRoZW0sIHRoZSByZXN0IHdoaWNoIHNheQokQyQgb24gdGhlbS4gIEluIHN1Y2ggYSBjYXNlICRSX3tpLEN9JCBpcyBiaW5vbWlhbGx5IGRpc3RyaWJ1dGVkLCAkTSQgZHJhd3Mgd2l0aApzdWNjZXNzIHByb2JhYmlsaXR5ICQxLVxtdSQuCjIuICoqJGkkIGlzIGhvbW96eWdvdXMgZm9yICRUJCAoaS5lLiwgJFlfe2ksMX0gPSBZX3tpLDJ9ID0gVCQpOioqIFNhbWUgYXJndW1lbnQKYXMgYWJvdmUsICRSX3tpLEN9JCBpcyBiaW5vbWlhbGx5IGRpc3RyaWJ1dGVkLCAkTSQgZHJhd3Mgd2l0aApzdWNjZXNzIHByb2JhYmlsaXR5ICRcbXUkIHRoaXMgdGltZSwgcmF0aGVyIHRoYW4gJFxtdSQuCjMuICoqJGkkIGlzIGhvbW96eWdvdXMgZm9yICRUJCAoaS5lLiwgJChZX3tpLDF9ID0gQywgWV97aSwyfSA9IFQpJApvciAkKFlfe2ksMX0gPSBULCBZX3tpLDJ9ID0gQykkKToqKiAgQmVjYXVzZSB3ZSBoYXZlIGFzc3VtZWQgc2VxdWVuY2luZyBlcnJvciByYXRlcwphcmUgc3ltbWV0cmljYWwgYmV0d2VlbiBkaWZmZXJlbnQgYmFzZXMsIHRoaXMgaXMgZWFzaWx5IGZpZ3VyZWQgb3V0LS0tdGhlIHJlYWRzIGFyZQpsaWtlIGJhbGxzIHlvdSBhcmUgc2FtcGxpbmcgKHdpdGggcmVwbGFjZW1lbnQpIGZyb20gYW4gVXJuIGluIHdoaWNoIGhhbGYgb2YgdGhlIGJhbGxzIAphcmUgJFQkJ3MgYW5kIGhhbGYgb2YgdGhlbSBhcmUgJEMkJ3MuCgojIyMgQSBsaXR0bGUgZmxhdm9yIG9mIGhvdyBNQ01DIHByb2NlZWRzCgpUaGUgdW5vYnNlcnZlZCBnZW5vdHlwZXMgb2YgdGhlIGluZGl2aWR1YWxzIGluIHRoZSBhYm92ZSBtb2RlbCBhcmUgd2hhdCBhcmUgc29tZXRpbWVzCmNhbGxlZCAibWlzc2luZyBkYXRhIi4gIFRoZXkgYXJlIG5vdCBtaXNzaW5nIGRhdGEgaW4gdGhlIHNlbnNlIG9mIHNtYWxsIGhvbGVzIGluIHlvdXIKZGF0YSBzZXQgdGhhdCByZXN1bHRlZCBmcm9tIHNvbWUgZGF0YS1jb2xsZWN0aW9uIGZhaWx1cmUuICBUaGV5IGFyZSBtaXNzaW5nIGluIHRoZSBzZW5zZQpvZiAiV2hhdCBpcyBtaXNzaW5nIGhlcmUgaXMgc29tZXRoaW5nIHRoYXQgd291bGQgbWFrZSB0aGlzIHdob2xlIHByb2JsZW0gZWFzaWVyIi4gIENsZWFybHksCmFzIHdlIHNob3dlZCBpbiBhbiBlYXJsaWVyIHNlY3Rpb24sIGlmIHdlIGtuZXcgdGhlc2UgZ2Vub3R5cGVzIGV4YWN0bHksIGRvaW5nIEJheWVzaWFuCmluZmVyZW5jZSBmb3IgJHBfQyQgaXMgcHJldHR5IGRhcm4gZWFzeS4gIAoKQW5vdGhlciBuYW1lIGZvciB0aGlzICJtaXNzaW5nIGRhdGEiIGlzICJsYXRlbnQgdmFyaWFibGVzLiIgIE1hbnkgZm9ybXVsYXRpb25zIG9mIE1DTUMgCmFyZSBkZXZlbG9wZWQgd2l0aCB0aGVzZSB0eXBlcyBvZiBsYXRlbnQgdmFyaWFibGVzLiAgSW4gb3VyIGNhc2UsIGEgYnJpZWYgc2tldGNoIG9mIGhvdyAKTUNNQyB3b3VsZCBwcm9jZWVkIHN0YXJ0cyB3aXRoIGEgYml0IG9mIHdpc2hmdWwgdGhpbmtpbmcuICBXZSBzYXksICJXb3VsZG4ndCBpdCBiZSBncmVhdCBpZgp3ZSBhY3R1YWxseSBrbmV3IHRoZSB2YWx1ZSBvZiAkcF9DJC4uLkhleSEgV2UgZG9uJ3QsIGJ1dCBsZXQncyBqdXN0IHN0YXJ0IHdpdGggYSBndWVzcyBhbmQgCnByZXRlbmQgaXQgaXMgdHJ1ZS4iICBTbywgd2Ugd291bGQgc3RhcnQgYnkgaW5pdGlhbGl6aW5nIHRoZSBtb2RlbCBhbmQgc2V0dGluZyAkcF9DJCB0byBzb21lIApyYW5kb20gdmFsdWUsIGxldCB1cyBjYWxsIHRoYXQgdmFsdWUgJHBfQ157KDApfSQuCgpOb3csIGlmIHdlIGtub3cgdGhlIHZhbHVlIG9mICRwX0MkLCB0aGVuIHRoZSBvbmx5IHRoaW5nIHRoYXQgd291bGQgYmUgbGVmdCB1bmtub3duIGluIHRoZSBtb2RlbAp3b3VsZCBiZSB0aGUgZ2Vub3R5cGVzIG9mIHRoZSBpbmRpdmlkdWFscy4gIEJ1dCBsb29raW5nIGF0IHRoZSBncmFwaCBpdCBpcyBjbGVhciB0aGF0IHRoZXkgCmFyZSBhbGwgY29uZGl0aW9uYWxseSBpbmRlbmRlbnQgZ2l2ZW4gJHBfQ157KDApfSQgYW5kIHRoZSB0aGUgb2JzZXJ2ZWQgcmVhZCBkZXB0aHMuICBTbywgCnByZXRlbmRpbmcgdGhhdCAkcF9DXnsoMCl9JCBpcyB0aGUgdHJ1dGgsIHdlIGNvdWxkIGNvbXB1dGUsIGZvciBlYWNoIGluZGl2aWR1YWwgJGksIHRoZSAKcG9zdGVyaW9yIHByb2JhYmlsaXRpZXMgb2YgJGkkJ3MgZ2Vub3R5cGUgKHRoZSB0aHJlZSBjYXNlcywgMS0tMyBhYm92ZSkuIChCeSB0aGUgd2F5LCB0aGlzIApkaXN0cmlidXRpb24gaXMgb2Z0ZW4gY2FsbGVkIHRoZSAiZnVsbCBjb25kaXRpb25hbCBkaXN0cmlidXRpb24iKS4gIAoKVGhlbiB3ZSB3b3VsZCBzaW11bGF0ZSB2YWx1ZXMgb2YgdGhlIGdlbm90eXBlcyBmcm9tIHRob3NlIHBvc3RlcmlvciBkaXN0cmlidXRpb25zLiAgQWhhIQpvbmNlIHdlIGhhdmUgdGhvc2Ugc2ltdWxhdGVkLCB3ZSBjYW4gcHJldGVuZCB0aGF0IHRoZXkgYXJlIHJlYWwgYW5kIHVzZSB0aGVtIHRvIApjb21lIHVwIHdpdGggYSBuZXcgZXN0aW1hdGUgb2YgJHBfQyQgYnkgY29tcHV0ZSB0aGUgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiAoZnVsbCBjb25kaXRpb25hbCkKZm9yICRwX0MkIGdpdmVuIHRoZSBjdXJyZW50IHZhbHVlcyBvZiB0aGUgZ2Vub3R5cGVzIGFuZCB0aGVuIHNpbXVsYXRpbmcgYSB2YWx1ZSBmcm9tCnRoYXQgZGlzdHJpYnV0aW9uLiAgQ2FsbCB0aGF0ICRwX0NeeygxKX0kLCBhbmQgdGhlbiBnbyBiYWNrIHRvIHNpbXVsYXRpbmcgbmV3IHZhbHVlcyBmb3IgdGhlCmdlbm90eXBlcy4gIAoKRG9pbmcgdGhhdCBvdmVyIGFuZCBvdmVyIGFnYWluIGNyZWF0ZXMgYSBNYXJrb3YgY2hhaW4gdGhhdCBkb2VzIGEgcmFuZG9tIHdhbGsgCm92ZXIgdGhlIHNwYWNlIG9mIGFsbCBwb3NzaWJsZSBnZW5vdHlwZXMgb2YgdGhlICRpJCBpbmRpdmlkdWFscyBhbmQgdGhlIHVua25vd24KYWxsZWxlIGZyZXF1ZW5jeSAkcF9DJCwgd2l0aCB0aGUgYW1vdW50IG9mIHRpbWUgdGhlIGNoYWluIHNwZW5kcyBpbiBhbnkgc3RhdGUgYmVpbmcgCl9wcm9wb3J0aW9uYWwgdG8gdGhlIHBvc3RlcmlvciBwcm9iYWJpbGl0eSBvZiB0aGF0IHN0YXRlIV8uCgoKCgoKIyMjIFNvbWUgb2YgdGhlIGFzc3VtcHRpb25zIGluIHRoZSBhYm92ZSBtb2RlbC4uLgoKVGhlcmUgYXJlIHF1aXRlIGEgZmV3IGJ1dCB0aGUgYmlnZ2VzdCBpcyB0aGF0IGVhY2ggcmVhZCBpcyBpbmRlcGVuZGVudCBvZiB0aGUgb3RoZXJzLgpUaGF0IGFzc3VtcHRpb24gd291bGQgYmUgdmlvbGF0ZWQgaWY6CgotIHRoZSBzZXF1ZW5jZXMgdXBvbiB3aGljaCB0aGUgJEMkIChvciB0aGUgJFQkKSBvY2N1cnJlZCB3ZXJlIHNvbWVob3cgc3ViamVjdCB0bwpncmVhdGVyIGFtcGxpZmljYXRpb24gZHVyaW5nIGFueSBQQ1Igc3RlcHMsIG9yIHdlcmUgbW9yZSBsaWtlbHkgdG8gYXR0YWNoIHRvCiJ0aGUgbGF3biIgb24gYW4gSWxsdW1pbmEgbWFjaGluZS4KLSB0aGVyZSBhcmUgUENSIGR1cGxpY2F0ZXMuICBUaGlzIGNhbiBiZSBhIHJlYWxseSBiaWcgaXNzdWUgZm9yIFJBRCBtZXRob2RzIHRoYXQKZG9uJ3QgaGF2ZSBhIGdvb2QgbWVjaGFuaXNtIGZvciBmaWx0ZXJpbmcgUENSIGR1cGxpY2F0ZXMuCgoKCgojIyMgV2h5IGlzIHRoaXMgYSBnb29kIGlkZWE/CgpCZWNhdXNlIHRoZSBhbGxlbGUgZnJlcXVlbmN5IGVzdGltYXRlIGlzIHRoZXJlIHRvIGluZm9ybSB0aGUgaW5mZXJlbmNlIG9mIGdlbm90eXBlcy4KCklmIHRoZSBmcmVxdWVuY3kgb2YgdGhlICRDJCBhbGxlbGUgaXMgcXVpdGUgbG93LCB0aGF0IHdpbGwgcHJvdmlkZSBhIGxvdCBvZgpldmlkZW5jZSBpbiB0aGUgbW9kZWwgYWdhaW5zdCBpbmZlcnJpbmcgc29tZW9uZSB0byBiZSBob21venlnb3VzIGZvciB0aGUgJEMkIGFsbGVsZS4KCkFuZCB0aGlzIHdvdWxkIGJlIGEgZ29vZCB0aGluZywgYmVjYXVzZSBhZnRlciBhIGxpdHRsZSBiaXQgb2YgbG9va2luZyBhdCBwdWJsaXNoZWQKZGF0YSBzZXRzIG9mIGdlbm90eXBlcyBjYWxsZWQgYnkgdHJhZGl0aW9uYWwgbWVhbnMgKGkuZS4gYXBwYXJlbnRseSB3aXRob3V0CmNvbnNpZGVyaW5nIGFsbGVsZSBmcmVxdWVuY2llcyksIGl0IGFwcGVhcnMgdGhlcmUgaXMgYSBiaXQgb2YgYW4gZXBpZGVtaWMKb2YgZ2Vub3R5cGluZyBlcnJvciBpbiBSQUQgc2VxdWVuY2VkIGRhdGEuCgoKCgojIyBFc3RpbWF0aW5nIEdlbm90eXBpbmcgRXJyb3IgUmF0ZXMgaW4gc29tZSBSQUQgZGF0YXNldHMKCkkgYmVjYW1lIGludGVyZXN0ZWQgaW4gd2lkZXNwcmVhZCBkZXBhcnR1cmVzIGZyb20gSGFyZHktV2VpbmJlcmcgZXF1aWxpYnJpdW0KaW4gY2FsbGVkIGdlbm90eXBlcyBmcm9tIFJBRCBzZXEgZGF0YSwgYW5kIGludmVzdGlnYXRlZCBpdCBhIGxpdHRsZSBiaXQuCgoqKkl0IGlzIGltcG9ydGFudCB0byByZWNvZ25pemUgaW4gdGhpcyBzZWN0aW9uIHRoYXQgd2UgYXJlIGRlYWxpbmcgb25seSB3aXRoCmNhbGxlZCBnZW5vdHlwZXMgYW5kIGhhdmUgbm90IHJldGFpbmVkIGFueSBvZiB0aGUgcmVhZCBkZXB0aCBpbmZvcm1hdGlvbiwgZXRjLgpXZSBhcmUganVzdCBsb29raW5nIGF0IGNhbGxlZCBnZW5vdHlwZXMhICoqCgojIyMgTG9va2luZyBhdCBXaWxsb3cgRmx5Y2F0Y2hlcnMKCk15IHdpZmUsIEtyaXN0ZW4gUnVlZ2csIGRvZXMgYSBsb3Qgb2YgUkFEIHNlcSBvbiBiaXJkcy4gIFNoZSBpcyBhIHN0aWNrbGVyIGZvciAKaGlnaC1xdWFsaXR5IEROQSBhbmQgaGlnaCByZWFkIGRlcHRocywgYW5kIHNoZSB3b3JrcyB3aXRoIHNvbWUgdmVyeSBnb29kIHRlY2huaWNpYW5zCmF0IFVDTEEuICBCZWxvdyBpcyBhIHBsb3QgSSBtYWRlIG9mIHNvbWUgb2YgaGVyIChhcyB5ZXQgdW5wdWJsaXNoZWQpCmRhdGEgZnJvbSBXaWxsb3cgRmx5Y2F0Y2hlcnMuICBUaGV5CmNhbGxlZCAxMDUsMDAwIFNOUHMgaW4gYWxtb3N0IDIwMCBpbmRpdmlkdWFscywgYW5kIHNob3duIGhlcmUgYXJlIDQ3IGluZGl2aWR1YWxzIGZyb20gdGhlCmltcGVyaWxlZCBwb3B1bGF0aW9uIG9mIHRoZSBfZXh0aW11c18gc3Vic3BlY2llcyBpbiBBcml6b25hLiBJdCBpcyBhIHBsb3Qgb2YgCnRoZSBleHBlY3RlZCBmcmVxdWVuY3kgb2YgZWFjaCBnZW5vdHlwZSAgKDAgPSBob21venlnb3VzIGZvciB0aGUgcmVmZXJlbmNlIGFsbGVsZSwgCjEgPSBoZXRlcm96eWdvdGUsIDIgPSBob21venlnb3VzIGZvciB0aGUgYWx0ZXJuYXRlIGFsbGVsZSkgb24gdGhlICR4JC1heGlzIGFnYWluc3QgdGhlIApvYnNlcnZlZCBmcmVxdWVuY3kgb2YgZWFjaCBnZW5vdHlwZSwgYWNyb3NzIGFsbCBsb2NpIHBvbHltb3JwaGljIGFtb25nc3QgdGhvc2UgNDcKaW5kaXZpZHVhbHMuCgohW10oZmlndXJlcy93aWZsX2JpZ19wb3Bfbm9fYm91bmRzLnBuZykKClRoZXNlIGRhdGEgd2VyZSBvYnRhaW5lZCBieSBhbGlnbm1lbnQgdG8gYSBkZS1ub3ZvIGFzc2VtYmxlZCBnZW5vbWUgd2l0aCBTTlBzIGNhbGxpbmcKdXNpbmcgR0FUSywgd2l0aCBsaWdodCBmaWx0ZXJpbmcgKHJlYWQgZGVwdGhzID4gNiBvciAxMCwgYW5kIFBocmVkLXNjYWxlZApnZW5vdHlwZSBsaWtlbGlob29kcyA+IDMwLCBJIHRoaW5rKS4KCk5vdGUgbnVtYmVycyB1cCB0aGVyZTogCgotICoqbioqIGlzIHRoZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMgaW4gdGhlIHBvcHVsYXRpb24uCi0gKipuX2YqKiBpcyB0aGUgbnVtYmVyIGxlZnQgYWZ0ZXIgdG9zc2luZyBvdXQgYW55b25lIHdpdGggbW9yZSB0aGFuIDkwJSBtaXNzaW5nIGRhdGEuCi0gKipMKiogaXMgdGhlIG51bWJlciBvZiBsb2NpIGluIHRoZSB3aG9sZSBkYXRhIHNldC4KLSAqKkxfZioqIGlzIHRoZSBudW1iZXIgb2YgbG9jaSByZW1haW5pbmcgYWZ0ZXIgcmVtb3ZpbmcgdGhvc2UgdGhhdCBhcmUgbW9ub21vcnBoaWMgaW4gdGhlCmZvY2FsIHBvcHVsYXRpb24sIG9yIHdoaWNoIGFyZSBtaXNzaW5nIGRhdGEgZnJvbSBtb3JlIHRoYW4gNzAlIG9mIHRoZSBpbmRpdmlkdWFscy4KCgoKSXQgbG9va3MgcmVhc29uYWJseSBnb29kLS0teW91IHdhbnQgdGhlIG9ic2VydmVkIHRvIGZhbGwgYWxvbmcgdGhlIGV4cGVjdGVkIGxpbmUtLS1hcGFydApmcm9tIHNvbWUgb2J2aW91cyBvdXRsaWVycyB0aGF0IGFyZSBhbGwgaGV0ZXJvenlnb3RlczogY2xlYXJseSBtb3JlIHRoYW4gb25lIGdlbm9taWMgcmVnaW9uCmFsaWduaW5nIHRvIHRoZSBzYW1lIHNwb3QgaW4gdGhlIGFzc2VtYmxlZCBnZW5vbWUuCgojIyMgV2hhdCBzaG91bGQgdGhlc2UgcGxvdHMgbG9vayBsaWtlPwoKSXQgaXMgZWFzeSB0byBzZWUgd2hhdCB0aGVzZSBwbG90cyBzaG91bGQgbG9vayBsaWtlIHVuZGVyIEhhcmR5LVdlaW5iZXJnIGVxdWlsaWJyaXVtCmJ5IHNpbXVsYXRpbmcgaXQuICBIZXJlIGFyZSByZXN1bHRzIG9mIHNpbXVsYXRpb25zIHdpdGggc2FtcGxlIHNpemVzIG9mIAoyMCBhbmQgNDAgaW5kaXZpZHVhbHMuCgohW10oZmlndXJlcy9zaW11bGF0ZWQtbmljZS1kYXRhLnBuZykKCkFsc28sIGlmIHlvdSBkbyBhIGxpdHRsZSB0aGlua2luZyBhbmQgc29tZSBhbGdlYnJhIHlvdSBjYW4gc2VlIHRoYXQsIGJlY2F1c2UKdGhlIGV4cGVjdGVkIGdlbm90eXBlIGZyZXF1ZW5jaWVzIGFyZSBjb21wdXRlZCBmcm9tIHRoZSBhbGxlbGUgZnJlcXVlbmNpZXMgCmVzdGltYXRlZCBmcm9tIHRoZSBvYnNlcnZlZCBnZW5vdHlwZXMsIHRoZXJlIGFyZSBzb21lIGJvdW5kcyBvbiB3aGVyZSB0aGUKcG9pbnRzIGNhbiBnby4gIFRob3NlIGFyZSBpbmRpY2F0ZWQgYnkgZGFzaGVkIGxpbmVzIGFib3ZlLgoKIyMjIFdoYXQgYWJvdXQgc29tZSBwdWJsaXNoZWQgZGF0YSBzZXRzPwoKSSB3ZW50IHRocm91Z2ggTW9sZWN1bGFyIEVjb2xvZ3kgYW5kIERyeWFkIGFuZCBmb3VuZCBhYm91dCAxMiBkYXRhIHNldHMgY3JlYXRlZCBieSBzb21lCnZlcnNpb24gb2YgUkFEIChSQUQsIFJBRC1QRSwgZGRSQUQsIGV0Yy4pIHRoYXQgd2VyZSBpbiBhIGZvcm1hdCB0aGF0IHdhcyBub3QKdG9vIGhhcmQgdG8gd3JhbmdsZSBpbnRvIGFuIDAxMiBtYXRyaXguICBGb3IgZWFjaCBkYXRhIHNldCwgSSBmb2N1c2VkIG9uIHRoZSAKc2luZ2xlIHNhbXBsaW5nIGxvY2F0aW9uIHdpdGggdGhlIGxhcmdlc3Qgc2FtcGxlIHNpemUgYW5kIG1hZGUgc2ltaWxhciBwbG90cyBmb3IKdGhlbS4gIEhlcmUgYXJlIHR3bzoKCiFbXShmaWd1cmVzL2xvYnN0ZXJfYmlnX3BvcC5wbmcpCgohW10oZmlndXJlcy9zbmFpbHNfYmlnX3BvcC5wbmcpCgpXb3chIFRob3NlIGFyZSBzb21lIGRhdGEgc2V0cyB0aGF0IGFyZSwgaW4gdGhlIGFnZ3JlZ2F0ZSwgc2hvd2luZyBzZXZlcmUKZGVwYXJ0dXJlcyBmcm9tIEhhcmR5LVdlaW5iZXJnIGVxdWlsaWJyaXVtLiAgCgpJIHRoaW5rIGluIG9uZSBvZiB0aGVtIHRoZSBhdXRob3JzCnNhaWQgdGhhdCB0aGV5IGZpbHRlcmVkIG91dCBsb2NpIHRoYXQgd2VyZSBzaWduaWZpY2FudGx5IG91dCBvZiBIV0UuICBTbywgaXQgbWlnaHQKYmUgdGhhdCB3aXRoIHNtYWxsIHNhbXBsZXMsIGFuZCBmb2N1c2luZyBvbmx5IG9uIGEgc2luZ2xlIG1hcmtlciBhdCBhIHRpbWUsIGl0IGlzIApoYXJkIHRvIGRldGVjdCB0aGVzZSBkaXN0b3J0aW9ucy4gIEJ1dCB0aGV5IGFyZSBxdWl0ZSBldmlkZW50IHdoZW4gdmlld2VkIGxpa2UgdGhpcy4KVGhlIG1haW4gcG9pbnQ6IHRoZXJlIGFyZSBmYXIgbW9yZSBob21venlnb3RlcyB0aGFuIHlvdSB3b3VsZCBleHBlY3QgdW5kZXIgSFdFLgoKIyMjIEEgU2ltcGxlIE1vZGVsIG9mIEdlbm90eXBpbmcgRXJyb3JzCgpXaGVuIEkgbG9vayBhdCB0aGVzZSBwaWN0dXJlcywgSSB0aGluaywgIkxldCdzIG1ha2UgYSBzdXBlciBzaW1wbGUgbW9kZWwgb2YgZ2Vub3R5cGluZwplcnJvciBhbmQgZXN0aW1hdGUgd2hhdCB0aGUgZ2Vub3R5cGluZyBlcnJvciByYXRlcyBtdXN0IGJlIHRvIGdldCB0aGluZ3MgdGhhdCBsb29rCnRoaXMgZGlzdG9ydGVkLiIKCk9idmlvdXNseSwgdGhlcmUgYXJlIHNvbWUgaGV0ZXJvenlnb3RlcyB0aGF0IGFyZSBiZWluZyBjYWxsZWQgYXMgaG9tb3p5Z290ZXMuIFNvLApsZXQncyBwcm9wb3NlIHRoaXM6IGFsbCBpbmRpdmlkdWFscyB0aGF0IGFyZSB0cnVseSBob21venlnb3RlcyBnZXQgY29ycmVjdGx5IGNhbGxlZAphcyBob21venlnb3RlcywgYnV0IGluZGl2aWR1YWxzIHRoYXQgYXJlIHRydWx5IGhldGVyb3p5Z291cyBoYXZlIGEgcHJvYmFiaWxpdHkgJG0kIG9mCmJlaW5nIG1pc2NhbGxlZCBhcyBhIGhvbW96eWdvdGUuICBJZiB0aGUgaW5kaXZpZHVhbCBpcyBtaXNjYWxsZWQsIHRoZW4gaXQgaGFzIGFuIGVxdWFsCmNoYW5jZSBvZiBiZWluZyBjYWxsZWQgYXMgZWl0aGVyIGhvbW96eWdvdGUuIAoKV2UgY2FuIGRyYXcgYSBEQUcgZm9yIHRoaXMgbW9kZWwsIGJ1dCBsZXQncyBlc3RhYmxpc2ggYSBjb252ZW50aW9uLCBmaXJzdDogcmF0aGVyIHRoYW4KbmFtaW5nIGFsbGVsZXMgYnkgdGhlIGJhc2VzIHRoYXQgdGhleSBjYXJyeSwgd2Ugd2lsbCBqdXN0IGxldCB0aGUgYWxsZWxlcyBiZQpsYWJlbGxlZCAwIGFuZCAxLiAgVGhlbiB0aGUgcG9zc2libGUgZ2Vub3R5cGVzLCAkRyQgYXJlIGRlbm90ZWQgMCwgMSwgb3IgMiwgYWNjb3JkaW5nIHRvCnRoZSBudW1iZXIgb2YgMSBhbGxlbGVzIGluIHRoZSBkaXBsb2lkIGdlbm90eXBlLgoKIVtdKGRpYWdyYW1zL2dlbm8tZXJyLW1vZGVsLnBuZykKCiRwXzEkIGlzIHRoZSBmcmVxdWVuY3kgb2YgdGhlICIxIiBhbGxlbGUuICAKCldlIGRvbid0IGhhdmUgdGltZSB0byBnbyBvdmVyIHRoZSBkZXRhaWxzIG9mIHRoZSBtb2RlbCwgYnV0IHRoZXkgYXJlIHN0cmFpZ2h0Zm9yd2FyZAphbmQgdHJpdmlhbC4gIEl0IHRha2VzIGp1c3QgYSBmZXcgbGluZXMgb2YgUiBjb2RlIHRvIGltcGxlbWVudCBNQ01DIGZvciBpdC4gSXQgbWl4ZXMKd2VsbCwgYW5kIGV2ZW4gb24gbGFyZ2UgZGF0YSBzZXRzIGl0IGRvZXNuJ3QgdGFrZSB0b28gbG9uZyB0byBnZXQgYW4gZXN0aW1hdGUgb2YgdGhhdApfaGV0ZXJvenlnb3RlIG1pc2NhbGwgcmF0ZV8gcGFyYW1ldGVyICRtJC4gIAoKIyMjIEEgR2FsbGVyeSBvZiBEYXRhIHNldHMKCkhlcmUgYXJlIGFsbCB0aGUgZGF0YSBzZXRzIEkgaW52ZXN0aWdhdGVkLCBvcmRlcmVkIGJ5ICRtJCBmcm9tIHNtYWxsZXN0IHRvIGxhcmdlc3QuCgojIyMjIGJvbm5ldGhlYWRfc2hhcmssICAkbSA9IDAuMDEkCgohW10oZmlndXJlcy9ib25uZXRoZWFkX3NoYXJrX2JpZ19wb3AucG5nKQoKCgoKIyMjIyB3YWtfY2hpbm9vaywgICRtID0gMC4wMiQKCiFbXShmaWd1cmVzL3dha19jaGlub29rX2JpZ19wb3AucG5nKQoKCiMjIyMgd2lmbCwgICRtID0gMC4wMyQKCiFbXShmaWd1cmVzL3dpZmxfYmlnX3BvcC5wbmcpCgoKCgojIyMjIHJlZF9kcnVtLCAgJG0gPSAwLjA1JAoKIVtdKGZpZ3VyZXMvcmVkX2RydW1fYmlnX3BvcC5wbmcpCgoKCgojIyMjIGFuZ3VpbGxhLCAgJG0gPSAwLjE0JAoKIVtdKGZpZ3VyZXMvYW5ndWlsbGFfYmlnX3BvcC5wbmcpCgoKCgojIyMjIGNoaW5vb2tfaGVjaHQsICAkbSA9IDAuMTckCgohW10oZmlndXJlcy9jaGlub29rX2hlY2h0X2JpZ19wb3AucG5nKQoKCgoKIyMjIyByb3N0cmF0YSwgICRtID0gMC4yMyQKCiFbXShmaWd1cmVzL3Jvc3RyYXRhX2JpZ19wb3AucG5nKQoKCgoKIyMjIyBsb2JzdGVyLCAgJG0gPSAwLjI1JAoKIVtdKGZpZ3VyZXMvbG9ic3Rlcl9iaWdfcG9wLnBuZykKCgoKCiMjIyMgYW5jaG92eSwgICRtID0gMC4yOCQKCiFbXShmaWd1cmVzL2FuY2hvdnlfYmlnX3BvcC5wbmcpCgoKCgojIyMjIHNuYWlscywgICRtID0gMC40NSQKCiFbXShmaWd1cmVzL3NuYWlsc19iaWdfcG9wLnBuZykKCgoKCiMjIyMgY2hpbm9va19nYXRrLCAgJG0gPSAwLjUwJAoKIVtdKGZpZ3VyZXMvY2hpbm9va19nYXRrX2JpZ19wb3AucG5nKQoKCgoKIyMjIyBkb2xwaGluX0xfYWxiaXJvc3RyaXMsICAkbSA9IDAuNjUkCgohW10oZmlndXJlcy9kb2xwaGluX0xfYWxiaXJvc3RyaXNfYmlnX3BvcC5wbmcpCgoKCgojIyMjIGRvbHBoaW5fTF9hY3V0dXMsICAkbSA9IDAuNzIkCgohW10oZmlndXJlcy9kb2xwaGluX0xfYWN1dHVzX2JpZ19wb3AucG5nKQoKCgoKCgojIyBBTkdTRCBhbmQgTG93IENvdmVyYWdlIFJBRCBEYXRhCgpXZSBqdXN0IHNhdyBldmlkZW5jZSBvZiB3aWRlc3ByZWFkIGdlbm90eXBpbmcgZXJyb3IgaW4gc29tZSBSQUQgZGF0YXNldHMuICBXaGF0IHNob3VsZApiZSBjbGVhciBpcyB0aGF0IG5vdCBhbGwgUkFEIGRhdGEgc2V0cyBoYXZlIGluYWNjdXJhdGUgZ2Vub3R5cGUgY2FsbHMuICBCdXQgc29tZSBvZiB0aGVtCmhhdmUgcmVhbGx5IGluYWNjdXJhdGUgZ2Vub3R5cGUgY2FsbHMuICBXZSBoYXZlbid0IGhhZCB0aW1lIHRvIGRvIGEgcHJvcGVyIGFuYWx5c2lzCm9mIGNvcnJlbGF0aW9ucyBvZiB0aGUgZ2Vub3R5cGluZyBlcnJvciByYXRlcyB3aXRoIHNlcXVlbmNpbmcgbWV0aG9kcyBhbmQgcHJvdG9jb2xzLApzbyB3ZSB3b24ndCBpbnZlc3RpZ2F0ZSB0aGF0LCBoZXJlLgoKSG93ZXZlciwgaXQgaXMgbmF0dXJhbCB0byBhc2sgd2hldGhlciBpdCBzZWVtcyBsaWtlbHkgdGhhdCBhIHByb2dyYW0gbGlrZSBBTkdTRCwgKHdoaWNoCmNhbGxzIGdlbm90eXBlcyBwcm9iYWJpbGlzdGljYWxseSB1c2luZyBhIG1vZGVsIG5vdCB1bmxpa2UgdGhlIG9uZSB0aGF0IHdlCmRldmVsb3BlZCBpbiBbYW4gZWFybGllciBzZWN0aW9uXSgjcHJvYmNhbGwpKSB3aWxsIGJlIGFibGUgdG8gYW1lbGlvcmF0ZSB0aGUgCmdlbm90eXBpbmcgZXJyb3Igc2l0dWF0aW9uIHdlIGhhdmUgZW5jb3VudGVyZWQuCgpJIGRvbid0IGhhdmUgYSB3aG9sZSBsb3Qgb2YgZXhwZXJpZW5jZSB1c2luZyBBTkdTRCwgYnV0IEkndmUgYmVlbiBpbnZvbHZlZAppbiBjaGVja2luZyBzb21lIHJlc3VsdHMgZnJvbSBhIHJlY2VudCBwYXBlciAoUHJpbmNlIGV0IGFsLikgb3V0IG9mIE1pa2UgTWlsbGVyJ3MgZ3JvdXAuICBUaGV5CnVzZWQgQU5HU0QgZm9yIG1vc3Qgb2YgdGhlaXIgYW5hbHlzZXMsIHNvIHdlIGNhbiB1c2UgdGhlaXIgZGF0YSB0byBzZWUgaG93IEFOR1NECmhhbmRsZXMgdGhpbmdzLgoKVGhlICoqY2hpbm9va19nYXRrKiogZGF0YSBzZXQgYWJvdmUgaXMgYWN0dWFsbHkgdGhlIENoaW5vb2sgZGF0YSBmcm9tIFByaW5jZSBldCBhbC4KdGhhdCBJIHJhbiB0aHJvdWdoIHRoZSBHQVRLIHBpcGVsaW5lIHVzZWQgZm9yIHRoZSB3aWZsIGRhdGEgc2V0LiAgSXQgaXMgb2J2aW91cyB0aGF0IAp0aGUgZGF0YSBkbyBub3QgY2FycnkgYXMgbXVjaCBpbmZvcm1hdGlvbiBhYm91dCBnZW5vdHlwZSBhcyB0aGUgd2lmbCBkYXRhLgoKQWxvbmdzaWRlIHRoZSBDaGlub29rIGRhdGEsIHRoZSBQcmluY2UgZXQgYWwuIHBhcGVyIGFsc28gYW5hbHl6ZWQgKGluIGEgdmVyeSBzaW1pbGFyIGZhc2hpb24pCmEgZGF0YSBzZXQgZnJvbSBzdGVlbGhlYWQgdHJvdXQuICBXZSBjYW4gc2hvdyBzb21lIEFOR1NEIHJlc3VsdHMgZnJvbSB0aGF0LgoKIyMjIEZvcmNpbmcgQU5HU0QgdG8gQ2FsbCBHZW5vdHlwZXMKCkFOR1NEIGRvZXMgbm90IGxpa2UgdG8gY2FsbCBnZW5vdHlwZXMuICBJdCBwcmVmZXJzIHRvIGNvbXB1dGUgZ2Vub3R5cGUgcG9zdGVyaW9ycwphbmQgdGhlbiBjYXJyeSB0aG9zZSB0byB0aGUgZG93bnN0cmVhbSBhbmFseXNlcy4gIEhvd2V2ZXIsIHlvdSBjYW4gZm9yY2UgaXQgdG8gY2FsbApnZW5vdHlwZXMgYW5kIHRoZW4gc3VibWl0IHRob3NlIHRvIGFuIGFuYWx5c2lzIHRvIGVzdGltYXRlICRtJCBsaWtlIHdlIGRpZCBhYm92ZS4KCkkndmUgZG9uZSB0aGF0IGZvciB0aGUgc3RlZWxoZWFkIGRhdGEsIHVzaW5nIHBhcmFtZXRlciBzZXR0aW5ncyBpZGVudGljYWwgdG8gdGhvc2UKdXNlZCBieSBQcmluY2UgZXQgYWwuIGZvciB0aGVpciBQQ0EgYW5hbHlzaXMuCgpIZXJlIGlzIHdoYXQgaXQgbG9va3MgbGlrZSB3aGVuIHdlIGRvIHRoYXQ6CgohW10oZmlndXJlcy9teWtpc3NfaHdlX3Bsb3QucG5nKQoKVGhlIHR3byBwb3B1bGF0aW9ucyBhYm92ZSBoYWQgdGhlIGhpZ2hlc3QgYXZlcmFnZSBudW1iZXIgb2YgaW5kaXZpZHVhbHMgd2l0aCBjYWxsZWQKZ2Vub3R5cGVzIG91dCBvZiBhbGwgdGhlIHNhbXBsaW5nIGxvY2F0aW9ucy4gIAoKV2hlbiB3ZSB0aHJvdyB0aGVzZSBkYXRhIGludG8gb3VyICRtJC1lc3RpbWF0aW9uIGZ1bmN0aW9uIHdlIGdldDoKClBvcHVsYXRpb24gICAgfCBFc3RpbWF0ZWQgJG0kIAotLS0tLS0tLS0tLSAgIHwgLS0tLS0tLS0tLS0tLS0KRWVsIFByZW1hdHVyZSB8IDAuNjYKVW1wcXVhIE1hdHVyZSB8IDAuNjkKClRoYXQgaXMgcXVpdGUgcG9vci4gIEJ1dCBub3RlIHRoYXQgZm9yIHRoZSBQQ0EsIFByaW5jZSBldCBhbCB1c2VkIGEgX3VuaWZvcm0gcHJpb3JfIG9uCmdlbm90eXBlcyAobWVhbmluZyB0aGF0LCBfYSBwcmlvcmlfLCBlYWNoIG9mIHRoZSB0aHJlZSBnZW5vdHlwZXMgaGFzIHRoZSBzYW1lIApwcm9iYWJpbGl0eSkuICBUaGlzIHR5cGUgb2YgbW9kZWwgaW4gQU5HU0QgZG9lcyAqKm5vdCoqIHVzZSB0aGUgZXN0aW1hdGVkIGFsbGVsZSBmcmVxdWVuY3kKdG8gcHJvdmlkZSBhIG1vZGVsIGZvciBnZW5vdHlwZSBmcmVxdWVuY2llcy4gIFNvLCB3ZSBzaG91bGQgbm90IGJlIHN1cnByaXNlZCB0aGF0IGl0IHBlcmZvcm1lZApzbyBwb29ybHkgaW4gcHJvdmlkaW5nIGluZmVycmVkIGdlbm90eXBlcy4gIAoKSG93ZXZlciwgaXQgaXMgd29ydGggbm90aW5nIHRoYXQgaWYgeW91IGFyZSBpbmZlcnJpbmcgYSBsb3Qgb2YgZ2Vub3R5cGVzIGZyb20gYSBsb3Qgb2YKZGlmZmVyZW50IHBvcHVsYXRpb25zLCB0aGlzIHByaW9yIG1ha2VzIG1vcmUgc2Vuc2UgdGhhbiB0aGUgYWxsZWxlIGZyZXF1ZW5jeSBwcmlvci4KCiMjIyBBTkdTRCB3aXRoIHRoZSBBbGxlbGUgRnJlcSBQcmlvciBmb3IgR2Vub3R5cGVzCgpXZSBnZXQgYSB2ZXJ5IGRpZmZlcmVudCBwaWN0dXJlIHdoZW4gd2UgYXBwbHkgYSBtb2RlbCBmb3IgdGhlIGdlbm90eXBlcyB0aGF0IG1ha2VzIHVzZSBvZiB0aGUKYWxsZWxlIGZyZXF1ZW5jaWVzIGFuZCBhc3N1bWVzIHRoYXQgZ2Vub3R5cGVzIHNob3VsZCBvY2N1ciBpbiBIYXJkeS1XZWluYmVyZyBwcm9wb3J0aW9ucy4gIEluIAp0aGF0IGNhc2UsIGhlcmUgYXJlIHdoYXQgdGhlIG9ic2VydmVkIHZlcnN1cyBleHBlY3RlZCBnZW5vdHlwZSBmcmVxdWVuY2llcyBwbG90IGxvb2tzIGxpa2U6CgojIyMjIFVtcHF1YSBNYXR1cmUKCiFbXShmaWd1cmVzL215a2lzc191bXBtX2FmcHJpb3JfcGxvdC5wbmcpCgoKIyMjIyBFZWwgUHJlbWF0dXJlCgohW10oZmlndXJlcy9teWtpc3NfZWVscF9hZnByaW9yX3Bsb3QucG5nKQoKVGhhdCBsb29rcyBiZXR0ZXIgdGhhbiBpdCBkb2VzIHdpdGggdGhlIHVuaWZvcm0gcHJpb3IsIGJ1dCBpdCBkb2Vzbid0IHJlYWxseSBsb29rCnRoYXQgZ29vZC4gIEl0IGNlcnRhaW5seSBkb2Vzbid0IGxvb2sgbGlrZSB3aGF0IHlvdSB3b3VsZCBleHBlY3QuICAKCldoYXQgYXJlIHRoZSBjb25zZXF1ZW5jZXMgb2YgdGhpcz8gSXQgc2VlbXMgcmVhc29uYWJsZSB0aGF0IHRoZXJlIGFyZSBhIG51bWJlcgpvZiBhbmFseXNlcyB0aGF0IG1pZ2h0IGJlIGFmZmVjdGVkIGJ5IHVucmVsaWFibGUgaW5mZXJlbmNlIG9mIGdlbm90eXBlcy4uLmFuZCBzb21lCnRoYXQgcHJvYmFibHkgYXJlIG5vdC4gIFRoYXQgd291bGQgYmUgYSBnb29kIGRpc2N1c3Npb24gaXRlbS4uLgoKIyMjIFN1YnNhbXBsaW5nIFJlYWRzIHRvIEJlZm9yZSBGZWVkaW5nIHRoZW0gaW50byBBTkdTRD8KCkRpc2NsYWltZXIgaGVyZTogSSBhbSBub3QgYW4gZXhwZXJ0IGF0IHVzaW5nIEFOR1NELCBidXQgSSBoYXZlIGFwcGxpZWQgaXQgYSBmZXcgdGltZXMuCk1vc3QgcmVjZW50bHkgSSB1c2VkIGl0IHRvIHJlcHJvZHVjZSBhIGxvdCBvZiB0aGUgd29yayBpbiB0aGUgcmVjZW50IFByaW5jZSBldCBhbC4gCnBhcGVyLiAgT25lIG9mIHRoZSB0aGluZ3MgdGhhdCBpbnRyaWd1ZWQgbWUgKGFzIGEgc3RhdGlzdGljaWFuKSB3YXMgdGhlaXIgcHJhY3RpY2UKb2YgcmFuZG9tbHkgc3Vic2FtcGxpbmcgYWxpZ25lZCwgZmlsdGVyZWQgcmVhZHMgb3V0IG9mIHRoZWlyIEJBTSBmaWxlcyBmb3IgZWFjaCBpbmRpdmlkdWFsIGJlZm9yZQphbmFseXppbmcgdGhlIGRhdGEgd2l0aCBBTkdTRC4gIFRoaXMgd2FzIGRvbmUsIGFwcGFyZW50bHksICJUbyByZW1vdmUgdmFyaWF0aW9uIGFzc29jaWF0ZWQKd2l0aCB2YXJpYWJsZSBzZXF1ZW5jaW5nIGRlcHRoLiIiIChJJ20gbm90IHN1cmUgaG93IHRoYXQgaXMgc3VwcG9zZWQgdG8gd29yay4gIFRoZSBtb2RlbHMgYXJlIHN1Y2ggdGhhdApldmVuIGlmIHlvdSBoYXZlIGEgbG90IG9mIHJlYWRzIGZyb20gb25lIGluZGl2aWR1YWwsIHRoYXQgaW5kaXZpZHVhbCB3aWxsIG5ldmVyIGJlIGdyYW50ZWQKbW9yZSB0aGFuIG9uZSBnZW5vdHlwZXMnIHdvcnRoIG9mIGluZm9ybWF0aW9uIGF0IGEgbG9jdXMpLgoKRm9yIG1vc3Qgb2YgdGhlaXIgYW5hbHlzZXMsIHRoZXkgb25seSB1c2VkIDYwLDAwMCBhbGlnbm1lbnRzIGZyb20gQ2hpbm9vayBhbmQgCjEyMCwwMDAgZnJvbSBfbXlraXNzXy4gIEhlcmUgaXMgYSBwbG90IHRoYXQgc2hvd3Mgd2hlcmUgdGhvc2UgbnVtYmVycyBhcmUgcmVsYXRpdmUKdG8gdGhlIGRpc3RyaWJ1dGlvbiBvZiBudW1iZXIgb2YgcmVhZHMgYWNyb3NzIGluZGl2aWR1YWxzLiAgVGhlIGJsYWNrIHZlcnRpY2FsIGxpbmVzIGFyZQphdCA2MEsgYW5kIDEyMEsgZm9yIENoaW5vb2sgYW5kIFN0ZWVsaGVhZCwgcmVzcGVjdGl2ZWx5LgoKIVtdKGZpZ3VyZXMvY2hpbl9teWtpc3NfcmVhZF9jb3VudF9oaXN0b3MucG5nKQoKSG9seSBNb2x5ISAgVGhhdCBpcyBhIGxvdCBvZiBkYXRhIHRoYXQgaXMgZ2V0dGluZyB0aHJvd24gYXdheS4gIChCeSBzdWJzYW1wbGluZyB0aGVzZQpCQU1zLCB0aGV5IGFyZSBlZmZlY3RpdmVseQp0b3NzaW5nIG91dCAkXGFwcHJveCQ3MCUgb2YgdGhlIHRvdGFsIG51bWJlciBvZiBhbGlnbm1uZW50cykuCgoKVGhhdCBjYW4ndCBiZSBnb29kLCBjYW4gaXQ/IAoKIyMjIEEgUENBIG9mIFdpbGxvdyBGbHljYXRjaGVycwoKSSB3YXMgYWJsZSB0byBhc3Nlc3MgdGhpcyAoYSBsaXR0bGUgYml0KSBieSB1c2luZyBLcmlzdGVuJ3MgV2lsbG93IEZseWNhdGNoZXIgZGF0YS4KV2hlbiBJIHBlcmZvcm0gYSBQQ0EgdXNpbmcgaGVyIGRhdGEgcnVuIHRocm91Z2ggaGVyIEdBVEsgcGlwZWxpbmUgKHVzaW5nIGFsbCB0aGUgcmVhZHMgbGVmdCBhZnRlcgphbGlnbm1lbnQgYW5kIGZpbHRlcmluZyBvZiBQQ1IgZHVwbGljYXRlcykgd2UgZ2V0IHF1aXRlIHN0cm9uZyBzZXBhcmF0aW9uCmJldHdlZW4gdGhlIGRpZmZlcmVudCBzdWJzcGVjaWVzIG9mIFdJRkxzIGFuZCBhbHNvIHNvbWUgZXZpZGVuY2Ugb2YgZ2VvZ3JhcGhpYwpzdHJ1Y3R1cmluZyB3aXRoaW4gdGhlIHN1YnNwZWNpZXM6CgohW10oZmlndXJlcy9nYXRrX3BjYS5wbmcpCgojIyMgQSBQQ0Egd2hlbiBXZSBTdWJzYW1wbGUgdG8gMTIwSyBSZWFkcyBhbmQgVXNlIEFOR1NEL25nc1Rvb2xzCgpIb3dldmVyLCB3ZSBjYW4gdGFrZSB0aGUgc2FtZSBkYXRhIHNldCBhbmQgYXNrLCAiV2hhdCB3b3VsZCB0aGlzIGxvb2sgbGlrZSBpZiBLcmlzdGVuCndlcmUgbm90IHN1cGVyIGRpbGlnZW50IGluIGdldHRpbmcgaGlnaCByZWFkIGRlcHRocyBmcm9tIGhpZ2ggcXVhbGl0eSBETkEsIGFuZCBzbywgaW5zdGVhZCwgCnNoZSBnb3QgbXVjaCBsb3dlciByZWFkIGRlcHRocyBhbmQgY2hvc2UgdG8gcnVuIGhlciBkYXRhIHRocm91Z2ggQU5HU0Qgd2hpbGUgc3Vic2FtcGxpbmcgaGVyCkJBTXMgdG8gMTIwSyByZWFkcz8iCgpUaGlzIGlzIGRvbmUgYnkgc2ltcGx5IHN1YnNhbXBsaW5nIHRoZSBCQU1zIHRvIDEyMEsgcmVhZHMgYW5kIHVzaW5nIG5nc0NvdmFyIHRvIHBlcmZvcm0gdGhlIApQQ0EuICBIZXJlIGlzIHdoYXQgdGhhdCBsb29rcyBsaWtlOgoKIVtdKGZpZ3VyZXMvYW5nc2RfcGNhLnBuZykKCkhtbS4uLnRoZSBfdHJhaWxpaV8gc3Vic3BlY2llcyBzaG93cyB1cCBhcyBhIGNsZWFybHkgZGlzdGluY3QgY2x1c3RlciwgYnV0IHRoZXJlIGlzIG9ubHkgbGltaXRlZApzZXBhcmF0aW9uIGJldHdlZW4gdGhlIHJlbWFpbmluZyBzdWJzcGVjaWVzLiAgVGhlIHBpY3R1cmUgaXMgbm90IHF1aXRlIHNvIGNsZWFyIGFzIGl0IGlzIHdpdGggYWxsCnRoZSBkYXRhLCBpdCBkb2Vzbid0IGFjY29yZCB3ZWxsIHdpdGggc3Vic3BlY2llcyBkZXNpZ25hdGlvbnMgYW5kIGdlb2dyYXBoaWMgc3RydWN0dXJpbmcsIGFuZCBpdAppcyBtdWNoIGhhcmRlciB0byBpZGVudGlmeSBtaXNpZGVudGlmaWVkIHNhbXBsZXMsIGV0Yy4gIAoKR2l2ZW4gdGhpcywgSSB0aGluayB0aGF0IGEgZ29vZCBkaXNjdXNzaW9uIHRvcGljIGZvciB0aGUgd2VlayBtaWdodCBiZSB0byBleHBsb3JlCmhvdyBmYXIgb25lIG91Z2h0IChvciBvdWdodG4ndCkgZ28gaW4gdGFyZ2V0aW5nIGxvdyBudW1iZXJzIG9mCnJlYWRzLCBzdWJzYW1wbGluZyB0aGVtIGV2ZW4gZnVydGhlciwgYW5kIHRoZW4gYmVsaWV2aW5nIHRoYXQgaXQKc2hvdWxkIGFsbCBiZSBPSyBiZWNhdXNlIG9uZSBpcwpnb2luZyB0byBjYWxsIGdlbm90eXBlcyBwcm9iYWJpbGlzdGljYWxseS4gIAoKIyMgV3JhcCBVcAoKS2V5IFRha2UgSG9tZSBNZXNzYWdlczoKCjEuIFRvIHRoZSBCYXllc2lhbiwgcHJvYmFiaWxpdHkgaXMgaG93IHdlIG1lYXN1cmUgdW5jZXJ0YWludHkuICAKMi4gVGhlIHBvc3RlcmlvciBpcyBwcm9wb3J0aW9uYWwgdG8gdGhlIHByaW9yIHRpbWVzIHRoZSBsaWtlbGlob29kLgozLiBNb250ZSBDYXJsbyBzYW1wbGluZyBmcm9tIGEgcG9zdGVyaW9yIGRpc3RyaWJ1dGlvbiBtYWtlcyBpdCB2ZXJ5IGVhc3kgdG8gYXNzZXNzIHRoZQpwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIG9mIGFueSBmdW5jdGlvbiBvZiB0aGUgc2FtcGxlcy4KNC4gTUNNQyBpcyB1c2VmdWwgdG8gQmF5ZXNpYW5zIGJlY2F1c2UgaXQgY2FuIHNpbXVsYXRlIGZyb20gdGhlIHBvc3RlcmlvciB3aXRob3V0IG5lZWRpbmcKdG8gY29tcHV0ZSB0aGUgbm9ybWFsaXppbmcgY29uc3RhbnQuCjUuIE1DTUMgaXMgZ3JlYXQsIGJ1dCBzaG91bGQgYmUgdXNlZCB3aXRoIGNhcmUuCjYuIEluIHRoZWlyIGVzc2VuY2UsIG1vZGVscyBmb3IgY2FsbGluZyBnZW5vdHlwZXMgcHJvYmFiaWxpc3RpY2FsbHkgd2hpbGUgZXN0aW1hdGluZyBhbmQKYWNjb3VudGluZyBmb3IgYWxsZWxlIGZyZXF1ZW5jaWVzIGFyZSBxdWl0ZSBzaW1wbGUsIGFuZCBtYWtlIGEgbG90IG9mIHNlbnNlLgo3LiBUaGVyZSBhcmUgYSBsb3Qgb2YgUkFEL0dCUy1kZXJpdmVkIGRhdGEgc2V0cyBvZiBnZW5vdHlwZXMgdGhhdCBzaG93IGV2aWRlbmNlCm9mIHByb2ZvdW5kbHkgaGlnaCByYXRlcyBvZiBoZXRlcm96eWdvdGVzIGJlaW5nIG1pc2NhbGxlZCBhcyBob21venlnb3Rlcy4gSXQgZG9lc24ndCBzZWVtCm91dCBvZiB0aGUgcXVlc3Rpb24gdGhhdCBzdWNoIGVycm9yIHJhdGVzIGNvdWxkIGluZmx1ZW5jZSBkb3duc3RyZWFtIGluZmVyZW5jZXMuCjguIEhvd2V2ZXIsIG5vdCBhbGwgc3R1ZGllcyBzaG93IHZlcnkgaGlnaCBnZW5vdHlwaW5nIGVycm9yIHJhdGVzLS0taGlnaCByZWFkIGRlcHRocyBhbmQKaW50ZWxsaWdlbnQvc3RyaW5nZW50IGZpbHRlcmluZyBjYW4gcHJldmFpbC4KOS4gUHJvYmFiaWxpc3RpYyBnZW5vdHlwZSBjYWxsaW5nIGlzIGNlcnRhaW5seSBhIHByaW5jaXBsZWQgd2F5IHRvIGFkZHJlc3MgdGhlc2UgaXNzdWVzLApidXQgaXQgaXMgbm90IGEgcGFuYWNlYS4gIEl0IHN0aWxsIGFkaGVyZXMgdG8gdGhlIHByaW5jaXBsZXMgb2YgR0lHTyBhbmQgY2FuJ3QgbWFrZSBzb21ldGhpbmcKZnJvbSBub3RoaW5nLiAKMTAuIERvbid0IGZvb2wgeW91cnNlbGYgaW50byB0aGlua2luZyB0aGF0IGJ5IHVzaW5nIHByb2JhYmlsaXN0aWMgZ2Vub3R5cGUgY2FsbGluZwp5b3Ugd29uJ3QgbG9zZSBhbnl0aGluZyB3aGVuIHlvdSBzaGF2ZSBzZXF1ZW5jaW5nIGVmZm9ydCBkb3duIHRvIGFzIGxpdHRsZSBhcyBwb3NzaWJsZS4gIApJdCBsb29rcyBsaWtlIGl0IGlzIHBvc3NpYmxlIHRvCmxvc2UgYSBmYWlyIGJpdCB3aGVuIHlvdSBnbyBkb3duIHRvIGxvdyByZWFkIGRlcHRoIC8gY292ZXJhZ2UuICBEb2luZyBzbwppbiB0aGUgY29udGV4dCBvZiB3aG9sZS1nZW5vbWUgc2VxdWVuY2luZyBtYWtlcyBzZW5zZSwgaXQgaXMgd29ydGggZGlzY3Vzc2luZyB3aGV0aGVyCmRvaW5nIFJBRCBzZXEgYW5kIHRoZW4gdGhyb3dpbmcgYXdheSBhIGxvdCBvZiB5b3VyIHJlYWRzIGFuZCByZWFkIGRlcHRoIG1ha2VzCm11Y2ggc2Vuc2UuCgoKCgoKCgoKCgoKCgoKCgoKCg==