1 Bisection Method

The bisection method is another approach to finding the root of a continuous function \(f(x)\) on an interval \([a,b]\). The method takes advantage of a corollary of the intermediate value theorem called Bolzano’s theorem which states that if the values of \(f(a)\) and \(f(b)\) have opposite signs, the interval must contain at least one root. The iteration steps of the bisection method are relatively straightforward, however; convergence towards a solution is slow compared to other root-finding methods.

1.1 Matematical Formula

first we calculating the midpoint, \[m=a/2+b/2\], of the interval. The function is then evaluated at that point \(f(m)\). Then , recalling Bolzano’s theorem, if \(f(a)\) and \(f(m)\) have opposite signs, the method replaces b with the computed midpoint, or if \(f(b)\) and \(f(m)\) have opposite signs, a is replaced by the midpoint. This step ensures there is still a root contained in the interval. Then the procedure continues to the next iteration. The solution is said to be found once the function equals to 0 at \(f(m)\) or is small enough to be sufficient.

1.2 The Bisection Algorithm

The bisection algorithm is a simple method for finding the roots of one-dimensional functions. The goal is to find a root
x0∈[a,b] such that \(f(x0)=0\). The algorithm starts with a large interval, known to contain x0, and then successively reduces the size of the interval until it brackets the root. The theoretical underpinning of the algorithm is the intermediate value theorem which states that if a continuous function f takes values \(f(a)\) and \(f(b)\) at the end points of the interval \([a,b]\), then f must take all values between \(f(a)\) and \(f(b)\) somewhere in the interval. So if \(f(a)<γ<f(b)\), then there exists \(a c ∈[a,b]\) such that \(f(c)=γ\).

Using this information, we can present the bisection algorithm. First we must check that sign(f(a))≠sign(f(b)). Otherwise, the interval does not contain the root and might need to be widened. Then we can proceed:

  1. Let \(c=a/2+b/2\).
  2. If \(f(c)=0\), stop and return \(c.\)
  3. If sign\((f(a))≠sign(f(c))\), then set \(b←c\). Else if \(sign(f(b))≠sign(f(c)), then set a←c.\)
  4. Goto the beginning and repeat until convergence (see below).

After n iterations, the size of the interval bracketing the root will be \(2^−n(b−a)\).

The bisection algorithm is useful, conceptually simple, and is easy to implement. In particular, you do not need any special information about the function

except the ability to evaluate it at various points in the interval. The downsides are that it is only useful in one dimension and its convergence is linear, which is the slowest rate of convergence for algorithms we will discuss (more on that later).

1.3 Bisection Algorithm in R

Suppose we want to find the root of the function \(x^3−2x−5\). It is often valuable to plot the function to find an interval containing the root.

1.3.1 Visualize the function

As we can see from the visualization above, we know that the root appears to lie close in 2. Next, we will use the interval [2,3] in Bisection Method.

1.3.2 Use NLRoot packages

On of the most usefull package for the Bisection Method in R is the NLRoot package, here you will apply BFfzero() to find the solution, as you can see below:

## [1] 1
## [1] 2.094553
## [1] 1.262094e-05
## [1] "finding root is successful"

The output of the function shows the root is located at \(x=2.094553\), which matches the results found in previous examples on other root finding methods such as the Newton-Raphson method and Secant method.

2 Newton’s Method

The Newton-Raphson method is a method for approximating the roots of polynomial equations of any order. In fact the method works for any equation, polynomial or not, as long as the function is differentiable in a desired interval. ’s often become increasingly better approximations of the function’s root. Newton’s method usually use for solving equations is another numerical method for solving an equation \(f(x)=0\). It is based on the geometry of a curve, using the tangent lines to a curve. As such, it requires calculus, in particular differentiation. Roughly, the idea of Newton’s method is as follows.

2.1 Matematical Formula

Newton’s method build a sequence of values \({x_n}\) via functional iteration that converges to the root of a function \(f\). Let that root be called \(x_∞\) and let \(x_n\) be the current estimate. By the mean value theorem, we know there exists some \(z\) such that \(f(x_n)=f′(z)(x_n−x_∞)\), where z is somewhere between xn and x∞. Rearranging terms, we can write \(x_∞=x_n− f(x_n)/f′(z)\) Obviously, we do not know x_∞ or z, so we can replace them with our next iterate xn+1 and our current iterate xn, giving us the Newton update formula, \(x_n+1=x_n−f(x_n)f′(x_n).\)

2.2 The Newton’s Algorithm

Newton’s method (also known as the Newton-Raphson method or the Newton-Fourier method) is an efficient algorithm for finding approximations to the zeros (or roots) of a real-valued function f(x).

The iteration goes on in this way:

