Basic calculations

You can use R for basic computations you would perform in a calculator

# Addition
2-3
[1] -1
# Division
2/3
[1] 0.6666667
# Exponentiation
2^3 
[1] 8
# Square root
sqrt(2)
[1] 1.414214
# Logarithms
log(2)
[1] 0.6931472

#We can see that subtraction, division, exponentiation, square root, and Logarithms work.

Before we move on to see how comparison operators work, lets test the exponentiation, square root and log 10 math operators

Often you will want to test whether something is less than, greater than or equal to something.

sqrt(9)
[1] 3
9^2
[1] 81
log10(10)
[1] 1
3 == 8
[1] FALSE
3 != 8
[1] TRUE
3 <= 8
[1] TRUE

We see that the mathematical operations we tested worked. Also the comparison operators functioned as expected. Lets test some more comparisons.

The logical operators are & for logical AND, | for logical OR, and ! for NOT. These are some examples:

4==4
[1] TRUE
4!=4
[1] FALSE
4<=3
[1] FALSE
# Logical Disjunction (or)
FALSE | FALSE
[1] FALSE
# Logical Conjunction (and)
TRUE & FALSE
[1] FALSE
# Negation
! FALSE
[1] TRUE
# Combination of statements
2 < 3 | 1 == 5
[1] TRUE

Lets test some operators like the & (and) and !(negation)

Assigning Values to Variables

In R, you create a variable and assign it a value using <- as follows

3<4&2!=4
[1] TRUE
! TRUE
[1] FALSE
foo <- 2 + 2
foo*3
[1] 12

#Here we can see that the logical operators & works, as well the negation #We also see that the value stored in the variable “foo” (4) equalled 12 when multiplied(*) by 3

lets create a new variable called “ton” store the value 5 and multiply it by 5 so that we get the result of 25

To see the variables that are currently defined, use ls (as in “list”)

ton <- 7-2
ton*5
ls()

we can see that the ls() function listed the two stored variables “foo” and “ton”

now lets test the remove and list functions. We’ll remove the variable ‘foo’ so only ‘ton’ should be left

To delete a variable, use rm (as in “remove”)

rm(foo)
ls()

we see the remove function worked and the only variable left was the ‘ton’ variable we created

Either <- or = can be used to assign a value to a variable, but I prefer <- because is less likely to be confused with the logical operator ==

Vectors

The basic type of object in R is a vector, which is an ordered list of values of the same type. You can create a vector using the c() function (as in “concatenate”).

bar <- c(2, 5, 10, 2, 1) 
bar

we see above how the variable bar stored the five values in a vector by using the concatenate(c) function

we will also see the same be achieve below for the baz variable, i used the = assignment operator instead of the <-

baz = c(2, 2, 3, 3, 3)
baz

There are also some functions that will create vectors with regular patterns, like repeated elements.

# replicate function
rep(2, 5)
# consecutive numbers
1:5
# sequence from 1 to 10 with a step of 2
seq(1, 10, by=2)

we can see that the replicate (rep) function created a vector with the number 2 repeated five times.

the consecutive numbers function created a vector ranging of consecutive numbers form 1 through 5 notice it incluede the last number 5, unlike pyhton we didnt have to list it to 6 to achive this

We see we can create a varaible that will list thru a specified range by the steps we designate

lets test the rep and seq function by repeating the number 6 in a vector four times, and a sequence from 1 thru 20 with steps of 3

Many functions and operators like + or - will work on all elements of the vector.

rep(6, 4)
seq(1,20, by=3)
# add vectors
bar + baz
# compare vectors
bar == baz
# find length of vector
length(bar)
# find minimum value in vector
min(bar)
# find average value in vector
mean(bar)

we can see both the vector generation functions we tested worked, 6 is listed four times and 1 thru 20 is listed with at intervals of three

we also see that the addition worked for each indexed value in the bar and baz variables, 2+2 = 4, 5+2=7, 10+3=13 and so forth

the comparison operator also showed that only the first comparison was true and all other values didn’t match between bar and baz

the length function did count the leng of the ‘bar’ vectors which is five. The minimum value of bar was one, and the mean of of the ’bar vectors values was 4.

lets test and see what the mean of the baz vector is ‘2.6’ and also if its length is five

