Overview

The literature on portfolio selection under parameter uncertainty is numerous. The most common techniques involve Bayesian statistics or shrinkage. For instance, Jorion (1986) demonstrates how a decision-maker can employ Bayesian statistics from a shrinkage point of view. This decision rule is commonly known as the Bayes-Stein. Another famous paradigm is the Black and Litterman (1990) model. The latter model allows the decision-maker to incorporate individual views/beliefs about the underlying assets. As the paper’s title indicates, these views could reflect a deviation from an equilibrium model. In either case, since estimation error can be severe, especially for the mean returns, the premise behind the analysis is motivated by a variance-bias trade-off. On the one hand, the decision-maker imposes a bias on the portfolio weights. On the other hand, the inclusion of the prior is fixed and less subjected to estimation. Overall, if the prior is informative, one expects that its inclusion leads to a lower mean-squared error.

This article discusses the portfolio selection problem from a Bayesian perspective. In doing so, I first provide an overview of the portfolio problem and motivate the decision-making process from an expected utility point of view. Then, I demonstrate the analytical solution to the problem and stress the intuition behind the Bayesian application. In particular, in the case of risky assets, the optimal portfolio corresponds to three funds. The first is the minimum variance portfolio, whereas the others denote two self-financing portfolios corresponding to the mean returns. The combination between the first and the second funds is consistent with the conventional mean-variance portfolio. Furthermore, with the inclusion of the third fund, the portfolio incorporates the priors/beliefs of the decision-making into the portfolio selection. Based on the analytical insights, I conduct a small empirical experiment using two ETFs. The experiment emulates a tactical asset allocation problem. All the empirical analysis is conducted using R.

The Portfolio Problem

The decision-making problem is denoted by a decision vector \(\mathbf{d}\) and future realization of the underlying assets denoted by \(\mathbf{y}\). The former denotes the portfolio weights allocated to risky \(N\) assets, whereas the latter denotes the asset returns. The two vectors determine the wealth/reward of the investor, which is uncertain. It is commonly assumed that the parameters of the \(\mathbf{y}\) are known denoted by \(\boldsymbol{\theta}\), such that the density of \(\mathbf{y}\) is known. Nonetheless, in practice, these parameters are unknown, and their estimation is subjected to uncertainty. As a result, the decision process takes into account the conditional distribution of \(\mathbf{y}\mid\boldsymbol{\theta}\). In this regard, if we know the conditional distribution, then the decision-making process boils down to maximizing the following conditional expected utility: \[ \underset{\mathbf{d}}{\text{max}}\,\mathbb{E}\left[U(\mathbf{y}^{\top}\mathbf{d})\mid\boldsymbol{\theta}\right] \]

The standard solution to the optimization problem replaces the parameters with the sample estimates and solves for optimal portfolio. This is known as the plug-in approach. However, it is well-recognized that such practice is associated with estimation risk and poor out-of-sample portfolio performance. Additionally, the derivation of this portfolio is inconsistent with utility theory (see, e.g., Klein and Bawa (1976)).

Uncertainty about \(\boldsymbol{\theta}\) can be taken into account employing Bayes’ decision criterion. According to the Bayes’ rule, we know that the posterior is proportional to the product between the likelihood function and the prior, i.e., \[\begin{equation} p(\boldsymbol{\theta}\mid\mathbf{X},\boldsymbol{\theta}_{0})\propto p(\mathbf{X}\mid\boldsymbol{\theta})\pi(\boldsymbol{\theta}) \end{equation}\] where \(\mathbf{X}\) and \(\pi(\boldsymbol{\theta})\) denote, respectively, the sample-related information and the prior distribution. Here, \(\boldsymbol{\theta}_{0}\) denotes the beliefs about the unknown parameters.

Assumptions

We make a couple of assumptions. The first is that the decision-maker’s preference is represented using a constant absolute risk aversion (CARA) utility function. The second assumption relates to the distribution function. For the returns, we assume that the \[\begin{equation} \mathbf{y}\,\mid\boldsymbol{\theta}\sim N(\boldsymbol{\mu},\boldsymbol{\Sigma}) \end{equation}\] where \(\boldsymbol{\mu}\) and \(\boldsymbol{\Sigma}\) are unknown.

To determine the expected utility, we need to postulate an assumption regarding the priors of these two unknowns. In particular, we assume that the joint distribution between the two is Normal-Wishart, such that \[\begin{equation} \boldsymbol{\theta}\sim NW\left(\boldsymbol{\mu}_{0},\tau,\boldsymbol{\Sigma}_{0},\nu\right) \end{equation}\] with \(\tau\) and \(\mu\) denoting the parameters that determine the strength of the prior belief, whereas \(\boldsymbol{\mu}_{0}\) and \(\boldsymbol{\Sigma}_{0}\) denote the prior knowledge about the mean vector and the covariance matrix, respectively.

Optimal Portfolio

Under the above assumptions, the posterior distribution \(p(\boldsymbol{\theta}\mid\mathbf{X},\boldsymbol{\theta}_{0})\) is known. We can determine the expected utility and, hence, the optimal portfolio accordingly. Under CARA utility, we have \[\begin{equation} U(w)=-\frac{1}{\gamma}e^{-\gamma w} \end{equation}\] with \(w=\mathbf{d}^{\top}\mathbf{y}\) denote the terminal wealth for allocation \(\mathbf{d}\). According to the tower property, we know that \[\begin{equation} \mathbb{E}[U(w)]=\mathbb{E}_{\boldsymbol{\theta}}\left[\mathbb{E}[U(w)\mid\boldsymbol{\theta}]\right] \end{equation}\] where \(\mathbb{E}_{\boldsymbol{\theta}}\) denotes the expectation condition on observing data \(\mathbf{X}\) and prior \(\boldsymbol{\theta}_{0}\).

If the parameters are known, then from the moment generating function of a Gaussian variable, we have \[\begin{equation} \mathbb{E}[U(w)\mid\boldsymbol{\theta}]=-\frac{1}{\gamma}\mathbb{E}[e^{-\gamma\mathbf{d}^{\top}\mathbf{y}}\mid\boldsymbol{\theta}]=-\frac{1}{\gamma}e^{-\gamma\mathbf{d}^{\top}\boldsymbol{\mu}+\frac{\gamma^{2}}{2}\mathbf{d}^{\top}\boldsymbol{\Sigma}\mathbf{d}} \end{equation}\] Finally, the expected utility function depends on finding the expectation of \[\begin{equation} \mathbb{E}[U(w)]=-\frac{1}{\gamma}\mathbb{E}_{\boldsymbol{\theta}}\left[e^{-\gamma\mathbf{d}^{\top}\boldsymbol{\mu}+\frac{\gamma^{2}}{2}\mathbf{d}^{\top}\boldsymbol{\Sigma}\mathbf{d}}\right] \end{equation}\] which requires knowing the posterior distribution \(p(\boldsymbol{\theta}\mid\mathbf{X},\boldsymbol{\theta}_{0})\). Alternatively, we can consider the predictive density function of \(\mathbf{y}\). Under the above assumptions, \(\mathbf{y}\mid\mathbf{X},\boldsymbol{\theta}_{0}\) follows a multivariate student-t distribution. Finding the expectation of which can be obtained numerically.

Known \(\Sigma\)

While a numerical solution provides a more accurate approximation, it comes at the cost of intuition. To gain further insights about the updating process, we make one simplification. We assume that the decision-maker knows the covariance matrix without any uncertainty. In this regards, we have \(\boldsymbol{\Sigma}=\boldsymbol{\Sigma}_{0}\). Therefore, the expected utility simplifies to \[\begin{equation} \mathbb{E}[U(w)]=-\frac{1}{\gamma}e^{\frac{\gamma^{2}}{2}\mathbf{d}^{\top}\boldsymbol{\Sigma}\mathbf{d}}\mathbb{E}_{\boldsymbol{\theta}}\left[e^{-\gamma\mathbf{d}^{\top}\boldsymbol{\mu}}\right]. \end{equation}\]

In this case, we know that \[\begin{equation} \boldsymbol{\mu}\mid\mathbf{X},\boldsymbol{\mu}_{0}\sim N\left(\boldsymbol{\Sigma}_{1}\boldsymbol{\Sigma}_{0}^{-1}\boldsymbol{\mu}_{0}+\boldsymbol{\Sigma}_{1}T\boldsymbol{\Sigma}_{0}^{-1}\bar{\mathbf{y}},\boldsymbol{\Sigma}_{1}\right) \end{equation}\] with \[\begin{equation} \boldsymbol{\Sigma}_{1}^{-1}=\boldsymbol{\Sigma}_{0}^{-1}+T\boldsymbol{\Sigma}^{-1} \end{equation}\] Since \(\boldsymbol{\Sigma}=\boldsymbol{\Sigma}_{0}\), then \[\begin{equation} \boldsymbol{\Sigma}_{1}=\frac{1}{1+T}\boldsymbol{\Sigma}_{0} \end{equation}\] and \[\begin{equation} \boldsymbol{\Sigma}_{1}\boldsymbol{\Sigma}_{0}^{-1}\boldsymbol{\mu}_{0}+\boldsymbol{\Sigma}_{1}T\boldsymbol{\Sigma}_{0}^{-1}\bar{\mathbf{y}}=\frac{1}{T}\boldsymbol{\mu}_{0}+\frac{T}{1+T}\bar{\mathbf{y}} \end{equation}\] with \(T\) denoting the sample size. As a result, we have \[\begin{equation} \boldsymbol{\mu}\mid\mathbf{X},\boldsymbol{\mu}_{0}\sim N\left(\alpha\boldsymbol{\mu}_{0}+(1-\alpha)\bar{\mathbf{y}},\frac{1}{1+T}\boldsymbol{\Sigma}_{0}\right) \end{equation}\] with

\[\begin{equation} \alpha=\frac{1}{1+T}\in(0,1)\:\text{for }T>0. \end{equation}\] The expected utility is given by \[\begin{equation} \mathbb{E}[U(w)]=-\frac{1}{\gamma}\text{exp}\left(-\gamma\mathbf{d}^{\top}\left[\alpha\boldsymbol{\mu}_{0}+(1-\alpha)\bar{\mathbf{y}}\right]+(1+\alpha)\frac{\gamma^{2}}{2}\mathbf{d}^{\top}\boldsymbol{\Sigma}_{0}\mathbf{d}\right). \end{equation}\] Applying a positive transformation on the expected utility, its optimization is consistent with the following mean-variance (MV) preference: \[\begin{equation} \mathbf{d}^{\top}\left[\alpha\boldsymbol{\mu}_{0}+(1-\alpha)\bar{\mathbf{y}}\right]-\frac{\gamma}{2}(1+\alpha)\mathbf{d}^{\top}\boldsymbol{\Sigma}_{0}\mathbf{d} \end{equation}\]

Consider the case of full information in which \(T\rightarrow\infty\) such that \(\alpha\rightarrow0\). Under this extreme scenario, it is clear that the Bayesian portfolio problem converges to the conventional MV optimization. For a finite sample size, \(\alpha\) denotes the ambiguity about the mean return. The larger it is, the more variance the decision market assigns to the portfolio variance and the greater weight is attributed to the prior.

Under the constraint that \(\mathbf{d}^{\top}\mathbf{1}=1\), the optimal portfolio is given by \[\begin{equation} \mathbf{d}^{*}=\mathbf{d}_{g}+\frac{1}{1+\alpha}\mathbf{B}[\alpha\boldsymbol{\mu}_{0}+(1-\alpha)\bar{\mathbf{y}}] \end{equation}\] with \[\begin{equation} \mathbf{d}_{g}=\frac{\boldsymbol{\Sigma}_{0}^{-1}\mathbf{1}}{\mathbf{1}^{\top}\boldsymbol{\Sigma}_{0}^{-1}\mathbf{1}} \end{equation}\] denoting the global minimum variance (GMV) portfolio and \[\begin{equation} \mathbf{B}=\boldsymbol{\Sigma}_{0}^{-1}\left[\mathbf{I}-\mathbf{1}\mathbf{d}_{g}^{\top}\right] \end{equation}\] is a centering matrix around the GMV portfolio (see, e.g., Simaan et al. (2018)).

It is clear that the MV optimal portfolio consists of three funds. The first is the GMV. The second (third) is the arbitrage portfolio that depends on the prior (sample) mean return: \[\begin{equation} \mathbf{d}^{*}=\mathbf{d}_{g}+\frac{\alpha}{1+\alpha}\mathbf{B}\boldsymbol{\mu}_{0}+\frac{1-\alpha}{1+\alpha}\mathbf{B}\bar{\mathbf{y}}. \end{equation}\] To simplify, let \(\mathbf{B}_{\alpha}=(1+\alpha)^{-1}\mathbf{B}\), such that

