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.
- The first argument gives the vector of data to select elements
from.
- The second argument (
size=) gives the size of the
sample to select.
Taking a simple random sample from a data frame is only slightly more
complicated, having two steps:
- Use
sample() to select a sample of size n
from a vector of the row numbers of the data frame.
- 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 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=