You can access parts of a vector by using [. Recall what the value is of the vector bar.

mean(baz)
length(baz)
bar
# If you want to get the first element:
bar[1]

we can see that the baz vectors values came out as we predicted

#above we can see that the ‘bar’ variable was called and it out put the vector for it as well as when we called for the first element(2)in the vector was output by using the select element [] on the bar variable

Now lets list the baz vector and select the last element which should be 3

If you want to get the last element of bar without explicitly typing the number of elements of bar, make use of the length function, which calculates the length of a vector:

baz
baz[5]
bar[length(bar)]

we were able to list the baz vector and its last element was as we predicted above

more useful for listing the last element of the function is the numerical value of thelength of the vector being used as the element location for the last value. Since there are five values then the output of the length would be 5 which is also the last element insaid vector.

You can also extract multiple values from a vector. For instance to get the 2nd through 4th values use

bar[c(2, 3, 4)]
bar[c(1, 3, 5)]

above we can see that the 2nd, 3rd, and 4th elements from the bar variable are listed correctley as 5, 10 , and 2

we also see that this works with elements in ancy sequence with the other line we called from the same variable since the 1st, 3rd, and 5th elements (2,10, and 1) were listed correctley.

Vectors can also be strings or logical values

quxx <- c("a", "b", "cde", "fg")
quxx

we can see above that the we are able to store string characters in a vector as well.

Data Frames

In statistical applications, data is often stored as a data frame, which is like a spreadsheet, with rows as observations and columns as variables.

To manually create a data frame, use the data.frame() function.

data.frame(foo = c(1, 2, 3), 
           bar = c("a", "b", "c"), 
           baz = c(1.5, 2.5, 3)) 
NA

we can see above that we were able to store the records for each vector in the dataframe as columns noticed its balanced. I was curios to see if an unbalanced dataframe would cause an error and after testing I proved it does. All columns must have a matching number of records/rows

Most often you will be using data frames loaded from a file. For example, load the results of a class survey. The function load or read.table can be used for this.

How to Make a Random Sample

To randomly select a sample use the function sample(). The following code selects 5 numbers between 1 and 10 at random (without duplication)

sample(1:10, size=5)
sample(1:20, size=8)

We can see that we are able to create a vector with randomized values by using the sample function, all we have to do is specify the range we want the numbers to be selected from and the (size) amount of numbers we want produced.

Taking a simple random sample from a data frame is only slightly more complicated, having two steps:

  1. Use sample() to select a sample of size n from a vector of the row numbers of the data frame.
  2. Use the index operator [ to select those rows from the data frame.

Consider the following example with fake data. First, make up a data frame with two columns. (LETTERS is a character vector of length 26 with capital letters “A” to “Z”; LETTERS is automatically defined and pre-loaded in R)

bar <- data.frame(var1 = LETTERS[1:10], var2 = 1:10)
# Check data frame
bar

above we can see that we created a dataframe(‘bar’ replacing the previous variale of the same name) with two columns by using the charactes from the ‘letters’ vector for the first varaible ans the numbers 1 thru 10 on the second variable by using the(:) vector creation function.

Suppose you want to select a random sample of size 5. First, define a variable n with the size of the sample, i.e. 5

n <- 5

#above we created the variable ‘n’ to store the value 5 so we can call it again later as the size(amount of numbers) we want selected for our random number sample

Now, select a sample of size 5 from the vector with 1 to 10 (the number of rows in bar). Use the function nrow() to find the number of rows in bar instead of manually entering that number.

Use : to create a vector with all the integers between 1 and the number of rows in bar.

samplerows <- sample(1:nrow(bar), size=n) 
# print sample rows
samplerows

above we can see we create the variable “samplerows” by using the sample function, we set the range from 1 to the number of rows(nrow) in the ‘bar’ dataframe (10), then we select the size (number of elements we want output) by using the variable we created before ‘n’. So we can see that only five random numers ranging from one thru 10 are listed when we call the varable ‘samplerows’

The variable samplerows contains the rows of bar which make a random sample from all the rows in bar. Extract those rows from bar with

# extract rows
barsample <- bar[samplerows, ]
# print sample
print(barsample)

above we can see ho we can select specific rows from a dataframe and store them in a new variable(barsample), by selecting the rows from our previous dataframe(bar) off of the values from our random sample(samplerows). My random sample produced 3 4 7 9 1 and those are corresponding rows where inserted into the barsample dataframe.

The code above creates a new data frame called barsample with a random sample of rows from bar.

In a single line of code:

bar[sample(1:nrow(bar), n), ]

above we can see how we replicate the previous work we did to create the ‘barsample’ dataframe in one line of code by usinge the element select function [] combined with the sample function and nrow function. Notice this doesn’t store the random sample dataframe like we did before, instead it only displays the selection.

Using Tables

The table() command allows us to look at tables. Its simplest usage looks like table(x) where x is a categorical variable.

For example, a survey asks people if they smoke or not. The data is

Yes, No, No, Yes, Yes

We can enter this into R with the c() command, and summarize with the table() command as follows

x <- c("Yes","No","No","Yes","Yes") 
table(x)

above we can see that we create a new variable with string characters stored in it. then we use the table() function to display the count of each value in this table, our output is 2 No’s and 3 Yes’s which is correct.

Numeric measures of center and spread

Suppose, CEO yearly compensations are sampled and the following are found (in millions)

12 .4 5 2 50 8 3 1 4 0.25

sals <- c(12, .4, 5, 2, 50, 8, 3, 1, 4, 0.25)
# the average
mean(sals) 
# the variance
var(sals)
# the standard deviation
sd(sals)
# the median
median(sals)
# Tukey's five number summary, usefull for boxplots
# five numbers: min, lower hinge, median, upper hinge, max
fivenum(sals)
# summary statistics
summary(sals)

Above we can see some common statistical analysis using built in functions to return the average, variance, standard deviation, median, five number summary, and summary statistics, all performed on the sals variables values we concated into a vector. Notice the statistical summary and five number summary are different.

How about the mode?

In R we can write our own functions, and a first example of a function is shown below in order to compute the mode of a vector of observations x

# Function to find the mode, i.e. most frequent value
getMode <- function(x) {
     ux <- unique(x)
     ux[which.max(tabulate(match(x, ux)))]
 }

Above we use the the function “function” to create our own function. In this case the function we create is called ‘getMode’ which will return the value that is repeated the most in a vector.

As an example, we can use the function defined above to find the most frequent value in te vector baz

# Most frequent value in baz
getMode(baz)

Here we use the function that we created ‘getMode’ on the variable ‘baz’ which has a vector made of 2,2,3,3,3. It ouputs 3 which we can see ist the mode of the ‘baz’ vector.

LS0tDQp0aXRsZTogIkZpcnN0IFN0ZXBzIGluIGBSYCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMgQmFzaWMgY2FsY3VsYXRpb25zDQoNCllvdSBjYW4gdXNlIFIgZm9yIGJhc2ljIGNvbXB1dGF0aW9ucyB5b3Ugd291bGQgcGVyZm9ybSBpbiBhIGNhbGN1bGF0b3INCg0KYGBge3J9DQojIEFkZGl0aW9uDQoyLTMNCiMgRGl2aXNpb24NCjIvMw0KIyBFeHBvbmVudGlhdGlvbg0KMl4zIA0KIyBTcXVhcmUgcm9vdA0Kc3FydCgyKQ0KIyBMb2dhcml0aG1zDQpsb2coMikNCmBgYA0KDQojV2UgY2FuIHNlZSB0aGF0IHN1YnRyYWN0aW9uLCBkaXZpc2lvbiwgZXhwb25lbnRpYXRpb24sIHNxdWFyZSByb290LCBhbmQgTG9nYXJpdGhtcyB3b3JrLg0KDQpCZWZvcmUgd2UgbW92ZSBvbiB0byBzZWUgaG93IGNvbXBhcmlzb24gb3BlcmF0b3JzIHdvcmssIGxldHMgdGVzdCB0aGUgZXhwb25lbnRpYXRpb24sIHNxdWFyZSByb290IGFuZCBsb2cgMTAgbWF0aCBvcGVyYXRvcnMNCg0KT2Z0ZW4geW91IHdpbGwgd2FudCB0byB0ZXN0IHdoZXRoZXIgc29tZXRoaW5nIGlzIGxlc3MgdGhhbiwgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIHNvbWV0aGluZy4NCg0KYGBge3J9DQpzcXJ0KDkpDQo5XjINCmxvZzEwKDEwKQ0KMyA9PSA4DQozICE9IDgNCjMgPD0gOA0KYGBgDQoNCldlIHNlZSB0aGF0IHRoZSBtYXRoZW1hdGljYWwgb3BlcmF0aW9ucyB3ZSB0ZXN0ZWQgd29ya2VkLiBBbHNvIHRoZSBjb21wYXJpc29uIG9wZXJhdG9ycyBmdW5jdGlvbmVkIGFzIGV4cGVjdGVkLiBMZXRzIHRlc3Qgc29tZSBtb3JlIGNvbXBhcmlzb25zLg0KDQpUaGUgKmxvZ2ljYWwgb3BlcmF0b3JzKiBhcmUgYCZgIGZvciBsb2dpY2FsICoqQU5EKiosIGB8YCBmb3IgbG9naWNhbCAqKk9SKiosIGFuZCBgIWAgZm9yICoqTk9UKiouIFRoZXNlIGFyZSBzb21lIGV4YW1wbGVzOg0KDQpgYGB7cn0NCjQ9PTQNCjQhPTQNCjQ8PTMNCg0KIyBMb2dpY2FsIERpc2p1bmN0aW9uIChvcikNCkZBTFNFIHwgRkFMU0UNCiMgTG9naWNhbCBDb25qdW5jdGlvbiAoYW5kKQ0KVFJVRSAmIEZBTFNFDQojIE5lZ2F0aW9uDQohIEZBTFNFDQojIENvbWJpbmF0aW9uIG9mIHN0YXRlbWVudHMNCjIgPCAzIHwgMSA9PSA1DQpgYGANCg0KTGV0cyB0ZXN0IHNvbWUgb3BlcmF0b3JzIGxpa2UgdGhlICYgKGFuZCkgYW5kICEobmVnYXRpb24pDQoNCiMgQXNzaWduaW5nIFZhbHVlcyB0byBWYXJpYWJsZXMNCg0KSW4gUiwgeW91IGNyZWF0ZSBhIHZhcmlhYmxlIGFuZCBhc3NpZ24gaXQgYSB2YWx1ZSB1c2luZyBgPC1gIGFzIGZvbGxvd3MNCg0KYGBge3J9DQozPDQmMiE9NA0KISBUUlVFDQpmb28gPC0gMiArIDINCmZvbyozDQpgYGANCg0KI0hlcmUgd2UgY2FuIHNlZSB0aGF0IHRoZSBsb2dpY2FsIG9wZXJhdG9ycyAmIHdvcmtzLCBhcyB3ZWxsIHRoZSBuZWdhdGlvbiAjV2UgYWxzbyBzZWUgdGhhdCB0aGUgdmFsdWUgc3RvcmVkIGluIHRoZSB2YXJpYWJsZSAiZm9vIiAoNCkgZXF1YWxsZWQgMTIgd2hlbiBtdWx0aXBsaWVkKFwqKSBieSAzDQoNCiMgbGV0cyBjcmVhdGUgYSBuZXcgdmFyaWFibGUgY2FsbGVkICJ0b24iIHN0b3JlIHRoZSB2YWx1ZSA1IGFuZCBtdWx0aXBseSBpdCBieSA1IHNvIHRoYXQgd2UgZ2V0IHRoZSByZXN1bHQgb2YgMjUNCg0KVG8gc2VlIHRoZSB2YXJpYWJsZXMgdGhhdCBhcmUgY3VycmVudGx5IGRlZmluZWQsIHVzZSBgbHNgIChhcyBpbiAibGlzdCIpDQoNCmBgYHtyfQ0KdG9uIDwtIDctMg0KdG9uKjUNCmxzKCkNCmBgYA0KDQojIHdlIGNhbiBzZWUgdGhhdCB0aGUgbHMoKSBmdW5jdGlvbiBsaXN0ZWQgdGhlIHR3byBzdG9yZWQgdmFyaWFibGVzICJmb28iIGFuZCAidG9uIg0KDQojIG5vdyBsZXRzIHRlc3QgdGhlIHJlbW92ZSBhbmQgbGlzdCBmdW5jdGlvbnMuIFdlJ2xsIHJlbW92ZSB0aGUgdmFyaWFibGUgJ2Zvbycgc28gb25seSAndG9uJyBzaG91bGQgYmUgbGVmdA0KDQpUbyBkZWxldGUgYSB2YXJpYWJsZSwgdXNlIGBybWAgKGFzIGluICJyZW1vdmUiKQ0KDQpgYGB7cn0NCnJtKGZvbykNCmxzKCkNCmBgYA0KDQojIHdlIHNlZSB0aGUgcmVtb3ZlIGZ1bmN0aW9uIHdvcmtlZCBhbmQgdGhlIG9ubHkgdmFyaWFibGUgbGVmdCB3YXMgdGhlICd0b24nIHZhcmlhYmxlIHdlIGNyZWF0ZWQNCg0KRWl0aGVyIGA8LWAgb3IgYD1gIGNhbiBiZSB1c2VkIHRvIGFzc2lnbiBhIHZhbHVlIHRvIGEgdmFyaWFibGUsIGJ1dCBJIHByZWZlciBgPC1gIGJlY2F1c2UgaXMgbGVzcyBsaWtlbHkgdG8gYmUgY29uZnVzZWQgd2l0aCB0aGUgbG9naWNhbCBvcGVyYXRvciBgPT1gDQoNCiMgVmVjdG9ycw0KDQpUaGUgYmFzaWMgdHlwZSBvZiBvYmplY3QgaW4gUiBpcyBhICp2ZWN0b3IqLCB3aGljaCBpcyBhbiBvcmRlcmVkIGxpc3Qgb2YgdmFsdWVzIG9mIHRoZSBzYW1lIHR5cGUuIFlvdSBjYW4gY3JlYXRlIGEgdmVjdG9yIHVzaW5nIHRoZSBgYygpYCBmdW5jdGlvbiAoYXMgaW4gImNvbmNhdGVuYXRlIikuDQoNCmBgYHtyfQ0KYmFyIDwtIGMoMiwgNSwgMTAsIDIsIDEpIA0KYmFyDQpgYGANCg0KIyB3ZSBzZWUgYWJvdmUgaG93IHRoZSB2YXJpYWJsZSBiYXIgc3RvcmVkIHRoZSBmaXZlIHZhbHVlcyBpbiBhIHZlY3RvciBieSB1c2luZyB0aGUgY29uY2F0ZW5hdGUoYykgZnVuY3Rpb24NCg0KIyB3ZSB3aWxsIGFsc28gc2VlIHRoZSBzYW1lIGJlIGFjaGlldmUgYmVsb3cgZm9yIHRoZSBiYXogdmFyaWFibGUsIGkgdXNlZCB0aGUgPSBhc3NpZ25tZW50IG9wZXJhdG9yIGluc3RlYWQgb2YgdGhlIFw8LQ0KDQpgYGB7cn0NCmJheiA9IGMoMiwgMiwgMywgMywgMykNCmJheg0KYGBgDQoNClRoZXJlIGFyZSBhbHNvIHNvbWUgZnVuY3Rpb25zIHRoYXQgd2lsbCBjcmVhdGUgdmVjdG9ycyB3aXRoIHJlZ3VsYXIgcGF0dGVybnMsIGxpa2UgcmVwZWF0ZWQgZWxlbWVudHMuDQoNCmBgYHtyfQ0KIyByZXBsaWNhdGUgZnVuY3Rpb24NCnJlcCgyLCA1KQ0KIyBjb25zZWN1dGl2ZSBudW1iZXJzDQoxOjUNCiMgc2VxdWVuY2UgZnJvbSAxIHRvIDEwIHdpdGggYSBzdGVwIG9mIDINCnNlcSgxLCAxMCwgYnk9MikNCmBgYA0KDQojIHdlIGNhbiBzZWUgdGhhdCB0aGUgcmVwbGljYXRlIChyZXApIGZ1bmN0aW9uIGNyZWF0ZWQgYSB2ZWN0b3Igd2l0aCB0aGUgbnVtYmVyIDIgcmVwZWF0ZWQgZml2ZSB0aW1lcy4NCg0KIyB0aGUgY29uc2VjdXRpdmUgbnVtYmVycyBmdW5jdGlvbiBjcmVhdGVkIGEgdmVjdG9yIHJhbmdpbmcgb2YgY29uc2VjdXRpdmUgbnVtYmVycyBmb3JtIDEgdGhyb3VnaCA1IG5vdGljZSBpdCBpbmNsdWVkZSB0aGUgbGFzdCBudW1iZXIgNSwgdW5saWtlIHB5aHRvbiB3ZSBkaWRudCBoYXZlIHRvIGxpc3QgaXQgdG8gNiB0byBhY2hpdmUgdGhpcw0KDQojIFdlIHNlZSB3ZSBjYW4gY3JlYXRlIGEgdmFyYWlibGUgdGhhdCB3aWxsIGxpc3QgdGhydSBhIHNwZWNpZmllZCByYW5nZSBieSB0aGUgc3RlcHMgd2UgZGVzaWduYXRlDQoNCiMgbGV0cyB0ZXN0IHRoZSByZXAgYW5kIHNlcSBmdW5jdGlvbiBieSByZXBlYXRpbmcgdGhlIG51bWJlciA2IGluIGEgdmVjdG9yIGZvdXIgdGltZXMsIGFuZCBhIHNlcXVlbmNlIGZyb20gMSB0aHJ1IDIwIHdpdGggc3RlcHMgb2YgMw0KDQpNYW55IGZ1bmN0aW9ucyBhbmQgb3BlcmF0b3JzIGxpa2UgYCtgIG9yIGAtYCB3aWxsIHdvcmsgb24gYWxsIGVsZW1lbnRzIG9mIHRoZSB2ZWN0b3IuDQoNCmBgYHtyfQ0KcmVwKDYsIDQpDQpzZXEoMSwyMCwgYnk9MykNCiMgYWRkIHZlY3RvcnMNCmJhciArIGJheg0KIyBjb21wYXJlIHZlY3RvcnMNCmJhciA9PSBiYXoNCiMgZmluZCBsZW5ndGggb2YgdmVjdG9yDQpsZW5ndGgoYmFyKQ0KIyBmaW5kIG1pbmltdW0gdmFsdWUgaW4gdmVjdG9yDQptaW4oYmFyKQ0KIyBmaW5kIGF2ZXJhZ2UgdmFsdWUgaW4gdmVjdG9yDQptZWFuKGJhcikNCmBgYA0KDQojIHdlIGNhbiBzZWUgYm90aCB0aGUgdmVjdG9yIGdlbmVyYXRpb24gZnVuY3Rpb25zIHdlIHRlc3RlZCB3b3JrZWQsIDYgaXMgbGlzdGVkIGZvdXIgdGltZXMgYW5kIDEgdGhydSAyMCBpcyBsaXN0ZWQgd2l0aCBhdCBpbnRlcnZhbHMgb2YgdGhyZWUNCg0KIyB3ZSBhbHNvIHNlZSB0aGF0IHRoZSBhZGRpdGlvbiB3b3JrZWQgZm9yIGVhY2ggaW5kZXhlZCB2YWx1ZSBpbiB0aGUgYmFyIGFuZCBiYXogdmFyaWFibGVzLCAyKzIgPSA0LCA1KzI9NywgMTArMz0xMyBhbmQgc28gZm9ydGgNCg0KIyB0aGUgY29tcGFyaXNvbiBvcGVyYXRvciBhbHNvIHNob3dlZCB0aGF0IG9ubHkgdGhlIGZpcnN0IGNvbXBhcmlzb24gd2FzIHRydWUgYW5kIGFsbCBvdGhlciB2YWx1ZXMgZGlkbid0IG1hdGNoIGJldHdlZW4gYmFyIGFuZCBiYXoNCg0KIyB0aGUgbGVuZ3RoIGZ1bmN0aW9uIGRpZCBjb3VudCB0aGUgbGVuZyBvZiB0aGUgJ2JhcicgdmVjdG9ycyB3aGljaCBpcyBmaXZlLiBUaGUgbWluaW11bSB2YWx1ZSBvZiBiYXIgd2FzIG9uZSwgYW5kIHRoZSBtZWFuIG9mIG9mIHRoZSAnYmFyIHZlY3RvcnMgdmFsdWVzIHdhcyA0Lg0KDQojIGxldHMgdGVzdCBhbmQgc2VlIHdoYXQgdGhlIG1lYW4gb2YgdGhlIGJheiB2ZWN0b3IgaXMgJzIuNicgYW5kIGFsc28gaWYgaXRzIGxlbmd0aCBpcyBmaXZlDQoNCllvdSBjYW4gYWNjZXNzIHBhcnRzIG9mIGEgdmVjdG9yIGJ5IHVzaW5nIGBbYC4gUmVjYWxsIHdoYXQgdGhlIHZhbHVlIGlzIG9mIHRoZSB2ZWN0b3IgYGJhcmAuDQoNCmBgYHtyfQ0KbWVhbihiYXopDQpsZW5ndGgoYmF6KQ0KYmFyDQojIElmIHlvdSB3YW50IHRvIGdldCB0aGUgZmlyc3QgZWxlbWVudDoNCmJhclsxXQ0KYGBgDQoNCiMgd2UgY2FuIHNlZSB0aGF0IHRoZSBiYXogdmVjdG9ycyB2YWx1ZXMgY2FtZSBvdXQgYXMgd2UgcHJlZGljdGVkDQoNCiNhYm92ZSB3ZSBjYW4gc2VlIHRoYXQgdGhlICdiYXInIHZhcmlhYmxlIHdhcyBjYWxsZWQgYW5kIGl0IG91dCBwdXQgdGhlIHZlY3RvciBmb3IgaXQgYXMgd2VsbCBhcyB3aGVuIHdlIGNhbGxlZCBmb3IgdGhlIGZpcnN0IGVsZW1lbnQoMilpbiB0aGUgdmVjdG9yIHdhcyBvdXRwdXQgYnkgdXNpbmcgdGhlIHNlbGVjdCBlbGVtZW50IFtdIG9uIHRoZSBiYXIgdmFyaWFibGUNCg0KIyBOb3cgbGV0cyBsaXN0IHRoZSBiYXogdmVjdG9yIGFuZCBzZWxlY3QgdGhlIGxhc3QgZWxlbWVudCB3aGljaCBzaG91bGQgYmUgMw0KDQpJZiB5b3Ugd2FudCB0byBnZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBgYmFyYCB3aXRob3V0IGV4cGxpY2l0bHkgdHlwaW5nIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgb2YgYGJhcmAsIG1ha2UgdXNlIG9mIHRoZSBgbGVuZ3RoYCBmdW5jdGlvbiwgd2hpY2ggY2FsY3VsYXRlcyB0aGUgbGVuZ3RoIG9mIGEgdmVjdG9yOg0KDQpgYGB7cn0NCmJheg0KYmF6WzVdDQpiYXJbbGVuZ3RoKGJhcildDQpgYGANCg0KIyB3ZSB3ZXJlIGFibGUgdG8gbGlzdCB0aGUgYmF6IHZlY3RvciBhbmQgaXRzIGxhc3QgZWxlbWVudCB3YXMgYXMgd2UgcHJlZGljdGVkIGFib3ZlDQoNCiMgbW9yZSB1c2VmdWwgZm9yIGxpc3RpbmcgdGhlIGxhc3QgZWxlbWVudCBvZiB0aGUgZnVuY3Rpb24gaXMgdGhlIG51bWVyaWNhbCB2YWx1ZSBvZiB0aGVsZW5ndGggb2YgdGhlIHZlY3RvciBiZWluZyB1c2VkIGFzIHRoZSBlbGVtZW50IGxvY2F0aW9uIGZvciB0aGUgbGFzdCB2YWx1ZS4gU2luY2UgdGhlcmUgYXJlIGZpdmUgdmFsdWVzIHRoZW4gdGhlIG91dHB1dCBvZiB0aGUgbGVuZ3RoIHdvdWxkIGJlIDUgd2hpY2ggaXMgYWxzbyB0aGUgbGFzdCBlbGVtZW50IGluc2FpZCB2ZWN0b3IuDQoNCllvdSBjYW4gYWxzbyBleHRyYWN0IG11bHRpcGxlIHZhbHVlcyBmcm9tIGEgdmVjdG9yLiBGb3IgaW5zdGFuY2UgdG8gZ2V0IHRoZSAybmQgdGhyb3VnaCA0dGggdmFsdWVzIHVzZQ0KDQpgYGB7cn0NCmJhcltjKDIsIDMsIDQpXQ0KYmFyW2MoMSwgMywgNSldDQoNCmBgYA0KDQojIGFib3ZlIHdlIGNhbiBzZWUgdGhhdCB0aGUgMm5kLCAzcmQsIGFuZCA0dGggZWxlbWVudHMgZnJvbSB0aGUgYmFyIHZhcmlhYmxlIGFyZSBsaXN0ZWQgY29ycmVjdGxleSBhcyA1LCAxMCAsIGFuZCAyDQoNCiMgd2UgYWxzbyBzZWUgdGhhdCB0aGlzIHdvcmtzIHdpdGggZWxlbWVudHMgaW4gYW5jeSBzZXF1ZW5jZSB3aXRoIHRoZSBvdGhlciBsaW5lIHdlIGNhbGxlZCBmcm9tIHRoZSBzYW1lIHZhcmlhYmxlIHNpbmNlIHRoZSAxc3QsIDNyZCwgYW5kIDV0aCBlbGVtZW50cyAoMiwxMCwgYW5kIDEpIHdlcmUgbGlzdGVkIGNvcnJlY3RsZXkuDQoNClZlY3RvcnMgY2FuIGFsc28gYmUgc3RyaW5ncyBvciBsb2dpY2FsIHZhbHVlcw0KDQpgYGB7cn0NCnF1eHggPC0gYygiYSIsICJiIiwgImNkZSIsICJmZyIpDQpxdXh4DQpgYGANCg0KIyB3ZSBjYW4gc2VlIGFib3ZlIHRoYXQgdGhlIHdlIGFyZSBhYmxlIHRvIHN0b3JlIHN0cmluZyBjaGFyYWN0ZXJzIGluIGEgdmVjdG9yIGFzIHdlbGwuDQoNCiMgRGF0YSBGcmFtZXMNCg0KSW4gc3RhdGlzdGljYWwgYXBwbGljYXRpb25zLCBkYXRhIGlzIG9mdGVuIHN0b3JlZCBhcyBhIGRhdGEgZnJhbWUsIHdoaWNoIGlzIGxpa2UgYSBzcHJlYWRzaGVldCwgd2l0aCAqcm93cyBhcyBvYnNlcnZhdGlvbnMqIGFuZCAqY29sdW1ucyBhcyB2YXJpYWJsZXMqLg0KDQpUbyBtYW51YWxseSBjcmVhdGUgYSBkYXRhIGZyYW1lLCB1c2UgdGhlIGBkYXRhLmZyYW1lKClgIGZ1bmN0aW9uLg0KDQpgYGB7cn0NCmRhdGEuZnJhbWUoZm9vID0gYygxLCAyLCAzKSwgDQogICAgICAgICAgIGJhciA9IGMoImEiLCAiYiIsICJjIiksIA0KICAgICAgICAgICBiYXogPSBjKDEuNSwgMi41LCAzKSkgDQoNCmBgYA0KDQojIHdlIGNhbiBzZWUgYWJvdmUgdGhhdCB3ZSB3ZXJlIGFibGUgdG8gc3RvcmUgdGhlIHJlY29yZHMgZm9yIGVhY2ggdmVjdG9yIGluIHRoZSBkYXRhZnJhbWUgYXMgY29sdW1ucyBub3RpY2VkIGl0cyBiYWxhbmNlZC4gSSB3YXMgY3VyaW9zIHRvIHNlZSBpZiBhbiB1bmJhbGFuY2VkIGRhdGFmcmFtZSB3b3VsZCBjYXVzZSBhbiBlcnJvciBhbmQgYWZ0ZXIgdGVzdGluZyBJIHByb3ZlZCBpdCBkb2VzLiBBbGwgY29sdW1ucyBtdXN0IGhhdmUgYSBtYXRjaGluZyBudW1iZXIgb2YgcmVjb3Jkcy9yb3dzDQoNCk1vc3Qgb2Z0ZW4geW91IHdpbGwgYmUgdXNpbmcgZGF0YSBmcmFtZXMgbG9hZGVkIGZyb20gYSBmaWxlLiBGb3IgZXhhbXBsZSwgbG9hZCB0aGUgcmVzdWx0cyBvZiBhIGNsYXNzIHN1cnZleS4gVGhlIGZ1bmN0aW9uIGBsb2FkYCBvciBgcmVhZC50YWJsZWAgY2FuIGJlIHVzZWQgZm9yIHRoaXMuDQoNCiMgSG93IHRvIE1ha2UgYSBSYW5kb20gU2FtcGxlDQoNClRvIHJhbmRvbWx5IHNlbGVjdCBhIHNhbXBsZSB1c2UgdGhlIGZ1bmN0aW9uIGBzYW1wbGUoKWAuIFRoZSBmb2xsb3dpbmcgY29kZSBzZWxlY3RzIDUgbnVtYmVycyBiZXR3ZWVuIDEgYW5kIDEwIGF0IHJhbmRvbSAod2l0aG91dCBkdXBsaWNhdGlvbikNCg0KYGBge3J9DQpzYW1wbGUoMToxMCwgc2l6ZT01KQ0Kc2FtcGxlKDE6MjAsIHNpemU9OCkNCmBgYA0KDQojIFdlIGNhbiBzZWUgdGhhdCB3ZSBhcmUgYWJsZSB0byBjcmVhdGUgYSB2ZWN0b3Igd2l0aCByYW5kb21pemVkIHZhbHVlcyBieSB1c2luZyB0aGUgc2FtcGxlIGZ1bmN0aW9uLCBhbGwgd2UgaGF2ZSB0byBkbyBpcyBzcGVjaWZ5IHRoZSByYW5nZSB3ZSB3YW50IHRoZSBudW1iZXJzIHRvIGJlIHNlbGVjdGVkIGZyb20gYW5kIHRoZSAoc2l6ZSkgYW1vdW50IG9mIG51bWJlcnMgd2Ugd2FudCBwcm9kdWNlZC4NCg0KLSAgIFRoZSBmaXJzdCBhcmd1bWVudCBnaXZlcyB0aGUgdmVjdG9yIG9mIGRhdGEgdG8gc2VsZWN0IGVsZW1lbnRzIGZyb20uDQotICAgVGhlIHNlY29uZCBhcmd1bWVudCAoYHNpemU9YCkgZ2l2ZXMgdGhlIHNpemUgb2YgdGhlIHNhbXBsZSB0byBzZWxlY3QuDQoNClRha2luZyBhIHNpbXBsZSByYW5kb20gc2FtcGxlIGZyb20gYSBkYXRhIGZyYW1lIGlzIG9ubHkgc2xpZ2h0bHkgbW9yZSBjb21wbGljYXRlZCwgaGF2aW5nIHR3byBzdGVwczoNCg0KMS4gIFVzZSBgc2FtcGxlKClgIHRvIHNlbGVjdCBhIHNhbXBsZSBvZiBzaXplIGBuYCBmcm9tIGEgdmVjdG9yIG9mIHRoZSByb3cgbnVtYmVycyBvZiB0aGUgZGF0YSBmcmFtZS4NCjIuICBVc2UgdGhlIGluZGV4IG9wZXJhdG9yIGBbYCB0byBzZWxlY3QgdGhvc2Ugcm93cyBmcm9tIHRoZSBkYXRhIGZyYW1lLg0KDQpDb25zaWRlciB0aGUgZm9sbG93aW5nIGV4YW1wbGUgd2l0aCAqZmFrZSBkYXRhKi4gRmlyc3QsIG1ha2UgdXAgYSBkYXRhIGZyYW1lIHdpdGggdHdvIGNvbHVtbnMuIChgTEVUVEVSU2AgaXMgYSBjaGFyYWN0ZXIgdmVjdG9yIG9mIGxlbmd0aCAyNiB3aXRoIGNhcGl0YWwgbGV0dGVycyDDosKAwpxBw6LCgMKdIHRvIMOiwoDCnFrDosKAwp07IGBMRVRURVJTYCBpcyBhdXRvbWF0aWNhbGx5IGRlZmluZWQgYW5kIHByZS1sb2FkZWQgaW4gYFJgKQ0KDQpgYGB7cn0NCmJhciA8LSBkYXRhLmZyYW1lKHZhcjEgPSBMRVRURVJTWzE6MTBdLCB2YXIyID0gMToxMCkNCiMgQ2hlY2sgZGF0YSBmcmFtZQ0KYmFyDQpgYGANCg0KIyBhYm92ZSB3ZSBjYW4gc2VlIHRoYXQgd2UgY3JlYXRlZCBhIGRhdGFmcmFtZSgnYmFyJyByZXBsYWNpbmcgdGhlIHByZXZpb3VzIHZhcmlhbGUgb2YgdGhlIHNhbWUgbmFtZSkgd2l0aCB0d28gY29sdW1ucyBieSB1c2luZyB0aGUgY2hhcmFjdGVzIGZyb20gdGhlICdsZXR0ZXJzJyB2ZWN0b3IgZm9yIHRoZSBmaXJzdCB2YXJhaWJsZSBhbnMgdGhlIG51bWJlcnMgMSB0aHJ1IDEwIG9uIHRoZSBzZWNvbmQgdmFyaWFibGUgYnkgdXNpbmcgdGhlKDopIHZlY3RvciBjcmVhdGlvbiBmdW5jdGlvbi4NCg0KU3VwcG9zZSB5b3Ugd2FudCB0byBzZWxlY3QgYSByYW5kb20gc2FtcGxlIG9mIHNpemUgNS4gRmlyc3QsIGRlZmluZSBhIHZhcmlhYmxlIGBuYCB3aXRoIHRoZSBzaXplIG9mIHRoZSBzYW1wbGUsIGkuZS4gNQ0KDQpgYGB7cn0NCm4gPC0gNQ0KYGBgDQoNCiNhYm92ZSB3ZSBjcmVhdGVkIHRoZSB2YXJpYWJsZSAnbicgdG8gc3RvcmUgdGhlIHZhbHVlIDUgc28gd2UgY2FuIGNhbGwgaXQgYWdhaW4gbGF0ZXIgYXMgdGhlIHNpemUoYW1vdW50IG9mIG51bWJlcnMpIHdlIHdhbnQgc2VsZWN0ZWQgZm9yIG91ciByYW5kb20gbnVtYmVyIHNhbXBsZQ0KDQpOb3csIHNlbGVjdCBhIHNhbXBsZSBvZiBzaXplIDUgZnJvbSB0aGUgdmVjdG9yIHdpdGggMSB0byAxMCAodGhlIG51bWJlciBvZiByb3dzIGluIGBiYXJgKS4gVXNlIHRoZSBmdW5jdGlvbiBgbnJvdygpYCB0byBmaW5kIHRoZSBudW1iZXIgb2Ygcm93cyBpbiBgYmFyYCBpbnN0ZWFkIG9mIG1hbnVhbGx5IGVudGVyaW5nIHRoYXQgbnVtYmVyLg0KDQpVc2UgYDpgIHRvIGNyZWF0ZSBhIHZlY3RvciB3aXRoIGFsbCB0aGUgaW50ZWdlcnMgYmV0d2VlbiAxIGFuZCB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gYGJhcmAuDQoNCmBgYHtyfQ0Kc2FtcGxlcm93cyA8LSBzYW1wbGUoMTpucm93KGJhciksIHNpemU9bikgDQojIHByaW50IHNhbXBsZSByb3dzDQpzYW1wbGVyb3dzDQpgYGANCg0KIyBhYm92ZSB3ZSBjYW4gc2VlIHdlIGNyZWF0ZSB0aGUgdmFyaWFibGUgInNhbXBsZXJvd3MiIGJ5IHVzaW5nIHRoZSBzYW1wbGUgZnVuY3Rpb24sIHdlIHNldCB0aGUgcmFuZ2UgZnJvbSAxIHRvIHRoZSBudW1iZXIgb2Ygcm93cyhucm93KSBpbiB0aGUgJ2JhcicgZGF0YWZyYW1lICgxMCksIHRoZW4gd2Ugc2VsZWN0IHRoZSBzaXplIChudW1iZXIgb2YgZWxlbWVudHMgd2Ugd2FudCBvdXRwdXQpIGJ5IHVzaW5nIHRoZSB2YXJpYWJsZSB3ZSBjcmVhdGVkIGJlZm9yZSAnbicuIFNvIHdlIGNhbiBzZWUgdGhhdCBvbmx5IGZpdmUgcmFuZG9tIG51bWVycyByYW5naW5nIGZyb20gb25lIHRocnUgMTAgYXJlIGxpc3RlZCB3aGVuIHdlIGNhbGwgdGhlIHZhcmFibGUgJ3NhbXBsZXJvd3MnDQoNClRoZSB2YXJpYWJsZSBgc2FtcGxlcm93c2AgY29udGFpbnMgdGhlIHJvd3Mgb2YgYGJhcmAgd2hpY2ggbWFrZSBhIHJhbmRvbSBzYW1wbGUgZnJvbSBhbGwgdGhlIHJvd3MgaW4gYGJhcmAuIEV4dHJhY3QgdGhvc2Ugcm93cyBmcm9tIGBiYXJgIHdpdGgNCg0KYGBge3J9DQojIGV4dHJhY3Qgcm93cw0KYmFyc2FtcGxlIDwtIGJhcltzYW1wbGVyb3dzLCBdDQojIHByaW50IHNhbXBsZQ0KcHJpbnQoYmFyc2FtcGxlKQ0KYGBgDQoNCiMgYWJvdmUgd2UgY2FuIHNlZSBobyB3ZSBjYW4gc2VsZWN0IHNwZWNpZmljIHJvd3MgZnJvbSBhIGRhdGFmcmFtZSBhbmQgc3RvcmUgdGhlbSBpbiBhIG5ldyB2YXJpYWJsZShiYXJzYW1wbGUpLCBieSBzZWxlY3RpbmcgdGhlIHJvd3MgZnJvbSBvdXIgcHJldmlvdXMgZGF0YWZyYW1lKGJhcikgb2ZmIG9mIHRoZSB2YWx1ZXMgZnJvbSBvdXIgcmFuZG9tIHNhbXBsZShzYW1wbGVyb3dzKS4gTXkgcmFuZG9tIHNhbXBsZSBwcm9kdWNlZCAzIDQgNyA5IDEgYW5kIHRob3NlIGFyZSBjb3JyZXNwb25kaW5nIHJvd3Mgd2hlcmUgaW5zZXJ0ZWQgaW50byB0aGUgYmFyc2FtcGxlIGRhdGFmcmFtZS4NCg0KVGhlIGNvZGUgYWJvdmUgY3JlYXRlcyBhIG5ldyAqZGF0YSBmcmFtZSogY2FsbGVkIGBiYXJzYW1wbGVgIHdpdGggYSByYW5kb20gc2FtcGxlIG9mIHJvd3MgZnJvbSBgYmFyYC4NCg0KSW4gYSBzaW5nbGUgbGluZSBvZiBjb2RlOg0KDQpgYGB7cn0NCmJhcltzYW1wbGUoMTpucm93KGJhciksIG4pLCBdDQpgYGANCg0KIyBhYm92ZSB3ZSBjYW4gc2VlIGhvdyB3ZSByZXBsaWNhdGUgdGhlIHByZXZpb3VzIHdvcmsgd2UgZGlkIHRvIGNyZWF0ZSB0aGUgJ2JhcnNhbXBsZScgZGF0YWZyYW1lIGluIG9uZSBsaW5lIG9mIGNvZGUgYnkgdXNpbmdlIHRoZSBlbGVtZW50IHNlbGVjdCBmdW5jdGlvbiBbXSBjb21iaW5lZCB3aXRoIHRoZSBzYW1wbGUgZnVuY3Rpb24gYW5kIG5yb3cgZnVuY3Rpb24uIE5vdGljZSB0aGlzIGRvZXNuJ3Qgc3RvcmUgdGhlIHJhbmRvbSBzYW1wbGUgZGF0YWZyYW1lIGxpa2Ugd2UgZGlkIGJlZm9yZSwgaW5zdGVhZCBpdCBvbmx5IGRpc3BsYXlzIHRoZSBzZWxlY3Rpb24uDQoNCiMgVXNpbmcgVGFibGVzDQoNClRoZSBgdGFibGUoKWAgY29tbWFuZCBhbGxvd3MgdXMgdG8gbG9vayBhdCB0YWJsZXMuIEl0cyBzaW1wbGVzdCB1c2FnZSBsb29rcyBsaWtlIGB0YWJsZSh4KWAgd2hlcmUgYHhgIGlzIGEgKmNhdGVnb3JpY2FsIHZhcmlhYmxlKi4NCg0KRm9yIGV4YW1wbGUsIGEgc3VydmV5IGFza3MgcGVvcGxlIGlmIHRoZXkgc21va2Ugb3Igbm90LiBUaGUgZGF0YSBpcw0KDQoqWWVzLCBObywgTm8sIFllcywgWWVzKg0KDQpXZSBjYW4gZW50ZXIgdGhpcyBpbnRvIFIgd2l0aCB0aGUgYGMoKWAgY29tbWFuZCwgYW5kIHN1bW1hcml6ZSB3aXRoIHRoZSBgdGFibGUoKWAgY29tbWFuZCBhcyBmb2xsb3dzDQoNCmBgYHtyfQ0KeCA8LSBjKCJZZXMiLCJObyIsIk5vIiwiWWVzIiwiWWVzIikgDQp0YWJsZSh4KQ0KDQpgYGANCg0KIyBhYm92ZSB3ZSBjYW4gc2VlIHRoYXQgd2UgY3JlYXRlIGEgbmV3IHZhcmlhYmxlIHdpdGggc3RyaW5nIGNoYXJhY3RlcnMgc3RvcmVkIGluIGl0LiB0aGVuIHdlIHVzZSB0aGUgdGFibGUoKSBmdW5jdGlvbiB0byBkaXNwbGF5IHRoZSBjb3VudCBvZiBlYWNoIHZhbHVlIGluIHRoaXMgdGFibGUsIG91ciBvdXRwdXQgaXMgMiBObydzIGFuZCAzIFllcydzIHdoaWNoIGlzIGNvcnJlY3QuDQoNCiMgTnVtZXJpYyBtZWFzdXJlcyBvZiBjZW50ZXIgYW5kIHNwcmVhZA0KDQpTdXBwb3NlLCBDRU8geWVhcmx5IGNvbXBlbnNhdGlvbnMgYXJlIHNhbXBsZWQgYW5kIHRoZSBmb2xsb3dpbmcgYXJlIGZvdW5kIChpbiBtaWxsaW9ucykNCg0KMTIgLjQgNSAyIDUwIDggMyAxIDQgMC4yNQ0KDQpgYGB7cn0NCnNhbHMgPC0gYygxMiwgLjQsIDUsIDIsIDUwLCA4LCAzLCAxLCA0LCAwLjI1KQ0KIyB0aGUgYXZlcmFnZQ0KbWVhbihzYWxzKSANCiMgdGhlIHZhcmlhbmNlDQp2YXIoc2FscykNCiMgdGhlIHN0YW5kYXJkIGRldmlhdGlvbg0Kc2Qoc2FscykNCiMgdGhlIG1lZGlhbg0KbWVkaWFuKHNhbHMpDQojIFR1a2V5J3MgZml2ZSBudW1iZXIgc3VtbWFyeSwgdXNlZnVsbCBmb3IgYm94cGxvdHMNCiMgZml2ZSBudW1iZXJzOiBtaW4sIGxvd2VyIGhpbmdlLCBtZWRpYW4sIHVwcGVyIGhpbmdlLCBtYXgNCmZpdmVudW0oc2FscykNCiMgc3VtbWFyeSBzdGF0aXN0aWNzDQpzdW1tYXJ5KHNhbHMpDQoNCmBgYA0KDQojIEFib3ZlIHdlIGNhbiBzZWUgc29tZSBjb21tb24gc3RhdGlzdGljYWwgYW5hbHlzaXMgdXNpbmcgYnVpbHQgaW4gZnVuY3Rpb25zIHRvIHJldHVybiB0aGUgYXZlcmFnZSwgdmFyaWFuY2UsIHN0YW5kYXJkIGRldmlhdGlvbiwgbWVkaWFuLCBmaXZlIG51bWJlciBzdW1tYXJ5LCBhbmQgc3VtbWFyeSBzdGF0aXN0aWNzLCBhbGwgcGVyZm9ybWVkIG9uIHRoZSBzYWxzIHZhcmlhYmxlcyB2YWx1ZXMgd2UgY29uY2F0ZWQgaW50byBhIHZlY3Rvci4gTm90aWNlIHRoZSBzdGF0aXN0aWNhbCBzdW1tYXJ5IGFuZCBmaXZlIG51bWJlciBzdW1tYXJ5IGFyZSBkaWZmZXJlbnQuDQoNCiMjIyBIb3cgYWJvdXQgdGhlICptb2RlKj8NCg0KSW4gUiB3ZSBjYW4gd3JpdGUgb3VyIG93biAqZnVuY3Rpb25zKiwgYW5kIGEgZmlyc3QgZXhhbXBsZSBvZiBhIGZ1bmN0aW9uIGlzIHNob3duIGJlbG93IGluIG9yZGVyIHRvIGNvbXB1dGUgKnRoZSBtb2RlKiBvZiBhIHZlY3RvciBvZiBvYnNlcnZhdGlvbnMgYHhgDQoNCmBgYHtyfQ0KIyBGdW5jdGlvbiB0byBmaW5kIHRoZSBtb2RlLCBpLmUuIG1vc3QgZnJlcXVlbnQgdmFsdWUNCmdldE1vZGUgPC0gZnVuY3Rpb24oeCkgew0KICAgICB1eCA8LSB1bmlxdWUoeCkNCiAgICAgdXhbd2hpY2gubWF4KHRhYnVsYXRlKG1hdGNoKHgsIHV4KSkpXQ0KIH0NCmBgYA0KDQojIEFib3ZlIHdlIHVzZSB0aGUgdGhlIGZ1bmN0aW9uICJmdW5jdGlvbiIgdG8gY3JlYXRlIG91ciBvd24gZnVuY3Rpb24uIEluIHRoaXMgY2FzZSB0aGUgZnVuY3Rpb24gd2UgY3JlYXRlIGlzIGNhbGxlZCAnZ2V0TW9kZScgd2hpY2ggd2lsbCByZXR1cm4gdGhlIHZhbHVlIHRoYXQgaXMgcmVwZWF0ZWQgdGhlIG1vc3QgaW4gYSB2ZWN0b3IuDQoNCkFzIGFuIGV4YW1wbGUsIHdlIGNhbiB1c2UgdGhlIGZ1bmN0aW9uIGRlZmluZWQgYWJvdmUgdG8gZmluZCB0aGUgbW9zdCBmcmVxdWVudCB2YWx1ZSBpbiB0ZSB2ZWN0b3IgYGJhemANCg0KYGBge3J9DQojIE1vc3QgZnJlcXVlbnQgdmFsdWUgaW4gYmF6DQpnZXRNb2RlKGJheikNCmBgYA0KDQojIEhlcmUgd2UgdXNlIHRoZSBmdW5jdGlvbiB0aGF0IHdlIGNyZWF0ZWQgJ2dldE1vZGUnIG9uIHRoZSB2YXJpYWJsZSAnYmF6JyB3aGljaCBoYXMgYSB2ZWN0b3IgbWFkZSBvZiAyLDIsMywzLDMuIEl0IG91cHV0cyAzIHdoaWNoIHdlIGNhbiBzZWUgaXN0IHRoZSBtb2RlIG9mIHRoZSAnYmF6JyB2ZWN0b3IuDQo=