\[\begin{equation} \mathbf{d}^{*}=\mathbf{d}_{g}+\alpha\mathbf{B}_{\alpha}\boldsymbol{\mu}_{0}+(1-\alpha)\mathbf{B}_{\alpha}\bar{\mathbf{y}}. \end{equation}\]

We observe that the Bayesian MV portfolio is a convex combination between two portfolios. Specifically, for \(\alpha\in(0,1)\) it follows that \[\begin{equation} \mathbf{d}^{*}=\alpha\mathbf{d}^{*}(\boldsymbol{\mu}_{0})+\left[1-\alpha\right]\mathbf{d}^{*}(\bar{\mathbf{y}}) \end{equation}\] with

\[\begin{equation} \mathbf{d}^{*}(\mathbf{u})=\mathbf{d}_{g}+\mathbf{B}_{\alpha}\mathbf{u}, \end{equation}\] denoting a linear function of vector \(\mathbf{u}\).

Empirical Example

Let us start with a simple numerical example. To do so, I will be working with two ETFs. The first one is the SPY ETF denoting the stock market portfolio, whereas the other is the IEF denoting the return on 7-10 years Treasury bonds.

library(quantmod)
library(lubridate)
v <- c("SPY","IEF")
t1 <- "1996-01-01" # the starting date
P.list <- lapply(v,function(x) get(getSymbols(x,from = t1)) )
P <- lapply(P.list,function(x) x[,grep("Adjusted",names(x))])
P <- Reduce(function(...) merge(...),P  )
names(P) <- v
P <- apply.monthly(P,function(x) x[nrow(x),] )
R <- na.omit(P/lag(P)-1)
R <- R["/2020-12-31",]

We consider the returns on both ETFs up to late 2020. Note that the inception of the IEF took place during the second half of 2002. For this reason, the data dates between

range(date(R))
[1] "2002-08-30" "2020-12-31"

The key to applying the Bayesian portfolio is to construct several matrices and vectors. We are also interested in evaluating the portfolio weights over time and, hence, its performance. To do so, we perform a simple backtesting procedure. At the end of each month, we consider the recent \(T\) months of data as our sample.

d <- ncol(R)
T_sample <- 12*2
month_series <- unique(ceiling_date(date(R),"m") - 1)
month_series <- month_series[year(month_series) > 2004] # keep two years for initial estimation
d_star_mat <- data.frame()
for (month_i in month_series) {
  alpha <- 1/(1+T_sample)
  e <- rep(1,d) # vector of ones
  I_mat <- diag(d) # diagonal matrix
  R_sub <- R[date(R) <= month_i,]
  R_sub <- tail(R_sub,T_sample) # sample 
  y_bar <- apply(R_sub,2,mean) # sample mean vector
  mu_0 <-  c(0.11,0.06)
  Sigma <- var(R_sub) # covariance matrix
  Sigma_inv <- solve(Sigma) # covariance matrix inverse
  d_g <- Sigma_inv%*%e/sum(Sigma_inv)
  B_mat <- Sigma_inv%*%(I_mat - e%*%t(d_g) )
  B_mat_a <- (1/(1+alpha))*B_mat
  d_star <- d_g + alpha*B_mat_a%*%mu_0 + (1-alpha)*B_mat_a%*%y_bar
  d_star <- exp(d_star)/(1+exp(d_star))
  d_star <- d_star/sum(d_star)
  d_star_mat <- rbind(d_star_mat,t(d_star))
}

A number of comments are in order. First, we note that the above procedure loops through all unique months in the data one by one. This application allows updating the sample estimates on a monthly basis. Second, the prior above corresponds to the total sample estimates of the mean return of each ETF. This approach is subjected to data snooping (look-ahead bias), since such information is only revealed after the fact. However, we do so for the sake of illustration. In the following discussion, we consider the sensitivity of the results to different priors. Third, it is well-recognized that the MV portfolio weights result in extreme positions that are considered unrealistic. To mitigate this, we consider a simple logit transformation, which is applied using these two commands:

d_star <- exp(d_star)/(1+exp(d_star))
d_star <- d_star/sum(d_star)

The second command normalizes the portfolio weights, such that its weights sum to one. While this may seem like an ad-hoc approach, this transformation results in a lower portfolio norm and is consistent with DeMiguel et al. (2009).

The plot below illustrates the weight allocated to the SPY ETF over time. We observe that the weight is above 80% the majority of the time. The weight decreases during market selloffs such as the 2007-09 financial crisis, late 2016, and COVID-19.

rownames(d_star_mat) <- month_series
d_star_mat <- as.xts(d_star_mat)
plot(d_star_mat[,1],main = "Weight to SPY")

Let us evaluate the portfolio performance in terms of return over time

R_out <- R[year(date(R)) > 2004 ,]
R_out <- as.matrix(R_out[-1,])
W_in <- as.matrix(d_star_mat[-nrow(d_star_mat)])
r_port_oos <- apply(W_in*R_out,1,sum)
names(r_port_oos) <- rownames(R_out)
r_port_oos <- as.xts(r_port_oos)

As a benchmark, we consider the famous 60-40 decision rule

W_naive <- matrix(c(0.6,0.4),nrow = nrow(W_in),2,byrow = T)
r_port_oos_naive <- apply(W_naive*R_out,1,sum)
names(r_port_oos_naive) <-  rownames(R_out)
r_port_oos_naive <- as.xts(r_port_oos_naive)
r_port_oos <- merge(r_port_oos,r_port_oos_naive) 
names(r_port_oos) <- c("Bayes","Naive")
plot(cumprod(r_port_oos+1),main = "Cumulative Return",legend.loc = "topleft")

Overall, we observe that the Bayesian portfolio outperforms the 60-40 decision rule.

Different Priors

In this section, we repeat the above analysis for different priors. For example, suppose that the decision-maker believes that the return on the SPY is negative 11%, whereas the return on the IEF stays the same. In this case, the corresponding portfolio would be tilted further towards the IEF (safer asset). As the figure below demonstrates, we note that Bayes portfolio underperforms in terms of cumulative return.

In terms of risk-adjusted returns, we compute the Sharpe-ratio for each portfolio and report below

SR_f <- function(x) sqrt(12)*mean(x)/sd(x)
result <- apply(r_port_oos, 2, SR_f)
round(data.frame(t(result)),2)

While the Bayes results in lower volatility, it is also associated with a lower return. Taken altogether, we realize that the Bayes results in a roughly similar Sharpe ratio.

In the next example, we modify the backtesting program a little. In doing so, the prior incorporates the recent one-month return as the investor’s belief. For example, at the end of month \(t\), after realizing the monthly returns between \(t-1\) and \(t\) denoted by \(\mathbf{y}_t\), the decision-maker sets the prior to \(\boldsymbol{\mu}_0 = \mathbf{y}_t\). To do so, we repeat the previous commands, however, with a small tweak in defining the prior mu_0, i.e.,

mu_0 <-  t(tail(R_sub,1))

We summarize the cumulative return in the plot below:

Interestingly, we observe that the Bayes portfolio outperforms the naive decision rule. Furthermore, in terms of risk-adjusted performance, we note that the Bayes rule outperforms the naive, resulting in a Sharpe ratio of 1.06:

result <- apply(r_port_oos, 2, SR_f)
round(data.frame(t(result)),2)

One concern with the above is that the Bayes portfolio may exhibit a higher turnover. Taking into account transaction costs (TC), it is unclear whether the Bayes still outperforms. To evaluate this, we consider a similar TC analysis pursued in this article

W_to <- W_in*(1+R_out)
W_to <- t(apply(W_to,1,function(x) t(x)/sum(x)))
W_to <- W_in[-1,] - W_to[-nrow(W_to),] 
W_to <- mean(apply(W_to,1,function(x) sum(abs(x))  ))
TO_bayes <- W_to

whereas for the naive portfolio, we have

W_to <- W_naive*(1+R_out)
W_to <- t(apply(W_to,1,function(x) t(x)/sum(x)))
W_to <- W_in[-1,] - W_to[-nrow(W_to),] 
W_to <- mean(apply(W_to,1,function(x) sum(abs(x))  ))
data.frame(Bayes = TO_bayes,Naive = W_to)

While the Bayes does include recent returns into the allocation and is subjected to more noise, its incorporation seems to have a mitigating effect. This result could potentially be due to the persistence of returns over time. To relate to this conjecture, consider the autocorrelation of each ETF over time. Using the same sample size T_sample, we compute the rolling window autocorrelation for each asset and plot the results below.

library(plyr)
R_lag <- na.omit(cbind(R_out,lag.xts(R_out,1)))
cor_roll <- rollapply(R_lag,T_sample, function(x) as.vector(cor(x)), by.column = F, align = "right")
cor_roll <- alply(cor_roll, 1, function(x) matrix(x, nrow = ncol(R_lag) )   )

spy_ar <- sapply(cor_roll,function(x) x[3,1])
ief_ar <- sapply(cor_roll,function(x) x[4,2])
AR_mat <- cbind(spy_ar,ief_ar)
rownames(AR_mat) <- rownames(R_lag)[T_sample:nrow(R_lag)]
AR_mat <- as.xts(AR_mat)
names(AR_mat) <- c("SPY","IEF")
plot(AR_mat,legend.loc = "bottomleft",main = "Autocorrelation")

The above analysis relies on the same trick done in the aforementioned article. Overall, we note the serial correlation varies over time, with values ranging between -53% and 45% for the SPY, whereas the corresponding numbers for IEF are -46% and 35%, respectively. Given the contemporaneous negative relation between the two ETFs, we also observe that both autocorrelations co-move together over time. Nonetheless, over the entire sample period, we note that both coefficients are positive.

AR_result <- data.frame(SPY = cor(R$SPY,lag(R$SPY), use = "pairwise"),
                        IEF = cor(R$IEF,lag(R$IEF), use = "pairwise"))
rownames(AR_result) <- "Autocorrelation (%)"
round(AR_result*100,2)

Remarks

The analysis above highlights several important aspects. First, the article illustrates a simple theory to link beliefs into the portfolio problem. Second, the empirical results illustrate a backtesting procedure using two assets and evaluate the sensitivity of the results using different priors. Finally, the above paradigm could provide theoretical justification for incorporating predictive models into mean-variance optimization. I leave this for future research.

References

  1. Black, F., & Litterman, R. (1990). Asset allocation: combining investor views with market equilibrium. Goldman Sachs Fixed Income Research, 115.

  2. DeMiguel, V., Garlappi, L., Nogales, F. J., & Uppal, R. (2009). A generalized approach to portfolio optimization: Improving performance by constraining portfolio norms. Management science, 55(5), 798-812.

  3. Jorion, P. (1986). Bayes-Stein estimation for portfolio analysis. Journal of Financial and Quantitative analysis, 21(3), 279-292.

  4. Klein, R. W., & Bawa, V. S. (1976). The effect of estimation risk on optimal portfolio choice. Journal of financial economics, 3(3), 215-231.

  5. Simaan, M., Simaan, Y., & Tang, Y. (2018). Estimation error in mean returns and the mean-variance efficient frontier. International Review of Economics & Finance, 56, 109-124.