\(x_{k + 1} = x_{k} - \frac{FUN(x_{k})}{FUN'(x_{k})}\)

From the starting value \(x_0\), vertical lines and points are plotted to show the location of the sequence of iteration values \(x_1, x_2, \ldots\); tangent lines are drawn to illustrate the relationship between successive iterations; the iteration values are in the right margin of the plot.

2.3 Newton’s Method in R

Suppose we want to find the root of the function \(f(x)=x^2−9 \text{ for, } x>0\). We assume that \(f\) is smooth (differentiable). Our goal is to find a root of \(f\) i.e a \(x\) value for which \(f(x)=0\). We illustrate the method with a simple example for which you know the root.

2.3.1 Visualize the function

## Warning: package 'ggplot2' was built under R version 3.6.3
##       x         f
## 1 0.100 -8.990000
## 2 0.199 -8.960399
## 3 0.298 -8.911196
## 4 0.397 -8.842391
## 5 0.496 -8.753984
## 6 0.595 -8.645975

By considering the visualization above, it’s looks like the function is 0 around 3. How do we know that exactly correct, let’s try zoom the visualization.

Next, let us visualize this to find the root of our function \(f(x)=x^2−9.\) First we need to create a function that returns the tangent line to the function f at some point a.

Then, plot the tangent line to the initial value \(f\) at \(x(0)=4\) which will be our first guess of the root.

Next, let us zoom in on \(2≤x≤4\) and try to see where the tangent line is equal to 0.

By considering the visualization above, looks like the tangent line is 0 around 3.1. This will be our updated guess at the root. Understand the rationale behind this. If f is approximately equal to its tangent line at 4, then the root of \(f\) is approximately equal to the root of the tangent line. Can you see this in the plot above?

The exact value when the tangent line is 0 is given by

\[ x^{(1)}=4−{f(4) \over f′(4)} =3.125\]

Then, add the tangent line at 3.125 to our data frame

Now let us zoom in on around 3 and try to see where the tangent line is equal to 0.

Looks like the tangent line is 0 around 3. In just two steps we are very close. This will be our updated guess at the root. The exact value when the tangent line is 0 is given by

\[ x^{(2)}=x^{(1)}−{f(x^{(1)}) \over f′(x^{(1)})}\] \[ x^{(2)}=3.125−{f(3.125) \over f′(3.125)} = 3.0025\]

We can continue until our guesses keep getting smaller and smaller.

2.3.2 Use NLRoot packages

The same packages as we use to the Bisection Method, this packages also available for Newton’s method.

## [1] 3
## [1] 1.081801e-12
## [1] "finding root is successful"

3 Case Study

In this lesson we will construct two functions that you will need for this course and begin to explore the R programming language. Run through the Chapter 1 of the book which talks about model building for a one-variable optimization problem. Example 1.1 (Meerschaert) A pig weighing 200 lbs gains 5 lbs per day and costs 45 cents per day to keep (feed and board). The market price for pigs is 65 cents per pound, but is falling 1 cent per day. When should the pig be sold?

Modeling the Problem:

Variables: t = time (days) w = weight of the pig(lbs) p = price for pigs (\(/lb) C = cost of keeping pig t days (\)) R = revenue obtained by selling pig (\() P = profit from selling pig (\))

Assumptions: \(w=200+5t\) \(p=0.65−0.01t\) \(C=0.45t\) \(R=p⋅w\) \(P=R−C\) \(t \geq 0\)

Objective: Maximize profits from the sell of the pig Let \(x\) be the time to sell the pig and develop the profit function using x as the independent variable. In the case of an optimization, the variable on which you will make a decision on is generally called a decision Profit Function = Objective function Given the description and mathematical explanation of the variables, lets write out the profit function: profit \((x)\) = (0.65-0.01x)(200+5x)-0.45x Let’s use R to “see” what the profit function looks like over the next 20 days.

## [1] 133.2

As you can see, there is a good and bad day to sell the pig if our assumptions remain the same over the next 20 days. Although we could use this graph in order to select the “winner”, we want to be able to use this tool (R programming language) to assist us in ensuring that we have all of the information needed to make a decision. That means that we need to get our hands dirty and figure out how to use our tools (in this case, R).

##Build the functions that we need to solve the problem We will create two functions that will be able to solve for an optimal point in R using mathematics / programming that we already know how to do.

Using this simple formula, let’s build a derivative of the profit function that we defined above. Notice how our function fprime(f,x) will work for ANY function that we assign to it.

##Root-Finding Solver Although we could use the graph above to find the solution for this particular problem, it is more appropriate to use math to make our solution automatic. There are many root-finding algorithms out there and feel free to use another, but we will use a simple algorithm known as the bisection method. This method only requires that you select two points that have opposite signs: if \(f(a)=− then f(b)=+\).

##Bisection Algorithm for finding the root of an equation. The simple idea of the bisection method is that you start with an interval [a,b] that has a positive and negative value for the function \(f(a)\) and \(f(b)\) - it does not matter which one is positive. You cut the interval in half and proceed with the interval that keeps one side positive and the other negative. In Figure 1, we start on the interval [2,9] which works because \(f(2)\) is positive and \(f(9)\) is negative. The first step cuts the interval in half and the decision must be made to continue with [2,5.5] or [5.5,9]. It should be pretty obvous from the picture that [2,5.5] is the right answer (we want to keep a root in the interval), but from an algorithm perspective, we simply test f(5.5) and find out that it is negative which causes us to replace 9 (\(f[9]\) was negative) with 5.5. We would continue this algorithm until we are satisfied that the width of the interval is small enough to make a conclusion about the value of the root.

## [1] 1.709967

Use our tool to solve the pig problem Use the tools at your disposal to solve the problem. Be able to make several alternatives to the proposed model and investigate the relationship between multiple variables. When do we sell the pig?

## [1] 8.000488

As you can see, we got approximately the same answer as the book. The difference is that our solution uses an estimation of the derivative instead of the closed-form solution as well as a solver for finding the day x where the profit is maximized (profit function derivative = 0). In the case of most problems, you will use numerical methods (like we did) because real world problems do not ususally have a easy answer. To become a good problem solver, you are going to need to invest in your coding abilities because you will usually need to develop some original code to help you solve a particular problem.

Sensitivity Analysis: Price of the Pig Let’s go back and examine more closely one of our original assumptions that may or may not hold to see how our solution is afftected by a different assumption. Does the optimal day to sell change if we assume some different price of the pig. Here we let the pig price drop to recreate the numbers in the book, but we are able to do so much more which will be demonstrated in the next analysis.

## [1] 15.000000 11.110840  8.000488  5.454102  3.332520

Sensitivity Analysis: Growth Rate of the Pig Since we are also concerned about the growth rate of the pig, let’s conduct see how the days to sell are affected by the growth rate. The weight (w) is calculated using the assumption that the pig will grow 5lbs per day so that: \[w=200+gt\] where \[g=5\]. Let’s see what happens if g is between 3 and 7. Remember the bisection method needs two boundary points that have the opposite values and if the growth rate is too small, think about what that does to the profit. Experiment with large and small growth rates and the profit function to figure it out for yourself if you don’t see it. We needed to make the starting point of the bisection method to the left (negative number) in order for it to find the zero for 3lbs and 3.5lbs per day.

##  [1] -90.002441 -49.169922 -28.749084 -16.499329  -8.332825  -2.500916
##  [7]   1.875305   5.278778   8.000183  10.227203  12.083435  13.653564
## [13]  14.999390  16.166687  17.187500  18.088150  18.889236  19.605637
## [19]  20.249939  20.833588  21.363449  21.847534  22.291565

LS0tDQp0aXRsZTogIkxhYjQ6IFNvbHZpbmcgTm9ubGluZWFyIEVxdWF0aW9ucyINCmF1dGhvcjogIk5pY2hvbGFzIEFuZHJpYW4iDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy5EYXRlKCksICclQiAlZCwgJVknKWAiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50OiANCiAgICBoaWdobGlnaHQ6IG1vbm9jaHJvbWUNCiAgICB0aGVtZTogc3BhY2VsYWINCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICAgIHRvYzogeWVzDQogICAgdG9jX2Zsb2F0OiB5ZXMNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCi0tLQ0KDQpgYGB7ciBMb2dvLCBlY2hvPUZBTFNFLGZpZy5hbGlnbj0nY2VudGVyJywgb3V0LndpZHRoID0gJzQwJSd9DQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly9naXRodWIuY29tL0Jha3RpLVNpcmVnYXIvaW1hZ2VzL2Jsb2IvbWFzdGVyL2xvZ28ucG5nP3Jhdz10cnVlIikNCmBgYA0KDQojIEJpc2VjdGlvbiBNZXRob2QNCg0KVGhlIGJpc2VjdGlvbiBtZXRob2QgaXMgYW5vdGhlciBhcHByb2FjaCB0byBmaW5kaW5nIHRoZSByb290IG9mIGEgY29udGludW91cyBmdW5jdGlvbiAkZih4KSQgb24gYW4gaW50ZXJ2YWwgJFthLGJdJC4gVGhlIG1ldGhvZCB0YWtlcyBhZHZhbnRhZ2Ugb2YgYSBjb3JvbGxhcnkgb2YgdGhlIGludGVybWVkaWF0ZSB2YWx1ZSB0aGVvcmVtIGNhbGxlZCBCb2x6YW5v4oCZcyB0aGVvcmVtIHdoaWNoIHN0YXRlcyB0aGF0IGlmIHRoZSB2YWx1ZXMgb2YgJGYoYSkkIGFuZCAkZihiKSQgaGF2ZSBvcHBvc2l0ZSBzaWducywgdGhlIGludGVydmFsIG11c3QgY29udGFpbiBhdCBsZWFzdCBvbmUgcm9vdC4gVGhlIGl0ZXJhdGlvbiBzdGVwcyBvZiB0aGUgYmlzZWN0aW9uIG1ldGhvZCBhcmUgcmVsYXRpdmVseSBzdHJhaWdodGZvcndhcmQsIGhvd2V2ZXI7IGNvbnZlcmdlbmNlIHRvd2FyZHMgYSBzb2x1dGlvbiBpcyBzbG93IGNvbXBhcmVkIHRvIG90aGVyIHJvb3QtZmluZGluZyBtZXRob2RzLg0KDQoNCiMjIE1hdGVtYXRpY2FsIEZvcm11bGENCg0KZmlyc3Qgd2UgY2FsY3VsYXRpbmcgdGhlIG1pZHBvaW50LCAkJG09YS8yK2IvMiQkLCBvZiB0aGUgaW50ZXJ2YWwuIFRoZSBmdW5jdGlvbiBpcyB0aGVuIGV2YWx1YXRlZCBhdCB0aGF0IHBvaW50ICRmKG0pJC4gVGhlbiAsIHJlY2FsbGluZyBCb2x6YW5v4oCZcyB0aGVvcmVtLCBpZiAkZihhKSQgYW5kICRmKG0pJCBoYXZlIG9wcG9zaXRlIHNpZ25zLCB0aGUgbWV0aG9kIHJlcGxhY2VzIGIgd2l0aCB0aGUgY29tcHV0ZWQgbWlkcG9pbnQsIG9yIGlmICRmKGIpJCBhbmQgJGYobSkkIGhhdmUgb3Bwb3NpdGUgc2lnbnMsIGEgaXMgcmVwbGFjZWQgYnkgdGhlIG1pZHBvaW50LiBUaGlzIHN0ZXAgZW5zdXJlcyB0aGVyZSBpcyBzdGlsbCBhIHJvb3QgY29udGFpbmVkIGluIHRoZSBpbnRlcnZhbC4gVGhlbiB0aGUgcHJvY2VkdXJlIGNvbnRpbnVlcyB0byB0aGUgbmV4dCBpdGVyYXRpb24uIFRoZSBzb2x1dGlvbiBpcyBzYWlkIHRvIGJlIGZvdW5kIG9uY2UgdGhlIGZ1bmN0aW9uIGVxdWFscyB0byAwIGF0ICRmKG0pJCBvciBpcyBzbWFsbCBlbm91Z2ggdG8gYmUgc3VmZmljaWVudC4NCg0KIyMgVGhlIEJpc2VjdGlvbiBBbGdvcml0aG0NCg0KVGhlIGJpc2VjdGlvbiBhbGdvcml0aG0gaXMgYSBzaW1wbGUgbWV0aG9kIGZvciBmaW5kaW5nIHRoZSByb290cyBvZiBvbmUtZGltZW5zaW9uYWwgZnVuY3Rpb25zLiBUaGUgZ29hbCBpcyB0byBmaW5kIGEgcm9vdCAgDQp4MOKIiFthLGJdIHN1Y2ggdGhhdCAkZih4MCk9MCQuIFRoZSBhbGdvcml0aG0gc3RhcnRzIHdpdGggYSBsYXJnZSBpbnRlcnZhbCwga25vd24gdG8gY29udGFpbiB4MCwgYW5kIHRoZW4gc3VjY2Vzc2l2ZWx5IHJlZHVjZXMgdGhlIHNpemUgb2YgdGhlIGludGVydmFsIHVudGlsIGl0IGJyYWNrZXRzIHRoZSByb290LiBUaGUgdGhlb3JldGljYWwgdW5kZXJwaW5uaW5nIG9mIHRoZSBhbGdvcml0aG0gaXMgdGhlIGludGVybWVkaWF0ZSB2YWx1ZSB0aGVvcmVtIHdoaWNoIHN0YXRlcyB0aGF0IGlmIGEgY29udGludW91cyBmdW5jdGlvbiBmIHRha2VzIHZhbHVlcyAkZihhKSQgYW5kICRmKGIpJCBhdCB0aGUgZW5kIHBvaW50cyBvZiB0aGUgaW50ZXJ2YWwgJFthLGJdJCwgdGhlbiBmIG11c3QgdGFrZSBhbGwgdmFsdWVzIGJldHdlZW4gJGYoYSkkIGFuZCAkZihiKSQgc29tZXdoZXJlIGluIHRoZSBpbnRlcnZhbC4gU28gaWYgJGYoYSk8zrM8ZihiKSQsIHRoZW4gdGhlcmUgZXhpc3RzICRhIGMg4oiIW2EsYl0kIHN1Y2ggdGhhdCAkZihjKT3OsyQuDQoNClVzaW5nIHRoaXMgaW5mb3JtYXRpb24sIHdlIGNhbiBwcmVzZW50IHRoZSBiaXNlY3Rpb24gYWxnb3JpdGhtLiBGaXJzdCB3ZSBtdXN0IGNoZWNrIHRoYXQgc2lnbihmKGEpKeKJoHNpZ24oZihiKSkuIE90aGVyd2lzZSwgdGhlIGludGVydmFsIGRvZXMgbm90IGNvbnRhaW4gdGhlIHJvb3QgYW5kIG1pZ2h0IG5lZWQgdG8gYmUgd2lkZW5lZC4gVGhlbiB3ZSBjYW4gcHJvY2VlZDoNCg0KMS4gTGV0ICRjPWEvMitiLzIkLiANCjIuIElmICRmKGMpPTAkLCBzdG9wIGFuZCByZXR1cm4gJGMuJCANCjMuIElmIHNpZ24kKGYoYSkp4omgc2lnbihmKGMpKSQsIHRoZW4gc2V0ICRi4oaQYyQuIEVsc2UgaWYgJHNpZ24oZihiKSniiaBzaWduKGYoYykpLCB0aGVuIHNldCBh4oaQYy4kDQo0LiBHb3RvIHRoZSBiZWdpbm5pbmcgYW5kIHJlcGVhdCB1bnRpbCBjb252ZXJnZW5jZSAoc2VlIGJlbG93KS4NCg0KQWZ0ZXIgbiBpdGVyYXRpb25zLCB0aGUgc2l6ZSBvZiB0aGUgaW50ZXJ2YWwgYnJhY2tldGluZyB0aGUgcm9vdCB3aWxsIGJlICQyXuKIkm4oYuKIkmEpJC4NCg0KVGhlIGJpc2VjdGlvbiBhbGdvcml0aG0gaXMgdXNlZnVsLCBjb25jZXB0dWFsbHkgc2ltcGxlLCBhbmQgaXMgZWFzeSB0byBpbXBsZW1lbnQuIEluIHBhcnRpY3VsYXIsIHlvdSBkbyBub3QgbmVlZCBhbnkgc3BlY2lhbCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZnVuY3Rpb24NCg0KZXhjZXB0IHRoZSBhYmlsaXR5IHRvIGV2YWx1YXRlIGl0IGF0IHZhcmlvdXMgcG9pbnRzIGluIHRoZSBpbnRlcnZhbC4gVGhlIGRvd25zaWRlcyBhcmUgdGhhdCBpdCBpcyBvbmx5IHVzZWZ1bCBpbiBvbmUgZGltZW5zaW9uIGFuZCBpdHMgY29udmVyZ2VuY2UgaXMgbGluZWFyLCB3aGljaCBpcyB0aGUgc2xvd2VzdCByYXRlIG9mIGNvbnZlcmdlbmNlIGZvciBhbGdvcml0aG1zIHdlIHdpbGwgZGlzY3VzcyAobW9yZSBvbiB0aGF0IGxhdGVyKS4NCg0KIyMgQmlzZWN0aW9uIEFsZ29yaXRobSBpbiBSDQoNClN1cHBvc2Ugd2Ugd2FudCB0byBmaW5kIHRoZSByb290IG9mIHRoZSBmdW5jdGlvbiAkeF4z4oiSMnjiiJI1JC4gSXQgaXMgb2Z0ZW4gdmFsdWFibGUgdG8gcGxvdCB0aGUgZnVuY3Rpb24gdG8gZmluZCBhbiBpbnRlcnZhbCBjb250YWluaW5nIHRoZSByb290Lg0KDQojIyMgVmlzdWFsaXplIHRoZSBmdW5jdGlvbg0KDQpgYGB7cn0NCmZ1bmMgPC0gZnVuY3Rpb24oeCkgew0KICB4XjMgLSAyICogeCAtIDUNCn0NCg0KY3VydmUoZnVuYywgeGxpbT1jKC0zLDMpLCBjb2w9J2JsdWUnLCBsd2Q9MS41LCBsdHk9MikNCmFibGluZShoPTApDQphYmxpbmUodj0wKQ0KYGBgDQoNCkFzIHdlIGNhbiBzZWUgZnJvbSB0aGUgdmlzdWFsaXphdGlvbiBhYm92ZSwgd2Uga25vdyB0aGF0IHRoZSByb290IGFwcGVhcnMgdG8gbGllIGNsb3NlIGluIDIuIE5leHQsIHdlIHdpbGwgdXNlIHRoZSBpbnRlcnZhbCBbMiwzXSBpbiBCaXNlY3Rpb24gTWV0aG9kLg0KDQojIyMgVXNlIGBOTFJvb3RgIHBhY2thZ2VzDQoNCk9uIG9mIHRoZSBtb3N0IHVzZWZ1bGwgcGFja2FnZSBmb3IgdGhlIEJpc2VjdGlvbiBNZXRob2QgaW4gUiBpcyB0aGUgYE5MUm9vdGAgcGFja2FnZSwgaGVyZSB5b3Ugd2lsbCBhcHBseSBgQkZmemVybygpYCB0byBmaW5kIHRoZSBzb2x1dGlvbiwgYXMgeW91IGNhbiBzZWUgYmVsb3c6DQoNCmBgYHtyfQ0KbGlicmFyeShOTFJvb3QpICAgICAgICAgICAgICAjIGxvYWRpbmcgdGhlIHBhY2thZ2UgDQpCRmZ6ZXJvKGZ1bmMsIDIsIDMpICAgICAgICAgICMgdG8gZmluZCB0aGUgc29sdXRpb24gKGp1c3QgYXMgc2ltcGxlIGxpa2UgdGhpcykNCmBgYA0KDQpUaGUgb3V0cHV0IG9mIHRoZSBmdW5jdGlvbiBzaG93cyB0aGUgcm9vdCBpcyBsb2NhdGVkIGF0ICR4PTIuMDk0NTUzJCwgd2hpY2ggbWF0Y2hlcyB0aGUgcmVzdWx0cyBmb3VuZCBpbiBwcmV2aW91cyBleGFtcGxlcyBvbiBvdGhlciByb290IGZpbmRpbmcgbWV0aG9kcyBzdWNoIGFzIHRoZSBOZXd0b24tUmFwaHNvbiBtZXRob2QgYW5kIFNlY2FudCBtZXRob2QuDQoNCg0KIyMjIFdyaXRlIEZ1bmN0aW9uDQoNCldlIGNhbiBhbHNvIHdyaXRlIGEgZnVuY3Rpb24gdGhhdCBpbXBsZW1lbnRzIHRoZSBiaXNlY3Rpb24gbWV0aG9kIHVzaW5nIHRoZSBpdGVyYXRpb24gc3RlcHMgZGV0YWlsZWQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgcG9zdC4NCg0KYGBge3J9DQpCYWt0aV9CaXNlY3Rpb24gPC0gZnVuY3Rpb24oZiwgYSwgYiwgbiA9IDEwMDAsIHRvbCA9IDFlLTcpIHsNCiAgIyBJZiB0aGUgc2lnbnMgb2YgdGhlIGZ1bmN0aW9uIGF0IHRoZSBldmFsdWF0ZWQgcG9pbnRzLCBhIGFuZCBiLCBzdG9wIHRoZSBmdW5jdGlvbiBhbmQgcmV0dXJuIG1lc3NhZ2UuDQogIGlmICghKGYoYSkgPCAwKSAmJiAoZihiKSA+IDApKSB7DQogICAgc3RvcCgnc2lnbnMgb2YgZihhKSBhbmQgZihiKSBkaWZmZXInKQ0KICB9IGVsc2UgaWYgKChmKGEpID4gMCkgJiYgKGYoYikgPCAwKSkgew0KICAgIHN0b3AoJ3NpZ25zIG9mIGYoYSkgYW5kIGYoYikgZGlmZmVyJykNCiAgfQ0KICANCiAgZm9yIChpIGluIDE6bikgew0KICAgIGMgPC0gKGEgKyBiKSAvIDIgIyBDYWxjdWxhdGUgbWlkcG9pbnQNCiAgICANCiAgICAjIElmIHRoZSBmdW5jdGlvbiBlcXVhbHMgMCBhdCB0aGUgbWlkcG9pbnQgb3IgdGhlIG1pZHBvaW50IGlzIGJlbG93IHRoZSBkZXNpcmVkIHRvbGVyYW5jZSwgc3RvcCB0aGUgDQogICAgIyBmdW5jdGlvbiBhbmQgcmV0dXJuIHRoZSByb290Lg0KICAgIGlmICgoZihjKSA9PSAwKSB8fCAoKGIgLSBhKSAvIDIpIDwgdG9sKSB7DQogICAgICByZXR1cm4oYykNCiAgICB9DQogICAgDQogICAgIyBJZiBhbm90aGVyIGl0ZXJhdGlvbiBpcyByZXF1aXJlZCwgDQogICAgIyBjaGVjayB0aGUgc2lnbnMgb2YgdGhlIGZ1bmN0aW9uIGF0IHRoZSBwb2ludHMgYyBhbmQgYSBhbmQgcmVhc3NpZ24NCiAgICAjIGEgb3IgYiBhY2NvcmRpbmdseSBhcyB0aGUgbWlkcG9pbnQgdG8gYmUgdXNlZCBpbiB0aGUgbmV4dCBpdGVyYXRpb24uDQogICAgaWZlbHNlKHNpZ24oZihjKSkgPT0gc2lnbihmKGEpKSwgDQogICAgICAgICAgIGEgPC0gYywNCiAgICAgICAgICAgYiA8LSBjKQ0KICB9DQogICMgSWYgdGhlIG1heCBudW1iZXIgb2YgaXRlcmF0aW9ucyBpcyByZWFjaGVkIGFuZCBubyByb290IGhhcyBiZWVuIGZvdW5kLCANCiAgIyByZXR1cm4gbWVzc2FnZSBhbmQgZW5kIGZ1bmN0aW9uLg0KICBwcmludCgnVG9vIG1hbnkgaXRlcmF0aW9ucycpDQp9DQpgYGANCg0KTm93LCB3ZSBjYW4gYXBwbHkgb3VyIGZ1bmN0aW9uIGZpbmQgdGhlIHJvb3Qgb2YgdGhlIGZ1bmN0aW9uICR4XjPiiJIyeOKIkjUkIGFzIHdlIGhhdmUgZG9uZSBhYm92ZSBieSB1c2luZyBgTkxSb290YCBwYWNrYWdlcy4gDQoNCmBgYHtyfQ0KQmFrdGlfQmlzZWN0aW9uKGZ1bmMsIDIsIDMpDQpgYGANCiMjIyBZb3VyIE93biBGdW5jdGlvbg0KDQpgYGB7cn0NCmZ1bmN0IDwtIGZ1bmN0aW9uKHgpIHsNCiAgeF4zIC0gMiAqIHggLSA2DQp9DQoNCmN1cnZlKGZ1bmN0LCB4bGltPWMoLTMsMyksIGNvbD0ncmVkJywgbHdkPTEuNSwgbHR5PTIpDQphYmxpbmUoaD0wKQ0KYWJsaW5lKHY9MCkNCg0KbGlicmFyeShOTFJvb3QpICAgICAgICAgICAgICANCkJGZnplcm8oZnVuY3QsIDIsIDMpIA0KDQp4X0Jpc2VjdGlvbiA8LSBmdW5jdGlvbihmLCBhLCBiLCBuID0gMTAwMDAsIHRvbCA9IDFlLTkpIHsNCiAgaWYgKCEoZihhKSA8IDApICYmIChmKGIpID4gMCkpIHsNCiAgICBzdG9wKCdzaWducyBvZiBmKGEpIGFuZCBmKGIpIGRpZmZlcicpDQogIH0gZWxzZSBpZiAoKGYoYSkgPiAwKSAmJiAoZihiKSA8IDApKSB7DQogICAgc3RvcCgnc2lnbnMgb2YgZihhKSBhbmQgZihiKSBkaWZmZXInKQ0KICB9DQogIA0KICBmb3IgKGkgaW4gMTpuKSB7DQogICAgYyA8LSAoYSArIGIpIC8gMiANCiAgICANCiAgICBpZiAoKGYoYykgPT0gMCkgfHwgKChiIC0gYSkgLyAyKSA8IHRvbCkgew0KICAgICAgcmV0dXJuKGMpDQogICAgfQ0KICAgIA0KICBpZmVsc2Uoc2lnbihmKGMpKSA9PSBzaWduKGYoYSkpLCANCiAgICAgICAgICAgYSA8LSBjLA0KICAgICAgICAgICBiIDwtIGMpDQogIH0NCiAgcHJpbnQoJ1RvbyBtYW55IGl0ZXJhdGlvbnMnKQ0KfQ0KeF9CaXNlY3Rpb24oZnVuY3QsIDIsMykNCmBgYA0KDQoNCiMgTmV3dG9u4oCZcyBNZXRob2QNCg0KDQpUaGUgTmV3dG9uLVJhcGhzb24gbWV0aG9kIGlzIGEgbWV0aG9kIGZvciBhcHByb3hpbWF0aW5nIHRoZSByb290cyBvZiBwb2x5bm9taWFsIGVxdWF0aW9ucyBvZiBhbnkgb3JkZXIuIEluIGZhY3QgdGhlIG1ldGhvZCB3b3JrcyBmb3IgYW55IGVxdWF0aW9uLCBwb2x5bm9taWFsIG9yIG5vdCwgYXMgbG9uZyBhcyB0aGUgZnVuY3Rpb24gaXMgZGlmZmVyZW50aWFibGUgaW4gYSBkZXNpcmVkIGludGVydmFsLiAncyBvZnRlbiBiZWNvbWUgaW5jcmVhc2luZ2x5IGJldHRlciBhcHByb3hpbWF0aW9ucyBvZiB0aGUgZnVuY3Rpb24ncyByb290LiBOZXd0b24ncyBtZXRob2QgdXN1YWxseSB1c2UgZm9yIHNvbHZpbmcgZXF1YXRpb25zIGlzIGFub3RoZXIgbnVtZXJpY2FsIG1ldGhvZCBmb3Igc29sdmluZyBhbiBlcXVhdGlvbiAkZih4KT0wJC4gSXQgaXMgYmFzZWQgb24gdGhlIGdlb21ldHJ5IG9mIGEgY3VydmUsIHVzaW5nIHRoZSB0YW5nZW50IGxpbmVzIHRvIGEgY3VydmUuIEFzIHN1Y2gsIGl0IHJlcXVpcmVzIFtjYWxjdWx1c10oaHR0cHM6Ly90dXRvcmlhbC5tYXRoLmxhbWFyLmVkdS9jbGFzc2VzL2NhbGNpL25ld3RvbnNtZXRob2QuYXNweCksIGluIHBhcnRpY3VsYXIgZGlmZmVyZW50aWF0aW9uLiBSb3VnaGx5LCB0aGUgaWRlYSBvZiBOZXd0b24ncyBtZXRob2QgaXMgYXMgZm9sbG93cy4NCg0KIyMgTWF0ZW1hdGljYWwgRm9ybXVsYQ0KDQpOZXd0b27igJlzIG1ldGhvZCBidWlsZCBhIHNlcXVlbmNlIG9mIHZhbHVlcyAke3hfbn0kIHZpYSBmdW5jdGlvbmFsIGl0ZXJhdGlvbiB0aGF0IGNvbnZlcmdlcyB0byB0aGUgcm9vdCBvZiBhIGZ1bmN0aW9uICRmJC4gTGV0IHRoYXQgcm9vdCBiZSBjYWxsZWQgJHhf4oieJCBhbmQgbGV0ICR4X24kIGJlIHRoZSBjdXJyZW50IGVzdGltYXRlLiBCeSB0aGUgbWVhbiB2YWx1ZSB0aGVvcmVtLCB3ZSBrbm93IHRoZXJlIGV4aXN0cyBzb21lICR6JCBzdWNoIHRoYXQgJGYoeF9uKT1m4oCyKHopKHhfbuKIknhf4oieKSQsIHdoZXJlIHogaXMgc29tZXdoZXJlIGJldHdlZW4geG4gYW5kIHjiiJ4uIFJlYXJyYW5naW5nIHRlcm1zLCB3ZSBjYW4gd3JpdGUgJHhf4oiePXhfbuKIkiBmKHhfbikvZuKAsih6KSQNCk9idmlvdXNseSwgd2UgZG8gbm90IGtub3cgIHhf4oieIG9yIHosIHNvIHdlIGNhbiByZXBsYWNlIHRoZW0gd2l0aCBvdXIgbmV4dCBpdGVyYXRlIHhuKzEgYW5kIG91ciBjdXJyZW50IGl0ZXJhdGUgeG4sIGdpdmluZyB1cyB0aGUgTmV3dG9uIHVwZGF0ZSBmb3JtdWxhLA0KJHhfbisxPXhfbuKIkmYoeF9uKWbigLIoeF9uKS4kDQoNCiMjIFRoZSBOZXd0b27igJlzIEFsZ29yaXRobQ0KDQpOZXd0b24ncyBtZXRob2QgKGFsc28ga25vd24gYXMgdGhlIE5ld3Rvbi1SYXBoc29uIG1ldGhvZCBvciB0aGUgTmV3dG9uLUZvdXJpZXIgbWV0aG9kKSBpcyBhbiBlZmZpY2llbnQgYWxnb3JpdGhtIGZvciBmaW5kaW5nIGFwcHJveGltYXRpb25zIHRvIHRoZSB6ZXJvcyAob3Igcm9vdHMpIG9mIGEgcmVhbC12YWx1ZWQgZnVuY3Rpb24gZih4KS4NCg0KVGhlIGl0ZXJhdGlvbiBnb2VzIG9uIGluIHRoaXMgd2F5Og0KDQokeF97ayArIDF9ID0geF97a30gLSBcZnJhY3tGVU4oeF97a30pfXtGVU4nKHhfe2t9KX0kDQoNCkZyb20gdGhlIHN0YXJ0aW5nIHZhbHVlIFwoeF8wXCksIHZlcnRpY2FsIGxpbmVzIGFuZCBwb2ludHMgYXJlIHBsb3R0ZWQgdG8gc2hvdyB0aGUgbG9jYXRpb24gb2YgdGhlIHNlcXVlbmNlIG9mIGl0ZXJhdGlvbiB2YWx1ZXMgXCh4XzEsIHhfMiwgXGxkb3RzXCk7IHRhbmdlbnQgbGluZXMgYXJlIGRyYXduIHRvIGlsbHVzdHJhdGUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHN1Y2Nlc3NpdmUgaXRlcmF0aW9uczsgdGhlIGl0ZXJhdGlvbiB2YWx1ZXMgYXJlIGluIHRoZSByaWdodCBtYXJnaW4gb2YgdGhlIHBsb3QuDQoNCg0KIyMgTmV3dG9u4oCZcyBNZXRob2QgaW4gUg0KDQpTdXBwb3NlIHdlIHdhbnQgdG8gZmluZCB0aGUgcm9vdCBvZiB0aGUgZnVuY3Rpb24gJGYoeCk9eF4y4oiSOSBcdGV4dHsgZm9yLCAgfSB4PjAkLiBXZSBhc3N1bWUgdGhhdCAkZiQgaXMgc21vb3RoIChkaWZmZXJlbnRpYWJsZSkuIE91ciBnb2FsIGlzIHRvIGZpbmQgYSByb290IG9mICRmJCBpLmUgYSAkeCQgdmFsdWUgZm9yIHdoaWNoICRmKHgpPTAkLiBXZSBpbGx1c3RyYXRlIHRoZSBtZXRob2Qgd2l0aCBhIHNpbXBsZSBleGFtcGxlIGZvciB3aGljaCB5b3Uga25vdyB0aGUgcm9vdC4NCg0KIyMjIFZpc3VhbGl6ZSB0aGUgZnVuY3Rpb24NCg0KYGBge3J9DQojIGZpcnN0IGdlbmVyYXRlIHRoZSBzZXF1ZW5jZQ0KeC5zZXEgPC0gc2VxKGZyb20gPSAwLjEsIHRvID0gMTAsIGxlbmd0aC5vdXQgPSAxMDEpDQpmIDwtIHNhcHBseSh4LnNlcSwgZnVuY3Rpb24oeCkgeF4yIC0gOSkNCmBgYA0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KIyBwdXQgdGhlIHggYW5kIHkgdmFsdWVzIGluIGEgZGF0YSBmcmFtZQ0KcGxvdF9kYXRhIDwtIGRhdGEuZnJhbWUoIngiID0geC5zZXEsICJmIiA9IGYpDQpoZWFkKHBsb3RfZGF0YSkNCmBgYA0KYGBge3J9DQojIGNyZWF0ZSB0aGUgYmFzZSBsYXllciBvZiBnZ3Bsb3Qgd2l0aCBnZW9tX0xpbmUNCnBsb3RfZiA8LSBnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IHgsIHkgPSBmKSkgKyANCiAgZ2VvbV9saW5lKGNvbG9yID0gInJlZCIsIHNpemUgPSAxLjApICsgDQogIGxhYnMoeCA9ICJ4IiwgeSA9ICJmKHgpID0geF4yIC0gOSIpDQojIGJlYXV0aWZ5IDogSW5jcmVhc2UgZm9udCBzaXplIGluIGF4ZXMgDQpwbG90X2YgKyB0aGVtZShheGlzLnRleHQueCA9IA0KICAgICAgICAgICAgICAgICBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIixzaXplID0gMTIpLA0KICAgICAgICAgICAgICAgYXhpcy50ZXh0LnkgPSANCiAgICAgICAgICAgICAgICAgZWxlbWVudF90ZXh0KGZhY2UgPSAiYm9sZCIsIHNpemUgPSAxMiksDQogICAgICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIiwgDQogICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEsIGxpbmV0eXBlID0gInNvbGlkIikpDQpgYGANCkJ5IGNvbnNpZGVyaW5nIHRoZSB2aXN1YWxpemF0aW9uIGFib3ZlLCBpdCdzIGxvb2tzIGxpa2UgdGhlIGZ1bmN0aW9uIGlzIDAgYXJvdW5kIDMuIEhvdyBkbyB3ZSBrbm93IHRoYXQgZXhhY3RseSBjb3JyZWN0LCBsZXQncyB0cnkgem9vbSB0aGUgdmlzdWFsaXphdGlvbi4NCg0KYGBge3J9DQpwbG90X2YgKyANCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4wMCwgY29sb3IgPSAiZ3JlZW4iLCBzaXplID0gMSkgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMiw0KSwgeWxpbSA9IGMoLTEsIDMpKQ0KYGBgDQoNCk5leHQsIGxldCB1cyB2aXN1YWxpemUgdGhpcyB0byBmaW5kIHRoZSByb290IG9mIG91ciBmdW5jdGlvbiAkZih4KT14XjLiiJI5LiQgRmlyc3Qgd2UgbmVlZCB0byBjcmVhdGUgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlIHRhbmdlbnQgbGluZSB0byB0aGUgZnVuY3Rpb24gZiBhdCBzb21lIHBvaW50IGEuDQoNCmBgYHtyfQ0KIyBMZXQgdXMgY3JlYXRlIG91ciB0YW5nZW50IGxpbmUgZnVuY3Rpb24gYXQgc29tZSBwb2ludCBhDQpmX3RhbmdlbnQgPC0gZnVuY3Rpb24oeCwgZiwgZGYsIGEpew0KICAjIFdlIG5lZWQgdGhlIGZ1bmN0aW9uIGFuZCBpdHMgZGVyaXZhdGl2ZSBkZg0KICAjIGEgaXMgdGhlIHBvaW50IHdoZXJlIHdlIGNyZWF0ZSB0aGUgdGFuZ2VudCB0byB0aGUgZnVuY3Rpb24NCiAgIyByZXR1cm5zIHRoZSB0YW5nZW50IGxpbmUgDQogIGRmKGEpKih4IC0gYSkgKyBmKGEpDQp9DQpgYGANCg0KVGhlbiwgcGxvdCB0aGUgdGFuZ2VudCBsaW5lIHRvIHRoZSBpbml0aWFsIHZhbHVlICRmJCAgYXQgJHgoMCk9NCQgIHdoaWNoIHdpbGwgYmUgb3VyIGZpcnN0IGd1ZXNzIG9mIHRoZSByb290Lg0KDQpgYGB7cn0NCiMgYWRkIHRoZSB0YW5nZW50IGxpbmUgYXQgNCB0byBvdXIgZGF0YSBmcmFtZQ0KcGxvdF9kYXRhJGYudGFuIDwtIHNhcHBseShwbG90X2RhdGEkeCwgZl90YW5nZW50LCBmID0gZnVuY3Rpb24oeCkgeF4yIC0gOSwgZGYgPSBmdW5jdGlvbih4KSAyKngsIGEgPSA0KQ0KDQojIGNyZWF0ZSB0aGUgYmFzZSBsYXllciBvZiBnZ3Bsb3Qgd2l0aCBnZW9tX0xpbmUNCnBsb3RfdGFuZ2VudF9saW5lIDwtIGdncGxvdChwbG90X2RhdGEsIGFlcyh4ID0geCkpICsgDQogIGdlb21fbGluZShhZXMoeSA9IGYpLCBjb2xvciA9ICJyZWQiLCBzaXplID0gMC45NSkgKw0KICBnZW9tX2xpbmUoYWVzKHkgPSBmLnRhbiksIGNvbG9yID0gImJsdWUiLCBzaXplID0gMC45NSkgKw0KICBsYWJzKHggPSAieCIsIHkgPSAiZih4KSBhbmQgdGFuZ2VudCBsaW5lIGF0IDQiKSANCnBsb3RfdGFuZ2VudF9saW5lDQpgYGANCg0KTmV4dCwgbGV0IHVzIHpvb20gaW4gb24gJDLiiaR44omkNCQgYW5kIHRyeSB0byBzZWUgd2hlcmUgdGhlIHRhbmdlbnQgbGluZSBpcyBlcXVhbCB0byAwLg0KDQpgYGB7cn0NCiMgem9vbSBpbiBiZXR3ZWVuIDMgYW5kIDQNCnBsb3RfdGFuZ2VudF9saW5lICsgDQogICMgYWRkIGEgaG9yaXpvbnRhbCBsaW5lIGF0IDANCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4wMCwgY29sb3IgPSAiZ3JlZW4iLCBzaXplID0gMSkgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMiw0KSwgeWxpbSA9IGMoLTUsIDEwKSkNCmBgYA0KDQpCeSBjb25zaWRlcmluZyB0aGUgdmlzdWFsaXphdGlvbiBhYm92ZSwgbG9va3MgbGlrZSB0aGUgdGFuZ2VudCBsaW5lIGlzIDAgYXJvdW5kIDMuMS4gVGhpcyB3aWxsIGJlIG91ciB1cGRhdGVkIGd1ZXNzIGF0IHRoZSByb290LiBVbmRlcnN0YW5kIHRoZSByYXRpb25hbGUgYmVoaW5kIHRoaXMuIElmIGYgaXMgYXBwcm94aW1hdGVseSBlcXVhbCB0byBpdHMgdGFuZ2VudCBsaW5lIGF0IDQsIHRoZW4gdGhlIHJvb3Qgb2YgJGYkIGlzIGFwcHJveGltYXRlbHkgZXF1YWwgdG8gdGhlIHJvb3Qgb2YgdGhlIHRhbmdlbnQgbGluZS4gQ2FuIHlvdSBzZWUgdGhpcyBpbiB0aGUgcGxvdCBhYm92ZT8NCg0KVGhlIGV4YWN0IHZhbHVlIHdoZW4gdGhlIHRhbmdlbnQgbGluZSBpcyAwIGlzIGdpdmVuIGJ5DQoNCiQkIHheeygxKX09NOKIkntmKDQpIFxvdmVyIGbigLIoNCl9ID0zLjEyNSQkDQoNClRoZW4sIGFkZCB0aGUgdGFuZ2VudCBsaW5lIGF0IDMuMTI1IHRvIG91ciBkYXRhIGZyYW1lDQoNCmBgYHtyfQ0KcGxvdF9kYXRhJGYudGFuIDwtIHNhcHBseShwbG90X2RhdGEkeCwgZl90YW5nZW50LCBmID0gZnVuY3Rpb24oeCkgeF4yIC0gOSwgZGYgPSBmdW5jdGlvbih4KSAyKngsIGEgPSAzLjEyNSkNCg0KIyBjcmVhdGUgdGhlIGJhc2UgbGF5ZXIgb2YgZ2dwbG90IHdpdGggZ2VvbV9MaW5lDQpwbG90X3RhbmdlbnRfbGluZSA8LSBnZ3Bsb3QocGxvdF9kYXRhLCBhZXMoeCA9IHgpKSArIA0KICBnZW9tX2xpbmUoYWVzKHkgPSBmKSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDAuOTUpICsNCiAgZ2VvbV9saW5lKGFlcyh5ID0gZi50YW4pLCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDAuOTUpICsNCiAgbGFicyh4ID0gIngiLCB5ID0gImYoeCkgYW5kIHRhbmdlbnQgbGluZSBhdCA0IikgDQpwbG90X3RhbmdlbnRfbGluZQ0KYGBgDQoNCk5vdyBsZXQgdXMgem9vbSBpbiBvbiBhcm91bmQgMyBhbmQgdHJ5IHRvIHNlZSB3aGVyZSB0aGUgdGFuZ2VudCBsaW5lIGlzIGVxdWFsIHRvIDAuDQoNCmBgYHtyfQ0KIyB6b29tIGluIGJldHdlZW4gMi45IGFuZCAzLjENCnBsb3RfdGFuZ2VudF9saW5lICsgDQogICMgYWRkIGEgaG9yaXpvbnRhbCBsaW5lIGF0IDANCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMC4wMCwgY29sb3IgPSAiZ3JlZW4iLCBzaXplID0gMSkgKw0KICBjb29yZF9jYXJ0ZXNpYW4oeGxpbSA9IGMoMi45LDMuMSksIHlsaW0gPSBjKC0yLjUsIDIuNSkpDQpgYGANCg0KTG9va3MgbGlrZSB0aGUgdGFuZ2VudCBsaW5lIGlzIDAgYXJvdW5kIDMuIEluIGp1c3QgdHdvIHN0ZXBzIHdlIGFyZSB2ZXJ5IGNsb3NlLiBUaGlzIHdpbGwgYmUgb3VyIHVwZGF0ZWQgZ3Vlc3MgYXQgdGhlIHJvb3QuIFRoZSBleGFjdCB2YWx1ZSB3aGVuIHRoZSB0YW5nZW50IGxpbmUgaXMgMCBpcyBnaXZlbiBieQ0KDQokJCB4XnsoMil9PXheeygxKX3iiJJ7Zih4XnsoMSl9KSBcb3ZlciBm4oCyKHheeygxKX0pfSQkDQokJCB4XnsoMil9PTMuMTI14oiSe2YoMy4xMjUpIFxvdmVyIGbigLIoMy4xMjUpfSA9IDMuMDAyNSQkDQoNCldlIGNhbiBjb250aW51ZSB1bnRpbCBvdXIgZ3Vlc3NlcyBrZWVwIGdldHRpbmcgc21hbGxlciBhbmQgc21hbGxlci4NCg0KIyMjIFVzZSBgTkxSb290YCBwYWNrYWdlcw0KDQpUaGUgc2FtZSBwYWNrYWdlcyBhcyB3ZSB1c2UgdG8gdGhlIEJpc2VjdGlvbiBNZXRob2QsIHRoaXMgcGFja2FnZXMgYWxzbyBhdmFpbGFibGUgZm9yIE5ld3RvbidzIG1ldGhvZC4gDQoNCmBgYHtyfQ0KbGlicmFyeShOTFJvb3QpDQojIGZpcnN0IGFyZ3VtZW50IGlzIHRoZSBmdW5jdGlvbiB3aG9zZSByb290IHdlIG5lZWQgdG8gZmluZA0KIyBzZWNvbmQgYXJndW1lbnQgaXMgdGhlIHRoZSBkZXJpdmF0aXZlIG9mIHRoZSBmdW5jdGlvbiB3aG9zZSANCiMgcm9vdCB3ZSBuZWVkIHRvIGZpbmQuDQojIHRoaXJkIGFyZ3VtZW50IGlzIGFuIGluaXRpYWwgZ3Vlc3MNCk5JTWZ6ZXJvKGZ1bmN0aW9uKHgpIHheMi05LCBmdW5jdGlvbih4KSAyKngsIHgwID0gNCkNCmBgYA0KDQoNCiMgW0Nhc2UgU3R1ZHldKGh0dHBzOi8vcnB1YnMuY29tL2pfbGFwb3J0ZS81NjQyODApIA0KSW4gdGhpcyBsZXNzb24gd2Ugd2lsbCBjb25zdHJ1Y3QgdHdvIGZ1bmN0aW9ucyB0aGF0IHlvdSB3aWxsIG5lZWQgZm9yIHRoaXMgY291cnNlIGFuZCBiZWdpbiB0byBleHBsb3JlIHRoZSBSIHByb2dyYW1taW5nIGxhbmd1YWdlLiBSdW4gdGhyb3VnaCB0aGUgQ2hhcHRlciAxIG9mIHRoZSBib29rIHdoaWNoIHRhbGtzIGFib3V0IG1vZGVsIGJ1aWxkaW5nIGZvciBhIG9uZS12YXJpYWJsZSBvcHRpbWl6YXRpb24gcHJvYmxlbS4gRXhhbXBsZSAxLjEgKE1lZXJzY2hhZXJ0KSBBIHBpZyB3ZWlnaGluZyAyMDAgbGJzIGdhaW5zIDUgbGJzIHBlciBkYXkgYW5kIGNvc3RzIDQ1IGNlbnRzIHBlciBkYXkgdG8ga2VlcCAoZmVlZCBhbmQgYm9hcmQpLiBUaGUgbWFya2V0IHByaWNlIGZvciBwaWdzIGlzIDY1IGNlbnRzIHBlciBwb3VuZCwgYnV0IGlzIGZhbGxpbmcgMSBjZW50IHBlciBkYXkuIFdoZW4gc2hvdWxkIHRoZSBwaWcgYmUgc29sZD8NCg0KTW9kZWxpbmcgdGhlIFByb2JsZW06DQoNClZhcmlhYmxlczoNCnQgPSB0aW1lIChkYXlzKQ0KdyA9IHdlaWdodCBvZiB0aGUgcGlnKGxicykNCnAgPSBwcmljZSBmb3IgcGlncyAoJC9sYikNCkMgPSBjb3N0IG9mIGtlZXBpbmcgcGlnIHQgZGF5cyAoJCkNClIgPSByZXZlbnVlIG9idGFpbmVkIGJ5IHNlbGxpbmcgcGlnICgkKQ0KUCA9IHByb2ZpdCBmcm9tIHNlbGxpbmcgcGlnICgkKQ0KDQpBc3N1bXB0aW9uczoNCiR3PTIwMCs1dCQNCiRwPTAuNjXiiJIwLjAxdCQNCiRDPTAuNDV0JA0KJFI9cOKLhXckDQokUD1S4oiSQyQNCiR0IFxnZXEgMCQNCg0KT2JqZWN0aXZlOiANCk1heGltaXplIHByb2ZpdHMgZnJvbSB0aGUgc2VsbCBvZiB0aGUgcGlnDQpMZXQgJHgkIGJlIHRoZSB0aW1lIHRvIHNlbGwgdGhlIHBpZyBhbmQgZGV2ZWxvcCB0aGUgcHJvZml0IGZ1bmN0aW9uIHVzaW5nIHggYXMgdGhlIGluZGVwZW5kZW50IHZhcmlhYmxlLiBJbiB0aGUgY2FzZSBvZiBhbiBvcHRpbWl6YXRpb24sIHRoZSB2YXJpYWJsZSBvbiB3aGljaCB5b3Ugd2lsbCBtYWtlIGEgZGVjaXNpb24gb24gaXMgZ2VuZXJhbGx5IGNhbGxlZCBhIGRlY2lzaW9uIA0KUHJvZml0IEZ1bmN0aW9uID0gT2JqZWN0aXZlIGZ1bmN0aW9uDQpHaXZlbiB0aGUgZGVzY3JpcHRpb24gYW5kIG1hdGhlbWF0aWNhbCBleHBsYW5hdGlvbiBvZiB0aGUgdmFyaWFibGVzLCBsZXRzIHdyaXRlIG91dCB0aGUgcHJvZml0IGZ1bmN0aW9uOg0KcHJvZml0ICQoeCkkID0gKDAuNjUtMC4wMXgpKDIwMCs1eCktMC40NXgNCkxldCdzIHVzZSBSIHRvIOKAnHNlZeKAnSB3aGF0IHRoZSBwcm9maXQgZnVuY3Rpb24gbG9va3MgbGlrZSBvdmVyIHRoZSBuZXh0IDIwIGRheXMuDQpgYGB7cn0NCnByb2ZpdCA9IGZ1bmN0aW9uICh4KXsNCiAgcmV0dXJuKCgwLjY1LTAuMDEqeCkqKDIwMCs1KngpLS40NSp4KQ0KfQ0KeCA9IHNlcSgwLDIwLDEpDQpwbG90KHgscHJvZml0KHgpLHR5cGU9Im8iKQ0KcHJpbnQocHJvZml0KDgpKQ0KYGBgDQpBcyB5b3UgY2FuIHNlZSwgdGhlcmUgaXMgYSBnb29kIGFuZCBiYWQgZGF5IHRvIHNlbGwgdGhlIHBpZyBpZiBvdXIgYXNzdW1wdGlvbnMgcmVtYWluIHRoZSBzYW1lIG92ZXIgdGhlIG5leHQgMjAgZGF5cy4gQWx0aG91Z2ggd2UgY291bGQgdXNlIHRoaXMgZ3JhcGggaW4gb3JkZXIgdG8gc2VsZWN0IHRoZSDigJx3aW5uZXLigJ0sIHdlIHdhbnQgdG8gYmUgYWJsZSB0byB1c2UgdGhpcyB0b29sIChSIHByb2dyYW1taW5nIGxhbmd1YWdlKSB0byBhc3Npc3QgdXMgaW4gZW5zdXJpbmcgdGhhdCB3ZSBoYXZlIGFsbCBvZiB0aGUgaW5mb3JtYXRpb24gbmVlZGVkIHRvIG1ha2UgYSBkZWNpc2lvbi4gVGhhdCBtZWFucyB0aGF0IHdlIG5lZWQgdG8gZ2V0IG91ciBoYW5kcyBkaXJ0eSBhbmQgZmlndXJlIG91dCBob3cgdG8gdXNlIG91ciB0b29scyAoaW4gdGhpcyBjYXNlLCBSKS4NCg0KIyNCdWlsZCB0aGUgZnVuY3Rpb25zIHRoYXQgd2UgbmVlZCB0byBzb2x2ZSB0aGUgcHJvYmxlbQ0KV2Ugd2lsbCBjcmVhdGUgdHdvIGZ1bmN0aW9ucyB0aGF0IHdpbGwgYmUgYWJsZSB0byBzb2x2ZSBmb3IgYW4gb3B0aW1hbCBwb2ludCBpbiBSIHVzaW5nIG1hdGhlbWF0aWNzIC8gcHJvZ3JhbW1pbmcgdGhhdCB3ZSBhbHJlYWR5IGtub3cgaG93IHRvIGRvLiANCg0KVXNpbmcgdGhpcyBzaW1wbGUgZm9ybXVsYSwgbGV04oCZcyBidWlsZCBhIGRlcml2YXRpdmUgb2YgdGhlIHByb2ZpdCBmdW5jdGlvbiB0aGF0IHdlIGRlZmluZWQgYWJvdmUuIE5vdGljZSBob3cgb3VyIGZ1bmN0aW9uIGZwcmltZShmLHgpIHdpbGwgd29yayBmb3IgQU5ZIGZ1bmN0aW9uIHRoYXQgd2UgYXNzaWduIHRvIGl0Lg0KYGBge3J9DQp4PXNlcSgwLDIwKQ0KZnByaW1lID0gZnVuY3Rpb24gKGYsYSxoPTAuMDAwMSl7KGYoYStoKS1mKGEtaCkpLygyKmgpfQ0KcGxvdCh4LGZwcmltZShwcm9maXQseCkpDQpgYGANCiMjUm9vdC1GaW5kaW5nIFNvbHZlcg0KQWx0aG91Z2ggd2UgY291bGQgdXNlIHRoZSBncmFwaCBhYm92ZSB0byBmaW5kIHRoZSBzb2x1dGlvbiBmb3IgdGhpcyBwYXJ0aWN1bGFyIHByb2JsZW0sIGl0IGlzIG1vcmUgYXBwcm9wcmlhdGUgdG8gdXNlIG1hdGggdG8gbWFrZSBvdXIgc29sdXRpb24gYXV0b21hdGljLiBUaGVyZSBhcmUgbWFueSByb290LWZpbmRpbmcgYWxnb3JpdGhtcyBvdXQgdGhlcmUgYW5kIGZlZWwgZnJlZSB0byB1c2UgYW5vdGhlciwgYnV0IHdlIHdpbGwgdXNlIGEgc2ltcGxlIGFsZ29yaXRobSBrbm93biBhcyB0aGUgYmlzZWN0aW9uIG1ldGhvZC4gVGhpcyBtZXRob2Qgb25seSByZXF1aXJlcyB0aGF0IHlvdSBzZWxlY3QgdHdvIHBvaW50cyB0aGF0IGhhdmUgb3Bwb3NpdGUgc2lnbnM6IGlmICRmKGEpPeKIkiB0aGVuIGYoYik9KyQuDQoNCiMjQmlzZWN0aW9uIEFsZ29yaXRobSBmb3IgZmluZGluZyB0aGUgcm9vdCBvZiBhbiBlcXVhdGlvbi4NClRoZSBzaW1wbGUgaWRlYSBvZiB0aGUgYmlzZWN0aW9uIG1ldGhvZCBpcyB0aGF0IHlvdSBzdGFydCB3aXRoIGFuIGludGVydmFsIFthLGJdIHRoYXQgaGFzIGEgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHZhbHVlIGZvciB0aGUgZnVuY3Rpb24gJGYoYSkkIGFuZCAkZihiKSQgLSBpdCBkb2VzIG5vdCBtYXR0ZXIgd2hpY2ggb25lIGlzIHBvc2l0aXZlLiBZb3UgY3V0IHRoZSBpbnRlcnZhbCBpbiBoYWxmIGFuZCBwcm9jZWVkIHdpdGggdGhlIGludGVydmFsIHRoYXQga2VlcHMgb25lIHNpZGUgcG9zaXRpdmUgYW5kIHRoZSBvdGhlciBuZWdhdGl2ZS4gSW4gRmlndXJlIDEsIHdlIHN0YXJ0IG9uIHRoZSBpbnRlcnZhbCBbMiw5XSB3aGljaCB3b3JrcyBiZWNhdXNlICRmKDIpJCBpcyBwb3NpdGl2ZSBhbmQgJGYoOSkkIGlzIG5lZ2F0aXZlLiBUaGUgZmlyc3Qgc3RlcCBjdXRzIHRoZSBpbnRlcnZhbCBpbiBoYWxmIGFuZCB0aGUgZGVjaXNpb24gbXVzdCBiZSBtYWRlIHRvIGNvbnRpbnVlIHdpdGggWzIsNS41XSBvciBbNS41LDldLiBJdCBzaG91bGQgYmUgcHJldHR5IG9idm91cyBmcm9tIHRoZSBwaWN0dXJlIHRoYXQgWzIsNS41XSBpcyB0aGUgcmlnaHQgYW5zd2VyICh3ZSB3YW50IHRvIGtlZXAgYSByb290IGluIHRoZSBpbnRlcnZhbCksIGJ1dCBmcm9tIGFuIGFsZ29yaXRobSBwZXJzcGVjdGl2ZSwgd2Ugc2ltcGx5IHRlc3QgZig1LjUpIGFuZCBmaW5kIG91dCB0aGF0IGl0IGlzIG5lZ2F0aXZlIHdoaWNoIGNhdXNlcyB1cyB0byByZXBsYWNlIDkgKCRmWzldJCB3YXMgbmVnYXRpdmUpIHdpdGggNS41LiBXZSB3b3VsZCBjb250aW51ZSB0aGlzIGFsZ29yaXRobSB1bnRpbCB3ZSBhcmUgc2F0aXNmaWVkIHRoYXQgdGhlIHdpZHRoIG9mIHRoZSBpbnRlcnZhbCBpcyBzbWFsbCBlbm91Z2ggdG8gbWFrZSBhIGNvbmNsdXNpb24gYWJvdXQgdGhlIHZhbHVlIG9mIHRoZSByb290Lg0KYGBge3J9DQpiaXNlY3Rpb24gPSBmdW5jdGlvbihmLGEsYix0b2w9MC4wMDAxKXsNCiAgaWYgKGYoYSkqZihiKSA+IDApew0KICAgIHJldHVybiAoIkJvdW5kYXJ5IENvbmRpdGlvbnMgTm90IE1ldCIpDQogIH0NCiAgZWxzZXsNCiAgICBtaWRkbGUgPSBhDQogICAgd2hpbGUgKGFicyhmKG1pZGRsZSkpPnRvbCl7DQogICAgICBtaWRkbGUgPSAoYStiKS8yDQogICAgICBpZiAoZihtaWRkbGUpKmYoYSk+MCkgKGEgPSBtaWRkbGUpDQogICAgICBlbHNlIChiID0gbWlkZGxlKQ0KICAgICAgeD1taWRkbGUNCiAgICAgIHk9ZihtaWRkbGUpDQogICAgICAjIyBpZiB5b3Ugd2FudCB0byAic2VlIiB3aGF0IGhhcHBlbnMgYXQgZXZlcnkgc3RlcCwgdGFrZSBvZmYgdGhlICMgb2YgdGhlIG5leHQgbGluZSAjIw0KICAgICAgI2NhdChzcHJpbnRmKCJ4LVZhbDogJS40ZiA7IGYoeC12YWwpOiAlLjRmXG4iLHgseSkpDQogICAgfQ0KICAgIHJldHVybiAobWlkZGxlKQ0KICB9DQp9DQojRXhhbXBsZSBvZiBhIGZpbmRpbmcgYSByb290IG9mIGEgZnVuY3Rpb24NCmYgPSBmdW5jdGlvbiAoeCl7eF4zLTV9ICNzaW5sZ2UgbGluZSBmdW5jdGlvbiBkZWZpbml0aW9uDQp6ZXJvPWJpc2VjdGlvbiAoZiwtMTAsMjApDQp4PXNlcSgtMSwyLDAuMDEpDQpwbG90KHgsZih4KSwibCIpDQphYmxpbmUoaD0wLGNvbD0icmVkIikNCmFibGluZSh2PXplcm8sY29sPSJwdXJwbGUiKQ0KDQpwcmludCh6ZXJvKQ0KYGBgDQoNClVzZSBvdXIgdG9vbCB0byBzb2x2ZSB0aGUgcGlnIHByb2JsZW0NClVzZSB0aGUgdG9vbHMgYXQgeW91ciBkaXNwb3NhbCB0byBzb2x2ZSB0aGUgcHJvYmxlbS4gQmUgYWJsZSB0byBtYWtlIHNldmVyYWwgYWx0ZXJuYXRpdmVzIHRvIHRoZSBwcm9wb3NlZCBtb2RlbCBhbmQgaW52ZXN0aWdhdGUgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG11bHRpcGxlIHZhcmlhYmxlcy4gV2hlbiBkbyB3ZSBzZWxsIHRoZSBwaWc/DQpgYGB7cn0NCmRQcm9maXQgPSBmdW5jdGlvbih4KXtmcHJpbWUocHJvZml0LHgpfSAjZGVyaXZhdGl2ZSBvZiBwcm9maXQgZnVuY3Rpb24NCmJpc2VjdGlvbihkUHJvZml0LDAsMjApDQpgYGANCkFzIHlvdSBjYW4gc2VlLCB3ZSBnb3QgYXBwcm94aW1hdGVseSB0aGUgc2FtZSBhbnN3ZXIgYXMgdGhlIGJvb2suIFRoZSBkaWZmZXJlbmNlIGlzIHRoYXQgb3VyIHNvbHV0aW9uIHVzZXMgYW4gZXN0aW1hdGlvbiBvZiB0aGUgZGVyaXZhdGl2ZSBpbnN0ZWFkIG9mIHRoZSBjbG9zZWQtZm9ybSBzb2x1dGlvbiBhcyB3ZWxsIGFzIGEgc29sdmVyIGZvciBmaW5kaW5nIHRoZSBkYXkgeCB3aGVyZSB0aGUgcHJvZml0IGlzIG1heGltaXplZCAocHJvZml0IGZ1bmN0aW9uIGRlcml2YXRpdmUgPSAwKS4gSW4gdGhlIGNhc2Ugb2YgbW9zdCBwcm9ibGVtcywgeW91IHdpbGwgdXNlIG51bWVyaWNhbCBtZXRob2RzIChsaWtlIHdlIGRpZCkgYmVjYXVzZSByZWFsIHdvcmxkIHByb2JsZW1zIGRvIG5vdCB1c3VzYWxseSBoYXZlIGEgZWFzeSBhbnN3ZXIuIFRvIGJlY29tZSBhIGdvb2QgcHJvYmxlbSBzb2x2ZXIsIHlvdSBhcmUgZ29pbmcgdG8gbmVlZCB0byBpbnZlc3QgaW4geW91ciBjb2RpbmcgYWJpbGl0aWVzIGJlY2F1c2UgeW91IHdpbGwgdXN1YWxseSBuZWVkIHRvIGRldmVsb3Agc29tZSBvcmlnaW5hbCBjb2RlIHRvIGhlbHAgeW91IHNvbHZlIGEgcGFydGljdWxhciBwcm9ibGVtLg0KDQpTZW5zaXRpdml0eSBBbmFseXNpczogUHJpY2Ugb2YgdGhlIFBpZw0KTGV04oCZcyBnbyBiYWNrIGFuZCBleGFtaW5lIG1vcmUgY2xvc2VseSBvbmUgb2Ygb3VyIG9yaWdpbmFsIGFzc3VtcHRpb25zIHRoYXQgbWF5IG9yIG1heSBub3QgaG9sZCB0byBzZWUgaG93IG91ciBzb2x1dGlvbiBpcyBhZmZ0ZWN0ZWQgYnkgYSBkaWZmZXJlbnQgYXNzdW1wdGlvbi4gRG9lcyB0aGUgb3B0aW1hbCBkYXkgdG8gc2VsbCBjaGFuZ2UgaWYgd2UgYXNzdW1lIHNvbWUgZGlmZmVyZW50IHByaWNlIG9mIHRoZSBwaWcuIEhlcmUgd2UgbGV0IHRoZSBwaWcgcHJpY2UgZHJvcCB0byByZWNyZWF0ZSB0aGUgbnVtYmVycyBpbiB0aGUgYm9vaywgYnV0IHdlIGFyZSBhYmxlIHRvIGRvIHNvIG11Y2ggbW9yZSB3aGljaCB3aWxsIGJlIGRlbW9uc3RyYXRlZCBpbiB0aGUgbmV4dCBhbmFseXNpcy4NCmBgYHtyfQ0KI1ByaWNlIGZhbGxpbmcgcGVyIGRheSA9IHAgDQpwID0gc2VxKDAuMDA4LDAuMDEyLDAuMDAxKQ0KYW5zID0gYXJyYXkoMCxsZW5ndGgocCkpDQpmb3IgKGkgaW4gMTpsZW5ndGgocCkpew0KICAgIHByb2ZpdCA9IGZ1bmN0aW9uICh4KXsNCiAgICAgIHJldHVybigoMC42NS1wW2ldKngpKigyMDArNSp4KS0uNDUqeCkNCiAgICB9DQogICAgZFByb2ZpdCA9IGZ1bmN0aW9uKHgpe2ZwcmltZShwcm9maXQseCwpfQ0KICAgIGFuc1tpXSA9IGJpc2VjdGlvbihkUHJvZml0LDAsMjAsMC4wMDAxKQ0KfQ0KcHJpbnQoYW5zKQ0KcGxvdChwLGFucywibyIseGxhYj0icCgkL2RheSkiLHlsYWI9IngoRGF5cyB0byBTZWxsKSIpDQp0aXRsZSgiU2Vuc2l0aXZpdHkgb2YgRmFsbGluZyBQcmljZSBvZiBQaWciKQ0KYGBgDQoNClNlbnNpdGl2aXR5IEFuYWx5c2lzOiBHcm93dGggUmF0ZSBvZiB0aGUgUGlnDQpTaW5jZSB3ZSBhcmUgYWxzbyBjb25jZXJuZWQgYWJvdXQgdGhlIGdyb3d0aCByYXRlIG9mIHRoZSBwaWcsIGxldOKAmXMgY29uZHVjdCBzZWUgaG93IHRoZSBkYXlzIHRvIHNlbGwgYXJlIGFmZmVjdGVkIGJ5IHRoZSBncm93dGggcmF0ZS4gVGhlIHdlaWdodCAodykgaXMgY2FsY3VsYXRlZCB1c2luZyB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSBwaWcgd2lsbCBncm93IDVsYnMgcGVyIGRheSBzbyB0aGF0OiAkJHc9MjAwK2d0JCQgd2hlcmUgJCRnPTUkJC4gTGV04oCZcyBzZWUgd2hhdCBoYXBwZW5zIGlmIGcgaXMgYmV0d2VlbiAzIGFuZCA3LiBSZW1lbWJlciB0aGUgYmlzZWN0aW9uIG1ldGhvZCBuZWVkcyB0d28gYm91bmRhcnkgcG9pbnRzIHRoYXQgaGF2ZSB0aGUgb3Bwb3NpdGUgdmFsdWVzIGFuZCBpZiB0aGUgZ3Jvd3RoIHJhdGUgaXMgdG9vIHNtYWxsLCB0aGluayBhYm91dCB3aGF0IHRoYXQgZG9lcyB0byB0aGUgcHJvZml0LiBFeHBlcmltZW50IHdpdGggbGFyZ2UgYW5kIHNtYWxsIGdyb3d0aCByYXRlcyBhbmQgdGhlIHByb2ZpdCBmdW5jdGlvbiB0byBmaWd1cmUgaXQgb3V0IGZvciB5b3Vyc2VsZiBpZiB5b3UgZG9u4oCZdCBzZWUgaXQuIFdlIG5lZWRlZCB0byBtYWtlIHRoZSBzdGFydGluZyBwb2ludCBvZiB0aGUgYmlzZWN0aW9uIG1ldGhvZCB0byB0aGUgbGVmdCAobmVnYXRpdmUgbnVtYmVyKSBpbiBvcmRlciBmb3IgaXQgdG8gZmluZCB0aGUgemVybyBmb3IgM2xicyBhbmQgMy41bGJzIHBlciBkYXkuDQpgYGB7cn0NCiNHcm93dGggcmF0ZSBvZiB0aGUgcGlnID0gZw0KZyA9IHNlcSgxLDEyLDAuNSkNCmFucyA9IGFycmF5KDAsbGVuZ3RoKGcpKQ0KZm9yIChpIGluIDE6bGVuZ3RoKGcpKXsNCiAgICBwcm9maXQgPSBmdW5jdGlvbiAoeCl7DQogICAgICByZXR1cm4oKDAuNjUtMC4wMSp4KSooMjAwK2dbaV0qeCktLjQ1KngpDQogICAgfQ0KICAgIGRQcm9maXQgPSBmdW5jdGlvbih4KXtmcHJpbWUocHJvZml0LHgsKX0NCiAgICBhbnNbaV0gPSBiaXNlY3Rpb24oZFByb2ZpdCwtMTAwLDUwLDAuMDAwMSkNCn0NCnByaW50KGFucykNCnBsb3QoZyxhbnMsIm8iLHhsYWI9ImcoZ3Jvd3RoL2RheSkiLHlsYWI9IngoRGF5cyB0byBTZWxsKSIpDQp0aXRsZSgiU2Vuc2l0aXZpdHkgb2YgR3Jvd3RoIFJhdGUgb2YgUGlnIikNCmBgYA0KDQoNCg0K