LS0tCnRpdGxlOiAiQmF5ZXNpYW4gUG9ydGZvbGlvIFNlbGVjdGlvbjogQXBwbGljYXRpb24gdG8gVGFjdGljYWwgQXNzZXQgQWxsb2NhdGlvbiIKI291dHB1dDogcm1hcmtkb3duOjpnaXRodWJfZG9jdW1lbnQKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKYXV0aG9yOiBNYWplZWQgU2ltYWFuCmRhdGU6IEp1bHkgNywgMjAyMQpmaWdfd2lkdGg6IDIwCi0tLQoKIyBPdmVydmlldwpUaGUgbGl0ZXJhdHVyZSBvbiBwb3J0Zm9saW8gc2VsZWN0aW9uIHVuZGVyIHBhcmFtZXRlciB1bmNlcnRhaW50eSBpcyBudW1lcm91cy4gVGhlIG1vc3QgY29tbW9uIHRlY2huaXF1ZXMgaW52b2x2ZSBCYXllc2lhbiBzdGF0aXN0aWNzIG9yIHNocmlua2FnZS4gRm9yIGluc3RhbmNlLCBKb3Jpb24gKDE5ODYpIGRlbW9uc3RyYXRlcyBob3cgYSBkZWNpc2lvbi1tYWtlciBjYW4gZW1wbG95IEJheWVzaWFuIHN0YXRpc3RpY3MgZnJvbSBhIHNocmlua2FnZSBwb2ludCBvZiB2aWV3LiBUaGlzIGRlY2lzaW9uIHJ1bGUgaXMgY29tbW9ubHkga25vd24gYXMgdGhlIEJheWVzLVN0ZWluLiBBbm90aGVyIGZhbW91cyBwYXJhZGlnbSBpcyB0aGUgQmxhY2sgYW5kIExpdHRlcm1hbiAoMTk5MCkgIG1vZGVsLiBUaGUgbGF0dGVyIG1vZGVsIGFsbG93cyB0aGUgZGVjaXNpb24tbWFrZXIgdG8gaW5jb3Jwb3JhdGUgaW5kaXZpZHVhbCB2aWV3cy9iZWxpZWZzIGFib3V0IHRoZSB1bmRlcmx5aW5nIGFzc2V0cy4gQXMgdGhlIHBhcGVyJ3MgdGl0bGUgaW5kaWNhdGVzLCB0aGVzZSB2aWV3cyBjb3VsZCByZWZsZWN0IGEgZGV2aWF0aW9uIGZyb20gYW4gZXF1aWxpYnJpdW0gbW9kZWwuIEluIGVpdGhlciBjYXNlLCBzaW5jZSBlc3RpbWF0aW9uIGVycm9yIGNhbiBiZSBzZXZlcmUsIGVzcGVjaWFsbHkgZm9yIHRoZSBtZWFuIHJldHVybnMsIHRoZSBwcmVtaXNlIGJlaGluZCB0aGUgYW5hbHlzaXMgaXMgbW90aXZhdGVkIGJ5IGEgdmFyaWFuY2UtYmlhcyB0cmFkZS1vZmYuIE9uIHRoZSBvbmUgaGFuZCwgdGhlIGRlY2lzaW9uLW1ha2VyIGltcG9zZXMgYSBiaWFzIG9uIHRoZSBwb3J0Zm9saW8gd2VpZ2h0cy4gT24gdGhlIG90aGVyIGhhbmQsIHRoZSBpbmNsdXNpb24gb2YgdGhlIHByaW9yIGlzIGZpeGVkIGFuZCBsZXNzIHN1YmplY3RlZCB0byBlc3RpbWF0aW9uLiBPdmVyYWxsLCBpZiB0aGUgcHJpb3IgaXMgaW5mb3JtYXRpdmUsIG9uZSBleHBlY3RzIHRoYXQgaXRzIGluY2x1c2lvbiBsZWFkcyB0byBhIGxvd2VyIG1lYW4tc3F1YXJlZCBlcnJvci4KCgpUaGlzIGFydGljbGUgZGlzY3Vzc2VzIHRoZSBwb3J0Zm9saW8gc2VsZWN0aW9uIHByb2JsZW0gZnJvbSBhIEJheWVzaWFuIHBlcnNwZWN0aXZlLiBJbiBkb2luZyBzbywgSSBmaXJzdCBwcm92aWRlIGFuIG92ZXJ2aWV3IG9mIHRoZSBwb3J0Zm9saW8gcHJvYmxlbSBhbmQgbW90aXZhdGUgdGhlIGRlY2lzaW9uLW1ha2luZyBwcm9jZXNzIGZyb20gYW4gZXhwZWN0ZWQgdXRpbGl0eSBwb2ludCBvZiB2aWV3LiBUaGVuLCBJIGRlbW9uc3RyYXRlIHRoZSBhbmFseXRpY2FsIHNvbHV0aW9uIHRvIHRoZSBwcm9ibGVtIGFuZCBzdHJlc3MgdGhlIGludHVpdGlvbiBiZWhpbmQgdGhlIEJheWVzaWFuIGFwcGxpY2F0aW9uLiBJbiBwYXJ0aWN1bGFyLCBpbiB0aGUgY2FzZSBvZiByaXNreSBhc3NldHMsIHRoZSBvcHRpbWFsIHBvcnRmb2xpbyBjb3JyZXNwb25kcyB0byB0aHJlZSBmdW5kcy4gVGhlIGZpcnN0IGlzIHRoZSBtaW5pbXVtIHZhcmlhbmNlIHBvcnRmb2xpbywgd2hlcmVhcyB0aGUgb3RoZXJzIGRlbm90ZSB0d28gc2VsZi1maW5hbmNpbmcgcG9ydGZvbGlvcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBtZWFuIHJldHVybnMuIFRoZSBjb21iaW5hdGlvbiBiZXR3ZWVuIHRoZSBmaXJzdCBhbmQgdGhlIHNlY29uZCBmdW5kcyBpcyBjb25zaXN0ZW50IHdpdGggdGhlIGNvbnZlbnRpb25hbCBtZWFuLXZhcmlhbmNlIHBvcnRmb2xpby4gRnVydGhlcm1vcmUsIHdpdGggdGhlIGluY2x1c2lvbiBvZiB0aGUgdGhpcmQgZnVuZCwgdGhlIHBvcnRmb2xpbyBpbmNvcnBvcmF0ZXMgdGhlIHByaW9ycy9iZWxpZWZzIG9mIHRoZSBkZWNpc2lvbi1tYWtpbmcgaW50byB0aGUgcG9ydGZvbGlvIHNlbGVjdGlvbi4gQmFzZWQgb24gdGhlIGFuYWx5dGljYWwgaW5zaWdodHMsIEkgY29uZHVjdCBhIHNtYWxsIGVtcGlyaWNhbCBleHBlcmltZW50IHVzaW5nIHR3byBFVEZzLiBUaGUgZXhwZXJpbWVudCBlbXVsYXRlcyBhIHRhY3RpY2FsIGFzc2V0IGFsbG9jYXRpb24gcHJvYmxlbS4gQWxsIHRoZSBlbXBpcmljYWwgYW5hbHlzaXMgaXMgY29uZHVjdGVkIHVzaW5nIFIuCgoKCiMgVGhlIFBvcnRmb2xpbyBQcm9ibGVtClRoZSBkZWNpc2lvbi1tYWtpbmcgcHJvYmxlbSBpcyBkZW5vdGVkIGJ5IGEgZGVjaXNpb24gdmVjdG9yICRcbWF0aGJme2R9JAphbmQgZnV0dXJlIHJlYWxpemF0aW9uIG9mIHRoZSB1bmRlcmx5aW5nIGFzc2V0cyBkZW5vdGVkIGJ5ICRcbWF0aGJme3l9JC4KVGhlIGZvcm1lciBkZW5vdGVzIHRoZSBwb3J0Zm9saW8gd2VpZ2h0cyBhbGxvY2F0ZWQgdG8gcmlza3kgJE4kIGFzc2V0cywKd2hlcmVhcyB0aGUgbGF0dGVyIGRlbm90ZXMgdGhlIGFzc2V0IHJldHVybnMuIFRoZSB0d28gdmVjdG9ycyBkZXRlcm1pbmUKdGhlIHdlYWx0aC9yZXdhcmQgb2YgdGhlIGludmVzdG9yLCB3aGljaCBpcyB1bmNlcnRhaW4uIEl0IGlzIGNvbW1vbmx5CmFzc3VtZWQgdGhhdCB0aGUgcGFyYW1ldGVycyBvZiB0aGUgJFxtYXRoYmZ7eX0kIGFyZSBrbm93biBkZW5vdGVkCmJ5ICRcYm9sZHN5bWJvbHtcdGhldGF9JCwgc3VjaCB0aGF0IHRoZSBkZW5zaXR5IG9mICRcbWF0aGJme3l9JAppcyBrbm93bi4gTm9uZXRoZWxlc3MsIGluIHByYWN0aWNlLCB0aGVzZSBwYXJhbWV0ZXJzIGFyZSB1bmtub3duLCBhbmQgdGhlaXIgZXN0aW1hdGlvbiBpcyBzdWJqZWN0ZWQgdG8gdW5jZXJ0YWludHkuIEFzIGEgcmVzdWx0LCB0aGUgZGVjaXNpb24gcHJvY2VzcyB0YWtlcyBpbnRvIGFjY291bnQgdGhlIGNvbmRpdGlvbmFsIGRpc3RyaWJ1dGlvbiBvZiAkXG1hdGhiZnt5fVxtaWRcYm9sZHN5bWJvbHtcdGhldGF9JC4KSW4gdGhpcyByZWdhcmQsIGlmIHdlIGtub3cgdGhlIGNvbmRpdGlvbmFsIGRpc3RyaWJ1dGlvbiwgdGhlbiB0aGUgZGVjaXNpb24tbWFraW5nIHByb2Nlc3MgYm9pbHMgZG93biB0bwptYXhpbWl6aW5nIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uYWwgZXhwZWN0ZWQgdXRpbGl0eToKJCQKXHVuZGVyc2V0e1xtYXRoYmZ7ZH19e1x0ZXh0e21heH19XCxcbWF0aGJie0V9XGxlZnRbVShcbWF0aGJme3l9XntcdG9wfVxtYXRoYmZ7ZH0pXG1pZFxib2xkc3ltYm9se1x0aGV0YX1ccmlnaHRdCiQkCgpUaGUgc3RhbmRhcmQgc29sdXRpb24gdG8gdGhlIG9wdGltaXphdGlvbiBwcm9ibGVtIHJlcGxhY2VzIHRoZSBwYXJhbWV0ZXJzIHdpdGggdGhlIHNhbXBsZSBlc3RpbWF0ZXMgYW5kIHNvbHZlcyBmb3Igb3B0aW1hbCBwb3J0Zm9saW8uIFRoaXMgaXMga25vd24gYXMgdGhlIHBsdWctaW4gYXBwcm9hY2guIEhvd2V2ZXIsIGl0IGlzIHdlbGwtcmVjb2duaXplZCB0aGF0IHN1Y2ggcHJhY3RpY2UgaXMgYXNzb2NpYXRlZCB3aXRoIGVzdGltYXRpb24gcmlzayBhbmQgcG9vciBvdXQtb2Ytc2FtcGxlIHBvcnRmb2xpbyBwZXJmb3JtYW5jZS4gQWRkaXRpb25hbGx5LCB0aGUgZGVyaXZhdGlvbiBvZiB0aGlzIHBvcnRmb2xpbyBpcyBpbmNvbnNpc3RlbnQgd2l0aCB1dGlsaXR5IHRoZW9yeSAoc2VlLCBlLmcuLCBLbGVpbiBhbmQgQmF3YSAoMTk3NikpLiAKClVuY2VydGFpbnR5IGFib3V0ICRcYm9sZHN5bWJvbHtcdGhldGF9JCBjYW4gYmUgdGFrZW4gaW50byBhY2NvdW50CmVtcGxveWluZyBCYXllcycgZGVjaXNpb24gY3JpdGVyaW9uLiBBY2NvcmRpbmcgdG8gdGhlIEJheWVzJyBydWxlLAp3ZSBrbm93IHRoYXQgdGhlIHBvc3RlcmlvciBpcyBwcm9wb3J0aW9uYWwgdG8gdGhlIHByb2R1Y3QgYmV0d2Vlbgp0aGUgbGlrZWxpaG9vZCBmdW5jdGlvbiBhbmQgdGhlIHByaW9yLCBpLmUuLApcYmVnaW57ZXF1YXRpb259CnAoXGJvbGRzeW1ib2x7XHRoZXRhfVxtaWRcbWF0aGJme1h9LFxib2xkc3ltYm9se1x0aGV0YX1fezB9KVxwcm9wdG8gcChcbWF0aGJme1h9XG1pZFxib2xkc3ltYm9se1x0aGV0YX0pXHBpKFxib2xkc3ltYm9se1x0aGV0YX0pClxlbmR7ZXF1YXRpb259CndoZXJlICRcbWF0aGJme1h9JCBhbmQgJFxwaShcYm9sZHN5bWJvbHtcdGhldGF9KSQgZGVub3RlLCByZXNwZWN0aXZlbHksCnRoZSBzYW1wbGUtcmVsYXRlZCBpbmZvcm1hdGlvbiBhbmQgdGhlIHByaW9yIGRpc3RyaWJ1dGlvbi4gSGVyZSwgJFxib2xkc3ltYm9se1x0aGV0YX1fezB9JApkZW5vdGVzIHRoZSBiZWxpZWZzIGFib3V0IHRoZSB1bmtub3duIHBhcmFtZXRlcnMuCgojIEFzc3VtcHRpb25zCldlIG1ha2UgYSBjb3VwbGUgb2YgYXNzdW1wdGlvbnMuIFRoZSBmaXJzdCBpcyB0aGF0IHRoZSBkZWNpc2lvbi1tYWtlcidzIHByZWZlcmVuY2UgaXMgcmVwcmVzZW50ZWQgdXNpbmcgYSBjb25zdGFudCBhYnNvbHV0ZSByaXNrCmF2ZXJzaW9uIChDQVJBKSB1dGlsaXR5IGZ1bmN0aW9uLiBUaGUgc2Vjb25kIGFzc3VtcHRpb24gcmVsYXRlcyB0bwp0aGUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uLiBGb3IgdGhlIHJldHVybnMsIHdlIGFzc3VtZSB0aGF0IHRoZSAKXGJlZ2lue2VxdWF0aW9ufQpcbWF0aGJme3l9XCxcbWlkXGJvbGRzeW1ib2x7XHRoZXRhfVxzaW0gTihcYm9sZHN5bWJvbHtcbXV9LFxib2xkc3ltYm9se1xTaWdtYX0pClxlbmR7ZXF1YXRpb259CndoZXJlICRcYm9sZHN5bWJvbHtcbXV9JCBhbmQgJFxib2xkc3ltYm9se1xTaWdtYX0kIGFyZSB1bmtub3duLiAKClRvIGRldGVybWluZSB0aGUgZXhwZWN0ZWQgdXRpbGl0eSwgd2UgbmVlZCB0byBwb3N0dWxhdGUgYW4gYXNzdW1wdGlvbgpyZWdhcmRpbmcgdGhlIHByaW9ycyBvZiB0aGVzZSB0d28gdW5rbm93bnMuIEluIHBhcnRpY3VsYXIsIHdlIGFzc3VtZQp0aGF0IHRoZSBqb2ludCBkaXN0cmlidXRpb24gYmV0d2VlbiB0aGUgdHdvIGlzIE5vcm1hbC1XaXNoYXJ0LCBzdWNoIHRoYXQKXGJlZ2lue2VxdWF0aW9ufQpcYm9sZHN5bWJvbHtcdGhldGF9XHNpbSBOV1xsZWZ0KFxib2xkc3ltYm9se1xtdX1fezB9LFx0YXUsXGJvbGRzeW1ib2x7XFNpZ21hfV97MH0sXG51XHJpZ2h0KQpcZW5ke2VxdWF0aW9ufQp3aXRoICRcdGF1JCBhbmQgJFxtdSQgZGVub3RpbmcgdGhlIHBhcmFtZXRlcnMgdGhhdCBkZXRlcm1pbmUgdGhlCnN0cmVuZ3RoIG9mIHRoZSBwcmlvciBiZWxpZWYsIHdoZXJlYXMgJFxib2xkc3ltYm9se1xtdX1fezB9JCBhbmQKJFxib2xkc3ltYm9se1xTaWdtYX1fezB9JCBkZW5vdGUgdGhlIHByaW9yIGtub3dsZWRnZSBhYm91dCB0aGUgbWVhbgp2ZWN0b3IgYW5kIHRoZSBjb3ZhcmlhbmNlIG1hdHJpeCwgcmVzcGVjdGl2ZWx5LgoKIyBPcHRpbWFsIFBvcnRmb2xpbwpVbmRlciB0aGUgYWJvdmUgYXNzdW1wdGlvbnMsIHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uICRwKFxib2xkc3ltYm9se1x0aGV0YX1cbWlkXG1hdGhiZntYfSxcYm9sZHN5bWJvbHtcdGhldGF9X3swfSkkCmlzIGtub3duLiBXZSBjYW4gZGV0ZXJtaW5lIHRoZSBleHBlY3RlZCB1dGlsaXR5IGFuZCwgaGVuY2UsIHRoZSBvcHRpbWFsCnBvcnRmb2xpbyBhY2NvcmRpbmdseS4gVW5kZXIgQ0FSQSB1dGlsaXR5LCB3ZSBoYXZlIApcYmVnaW57ZXF1YXRpb259ClUodyk9LVxmcmFjezF9e1xnYW1tYX1lXnstXGdhbW1hIHd9ClxlbmR7ZXF1YXRpb259CndpdGggJHc9XG1hdGhiZntkfV57XHRvcH1cbWF0aGJme3l9JCBkZW5vdGUgdGhlIHRlcm1pbmFsIHdlYWx0aCBmb3IKYWxsb2NhdGlvbiAkXG1hdGhiZntkfSQuIEFjY29yZGluZyB0byB0aGUgdG93ZXIgcHJvcGVydHksIHdlIGtub3cKdGhhdApcYmVnaW57ZXF1YXRpb259ClxtYXRoYmJ7RX1bVSh3KV09XG1hdGhiYntFfV97XGJvbGRzeW1ib2x7XHRoZXRhfX1cbGVmdFtcbWF0aGJie0V9W1UodylcbWlkXGJvbGRzeW1ib2x7XHRoZXRhfV1ccmlnaHRdClxlbmR7ZXF1YXRpb259CndoZXJlICRcbWF0aGJie0V9X3tcYm9sZHN5bWJvbHtcdGhldGF9fSQgZGVub3RlcyB0aGUgZXhwZWN0YXRpb24KY29uZGl0aW9uIG9uIG9ic2VydmluZyBkYXRhICRcbWF0aGJme1h9JCBhbmQgcHJpb3IgJFxib2xkc3ltYm9se1x0aGV0YX1fezB9JC4KCklmIHRoZSBwYXJhbWV0ZXJzIGFyZSBrbm93biwgdGhlbiBmcm9tIHRoZSBtb21lbnQgZ2VuZXJhdGluZyBmdW5jdGlvbgpvZiBhIEdhdXNzaWFuIHZhcmlhYmxlLCB3ZSBoYXZlIApcYmVnaW57ZXF1YXRpb259ClxtYXRoYmJ7RX1bVSh3KVxtaWRcYm9sZHN5bWJvbHtcdGhldGF9XT0tXGZyYWN7MX17XGdhbW1hfVxtYXRoYmJ7RX1bZV57LVxnYW1tYVxtYXRoYmZ7ZH1ee1x0b3B9XG1hdGhiZnt5fX1cbWlkXGJvbGRzeW1ib2x7XHRoZXRhfV09LVxmcmFjezF9e1xnYW1tYX1lXnstXGdhbW1hXG1hdGhiZntkfV57XHRvcH1cYm9sZHN5bWJvbHtcbXV9K1xmcmFje1xnYW1tYV57Mn19ezJ9XG1hdGhiZntkfV57XHRvcH1cYm9sZHN5bWJvbHtcU2lnbWF9XG1hdGhiZntkfX0KXGVuZHtlcXVhdGlvbn0KRmluYWxseSwgdGhlIGV4cGVjdGVkIHV0aWxpdHkgZnVuY3Rpb24gZGVwZW5kcyBvbiBmaW5kaW5nIHRoZSBleHBlY3RhdGlvbgpvZiAKXGJlZ2lue2VxdWF0aW9ufQpcbWF0aGJie0V9W1UodyldPS1cZnJhY3sxfXtcZ2FtbWF9XG1hdGhiYntFfV97XGJvbGRzeW1ib2x7XHRoZXRhfX1cbGVmdFtlXnstXGdhbW1hXG1hdGhiZntkfV57XHRvcH1cYm9sZHN5bWJvbHtcbXV9K1xmcmFje1xnYW1tYV57Mn19ezJ9XG1hdGhiZntkfV57XHRvcH1cYm9sZHN5bWJvbHtcU2lnbWF9XG1hdGhiZntkfX1ccmlnaHRdClxlbmR7ZXF1YXRpb259CndoaWNoIHJlcXVpcmVzIGtub3dpbmcgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24gJHAoXGJvbGRzeW1ib2x7XHRoZXRhfVxtaWRcbWF0aGJme1h9LFxib2xkc3ltYm9se1x0aGV0YX1fezB9KSQuCkFsdGVybmF0aXZlbHksIHdlIGNhbiBjb25zaWRlciB0aGUgcHJlZGljdGl2ZSBkZW5zaXR5IGZ1bmN0aW9uIG9mCiRcbWF0aGJme3l9JC4gVW5kZXIgdGhlIGFib3ZlIGFzc3VtcHRpb25zLCAgJFxtYXRoYmZ7eX1cbWlkXG1hdGhiZntYfSxcYm9sZHN5bWJvbHtcdGhldGF9X3swfSQKZm9sbG93cyBhIG11bHRpdmFyaWF0ZSBzdHVkZW50LXQgZGlzdHJpYnV0aW9uLiBGaW5kaW5nIHRoZSBleHBlY3RhdGlvbgpvZiB3aGljaCBjYW4gYmUgb2J0YWluZWQgbnVtZXJpY2FsbHkuIAoKIyMgS25vd24gJFxTaWdtYSQKV2hpbGUgYSBudW1lcmljYWwgc29sdXRpb24gcHJvdmlkZXMgYSBtb3JlIGFjY3VyYXRlIGFwcHJveGltYXRpb24sIGl0IGNvbWVzIGF0IHRoZSBjb3N0IG9mIGludHVpdGlvbi4gVG8gZ2FpbiBmdXJ0aGVyIGluc2lnaHRzIGFib3V0IHRoZSB1cGRhdGluZyBwcm9jZXNzLCB3ZSBtYWtlIG9uZSBzaW1wbGlmaWNhdGlvbi4gV2UgYXNzdW1lIHRoYXQgdGhlIGRlY2lzaW9uLW1ha2VyIGtub3dzIHRoZSBjb3ZhcmlhbmNlIG1hdHJpeCB3aXRob3V0IGFueSB1bmNlcnRhaW50eS4gSW4gdGhpcyByZWdhcmRzLCB3ZSBoYXZlICRcYm9sZHN5bWJvbHtcU2lnbWF9PVxib2xkc3ltYm9se1xTaWdtYX1fezB9JC4gVGhlcmVmb3JlLCB0aGUgZXhwZWN0ZWQgdXRpbGl0eSBzaW1wbGlmaWVzIHRvIApcYmVnaW57ZXF1YXRpb259ClxtYXRoYmJ7RX1bVSh3KV09LVxmcmFjezF9e1xnYW1tYX1lXntcZnJhY3tcZ2FtbWFeezJ9fXsyfVxtYXRoYmZ7ZH1ee1x0b3B9XGJvbGRzeW1ib2x7XFNpZ21hfVxtYXRoYmZ7ZH19XG1hdGhiYntFfV97XGJvbGRzeW1ib2x7XHRoZXRhfX1cbGVmdFtlXnstXGdhbW1hXG1hdGhiZntkfV57XHRvcH1cYm9sZHN5bWJvbHtcbXV9fVxyaWdodF0uClxlbmR7ZXF1YXRpb259CgpJbiB0aGlzIGNhc2UsIHdlIGtub3cgdGhhdApcYmVnaW57ZXF1YXRpb259Clxib2xkc3ltYm9se1xtdX1cbWlkXG1hdGhiZntYfSxcYm9sZHN5bWJvbHtcbXV9X3swfVxzaW0gTlxsZWZ0KFxib2xkc3ltYm9se1xTaWdtYX1fezF9XGJvbGRzeW1ib2x7XFNpZ21hfV97MH1eey0xfVxib2xkc3ltYm9se1xtdX1fezB9K1xib2xkc3ltYm9se1xTaWdtYX1fezF9VFxib2xkc3ltYm9se1xTaWdtYX1fezB9XnstMX1cYmFye1xtYXRoYmZ7eX19LFxib2xkc3ltYm9se1xTaWdtYX1fezF9XHJpZ2h0KQpcZW5ke2VxdWF0aW9ufQp3aXRoClxiZWdpbntlcXVhdGlvbn0KXGJvbGRzeW1ib2x7XFNpZ21hfV97MX1eey0xfT1cYm9sZHN5bWJvbHtcU2lnbWF9X3swfV57LTF9K1RcYm9sZHN5bWJvbHtcU2lnbWF9XnstMX0KXGVuZHtlcXVhdGlvbn0KU2luY2UgJFxib2xkc3ltYm9se1xTaWdtYX09XGJvbGRzeW1ib2x7XFNpZ21hfV97MH0kLCB0aGVuClxiZWdpbntlcXVhdGlvbn0KXGJvbGRzeW1ib2x7XFNpZ21hfV97MX09XGZyYWN7MX17MStUfVxib2xkc3ltYm9se1xTaWdtYX1fezB9ClxlbmR7ZXF1YXRpb259CmFuZApcYmVnaW57ZXF1YXRpb259Clxib2xkc3ltYm9se1xTaWdtYX1fezF9XGJvbGRzeW1ib2x7XFNpZ21hfV97MH1eey0xfVxib2xkc3ltYm9se1xtdX1fezB9K1xib2xkc3ltYm9se1xTaWdtYX1fezF9VFxib2xkc3ltYm9se1xTaWdtYX1fezB9XnstMX1cYmFye1xtYXRoYmZ7eX19PVxmcmFjezF9e1R9XGJvbGRzeW1ib2x7XG11fV97MH0rXGZyYWN7VH17MStUfVxiYXJ7XG1hdGhiZnt5fX0KXGVuZHtlcXVhdGlvbn0Kd2l0aCAkVCQgZGVub3RpbmcgdGhlIHNhbXBsZSBzaXplLiBBcyBhIHJlc3VsdCwgd2UgaGF2ZQpcYmVnaW57ZXF1YXRpb259Clxib2xkc3ltYm9se1xtdX1cbWlkXG1hdGhiZntYfSxcYm9sZHN5bWJvbHtcbXV9X3swfVxzaW0gTlxsZWZ0KFxhbHBoYVxib2xkc3ltYm9se1xtdX1fezB9KygxLVxhbHBoYSlcYmFye1xtYXRoYmZ7eX19LFxmcmFjezF9ezErVH1cYm9sZHN5bWJvbHtcU2lnbWF9X3swfVxyaWdodCkKXGVuZHtlcXVhdGlvbn0Kd2l0aAoKXGJlZ2lue2VxdWF0aW9ufQpcYWxwaGE9XGZyYWN7MX17MStUfVxpbigwLDEpXDpcdGV4dHtmb3IgfVQ+MC4KXGVuZHtlcXVhdGlvbn0KVGhlIGV4cGVjdGVkIHV0aWxpdHkgaXMgZ2l2ZW4gYnkKXGJlZ2lue2VxdWF0aW9ufQpcbWF0aGJie0V9W1UodyldPS1cZnJhY3sxfXtcZ2FtbWF9XHRleHR7ZXhwfVxsZWZ0KC1cZ2FtbWFcbWF0aGJme2R9XntcdG9wfVxsZWZ0W1xhbHBoYVxib2xkc3ltYm9se1xtdX1fezB9KygxLVxhbHBoYSlcYmFye1xtYXRoYmZ7eX19XHJpZ2h0XSsoMStcYWxwaGEpXGZyYWN7XGdhbW1hXnsyfX17Mn1cbWF0aGJme2R9XntcdG9wfVxib2xkc3ltYm9se1xTaWdtYX1fezB9XG1hdGhiZntkfVxyaWdodCkuClxlbmR7ZXF1YXRpb259CkFwcGx5aW5nIGEgcG9zaXRpdmUgdHJhbnNmb3JtYXRpb24gb24gdGhlIGV4cGVjdGVkIHV0aWxpdHksIGl0cyBvcHRpbWl6YXRpb24KaXMgY29uc2lzdGVudCB3aXRoIHRoZSBmb2xsb3dpbmcgbWVhbi12YXJpYW5jZSAoTVYpIHByZWZlcmVuY2U6ClxiZWdpbntlcXVhdGlvbn0KXG1hdGhiZntkfV57XHRvcH1cbGVmdFtcYWxwaGFcYm9sZHN5bWJvbHtcbXV9X3swfSsoMS1cYWxwaGEpXGJhcntcbWF0aGJme3l9fVxyaWdodF0tXGZyYWN7XGdhbW1hfXsyfSgxK1xhbHBoYSlcbWF0aGJme2R9XntcdG9wfVxib2xkc3ltYm9se1xTaWdtYX1fezB9XG1hdGhiZntkfQpcZW5ke2VxdWF0aW9ufQoKQ29uc2lkZXIgdGhlIGNhc2Ugb2YgZnVsbCBpbmZvcm1hdGlvbiBpbiB3aGljaCAkVFxyaWdodGFycm93XGluZnR5JApzdWNoIHRoYXQgJFxhbHBoYVxyaWdodGFycm93MCQuIFVuZGVyIHRoaXMgZXh0cmVtZSBzY2VuYXJpbywgaXQgaXMKY2xlYXIgdGhhdCB0aGUgQmF5ZXNpYW4gcG9ydGZvbGlvIHByb2JsZW0gY29udmVyZ2VzIHRvIHRoZSBjb252ZW50aW9uYWwKTVYgb3B0aW1pemF0aW9uLiBGb3IgYSBmaW5pdGUgc2FtcGxlIHNpemUsICRcYWxwaGEkIGRlbm90ZXMgdGhlIGFtYmlndWl0eQphYm91dCB0aGUgbWVhbiByZXR1cm4uIFRoZSBsYXJnZXIgaXQgaXMsIHRoZSBtb3JlIHZhcmlhbmNlIHRoZSBkZWNpc2lvbgptYXJrZXQgYXNzaWducyB0byB0aGUgcG9ydGZvbGlvIHZhcmlhbmNlIGFuZCB0aGUgZ3JlYXRlciB3ZWlnaHQgaXMKYXR0cmlidXRlZCB0byB0aGUgcHJpb3IuCgpVbmRlciB0aGUgY29uc3RyYWludCB0aGF0ICRcbWF0aGJme2R9XntcdG9wfVxtYXRoYmZ7MX09MSQsIHRoZSBvcHRpbWFsCnBvcnRmb2xpbyBpcyBnaXZlbiBieSAKXGJlZ2lue2VxdWF0aW9ufQpcbWF0aGJme2R9XnsqfT1cbWF0aGJme2R9X3tnfStcZnJhY3sxfXsxK1xhbHBoYX1cbWF0aGJme0J9W1xhbHBoYVxib2xkc3ltYm9se1xtdX1fezB9KygxLVxhbHBoYSlcYmFye1xtYXRoYmZ7eX19XQpcZW5ke2VxdWF0aW9ufQp3aXRoIApcYmVnaW57ZXF1YXRpb259ClxtYXRoYmZ7ZH1fe2d9PVxmcmFje1xib2xkc3ltYm9se1xTaWdtYX1fezB9XnstMX1cbWF0aGJmezF9fXtcbWF0aGJmezF9XntcdG9wfVxib2xkc3ltYm9se1xTaWdtYX1fezB9XnstMX1cbWF0aGJmezF9fQpcZW5ke2VxdWF0aW9ufQpkZW5vdGluZyB0aGUgZ2xvYmFsIG1pbmltdW0gdmFyaWFuY2UgKEdNVikgcG9ydGZvbGlvIGFuZCAKXGJlZ2lue2VxdWF0aW9ufQpcbWF0aGJme0J9PVxib2xkc3ltYm9se1xTaWdtYX1fezB9XnstMX1cbGVmdFtcbWF0aGJme0l9LVxtYXRoYmZ7MX1cbWF0aGJme2R9X3tnfV57XHRvcH1ccmlnaHRdClxlbmR7ZXF1YXRpb259CmlzIGEgY2VudGVyaW5nIG1hdHJpeCBhcm91bmQgdGhlIEdNViBwb3J0Zm9saW8gKHNlZSwgZS5nLiwgU2ltYWFuIGV0IGFsLiAoMjAxOCkpLiAKCkl0IGlzIGNsZWFyIHRoYXQgdGhlIE1WIG9wdGltYWwgcG9ydGZvbGlvIGNvbnNpc3RzIG9mIHRocmVlIGZ1bmRzLiBUaGUgZmlyc3QgaXMgdGhlIEdNVi4gVGhlIHNlY29uZCAodGhpcmQpIGlzIHRoZSBhcmJpdHJhZ2UgcG9ydGZvbGlvIHRoYXQgZGVwZW5kcyBvbiB0aGUgcHJpb3IgKHNhbXBsZSkgbWVhbiByZXR1cm46ClxiZWdpbntlcXVhdGlvbn0KXG1hdGhiZntkfV57Kn09XG1hdGhiZntkfV97Z30rXGZyYWN7XGFscGhhfXsxK1xhbHBoYX1cbWF0aGJme0J9XGJvbGRzeW1ib2x7XG11fV97MH0rXGZyYWN7MS1cYWxwaGF9ezErXGFscGhhfVxtYXRoYmZ7Qn1cYmFye1xtYXRoYmZ7eX19LgpcZW5ke2VxdWF0aW9ufQpUbyBzaW1wbGlmeSwgbGV0ICRcbWF0aGJme0J9X3tcYWxwaGF9PSgxK1xhbHBoYSleey0xfVxtYXRoYmZ7Qn0kLApzdWNoIHRoYXQKClxiZWdpbntlcXVhdGlvbn0KXG1hdGhiZntkfV57Kn09XG1hdGhiZntkfV97Z30rXGFscGhhXG1hdGhiZntCfV97XGFscGhhfVxib2xkc3ltYm9se1xtdX1fezB9KygxLVxhbHBoYSlcbWF0aGJme0J9X3tcYWxwaGF9XGJhcntcbWF0aGJme3l9fS4KXGVuZHtlcXVhdGlvbn0KCldlIG9ic2VydmUgdGhhdCB0aGUgQmF5ZXNpYW4gTVYgcG9ydGZvbGlvIGlzIGEgY29udmV4IGNvbWJpbmF0aW9uCmJldHdlZW4gdHdvIHBvcnRmb2xpb3MuIFNwZWNpZmljYWxseSwgZm9yICRcYWxwaGFcaW4oMCwxKSQgaXQgZm9sbG93cwp0aGF0ClxiZWdpbntlcXVhdGlvbn0KXG1hdGhiZntkfV57Kn09XGFscGhhXG1hdGhiZntkfV57Kn0oXGJvbGRzeW1ib2x7XG11fV97MH0pK1xsZWZ0WzEtXGFscGhhXHJpZ2h0XVxtYXRoYmZ7ZH1eeyp9KFxiYXJ7XG1hdGhiZnt5fX0pClxlbmR7ZXF1YXRpb259CndpdGgKClxiZWdpbntlcXVhdGlvbn0KXG1hdGhiZntkfV57Kn0oXG1hdGhiZnt1fSk9XG1hdGhiZntkfV97Z30rXG1hdGhiZntCfV97XGFscGhhfVxtYXRoYmZ7dX0sClxlbmR7ZXF1YXRpb259CmRlbm90aW5nIGEgbGluZWFyIGZ1bmN0aW9uIG9mIHZlY3RvciAkXG1hdGhiZnt1fSQuIAoKIyBFbXBpcmljYWwgRXhhbXBsZQpMZXQgdXMgc3RhcnQgd2l0aCBhIHNpbXBsZSBudW1lcmljYWwgZXhhbXBsZS4gVG8gZG8gc28sIEkgd2lsbCBiZSB3b3JraW5nIHdpdGggdHdvIEVURnMuIFRoZSBmaXJzdCBvbmUgaXMgdGhlIFNQWSBFVEYgZGVub3RpbmcgdGhlIHN0b2NrIG1hcmtldCBwb3J0Zm9saW8sIHdoZXJlYXMgdGhlIG90aGVyIGlzIHRoZSBJRUYgZGVub3RpbmcgdGhlIHJldHVybiBvbiA3LTEwIHllYXJzIFRyZWFzdXJ5IGJvbmRzLiAKYGBge3IsbWVzc2FnZT1GLHdhcm5pbmc9Rn0KbGlicmFyeShxdWFudG1vZCkKbGlicmFyeShsdWJyaWRhdGUpCnYgPC0gYygiU1BZIiwiSUVGIikKdDEgPC0gIjE5OTYtMDEtMDEiICMgdGhlIHN0YXJ0aW5nIGRhdGUKUC5saXN0IDwtIGxhcHBseSh2LGZ1bmN0aW9uKHgpIGdldChnZXRTeW1ib2xzKHgsZnJvbSA9IHQxKSkgKQpQIDwtIGxhcHBseShQLmxpc3QsZnVuY3Rpb24oeCkgeFssZ3JlcCgiQWRqdXN0ZWQiLG5hbWVzKHgpKV0pClAgPC0gUmVkdWNlKGZ1bmN0aW9uKC4uLikgbWVyZ2UoLi4uKSxQICApCm5hbWVzKFApIDwtIHYKUCA8LSBhcHBseS5tb250aGx5KFAsZnVuY3Rpb24oeCkgeFtucm93KHgpLF0gKQpSIDwtIG5hLm9taXQoUC9sYWcoUCktMSkKUiA8LSBSWyIvMjAyMC0xMi0zMSIsXQpgYGAKCldlIGNvbnNpZGVyIHRoZSByZXR1cm5zIG9uIGJvdGggRVRGcyB1cCB0byBsYXRlIDIwMjAuIE5vdGUgdGhhdCB0aGUgaW5jZXB0aW9uIG9mIHRoZSBJRUYgdG9vayBwbGFjZSBkdXJpbmcgdGhlIHNlY29uZCBoYWxmIG9mIDIwMDIuICBGb3IgdGhpcyByZWFzb24sIHRoZSBkYXRhIGRhdGVzIGJldHdlZW4KYGBge3J9CnJhbmdlKGRhdGUoUikpCmBgYApUaGUga2V5IHRvIGFwcGx5aW5nIHRoZSBCYXllc2lhbiBwb3J0Zm9saW8gaXMgdG8gY29uc3RydWN0IHNldmVyYWwgbWF0cmljZXMgYW5kIHZlY3RvcnMuIFdlIGFyZSBhbHNvIGludGVyZXN0ZWQgaW4gZXZhbHVhdGluZyB0aGUgcG9ydGZvbGlvIHdlaWdodHMgb3ZlciB0aW1lIGFuZCwgaGVuY2UsIGl0cyBwZXJmb3JtYW5jZS4gVG8gZG8gc28sIHdlIHBlcmZvcm0gYSBzaW1wbGUgYmFja3Rlc3RpbmcgcHJvY2VkdXJlLiBBdCB0aGUgZW5kIG9mIGVhY2ggbW9udGgsIHdlIGNvbnNpZGVyIHRoZSByZWNlbnQgJFQkIG1vbnRocyBvZiBkYXRhIGFzIG91ciBzYW1wbGUuCmBgYHtyLG91dC53aWR0aCA9ICc3NSUnLGZpZy5hbGlnbj0iY2VudGVyIn0KZCA8LSBuY29sKFIpClRfc2FtcGxlIDwtIDEyKjIKbW9udGhfc2VyaWVzIDwtIHVuaXF1ZShjZWlsaW5nX2RhdGUoZGF0ZShSKSwibSIpIC0gMSkKbW9udGhfc2VyaWVzIDwtIG1vbnRoX3Nlcmllc1t5ZWFyKG1vbnRoX3NlcmllcykgPiAyMDA0XSAjIGtlZXAgdHdvIHllYXJzIGZvciBpbml0aWFsIGVzdGltYXRpb24KZF9zdGFyX21hdCA8LSBkYXRhLmZyYW1lKCkKZm9yIChtb250aF9pIGluIG1vbnRoX3NlcmllcykgewogIGFscGhhIDwtIDEvKDErVF9zYW1wbGUpCiAgZSA8LSByZXAoMSxkKSAjIHZlY3RvciBvZiBvbmVzCiAgSV9tYXQgPC0gZGlhZyhkKSAjIGRpYWdvbmFsIG1hdHJpeAogIFJfc3ViIDwtIFJbZGF0ZShSKSA8PSBtb250aF9pLF0KICBSX3N1YiA8LSB0YWlsKFJfc3ViLFRfc2FtcGxlKSAjIHNhbXBsZSAKICB5X2JhciA8LSBhcHBseShSX3N1YiwyLG1lYW4pICMgc2FtcGxlIG1lYW4gdmVjdG9yCiAgbXVfMCA8LSAgYygwLjExLDAuMDYpCiAgU2lnbWEgPC0gdmFyKFJfc3ViKSAjIGNvdmFyaWFuY2UgbWF0cml4CiAgU2lnbWFfaW52IDwtIHNvbHZlKFNpZ21hKSAjIGNvdmFyaWFuY2UgbWF0cml4IGludmVyc2UKICBkX2cgPC0gU2lnbWFfaW52JSolZS9zdW0oU2lnbWFfaW52KQogIEJfbWF0IDwtIFNpZ21hX2ludiUqJShJX21hdCAtIGUlKiV0KGRfZykgKQogIEJfbWF0X2EgPC0gKDEvKDErYWxwaGEpKSpCX21hdAogIGRfc3RhciA8LSBkX2cgKyBhbHBoYSpCX21hdF9hJSolbXVfMCArICgxLWFscGhhKSpCX21hdF9hJSoleV9iYXIKICBkX3N0YXIgPC0gZXhwKGRfc3RhcikvKDErZXhwKGRfc3RhcikpCiAgZF9zdGFyIDwtIGRfc3Rhci9zdW0oZF9zdGFyKQogIGRfc3Rhcl9tYXQgPC0gcmJpbmQoZF9zdGFyX21hdCx0KGRfc3RhcikpCn0KYGBgCkEgbnVtYmVyIG9mIGNvbW1lbnRzIGFyZSBpbiBvcmRlci4gRmlyc3QsIHdlIG5vdGUgdGhhdCB0aGUgYWJvdmUgcHJvY2VkdXJlIGxvb3BzIHRocm91Z2ggYWxsIHVuaXF1ZSBtb250aHMgaW4gdGhlIGRhdGEgb25lIGJ5IG9uZS4gVGhpcyBhcHBsaWNhdGlvbiBhbGxvd3MgdXBkYXRpbmcgdGhlIHNhbXBsZSBlc3RpbWF0ZXMgb24gYSBtb250aGx5IGJhc2lzLiAKU2Vjb25kLCB0aGUgcHJpb3IgYWJvdmUgY29ycmVzcG9uZHMgdG8gdGhlIHRvdGFsIHNhbXBsZSBlc3RpbWF0ZXMgb2YgdGhlIG1lYW4gcmV0dXJuIG9mIGVhY2ggRVRGLiBUaGlzIGFwcHJvYWNoIGlzIHN1YmplY3RlZCB0byBkYXRhIHNub29waW5nIChsb29rLWFoZWFkIGJpYXMpLCBzaW5jZSBzdWNoIGluZm9ybWF0aW9uIGlzIG9ubHkgcmV2ZWFsZWQgYWZ0ZXIgdGhlIGZhY3QuIEhvd2V2ZXIsIHdlIGRvIHNvIGZvciB0aGUgc2FrZSBvZiBpbGx1c3RyYXRpb24uIEluIHRoZSBmb2xsb3dpbmcgZGlzY3Vzc2lvbiwgd2UgY29uc2lkZXIgdGhlIHNlbnNpdGl2aXR5IG9mIHRoZSByZXN1bHRzIHRvIGRpZmZlcmVudCBwcmlvcnMuClRoaXJkLCBpdCBpcyB3ZWxsLXJlY29nbml6ZWQgdGhhdCB0aGUgTVYgcG9ydGZvbGlvIHdlaWdodHMgcmVzdWx0IGluIGV4dHJlbWUgcG9zaXRpb25zIHRoYXQgYXJlIGNvbnNpZGVyZWQgdW5yZWFsaXN0aWMuIFRvIG1pdGlnYXRlIHRoaXMsIHdlIGNvbnNpZGVyIGEgc2ltcGxlIGxvZ2l0IHRyYW5zZm9ybWF0aW9uLCB3aGljaCBpcyBhcHBsaWVkIHVzaW5nIHRoZXNlIHR3byBjb21tYW5kczoKYGBge3IsZXZhbD1GQUxTRX0KZF9zdGFyIDwtIGV4cChkX3N0YXIpLygxK2V4cChkX3N0YXIpKQpkX3N0YXIgPC0gZF9zdGFyL3N1bShkX3N0YXIpCmBgYApUaGUgc2Vjb25kIGNvbW1hbmQgbm9ybWFsaXplcyB0aGUgcG9ydGZvbGlvIHdlaWdodHMsIHN1Y2ggdGhhdCBpdHMgd2VpZ2h0cyBzdW0gdG8gb25lLiBXaGlsZSB0aGlzIG1heSBzZWVtIGxpa2UgYW4gYWQtaG9jIGFwcHJvYWNoLCB0aGlzIHRyYW5zZm9ybWF0aW9uIHJlc3VsdHMgaW4gYSBsb3dlciBwb3J0Zm9saW8gbm9ybSBhbmQgaXMgY29uc2lzdGVudCB3aXRoIERlTWlndWVsIGV0IGFsLiAoMjAwOSkuIAoKVGhlIHBsb3QgYmVsb3cgaWxsdXN0cmF0ZXMgdGhlIHdlaWdodCBhbGxvY2F0ZWQgdG8gdGhlIFNQWSBFVEYgb3ZlciB0aW1lLiBXZSBvYnNlcnZlIHRoYXQgdGhlIHdlaWdodCBpcyBhYm92ZSA4MFwlIHRoZSBtYWpvcml0eSBvZiB0aGUgdGltZS4gVGhlIHdlaWdodCBkZWNyZWFzZXMgZHVyaW5nIG1hcmtldCBzZWxsb2ZmcyBzdWNoIGFzIHRoZSAyMDA3LTA5IGZpbmFuY2lhbCBjcmlzaXMsIGxhdGUgMjAxNiwgYW5kIENPVklELTE5LiAKYGBge3J9CnJvd25hbWVzKGRfc3Rhcl9tYXQpIDwtIG1vbnRoX3NlcmllcwpkX3N0YXJfbWF0IDwtIGFzLnh0cyhkX3N0YXJfbWF0KQpwbG90KGRfc3Rhcl9tYXRbLDFdLG1haW4gPSAiV2VpZ2h0IHRvIFNQWSIpCmBgYAoKTGV0IHVzIGV2YWx1YXRlIHRoZSBwb3J0Zm9saW8gcGVyZm9ybWFuY2UgaW4gdGVybXMgb2YgcmV0dXJuIG92ZXIgdGltZQpgYGB7cn0KUl9vdXQgPC0gUlt5ZWFyKGRhdGUoUikpID4gMjAwNCAsXQpSX291dCA8LSBhcy5tYXRyaXgoUl9vdXRbLTEsXSkKV19pbiA8LSBhcy5tYXRyaXgoZF9zdGFyX21hdFstbnJvdyhkX3N0YXJfbWF0KV0pCnJfcG9ydF9vb3MgPC0gYXBwbHkoV19pbipSX291dCwxLHN1bSkKbmFtZXMocl9wb3J0X29vcykgPC0gcm93bmFtZXMoUl9vdXQpCnJfcG9ydF9vb3MgPC0gYXMueHRzKHJfcG9ydF9vb3MpCmBgYApBcyBhIGJlbmNobWFyaywgd2UgY29uc2lkZXIgdGhlIGZhbW91cyA2MC00MCBkZWNpc2lvbiBydWxlCmBgYHtyfQpXX25haXZlIDwtIG1hdHJpeChjKDAuNiwwLjQpLG5yb3cgPSBucm93KFdfaW4pLDIsYnlyb3cgPSBUKQpyX3BvcnRfb29zX25haXZlIDwtIGFwcGx5KFdfbmFpdmUqUl9vdXQsMSxzdW0pCm5hbWVzKHJfcG9ydF9vb3NfbmFpdmUpIDwtICByb3duYW1lcyhSX291dCkKcl9wb3J0X29vc19uYWl2ZSA8LSBhcy54dHMocl9wb3J0X29vc19uYWl2ZSkKYGBgCgpgYGB7cixvdXQud2lkdGggPSAnNzUlJyxmaWcuYWxpZ249ImNlbnRlciJ9CnJfcG9ydF9vb3MgPC0gbWVyZ2Uocl9wb3J0X29vcyxyX3BvcnRfb29zX25haXZlKSAKbmFtZXMocl9wb3J0X29vcykgPC0gYygiQmF5ZXMiLCJOYWl2ZSIpCnBsb3QoY3VtcHJvZChyX3BvcnRfb29zKzEpLG1haW4gPSAiQ3VtdWxhdGl2ZSBSZXR1cm4iLGxlZ2VuZC5sb2MgPSAidG9wbGVmdCIpCmBgYApPdmVyYWxsLCB3ZSBvYnNlcnZlIHRoYXQgdGhlIEJheWVzaWFuIHBvcnRmb2xpbyBvdXRwZXJmb3JtcyB0aGUgNjAtNDAgZGVjaXNpb24gcnVsZS4gCgojIyBEaWZmZXJlbnQgUHJpb3JzCkluIHRoaXMgc2VjdGlvbiwgd2UgcmVwZWF0IHRoZSBhYm92ZSBhbmFseXNpcyBmb3IgZGlmZmVyZW50IHByaW9ycy4gRm9yIGV4YW1wbGUsIHN1cHBvc2UgdGhhdCB0aGUgZGVjaXNpb24tbWFrZXIgYmVsaWV2ZXMgdGhhdCB0aGUgcmV0dXJuIG9uIHRoZSBTUFkgaXMgbmVnYXRpdmUgMTFcJSwgd2hlcmVhcyB0aGUgcmV0dXJuIG9uIHRoZSBJRUYgc3RheXMgdGhlIHNhbWUuIEluIHRoaXMgY2FzZSwgdGhlIGNvcnJlc3BvbmRpbmcgcG9ydGZvbGlvIHdvdWxkIGJlIHRpbHRlZCBmdXJ0aGVyIHRvd2FyZHMgdGhlIElFRiAoc2FmZXIgYXNzZXQpLiBBcyB0aGUgZmlndXJlIGJlbG93IGRlbW9uc3RyYXRlcywgd2Ugbm90ZSB0aGF0IEJheWVzIHBvcnRmb2xpbyB1bmRlcnBlcmZvcm1zIGluIHRlcm1zIG9mIGN1bXVsYXRpdmUgcmV0dXJuLgpgYGB7cixlY2hvPUYsZmlnLmFsaWduPSJjZW50ZXIiLG91dC53aWR0aCA9ICc3NSUnfQpkX3N0YXJfbWF0IDwtIGRhdGEuZnJhbWUoKQpmb3IgKG1vbnRoX2kgaW4gbW9udGhfc2VyaWVzKSB7CiAgYWxwaGEgPC0gMS8oMStUX3NhbXBsZSkKICBlIDwtIHJlcCgxLGQpICMgdmVjdG9yIG9mIG9uZXMKICBJX21hdCA8LSBkaWFnKGQpICMgZGlhZ29uYWwgbWF0cml4CiAgUl9zdWIgPC0gUltkYXRlKFIpIDw9IG1vbnRoX2ksXQogIFJfc3ViIDwtIHRhaWwoUl9zdWIsVF9zYW1wbGUpICMgc2FtcGxlIAogIHlfYmFyIDwtIGFwcGx5KFJfc3ViLDIsbWVhbikgIyBzYW1wbGUgbWVhbiB2ZWN0b3IKICBtdV8wIDwtICBjKC0wLjExLDAuMDYpCiAgU2lnbWEgPC0gdmFyKFJfc3ViKSAjIGNvdmFyaWFuY2UgbWF0cml4CiAgU2lnbWFfaW52IDwtIHNvbHZlKFNpZ21hKSAjIGNvdmFyaWFuY2UgbWF0cml4IGludmVyc2UKICBkX2cgPC0gU2lnbWFfaW52JSolZS9zdW0oU2lnbWFfaW52KQogIEJfbWF0IDwtIFNpZ21hX2ludiUqJShJX21hdCAtIGUlKiV0KGRfZykgKQogIEJfbWF0X2EgPC0gKDEvKDErYWxwaGEpKSpCX21hdAogIGRfc3RhciA8LSBkX2cgKyBhbHBoYSpCX21hdF9hJSolbXVfMCArICgxLWFscGhhKSpCX21hdF9hJSoleV9iYXIKICBkX3N0YXIgPC0gZXhwKGRfc3RhcikvKDErZXhwKGRfc3RhcikpCiAgZF9zdGFyIDwtIGRfc3Rhci9zdW0oZF9zdGFyKQogIGRfc3Rhcl9tYXQgPC0gcmJpbmQoZF9zdGFyX21hdCx0KGRfc3RhcikpCn0KCnJvd25hbWVzKGRfc3Rhcl9tYXQpIDwtIG1vbnRoX3NlcmllcwpkX3N0YXJfbWF0IDwtIGFzLnh0cyhkX3N0YXJfbWF0KQpSX291dCA8LSBSW3llYXIoZGF0ZShSKSkgPiAyMDA0ICxdClJfb3V0IDwtIGFzLm1hdHJpeChSX291dFstMSxdKQpXX2luIDwtIGFzLm1hdHJpeChkX3N0YXJfbWF0Wy1ucm93KGRfc3Rhcl9tYXQpXSkKcl9wb3J0X29vcyA8LSBhcHBseShXX2luKlJfb3V0LDEsc3VtKQpuYW1lcyhyX3BvcnRfb29zKSA8LSByb3duYW1lcyhSX291dCkKcl9wb3J0X29vcyA8LSBhcy54dHMocl9wb3J0X29vcykKCldfbmFpdmUgPC0gbWF0cml4KGMoMC42LDAuNCksbnJvdyA9IG5yb3coV19pbiksMixieXJvdyA9IFQpCnJfcG9ydF9vb3NfbmFpdmUgPC0gYXBwbHkoV19uYWl2ZSpSX291dCwxLHN1bSkKbmFtZXMocl9wb3J0X29vc19uYWl2ZSkgPC0gIHJvd25hbWVzKFJfb3V0KQpyX3BvcnRfb29zX25haXZlIDwtIGFzLnh0cyhyX3BvcnRfb29zX25haXZlKQoKcl9wb3J0X29vcyA8LSBtZXJnZShyX3BvcnRfb29zLHJfcG9ydF9vb3NfbmFpdmUpIApuYW1lcyhyX3BvcnRfb29zKSA8LSBjKCJCYXllcyIsIk5haXZlIikKcGxvdChjdW1wcm9kKHJfcG9ydF9vb3MrMSksbWFpbiA9ICJDdW11bGF0aXZlIFJldHVybiIsbGVnZW5kLmxvYyA9ICJ0b3BsZWZ0IikKYGBgCkluIHRlcm1zIG9mIHJpc2stYWRqdXN0ZWQgcmV0dXJucywgd2UgY29tcHV0ZSB0aGUgU2hhcnBlLXJhdGlvIGZvciBlYWNoIHBvcnRmb2xpbyBhbmQgcmVwb3J0IGJlbG93CmBgYHtyfQpTUl9mIDwtIGZ1bmN0aW9uKHgpIHNxcnQoMTIpKm1lYW4oeCkvc2QoeCkKcmVzdWx0IDwtIGFwcGx5KHJfcG9ydF9vb3MsIDIsIFNSX2YpCnJvdW5kKGRhdGEuZnJhbWUodChyZXN1bHQpKSwyKQpgYGAKV2hpbGUgdGhlIEJheWVzIHJlc3VsdHMgaW4gbG93ZXIgdm9sYXRpbGl0eSwgaXQgaXMgYWxzbyBhc3NvY2lhdGVkIHdpdGggYSBsb3dlciByZXR1cm4uIFRha2VuIGFsdG9nZXRoZXIsIHdlIHJlYWxpemUgdGhhdCB0aGUgQmF5ZXMgcmVzdWx0cyBpbiBhIHJvdWdobHkgc2ltaWxhciBTaGFycGUgcmF0aW8uCgpJbiB0aGUgbmV4dCBleGFtcGxlLCB3ZSBtb2RpZnkgdGhlIGJhY2t0ZXN0aW5nIHByb2dyYW0gYSBsaXR0bGUuIEluIGRvaW5nIHNvLCB0aGUgcHJpb3IgaW5jb3Jwb3JhdGVzIHRoZSByZWNlbnQgb25lLW1vbnRoIHJldHVybiBhcyB0aGUgaW52ZXN0b3IncyBiZWxpZWYuIEZvciBleGFtcGxlLCBhdCB0aGUgZW5kIG9mIG1vbnRoICR0JCwgYWZ0ZXIgcmVhbGl6aW5nIHRoZSBtb250aGx5IHJldHVybnMgYmV0d2VlbiAkdC0xJCBhbmQgJHQkIGRlbm90ZWQgYnkgJFxtYXRoYmZ7eX1fdCQsIHRoZSBkZWNpc2lvbi1tYWtlciBzZXRzIHRoZSBwcmlvciB0byAkXGJvbGRzeW1ib2x7XG11fV8wID0gXG1hdGhiZnt5fV90JC4gVG8gZG8gc28sIHdlIHJlcGVhdCB0aGUgcHJldmlvdXMgY29tbWFuZHMsIGhvd2V2ZXIsIHdpdGggYSBzbWFsbCB0d2VhayBpbiBkZWZpbmluZyB0aGUgcHJpb3IgYG11XzBgLCBpLmUuLApgYGB7cixldmFsPUZBTFNFfQptdV8wIDwtICB0KHRhaWwoUl9zdWIsMSkpCmBgYApXZSBzdW1tYXJpemUgdGhlIGN1bXVsYXRpdmUgcmV0dXJuIGluIHRoZSBwbG90IGJlbG93OgpgYGB7cixmaWcuYWxpZ249ImNlbnRlciIsZWNobz1GQUxTRSxvdXQud2lkdGggPSAnNzUlJ30KZF9zdGFyX21hdCA8LSBkYXRhLmZyYW1lKCkKZm9yIChtb250aF9pIGluIG1vbnRoX3NlcmllcykgewogIGFscGhhIDwtIDEvKDErVF9zYW1wbGUpCiAgZSA8LSByZXAoMSxkKSAjIHZlY3RvciBvZiBvbmVzCiAgSV9tYXQgPC0gZGlhZyhkKSAjIGRpYWdvbmFsIG1hdHJpeAogIFJfc3ViIDwtIFJbZGF0ZShSKSA8PSBtb250aF9pLF0KICBSX3N1YiA8LSB0YWlsKFJfc3ViLFRfc2FtcGxlKSAjIHNhbXBsZSAKICB5X2JhciA8LSBhcHBseShSX3N1YiwyLG1lYW4pICMgc2FtcGxlIG1lYW4gdmVjdG9yCiAgbXVfMCA8LSAgdCh0YWlsKFJfc3ViLDEpKQogIFNpZ21hIDwtIHZhcihSX3N1YikgIyBjb3ZhcmlhbmNlIG1hdHJpeAogIFNpZ21hX2ludiA8LSBzb2x2ZShTaWdtYSkgIyBjb3ZhcmlhbmNlIG1hdHJpeCBpbnZlcnNlCiAgZF9nIDwtIFNpZ21hX2ludiUqJWUvc3VtKFNpZ21hX2ludikKICBCX21hdCA8LSBTaWdtYV9pbnYlKiUoSV9tYXQgLSBlJSoldChkX2cpICkKICBCX21hdF9hIDwtICgxLygxK2FscGhhKSkqQl9tYXQKICBkX3N0YXIgPC0gZF9nICsgYWxwaGEqQl9tYXRfYSUqJW11XzAgKyAoMS1hbHBoYSkqQl9tYXRfYSUqJXlfYmFyCiAgZF9zdGFyIDwtIGV4cChkX3N0YXIpLygxK2V4cChkX3N0YXIpKQogIGRfc3RhciA8LSBkX3N0YXIvc3VtKGRfc3RhcikKICBkX3N0YXJfbWF0IDwtIHJiaW5kKGRfc3Rhcl9tYXQsdChkX3N0YXIpKQp9Cgpyb3duYW1lcyhkX3N0YXJfbWF0KSA8LSBtb250aF9zZXJpZXMKZF9zdGFyX21hdCA8LSBhcy54dHMoZF9zdGFyX21hdCkKUl9vdXQgPC0gUlt5ZWFyKGRhdGUoUikpID4gMjAwNCAsXQpSX291dCA8LSBhcy5tYXRyaXgoUl9vdXRbLTEsXSkKV19pbiA8LSBhcy5tYXRyaXgoZF9zdGFyX21hdFstbnJvdyhkX3N0YXJfbWF0KV0pCnJfcG9ydF9vb3MgPC0gYXBwbHkoV19pbipSX291dCwxLHN1bSkKbmFtZXMocl9wb3J0X29vcykgPC0gcm93bmFtZXMoUl9vdXQpCnJfcG9ydF9vb3MgPC0gYXMueHRzKHJfcG9ydF9vb3MpCgpXX25haXZlIDwtIG1hdHJpeChjKDAuNiwwLjQpLG5yb3cgPSBucm93KFdfaW4pLDIsYnlyb3cgPSBUKQpyX3BvcnRfb29zX25haXZlIDwtIGFwcGx5KFdfbmFpdmUqUl9vdXQsMSxzdW0pCm5hbWVzKHJfcG9ydF9vb3NfbmFpdmUpIDwtICByb3duYW1lcyhSX291dCkKcl9wb3J0X29vc19uYWl2ZSA8LSBhcy54dHMocl9wb3J0X29vc19uYWl2ZSkKCnJfcG9ydF9vb3MgPC0gbWVyZ2Uocl9wb3J0X29vcyxyX3BvcnRfb29zX25haXZlKSAKbmFtZXMocl9wb3J0X29vcykgPC0gYygiQmF5ZXMiLCJOYWl2ZSIpCnBsb3QoY3VtcHJvZChyX3BvcnRfb29zKzEpLG1haW4gPSAiQ3VtdWxhdGl2ZSBSZXR1cm4iLGxlZ2VuZC5sb2MgPSAidG9wbGVmdCIpCmBgYApJbnRlcmVzdGluZ2x5LCB3ZSBvYnNlcnZlIHRoYXQgdGhlIEJheWVzIHBvcnRmb2xpbyBvdXRwZXJmb3JtcyB0aGUgbmFpdmUgZGVjaXNpb24gcnVsZS4gRnVydGhlcm1vcmUsIGluIHRlcm1zIG9mIHJpc2stYWRqdXN0ZWQgcGVyZm9ybWFuY2UsIHdlIG5vdGUgdGhhdCB0aGUgQmF5ZXMgcnVsZSBvdXRwZXJmb3JtcyB0aGUgbmFpdmUsIHJlc3VsdGluZyBpbiBhIFNoYXJwZSByYXRpbyBvZiBgciByb3VuZChyZXN1bHQsMilbMV1gOgpgYGB7cn0KcmVzdWx0IDwtIGFwcGx5KHJfcG9ydF9vb3MsIDIsIFNSX2YpCnJvdW5kKGRhdGEuZnJhbWUodChyZXN1bHQpKSwyKQpgYGAKCk9uZSBjb25jZXJuIHdpdGggdGhlIGFib3ZlIGlzIHRoYXQgdGhlIEJheWVzIHBvcnRmb2xpbyBtYXkgZXhoaWJpdCBhIGhpZ2hlciB0dXJub3Zlci4gVGFraW5nIGludG8gYWNjb3VudCB0cmFuc2FjdGlvbiBjb3N0cyAoVEMpLCBpdCBpcyB1bmNsZWFyIHdoZXRoZXIgdGhlIEJheWVzIHN0aWxsIG91dHBlcmZvcm1zLiBUbyBldmFsdWF0ZSB0aGlzLCB3ZSBjb25zaWRlciBhIHNpbWlsYXIgVEMgYW5hbHlzaXMgcHVyc3VlZCBpbiB0aGlzIFthcnRpY2xlXShodHRwczovL3JwdWJzLmNvbS9zaW1hYW44NC9wb3J0X29wdCkKYGBge3J9CldfdG8gPC0gV19pbiooMStSX291dCkKV190byA8LSB0KGFwcGx5KFdfdG8sMSxmdW5jdGlvbih4KSB0KHgpL3N1bSh4KSkpCldfdG8gPC0gV19pblstMSxdIC0gV190b1stbnJvdyhXX3RvKSxdIApXX3RvIDwtIG1lYW4oYXBwbHkoV190bywxLGZ1bmN0aW9uKHgpIHN1bShhYnMoeCkpICApKQpUT19iYXllcyA8LSBXX3RvCmBgYAp3aGVyZWFzIGZvciB0aGUgbmFpdmUgcG9ydGZvbGlvLCB3ZSBoYXZlCmBgYHtyfQpXX3RvIDwtIFdfbmFpdmUqKDErUl9vdXQpCldfdG8gPC0gdChhcHBseShXX3RvLDEsZnVuY3Rpb24oeCkgdCh4KS9zdW0oeCkpKQpXX3RvIDwtIFdfaW5bLTEsXSAtIFdfdG9bLW5yb3coV190byksXSAKV190byA8LSBtZWFuKGFwcGx5KFdfdG8sMSxmdW5jdGlvbih4KSBzdW0oYWJzKHgpKSAgKSkKZGF0YS5mcmFtZShCYXllcyA9IFRPX2JheWVzLE5haXZlID0gV190bykKYGBgCgpXaGlsZSB0aGUgQmF5ZXMgZG9lcyBpbmNsdWRlIHJlY2VudCByZXR1cm5zIGludG8gdGhlIGFsbG9jYXRpb24gYW5kIGlzIHN1YmplY3RlZCB0byBtb3JlIG5vaXNlLCBpdHMgaW5jb3Jwb3JhdGlvbiBzZWVtcyB0byBoYXZlIGEgbWl0aWdhdGluZyBlZmZlY3QuIFRoaXMgcmVzdWx0IGNvdWxkIHBvdGVudGlhbGx5IGJlIGR1ZSB0byB0aGUgcGVyc2lzdGVuY2Ugb2YgcmV0dXJucyBvdmVyIHRpbWUuIFRvIHJlbGF0ZSB0byB0aGlzIGNvbmplY3R1cmUsIGNvbnNpZGVyIHRoZSBhdXRvY29ycmVsYXRpb24gb2YgZWFjaCBFVEYgb3ZlciB0aW1lLiBVc2luZyB0aGUgc2FtZSBzYW1wbGUgc2l6ZSBgVF9zYW1wbGVgLCB3ZSBjb21wdXRlIHRoZSByb2xsaW5nIHdpbmRvdyBhdXRvY29ycmVsYXRpb24gZm9yIGVhY2ggYXNzZXQgYW5kIHBsb3QgdGhlIHJlc3VsdHMgYmVsb3cuCmBgYHtyLHdhcm5pbmc9RixtZXNzYWdlPUYsb3V0LndpZHRoID0gJzc1JScsZmlnLmFsaWduPSJjZW50ZXIifQpsaWJyYXJ5KHBseXIpClJfbGFnIDwtIG5hLm9taXQoY2JpbmQoUl9vdXQsbGFnLnh0cyhSX291dCwxKSkpCmNvcl9yb2xsIDwtIHJvbGxhcHBseShSX2xhZyxUX3NhbXBsZSwgZnVuY3Rpb24oeCkgYXMudmVjdG9yKGNvcih4KSksIGJ5LmNvbHVtbiA9IEYsIGFsaWduID0gInJpZ2h0IikKY29yX3JvbGwgPC0gYWxwbHkoY29yX3JvbGwsIDEsIGZ1bmN0aW9uKHgpIG1hdHJpeCh4LCBucm93ID0gbmNvbChSX2xhZykgKSAgICkKCnNweV9hciA8LSBzYXBwbHkoY29yX3JvbGwsZnVuY3Rpb24oeCkgeFszLDFdKQppZWZfYXIgPC0gc2FwcGx5KGNvcl9yb2xsLGZ1bmN0aW9uKHgpIHhbNCwyXSkKQVJfbWF0IDwtIGNiaW5kKHNweV9hcixpZWZfYXIpCnJvd25hbWVzKEFSX21hdCkgPC0gcm93bmFtZXMoUl9sYWcpW1Rfc2FtcGxlOm5yb3coUl9sYWcpXQpBUl9tYXQgPC0gYXMueHRzKEFSX21hdCkKbmFtZXMoQVJfbWF0KSA8LSBjKCJTUFkiLCJJRUYiKQpwbG90KEFSX21hdCxsZWdlbmQubG9jID0gImJvdHRvbWxlZnQiLG1haW4gPSAiQXV0b2NvcnJlbGF0aW9uIikKCmBgYApUaGUgYWJvdmUgYW5hbHlzaXMgcmVsaWVzIG9uIHRoZSBzYW1lIHRyaWNrIGRvbmUgaW4gdGhlIGFmb3JlbWVudGlvbmVkIFthcnRpY2xlXShodHRwczovL3JwdWJzLmNvbS9zaW1hYW44NC9wb3J0X29wdCkuIE92ZXJhbGwsIHdlIG5vdGUgdGhlIHNlcmlhbCBjb3JyZWxhdGlvbiB2YXJpZXMgb3ZlciB0aW1lLCB3aXRoIHZhbHVlcyByYW5naW5nIGJldHdlZW4gLTUzXCUgYW5kIDQ1XCUgZm9yIHRoZSBTUFksIHdoZXJlYXMgdGhlIGNvcnJlc3BvbmRpbmcgbnVtYmVycyBmb3IgSUVGIGFyZSAtNDZcJSBhbmQgMzVcJSwgcmVzcGVjdGl2ZWx5LiBHaXZlbiB0aGUgY29udGVtcG9yYW5lb3VzIG5lZ2F0aXZlIHJlbGF0aW9uIGJldHdlZW4gdGhlIHR3byBFVEZzLCB3ZSBhbHNvIG9ic2VydmUgdGhhdCBib3RoIGF1dG9jb3JyZWxhdGlvbnMgY28tbW92ZSB0b2dldGhlciBvdmVyIHRpbWUuIE5vbmV0aGVsZXNzLCBvdmVyIHRoZSBlbnRpcmUgc2FtcGxlIHBlcmlvZCwgd2Ugbm90ZSB0aGF0IGJvdGggY29lZmZpY2llbnRzIGFyZSBwb3NpdGl2ZS4KYGBge3J9CkFSX3Jlc3VsdCA8LSBkYXRhLmZyYW1lKFNQWSA9IGNvcihSJFNQWSxsYWcoUiRTUFkpLCB1c2UgPSAicGFpcndpc2UiKSwKICAgICAgICAgICAgICAgICAgICAgICAgSUVGID0gY29yKFIkSUVGLGxhZyhSJElFRiksIHVzZSA9ICJwYWlyd2lzZSIpKQpyb3duYW1lcyhBUl9yZXN1bHQpIDwtICJBdXRvY29ycmVsYXRpb24gKCUpIgpyb3VuZChBUl9yZXN1bHQqMTAwLDIpCmBgYAoKIyBSZW1hcmtzClRoZSBhbmFseXNpcyBhYm92ZSBoaWdobGlnaHRzIHNldmVyYWwgaW1wb3J0YW50IGFzcGVjdHMuIEZpcnN0LCB0aGUgYXJ0aWNsZSBpbGx1c3RyYXRlcyBhIHNpbXBsZSB0aGVvcnkgdG8gbGluayBiZWxpZWZzIGludG8gdGhlIHBvcnRmb2xpbyBwcm9ibGVtLiBTZWNvbmQsIHRoZSBlbXBpcmljYWwgcmVzdWx0cyBpbGx1c3RyYXRlIGEgYmFja3Rlc3RpbmcgcHJvY2VkdXJlIHVzaW5nIHR3byBhc3NldHMgYW5kIGV2YWx1YXRlIHRoZSBzZW5zaXRpdml0eSBvZiB0aGUgcmVzdWx0cyB1c2luZyBkaWZmZXJlbnQgcHJpb3JzLiBGaW5hbGx5LCB0aGUgYWJvdmUgcGFyYWRpZ20gY291bGQgcHJvdmlkZSB0aGVvcmV0aWNhbCBqdXN0aWZpY2F0aW9uIGZvciBpbmNvcnBvcmF0aW5nIHByZWRpY3RpdmUgbW9kZWxzIGludG8gbWVhbi12YXJpYW5jZSBvcHRpbWl6YXRpb24uIEkgbGVhdmUgdGhpcyBmb3IgZnV0dXJlIHJlc2VhcmNoLiAgCgoKCiMgUmVmZXJlbmNlcyAKCjEuIEJsYWNrLCBGLiwgJiBMaXR0ZXJtYW4sIFIuICgxOTkwKS4gQXNzZXQgYWxsb2NhdGlvbjogY29tYmluaW5nIGludmVzdG9yIHZpZXdzIHdpdGggbWFya2V0IGVxdWlsaWJyaXVtLiBHb2xkbWFuIFNhY2hzIEZpeGVkIEluY29tZSBSZXNlYXJjaCwgMTE1LgoKMi4gRGVNaWd1ZWwsIFYuLCBHYXJsYXBwaSwgTC4sIE5vZ2FsZXMsIEYuIEouLCAmIFVwcGFsLCBSLiAoMjAwOSkuIEEgZ2VuZXJhbGl6ZWQgYXBwcm9hY2ggdG8gcG9ydGZvbGlvIG9wdGltaXphdGlvbjogSW1wcm92aW5nIHBlcmZvcm1hbmNlIGJ5IGNvbnN0cmFpbmluZyBwb3J0Zm9saW8gbm9ybXMuIE1hbmFnZW1lbnQgc2NpZW5jZSwgNTUoNSksIDc5OC04MTIuCgozLiBKb3Jpb24sIFAuICgxOTg2KS4gQmF5ZXMtU3RlaW4gZXN0aW1hdGlvbiBmb3IgcG9ydGZvbGlvIGFuYWx5c2lzLiBKb3VybmFsIG9mIEZpbmFuY2lhbCBhbmQgUXVhbnRpdGF0aXZlIGFuYWx5c2lzLCAyMSgzKSwgMjc5LTI5Mi4KCgo0LiBLbGVpbiwgUi4gVy4sICYgQmF3YSwgVi4gUy4gKDE5NzYpLiBUaGUgZWZmZWN0IG9mIGVzdGltYXRpb24gcmlzayBvbiBvcHRpbWFsIHBvcnRmb2xpbyBjaG9pY2UuIEpvdXJuYWwgb2YgZmluYW5jaWFsIGVjb25vbWljcywgMygzKSwgMjE1LTIzMS4KCgo1LiBTaW1hYW4sIE0uLCBTaW1hYW4sIFkuLCAmIFRhbmcsIFkuICgyMDE4KS4gRXN0aW1hdGlvbiBlcnJvciBpbiBtZWFuIHJldHVybnMgYW5kIHRoZSBtZWFuLXZhcmlhbmNlIGVmZmljaWVudCBmcm9udGllci4gSW50ZXJuYXRpb25hbCBSZXZpZXcgb2YgRWNvbm9taWNzICYgRmluYW5jZSwgNTYsIDEwOS0xMjQu