Data Structures
Lists
Lists are R objects that can store elements of different classes,
oposite to vectors which can be used to store elements of the same class
only. Each element of a list can be of any object class such as data
frames, numeric vectors, matrices or even list. For example, we can
create a list to store information of a financial portfolio.
I will create a list that represents information of a financial
portfolio. I first create the elements of the portfolio:
# Create vectors for stock tickers and expected stock returns:
tickers <- c("AAPL","AMZN","WMT")
expected_stock_returns <- c(0.020,0.015,0.010)
expected_stock_risk <- c(0.04,0.045,0.02)
tickers
expected_stock_returns
expected_stock_risk
Now I will indicate how much (in %) I will allocate for each asset in
my portfolio. I will assign 50% to Apple, and 25% to Amazon and
Wal-Mart. I create a vector with these weights (in decimal):
stock_weights <- c(0.50,0.25,0.25)
Now I will calculate the expected portfolio return as a weighted
average the stock expected returns:
weighted_returns <- expected_stock_returns*stock_weights
weighted_returns
When you multiply 2 vectors you get an element-by-element
multiplication. This is called a “vectorization” operation. By default R
“vectorizes” mathematical operations. This means the first element of
the first vector is multiplied by the first element of the second
vector. The same for the 2nd. and 3rd. elements of each vector.
Now I just sum all the elements of this vector that contains the
weighted returns to get the expected return of my portfolio:
expected_portfolio_return <- sum(weighted_returns)
I used the function sum to the weighted_returns vector, so each
element of the vector is added to get the expected portfolio return.
I now create a list with all these pieces of information of my
portfolio. I use the function list() to create the portfolio object as a
list that contains the tickers vector, and the vectors for expected
stock return, expected stock risk, stock weights and the expected
portfolio return:
portfolio1 <- list(tickers, expected_stock_returns, expected_stock_risk,
stock_weights, expected_portfolio_return)
# I assign names to each element of the portfolio:
names(portfolio1)<-c("Tickers","Stock_returns","Stock_risk","Stock_weights",
"Portfolio expected Return")
# I display the portfolio object:
portfolio1
I can access the elements of the portfolio1 list using either the
name of each element, or the number of the element using double squared
brackets[[]]:
# I display the expected stock tickers:
portfolio1$Tickers
# I can also display expected stock tickers using the element number and double
# brackets:
portfolio1[[1]]
# I display the class and length of the first element:
class(portfolio1$Tickers)
length(portfolio1$Tickers)
The xts data class
R has different data classes (or R objects). Actually, you can create
your own data class, which is a set one or more data structures. For
time series datasets, which are very common in Finance, the most popular
data classes are: ts, zoo and xts. xts stands for extensible time series
class. An xts object contains a set of columns that can be of any type
(alphabetic, numeric, boolean) and it has a time index. All xts objects
are usually sorted chronologically.
The index of an xts object is like the first column of the object,
but it is actually its index; it is not considered a column of the
object. An xts object has the advantage that we can apply several
functions to that object for data merging, sorting, selecting, etc.
Try the following example. Download a sample dataset called edhec,
which comes with the PerformanceAnalytics package. In R, we can use
thousands of available packages to do different types of calculations
and operations. PerformanceAnalytics package is a package with many
functions related to Financial analytics. We will use some of these
functions later in the course.
we need the PerformanceAnalytics package, so you can install it from
the Package menu (right-bottom of your RStudio).
Once the package is installed in my computer, I do not need to
re-install it again. However, each time I need to use the package, I
need to load it into memory:
library(PerformanceAnalytics)
I download the sample dataset edhec, which contains monthly returns
of different hedge fund indexes created by the EDHEC Risk Institute.
data("edhec")
The edhec dataset will appear in my Global Environment.
edhec is an xts R object that contains historical monthly returns of
different hedge fund indexes. We can easily do different calculations
with specific functions that apply to xts objects. For now, we will
learn how to do subsetting with xts objects.
If you want to know more functions for the xts R objects, you can
check the xts CheatSheet at: https://s3.amazonaws.com/assets.datacamp.com/blog_assets/xts_Cheat_Sheet_R.pdf
Subsetting data
R has powerful indexing features for accessing object elements. These
features can be used to select and exclude columns and rows
(observations). In the next paragraphs we will learn how to extract the
information we want from an xts object. Several of these functions also
apply to data frames.
I see the structure of the edhec R dataset and the first and last
rows:
str(edhec)
head(edhec)
tail(edhec)
From the results above, we see that this xts object has 13 columns,
which are returns of different hedge fund indexes.
I can subset either rows, columns or both. For example I can select
in which months the Emeging market fund has had negative returns:
negative_returns_em <- edhec[edhec$`Emerging Markets`<0,4]
# I display the first rows of this new object, which has only negative returns for Emerging Markets:
head(negative_returns_em)
negative_returns_em_all <- edhec[edhec$`Emerging Markets`<0,]
head(negative_returns_em_all)
As you see, to do subsetting I use squared brackets afher the object,
and the first number refers to the ROWS to be selected, and the second
parameter refers to the COLUMNS to be selected. In this case, after the
coma I wrote NOTHING, indicating that I want ALL COLUMNS!
If I want to do a subsetting of specific rows using a range of dates,
I can do the following. Since this is an xts object, it is very easy to
subset using dates. I select the returns of the 12 months of the year
2008:
edhec2008<-edhec["2008-01-01/2008-12-31",]
I can also select those months where the Emerging Markets fund and
the Convertible Arbitrage fund had positive returns in 2008:
positive_edhec2008<-edhec2008[edhec2008$`Convertible Arbitrage`>0 & edhec2008$`Emerging Markets`>0,]
positive_edhec2008
We can see that only 2 months had positive returns in these funds in
2008.
There are several logical operators to be used for the subsetting
condition of rows. These operators are:
== equal to != different to < less than <= less than or equal
to > more than >= more than or equal to or & and
There are several logical operators to be used for the subsetting
condition of rows. These operators are:
== equal to != different to < less than <= less than or equal
to > more than >= more than or equal to or & and
##Control-flow commands Control-flow commands or constructs are used
to program a series of tasks using conditions and/or loops.
There are 7 main control structures:
if/else: testing a condition for: execute a loop a fixed number of
times repeat: execute an infinite loop while: execute a loop while a
condition is true break: break the execution of a loop next: skip an
interation of a loop return: exit a function
The most simple ones are the conditionals if() and if/else, which
allow you to implement some basic algorithm logic in your analysis. We
will start with the conditionals statements and then the loop
statements.
Conditionals
If and if else
if(<condition1>) {
## do stuff
}
Here is a simple example, that is self-explanatory:
grade <- 70
if(grade > 69){cat("You have passed this course. Well done!")}
In this case the condition will be true, so the message will be
displayed. You can try different values for grade and re-run this code
to see what happens.
ELSE IF
Imagine that you have several conditions, not only one as the
previous example. In this case, you need to use the else if statement.
The structure looks like this:
if(<condition1>) {
## do something
} else if(<condition2>) {
## do something different
}
So our previous example can be upgraded as follows. Try chaging the
values in the input variables.
gradePartial1 <- 80
gradePartial2 <- 60
gradeFinalExam <- 100
FinalGrade <- (gradePartial1*0.25 + gradePartial1*0.25 + gradeFinalExam*0.5)
if(FinalGrade > 90){
"You did an Excellent job!"
} else if(FinalGrade > 69){
"You have passed this course. Well done."
} else if(FinalGrade > 0){
"Sorry you have failed the course."
}
ELSE
Now imagine that we have several conditionals but we want to do
something with the remaining variables that don’t fulfill the previous
conditionals, then we use else. The structure looks like:
gradePartial1 <- -70
gradePartial2 <- 60
gradeFinalExam <- -60
FinalGrade <- (gradePartial1*0.25 + gradePartial1*0.25 + gradeFinalExam*0.5)
if(FinalGrade > 90){
"You did awesome!"
} else if(FinalGrade > 69){
"You have passed this course. Well done."
} else if(FinalGrade > 0){
"Sorry you have failed the course."
} else {
"You have negative grades; it should be an error"
}
%in%
In the next example we use the operator %in%. This operator checks
whether a value exists inside a vector. For each element of the vector
it returns TRUE if the value is contained in the verctor and 0
otherwise:
# Both elements in the first vector appears in the second vector
c(1,2) %in% c(6,4,8,3,2,1)
# Only the last two elements of the first verctor appear in the second
c(6,4,8,3,2,1) %in% c(1,2)
For Loop
As you see, the result of using the %in% operator is a vector of
Boolean values (TRUE OR FALSE). If the first element is TRUE, it means
that the first number of the first vector is inside the second
vector.
students<-c("Pedro","Laura","Bryan")
for(name in students){
##Instead of name you can write any variable just change it inside the loop
cat("Hi, my name is",name)
}
In the next example we will use the quantmod library to download some
financial data from online data sources such as Yahoo finance and Google
Finance. Our initial vector indicate the tickers to download, in this
case AAPL,JPM and GE.
You have to install the package in the Package tab of the
bottom-right windows of RStudio.
Once you install the command, you have to load it with the library
function. This quantmod library has the getSymbols function that is used
to download online data from the web:
library(quantmod)
#Vector of tickers
tickers <-c("AAPL","JPM","GE")
for(i in tickers){
getSymbols(i)
cat("the prices of the ticker",i,"have been downloaded")
}
In the next example we do a similar process for a different ticker
list. In the case of GE and AAPL we are going to download the data from
yahoo, while INTGSTMXM193N from the FED. What happens with the
remainning tickers?
tickers <- c("AAPL","GM","INTGSTMXM193N","GE","JPM")
for(i in tickers){
if(i %in% c("AAPL","GE")){
getSymbols(i,src = "yahoo")
cat("the prices of the ticker",i,"have been downloaded from yahoo")
}
else if(i=="INTGSTMXM193N"){
getSymbols(i,src = "FRED")
#Note that the source for the FED is called FRED
cat("the data of the ticker",i,"have been downloaded from the FED (Federal US Bank) ")
}
}
We are going to use the previous example, but in this case we want
also to add a condition to print the tickers that have NOT been
downloaded.
tickers <- c("AAPL","GM","INTGSTMXM193N","GE","JPM")
for(i in tickers){
if(i %in% c("AAPL","GE")){
getSymbols(i,src = "yahoo")
cat("the prices of the ticker",i,"have been downloaded from yahoo")
}
else if(i=="INTGSTMXM193N"){
getSymbols(i,src = "FRED")
cat("the data of the ticker",i,"have been downloaded from the FED (Federal US Bank) ")
}
else {
cat("The ticker",i,"has not been downloaded")
}
}
WHILE AND REPEAT TOOLS
In a similar manner than the for loop, it is possible to program a
loop with while and repeat control-flow statements. The main difference
is that in both you need to specify what is the exit condition, and it
may be possible that NOT all the itereations has to be performed (like
in the for case).
For the while you need to specify the condition at the beginning.
Here an example. If you want to know how many years you need to keep an
investment with a fixed interest rate in order to duplicate your initial
investment:
APR<-0.10
# I define Annual Percentage Rate to be equal to 10%
INV<-100
# Initial investment equal to $100
MULTIPLE<-2
# Multiple = 2 to check when the investment double
BALANCE<-INV
# I start assigning the balance equal to the initial investment
year<-0
# I start with year equal to zero
while (BALANCE<MULTIPLE*INV) {
# the exit condition means that while the balance is less than the initial investment
# multiplied by the multiple, then continue with the iterations of the loop
year<-year+1
# I increase the value of year by 1
BALANCE<-BALANCE*(1+APR)
# I multiply the current balance times the growth factor (1+APR) using to the
# Annual Percentage Rate
}
cat(
"To multiply your investment times ", MULTIPLE, "you need ", year, " years.")
cat(
"Your balance after ", year, " years will be $",BALANCE)
Unlike the while statement, you can use the repeat statement to do a
loop, but in the case of repeat, you have to specify the exit condition
using if and the break statement any place within the loop. Here is the
same loop we did above but using repeat:
APR<-0.10
# I define Annual Percentage Rate to be equal to 10%
INV<-100
# Initial investment equal to $100
MULTIPLE<-2
# Multiple = 2 to check when the investment double
BALANCE<-INV
# I start assigning the balance equal to the initial investment
year<-0
# I start with year equal to zero
repeat {
year<-year+1
# I increase the value of year by 1
BALANCE<-BALANCE*(1+APR)
# I multiply the current balance times the growth factor (1+APR) using to the
# Annual Percentage Rate
if (BALANCE>=MULTIPLE*INV) {
break
}
# If the balance is greater than the multiple times the investment, then
# the break statement is executed, so the program stops the interations
}
cat(
"To multiply your investment times ", MULTIPLE, "you need ", year, " years.")
cat(
"Your balance after ", year, " years will be $",BALANCE)
5.4 Looping vs R-vectorization Most R programmers believe that loops
must be AVOIDED! This is wierd since most of the time programming
requires to do repetitive tasks. However, in R, unlike other traditional
computer languages such as C, there is an alternative way to do loops
without writing loops!
A <-c(3,3,4,6,8)
B <-c(-2,-3,-1,3,5)
# A and B are vectors with the annual free cash flows of each product
sumcashflows<-vector(length=5)
for (i in 1:length(A)) {
sumcashflows[i]<-A[i] + B[i]
# We sum the element i of both vectors and leave the result
# in the position i of the vector sumcashflows
}
sumcashflows
A <-c(3,3,4,6,8)
B <-c(-2,-3,-1,3,5)
sumcashflows<-A+B
# We just sum both vectors as if they were numbers
sumcashflows
5.5 Application: Present value of future cash flows Now, how can you
calculate the Present Value of these cash flows? You have to remember
the basics of time value of money. To calculate the present value (PV0)
of a sequence of cash flows in the future, you just have to apply the
following formula for the sequence of cash flows:
con loop
# I assign 0 the the variable PV, present value
PV <- 0
# I defined the discount rate as R:
R <- 0.15
for (i in 1:length(sumcashflows)) {
# I calculate the present value of each cash flow i:
PVCF <- sumcashflows[i] / (1 + R)^i
# I sum each corresponding cash flow i to the cumulative variable PV
PV <- PV + PVCF
}
# The loop iterates 5 times, one for each cash flow and will ends with the sum of all
cat("The Present Value of all cash flows is ", PV)
sin loop
# I assign a sequence from 1 to 5, for the exponents of the formula of present value
# for each cash fow
exponents <- seq(1,5)
# The seq is a function that generates a sequence. Here I specified to start the
# sequence in 1 and finish in 5
# I calculate a vector with the present value for each cash flow. I use vectorization:
PVvector <- sumcashflows / (1 + R)^exponents
# Note that this mathematical expression applies to each of the element of the vector.
# Also, each vector has the same dimension.
# I finally sum all elements of the vector using the function sum:
PV<-sum(PVvector)
cat("The Present Value of all cash flows is ", PV)
##7 CHALLENGE 1 You have to write a program to calculate the number
of months needed to finish paying a mortgage loan. The information about
the loan is the following:
Loan amount = $3,000,000.00 pesos
APR (Annual % rate) = 11% (compounded monthly)
Monthly Fixed Payment = $40,000.00 (includes interests and
capital)
Your program has to provide 2 results: the number of months needed to
finish paying the loan, and the amount of the last payment if the
payment is less than the fixed payment amount. Your program has to be
able to run with any change in any of the values of the above
variables.
This is a quite challenging exercise!
Hint: if you are familiar with Excel, start solving the problem in
Excel, and then try to write your program in R.
##8 CHALLENGE 2 Write a program that calculates the price of the
following bond issued by the company ABC. ABC needs to finance an
important project to develop a new technological device.
To get the money, ABC issued a bond with the following
characteristics:
Principal: $3,000,000 Time to maturity: 20 years Coupon rate: 11%
(annual) coupons are payed each 6 months Calculate the price of this
bond for each of the following annual interest rates:
8% 11% 13% You have to get the price for the bond for each of these 3
interest rates.
Remember that the price of a bond is the present value of its future
cash flows.
CHALLENGE 1
You have to write a program to calculate the number of months needed
to finish paying a mortgage loan. The information about the loan is the
following:
Loan amount = $3,000,000.00 pesos
APR (Annual % rate) = 11% (compounded monthly)
Monthly Fixed Payment = $40,000.00 (includes interests and
capital)
Your program has to provide 2 results: the number of months needed to
finish paying the loan, and the amount of the last payment if the
payment is less than the fixed payment amount. Your program has to be
able to run with any change in any of the values of the above
variables.
This is a quite challenging exercise!
Hint: if you are familiar with Excel, start solving the problem in
Excel, and then try to write your program in R.
FinancialMath::amort.period(Loan = 3000000, pmt = 40000, i = .11, n = NA)
Error in FinancialMath::amort.period(Loan = 3e+06, pmt = 40000, i = 0.11, :
Too small of pmt.
CHALLENGE 2
Write a program that calculates the price of the following bond
issued by the company ABC. ABC needs to finance an important project to
develop a new technological device.
To get the money, ABC issued a bond with the following
characteristics:
Principal: $3,000,000 Time to maturity: 20 years Coupon rate: 11%
(annual) coupons are payed each 6 months Calculate the price of this
bond for each of the following annual interest rates:
8% 11% 13% You have to get the price for the bond for each of these 3
interest rates.
Remember that the price of a bond is the present value of its future
cash flows.
FinancialMath::bond(t = NA, f = 3000000, r = 20, n = 11, i = .08, c = 1)
Bond Summary
Price 4.283379e+08
Premium 4.283379e+08
Coupon 6.000000e+07
Eff Rate 8.000000e-02
Years 1.100000e+01
MAC D 5.239503e+00
MOD D 4.851392e+00
MAC C 3.710111e+01
MOD C 3.630025e+01
(I think?)
FinancialMath::bond(t = NA, f = 3000000, r = 20, n = 11, i = .11, c = 1)
Bond Summary
Price 3.723909e+08
Premium 3.723909e+08
Coupon 6.000000e+07
Eff Rate 1.100000e-01
Years 1.100000e+01
MAC D 4.978808e+00
MOD D 4.485413e+00
MAC C 3.415739e+01
MOD C 3.176382e+01
FinancialMath::bond(t = NA, f = 3000000, r = 20, n = 13, i = .11, c = 1)
Bond Summary
Price 4.049922e+08
Premium 4.049922e+08
Coupon 6.000000e+07
Eff Rate 1.100000e-01
Years 1.300000e+01
MAC D 5.582155e+00
MOD D 5.028969e+00
MAC C 4.395334e+01
MOD C 4.020412e+01
LS0tCnRpdGxlOiAiV29ya3Nob3AgMiwgRmluYW5jaWFsIFByb2dyYW1taW5nIgphdXRob3I6IFN0ZWZhbiBTY2h3ZWl0emVyIC0gQTAxMjA5NzU1Cm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjICpXb3Jrc2hvcCAyLCBGaW5hY2lhbCBQcm9ncmFtbWluZyoKCiMgRGF0YSBTdHJ1Y3R1cmVzIAojIyBMaXN0cwoKTGlzdHMgYXJlIFIgb2JqZWN0cyB0aGF0IGNhbiBzdG9yZSBlbGVtZW50cyBvZiBkaWZmZXJlbnQgY2xhc3Nlcywgb3Bvc2l0ZSB0byB2ZWN0b3JzIHdoaWNoIGNhbiBiZSB1c2VkIHRvIHN0b3JlIGVsZW1lbnRzIG9mIHRoZSBzYW1lIGNsYXNzIG9ubHkuIEVhY2ggZWxlbWVudCBvZiBhIGxpc3QgY2FuIGJlIG9mIGFueSBvYmplY3QgY2xhc3Mgc3VjaCBhcyBkYXRhIGZyYW1lcywgbnVtZXJpYyB2ZWN0b3JzLCBtYXRyaWNlcyBvciBldmVuIGxpc3QuIEZvciBleGFtcGxlLCB3ZSBjYW4gY3JlYXRlIGEgbGlzdCB0byBzdG9yZSBpbmZvcm1hdGlvbiBvZiBhIGZpbmFuY2lhbCBwb3J0Zm9saW8uCgpJIHdpbGwgY3JlYXRlIGEgbGlzdCB0aGF0IHJlcHJlc2VudHMgaW5mb3JtYXRpb24gb2YgYSBmaW5hbmNpYWwgcG9ydGZvbGlvLiBJIGZpcnN0IGNyZWF0ZSB0aGUgZWxlbWVudHMgb2YgdGhlIHBvcnRmb2xpbzoKCmBgYHtyfQojIENyZWF0ZSB2ZWN0b3JzIGZvciBzdG9jayB0aWNrZXJzIGFuZCBleHBlY3RlZCBzdG9jayByZXR1cm5zOgp0aWNrZXJzIDwtIGMoIkFBUEwiLCJBTVpOIiwiV01UIikKZXhwZWN0ZWRfc3RvY2tfcmV0dXJucyA8LSBjKDAuMDIwLDAuMDE1LDAuMDEwKQpleHBlY3RlZF9zdG9ja19yaXNrIDwtIGMoMC4wNCwwLjA0NSwwLjAyKQp0aWNrZXJzCmV4cGVjdGVkX3N0b2NrX3JldHVybnMKZXhwZWN0ZWRfc3RvY2tfcmlzawpgYGAKCk5vdyBJIHdpbGwgaW5kaWNhdGUgaG93IG11Y2ggKGluICUpIEkgd2lsbCBhbGxvY2F0ZSBmb3IgZWFjaCBhc3NldCBpbiBteSBwb3J0Zm9saW8uIEkgd2lsbCBhc3NpZ24gNTAlIHRvIEFwcGxlLCBhbmQgMjUlIHRvIEFtYXpvbiBhbmQgV2FsLU1hcnQuIEkgY3JlYXRlIGEgdmVjdG9yIHdpdGggdGhlc2Ugd2VpZ2h0cyAoaW4gZGVjaW1hbCk6CgpgYGB7cn0Kc3RvY2tfd2VpZ2h0cyA8LSBjKDAuNTAsMC4yNSwwLjI1KQpgYGAKCk5vdyBJIHdpbGwgY2FsY3VsYXRlIHRoZSBleHBlY3RlZCBwb3J0Zm9saW8gcmV0dXJuIGFzIGEgd2VpZ2h0ZWQgYXZlcmFnZSB0aGUgc3RvY2sgZXhwZWN0ZWQgcmV0dXJuczoKCmBgYHtyfQp3ZWlnaHRlZF9yZXR1cm5zIDwtIGV4cGVjdGVkX3N0b2NrX3JldHVybnMqc3RvY2tfd2VpZ2h0cwp3ZWlnaHRlZF9yZXR1cm5zCmBgYAoKV2hlbiB5b3UgbXVsdGlwbHkgMiB2ZWN0b3JzIHlvdSBnZXQgYW4gZWxlbWVudC1ieS1lbGVtZW50IG11bHRpcGxpY2F0aW9uLiBUaGlzIGlzIGNhbGxlZCBhIOKAnHZlY3Rvcml6YXRpb27igJ0gb3BlcmF0aW9uLiBCeSBkZWZhdWx0IFIg4oCcdmVjdG9yaXplc+KAnSBtYXRoZW1hdGljYWwgb3BlcmF0aW9ucy4gVGhpcyBtZWFucyB0aGUgZmlyc3QgZWxlbWVudCBvZiB0aGUgZmlyc3QgdmVjdG9yIGlzIG11bHRpcGxpZWQgYnkgdGhlIGZpcnN0IGVsZW1lbnQgb2YgdGhlIHNlY29uZCB2ZWN0b3IuIFRoZSBzYW1lIGZvciB0aGUgMm5kLiBhbmQgM3JkLiBlbGVtZW50cyBvZiBlYWNoIHZlY3Rvci4KCk5vdyBJIGp1c3Qgc3VtIGFsbCB0aGUgZWxlbWVudHMgb2YgdGhpcyB2ZWN0b3IgdGhhdCBjb250YWlucyB0aGUgd2VpZ2h0ZWQgcmV0dXJucyB0byBnZXQgdGhlIGV4cGVjdGVkIHJldHVybiBvZiBteSBwb3J0Zm9saW86CmBgYHtyfQpleHBlY3RlZF9wb3J0Zm9saW9fcmV0dXJuIDwtIHN1bSh3ZWlnaHRlZF9yZXR1cm5zKSAKYGBgCkkgdXNlZCB0aGUgZnVuY3Rpb24gc3VtIHRvIHRoZSB3ZWlnaHRlZF9yZXR1cm5zIHZlY3Rvciwgc28gZWFjaCBlbGVtZW50IG9mIHRoZSB2ZWN0b3IgaXMgYWRkZWQgdG8gZ2V0IHRoZSBleHBlY3RlZCBwb3J0Zm9saW8gcmV0dXJuLgoKSSBub3cgY3JlYXRlIGEgbGlzdCB3aXRoIGFsbCB0aGVzZSBwaWVjZXMgb2YgaW5mb3JtYXRpb24gb2YgbXkgcG9ydGZvbGlvLiBJIHVzZSB0aGUgZnVuY3Rpb24gbGlzdCgpIHRvIGNyZWF0ZSB0aGUgcG9ydGZvbGlvIG9iamVjdCBhcyBhIGxpc3QgdGhhdCBjb250YWlucyB0aGUgdGlja2VycyB2ZWN0b3IsIGFuZCB0aGUgdmVjdG9ycyBmb3IgZXhwZWN0ZWQgc3RvY2sgcmV0dXJuLCBleHBlY3RlZCBzdG9jayByaXNrLCBzdG9jayB3ZWlnaHRzIGFuZCB0aGUgZXhwZWN0ZWQgcG9ydGZvbGlvIHJldHVybjoKCmBgYHtyfQpwb3J0Zm9saW8xIDwtIGxpc3QodGlja2VycywgZXhwZWN0ZWRfc3RvY2tfcmV0dXJucywgZXhwZWN0ZWRfc3RvY2tfcmlzaywgCiAgICAgICAgICAgICAgICAgICBzdG9ja193ZWlnaHRzLCBleHBlY3RlZF9wb3J0Zm9saW9fcmV0dXJuKQojIEkgYXNzaWduIG5hbWVzIHRvIGVhY2ggZWxlbWVudCBvZiB0aGUgcG9ydGZvbGlvOgpuYW1lcyhwb3J0Zm9saW8xKTwtYygiVGlja2VycyIsIlN0b2NrX3JldHVybnMiLCJTdG9ja19yaXNrIiwiU3RvY2tfd2VpZ2h0cyIsCiAgICAgICAgICAgICAgICAgICAgICJQb3J0Zm9saW8gZXhwZWN0ZWQgUmV0dXJuIikKIyBJIGRpc3BsYXkgdGhlIHBvcnRmb2xpbyBvYmplY3Q6CnBvcnRmb2xpbzEKYGBgCgpJIGNhbiBhY2Nlc3MgdGhlIGVsZW1lbnRzIG9mIHRoZSBwb3J0Zm9saW8xIGxpc3QgdXNpbmcgZWl0aGVyIHRoZSBuYW1lIG9mIGVhY2ggZWxlbWVudCwgb3IgdGhlIG51bWJlciBvZiB0aGUgZWxlbWVudCB1c2luZyBkb3VibGUgc3F1YXJlZCBicmFja2V0c1tbXV06CgpgYGB7cn0KIyBJIGRpc3BsYXkgdGhlIGV4cGVjdGVkIHN0b2NrIHRpY2tlcnM6CnBvcnRmb2xpbzEkVGlja2VycwpgYGAKCmBgYHtyfQojIEkgY2FuIGFsc28gZGlzcGxheSBleHBlY3RlZCBzdG9jayB0aWNrZXJzIHVzaW5nIHRoZSBlbGVtZW50IG51bWJlciBhbmQgZG91YmxlCiMgIGJyYWNrZXRzOgpwb3J0Zm9saW8xW1sxXV0KYGBgCgpgYGB7cn0KIyBJIGRpc3BsYXkgdGhlIGNsYXNzIGFuZCBsZW5ndGggb2YgdGhlIGZpcnN0IGVsZW1lbnQ6CmNsYXNzKHBvcnRmb2xpbzEkVGlja2VycykKYGBgCgpgYGB7cn0KbGVuZ3RoKHBvcnRmb2xpbzEkVGlja2VycykKYGBgCgojIyBUaGUgeHRzIGRhdGEgY2xhc3MKUiBoYXMgZGlmZmVyZW50IGRhdGEgY2xhc3NlcyAob3IgUiBvYmplY3RzKS4gQWN0dWFsbHksIHlvdSBjYW4gY3JlYXRlIHlvdXIgb3duIGRhdGEgY2xhc3MsIHdoaWNoIGlzIGEgc2V0IG9uZSBvciBtb3JlIGRhdGEgc3RydWN0dXJlcy4gRm9yIHRpbWUgc2VyaWVzIGRhdGFzZXRzLCB3aGljaCBhcmUgdmVyeSBjb21tb24gaW4gRmluYW5jZSwgdGhlIG1vc3QgcG9wdWxhciBkYXRhIGNsYXNzZXMgYXJlOiB0cywgem9vIGFuZCB4dHMuIHh0cyBzdGFuZHMgZm9yIGV4dGVuc2libGUgdGltZSBzZXJpZXMgY2xhc3MuIEFuIHh0cyBvYmplY3QgY29udGFpbnMgYSBzZXQgb2YgY29sdW1ucyB0aGF0IGNhbiBiZSBvZiBhbnkgdHlwZSAoYWxwaGFiZXRpYywgbnVtZXJpYywgYm9vbGVhbikgYW5kIGl0IGhhcyBhIHRpbWUgaW5kZXguIEFsbCB4dHMgb2JqZWN0cyBhcmUgdXN1YWxseSBzb3J0ZWQgY2hyb25vbG9naWNhbGx5LgoKVGhlIGluZGV4IG9mIGFuIHh0cyBvYmplY3QgaXMgbGlrZSB0aGUgZmlyc3QgY29sdW1uIG9mIHRoZSBvYmplY3QsIGJ1dCBpdCBpcyBhY3R1YWxseSBpdHMgaW5kZXg7IGl0IGlzIG5vdCBjb25zaWRlcmVkIGEgY29sdW1uIG9mIHRoZSBvYmplY3QuIEFuIHh0cyBvYmplY3QgaGFzIHRoZSBhZHZhbnRhZ2UgdGhhdCB3ZSBjYW4gYXBwbHkgc2V2ZXJhbCBmdW5jdGlvbnMgdG8gdGhhdCBvYmplY3QgZm9yIGRhdGEgbWVyZ2luZywgc29ydGluZywgc2VsZWN0aW5nLCBldGMuCgpUcnkgdGhlIGZvbGxvd2luZyBleGFtcGxlLiBEb3dubG9hZCBhIHNhbXBsZSBkYXRhc2V0IGNhbGxlZCBlZGhlYywgd2hpY2ggY29tZXMgd2l0aCB0aGUgUGVyZm9ybWFuY2VBbmFseXRpY3MgcGFja2FnZS4gSW4gUiwgd2UgY2FuIHVzZSB0aG91c2FuZHMgb2YgYXZhaWxhYmxlIHBhY2thZ2VzIHRvIGRvIGRpZmZlcmVudCB0eXBlcyBvZiBjYWxjdWxhdGlvbnMgYW5kIG9wZXJhdGlvbnMuIFBlcmZvcm1hbmNlQW5hbHl0aWNzIHBhY2thZ2UgaXMgYSBwYWNrYWdlIHdpdGggbWFueSBmdW5jdGlvbnMgcmVsYXRlZCB0byBGaW5hbmNpYWwgYW5hbHl0aWNzLiBXZSB3aWxsIHVzZSBzb21lIG9mIHRoZXNlIGZ1bmN0aW9ucyBsYXRlciBpbiB0aGUgY291cnNlLgoKd2UgbmVlZCB0aGUgUGVyZm9ybWFuY2VBbmFseXRpY3MgcGFja2FnZSwgc28geW91IGNhbiBpbnN0YWxsIGl0IGZyb20gdGhlIFBhY2thZ2UgbWVudSAocmlnaHQtYm90dG9tIG9mIHlvdXIgUlN0dWRpbykuCgpPbmNlIHRoZSBwYWNrYWdlIGlzIGluc3RhbGxlZCBpbiBteSBjb21wdXRlciwgSSBkbyBub3QgbmVlZCB0byByZS1pbnN0YWxsIGl0IGFnYWluLiBIb3dldmVyLCBlYWNoIHRpbWUgSSBuZWVkIHRvIHVzZSB0aGUgcGFja2FnZSwgSSBuZWVkIHRvIGxvYWQgaXQgaW50byBtZW1vcnk6CgoKYGBge3J9CmxpYnJhcnkoUGVyZm9ybWFuY2VBbmFseXRpY3MpCmBgYAoKSSBkb3dubG9hZCB0aGUgc2FtcGxlIGRhdGFzZXQgZWRoZWMsIHdoaWNoIGNvbnRhaW5zIG1vbnRobHkgcmV0dXJucyBvZiBkaWZmZXJlbnQgaGVkZ2UgZnVuZCBpbmRleGVzIGNyZWF0ZWQgYnkgdGhlIEVESEVDIFJpc2sgSW5zdGl0dXRlLgoKYGBge3J9CmRhdGEoImVkaGVjIikKYGBgClRoZSBlZGhlYyBkYXRhc2V0IHdpbGwgYXBwZWFyIGluIG15IEdsb2JhbCBFbnZpcm9ubWVudC4KCmVkaGVjIGlzIGFuIHh0cyBSIG9iamVjdCB0aGF0IGNvbnRhaW5zIGhpc3RvcmljYWwgbW9udGhseSByZXR1cm5zIG9mIGRpZmZlcmVudCBoZWRnZSBmdW5kIGluZGV4ZXMuIFdlIGNhbiBlYXNpbHkgZG8gZGlmZmVyZW50IGNhbGN1bGF0aW9ucyB3aXRoIHNwZWNpZmljIGZ1bmN0aW9ucyB0aGF0IGFwcGx5IHRvIHh0cyBvYmplY3RzLiBGb3Igbm93LCB3ZSB3aWxsIGxlYXJuIGhvdyB0byBkbyBzdWJzZXR0aW5nIHdpdGggeHRzIG9iamVjdHMuCgpJZiB5b3Ugd2FudCB0byBrbm93IG1vcmUgZnVuY3Rpb25zIGZvciB0aGUgeHRzIFIgb2JqZWN0cywgeW91IGNhbiBjaGVjayB0aGUgeHRzIENoZWF0U2hlZXQgYXQ6IGh0dHBzOi8vczMuYW1hem9uYXdzLmNvbS9hc3NldHMuZGF0YWNhbXAuY29tL2Jsb2dfYXNzZXRzL3h0c19DaGVhdF9TaGVldF9SLnBkZgoKIyMgU3Vic2V0dGluZyBkYXRhCgpSIGhhcyBwb3dlcmZ1bCBpbmRleGluZyBmZWF0dXJlcyBmb3IgYWNjZXNzaW5nIG9iamVjdCBlbGVtZW50cy4gVGhlc2UgZmVhdHVyZXMgY2FuIGJlIHVzZWQgdG8gc2VsZWN0IGFuZCBleGNsdWRlIGNvbHVtbnMgYW5kIHJvd3MgKG9ic2VydmF0aW9ucykuIEluIHRoZSBuZXh0IHBhcmFncmFwaHMgd2Ugd2lsbCBsZWFybiBob3cgdG8gZXh0cmFjdCB0aGUgaW5mb3JtYXRpb24gd2Ugd2FudCBmcm9tIGFuIHh0cyBvYmplY3QuIFNldmVyYWwgb2YgdGhlc2UgZnVuY3Rpb25zIGFsc28gYXBwbHkgdG8gZGF0YSBmcmFtZXMuCgpJIHNlZSB0aGUgc3RydWN0dXJlIG9mIHRoZSBlZGhlYyBSIGRhdGFzZXQgYW5kIHRoZSBmaXJzdCBhbmQgbGFzdCByb3dzOgoKYGBge3J9CnN0cihlZGhlYykKYGBgCgpgYGB7cn0KaGVhZChlZGhlYykKYGBgCgpgYGB7cn0KdGFpbChlZGhlYykKYGBgCkZyb20gdGhlIHJlc3VsdHMgYWJvdmUsIHdlIHNlZSB0aGF0IHRoaXMgeHRzIG9iamVjdCBoYXMgMTMgY29sdW1ucywgd2hpY2ggYXJlIHJldHVybnMgb2YgZGlmZmVyZW50IGhlZGdlIGZ1bmQgaW5kZXhlcy4KCkkgY2FuIHN1YnNldCBlaXRoZXIgcm93cywgY29sdW1ucyBvciBib3RoLiBGb3IgZXhhbXBsZSBJIGNhbiBzZWxlY3QgaW4gd2hpY2ggbW9udGhzIHRoZSBFbWVnaW5nIG1hcmtldCBmdW5kIGhhcyBoYWQgbmVnYXRpdmUgcmV0dXJuczoKCmBgYHtyfQogbmVnYXRpdmVfcmV0dXJuc19lbSA8LSBlZGhlY1tlZGhlYyRgRW1lcmdpbmcgTWFya2V0c2A8MCw0XQojIEkgZGlzcGxheSB0aGUgZmlyc3Qgcm93cyBvZiB0aGlzIG5ldyBvYmplY3QsIHdoaWNoIGhhcyBvbmx5IG5lZ2F0aXZlIHJldHVybnMgZm9yIEVtZXJnaW5nIE1hcmtldHM6CmhlYWQobmVnYXRpdmVfcmV0dXJuc19lbSkKYGBgCgoKYGBge3J9CiBuZWdhdGl2ZV9yZXR1cm5zX2VtX2FsbCA8LSBlZGhlY1tlZGhlYyRgRW1lcmdpbmcgTWFya2V0c2A8MCxdCiBoZWFkKG5lZ2F0aXZlX3JldHVybnNfZW1fYWxsKQpgYGAKCkFzIHlvdSBzZWUsIHRvIGRvIHN1YnNldHRpbmcgSSB1c2Ugc3F1YXJlZCBicmFja2V0cyBhZmhlciB0aGUgb2JqZWN0LCBhbmQgdGhlIGZpcnN0IG51bWJlciByZWZlcnMgdG8gdGhlIFJPV1MgdG8gYmUgc2VsZWN0ZWQsIGFuZCB0aGUgc2Vjb25kIHBhcmFtZXRlciByZWZlcnMgdG8gdGhlIENPTFVNTlMgdG8gYmUgc2VsZWN0ZWQuIEluIHRoaXMgY2FzZSwgYWZ0ZXIgdGhlIGNvbWEgSSB3cm90ZSBOT1RISU5HLCBpbmRpY2F0aW5nIHRoYXQgSSB3YW50IEFMTCBDT0xVTU5TIQoKSWYgSSB3YW50IHRvIGRvIGEgc3Vic2V0dGluZyBvZiBzcGVjaWZpYyByb3dzIHVzaW5nIGEgcmFuZ2Ugb2YgZGF0ZXMsIEkgY2FuIGRvIHRoZSBmb2xsb3dpbmcuIFNpbmNlIHRoaXMgaXMgYW4geHRzIG9iamVjdCwgaXQgaXMgdmVyeSBlYXN5IHRvIHN1YnNldCB1c2luZyBkYXRlcy4gSSBzZWxlY3QgdGhlIHJldHVybnMgb2YgdGhlIDEyIG1vbnRocyBvZiB0aGUgeWVhciAyMDA4OgoKYGBge3J9CiBlZGhlYzIwMDg8LWVkaGVjWyIyMDA4LTAxLTAxLzIwMDgtMTItMzEiLF0KYGBgCgpJIGNhbiBhbHNvIHNlbGVjdCB0aG9zZSBtb250aHMgd2hlcmUgdGhlIEVtZXJnaW5nIE1hcmtldHMgZnVuZCBhbmQgdGhlIENvbnZlcnRpYmxlIEFyYml0cmFnZSBmdW5kIGhhZCBwb3NpdGl2ZSByZXR1cm5zIGluIDIwMDg6CgpgYGB7cn0KIHBvc2l0aXZlX2VkaGVjMjAwODwtZWRoZWMyMDA4W2VkaGVjMjAwOCRgQ29udmVydGlibGUgQXJiaXRyYWdlYD4wICYgZWRoZWMyMDA4JGBFbWVyZ2luZyBNYXJrZXRzYD4wLF0KcG9zaXRpdmVfZWRoZWMyMDA4CmBgYAoKV2UgY2FuIHNlZSB0aGF0IG9ubHkgMiBtb250aHMgaGFkIHBvc2l0aXZlIHJldHVybnMgaW4gdGhlc2UgZnVuZHMgaW4gMjAwOC4KClRoZXJlIGFyZSBzZXZlcmFsIGxvZ2ljYWwgb3BlcmF0b3JzIHRvIGJlIHVzZWQgZm9yIHRoZSBzdWJzZXR0aW5nIGNvbmRpdGlvbiBvZiByb3dzLiBUaGVzZSBvcGVyYXRvcnMgYXJlOgoKPT0gZXF1YWwgdG8KIT0gZGlmZmVyZW50IHRvCjwgbGVzcyB0aGFuCjw9IGxlc3MgdGhhbiBvciBlcXVhbCB0bwo+IG1vcmUgdGhhbgo+PSBtb3JlIHRoYW4gb3IgZXF1YWwgdG8Kb3IKJiBhbmQKClRoZXJlIGFyZSBzZXZlcmFsIGxvZ2ljYWwgb3BlcmF0b3JzIHRvIGJlIHVzZWQgZm9yIHRoZSBzdWJzZXR0aW5nIGNvbmRpdGlvbiBvZiByb3dzLiBUaGVzZSBvcGVyYXRvcnMgYXJlOgoKPT0gZXF1YWwgdG8KIT0gZGlmZmVyZW50IHRvCjwgbGVzcyB0aGFuCjw9IGxlc3MgdGhhbiBvciBlcXVhbCB0bwo+IG1vcmUgdGhhbgo+PSBtb3JlIHRoYW4gb3IgZXF1YWwgdG8Kb3IKJiBhbmQKCgojI0NvbnRyb2wtZmxvdyBjb21tYW5kcwpDb250cm9sLWZsb3cgY29tbWFuZHMgb3IgY29uc3RydWN0cyBhcmUgdXNlZCB0byBwcm9ncmFtIGEgc2VyaWVzIG9mIHRhc2tzIHVzaW5nIGNvbmRpdGlvbnMgYW5kL29yIGxvb3BzLgoKVGhlcmUgYXJlIDcgbWFpbiBjb250cm9sIHN0cnVjdHVyZXM6CgppZi9lbHNlOiB0ZXN0aW5nIGEgY29uZGl0aW9uCmZvcjogZXhlY3V0ZSBhIGxvb3AgYSBmaXhlZCBudW1iZXIgb2YgdGltZXMKcmVwZWF0OiBleGVjdXRlIGFuIGluZmluaXRlIGxvb3AKd2hpbGU6IGV4ZWN1dGUgYSBsb29wIHdoaWxlIGEgY29uZGl0aW9uIGlzIHRydWUKYnJlYWs6IGJyZWFrIHRoZSBleGVjdXRpb24gb2YgYSBsb29wCm5leHQ6IHNraXAgYW4gaW50ZXJhdGlvbiBvZiBhIGxvb3AKcmV0dXJuOiBleGl0IGEgZnVuY3Rpb24KClRoZSBtb3N0IHNpbXBsZSBvbmVzIGFyZSB0aGUgY29uZGl0aW9uYWxzIGlmKCkgYW5kIGlmL2Vsc2UsIHdoaWNoIGFsbG93IHlvdSB0byBpbXBsZW1lbnQgc29tZSBiYXNpYyBhbGdvcml0aG0gbG9naWMgaW4geW91ciBhbmFseXNpcy4gV2Ugd2lsbCBzdGFydCB3aXRoIHRoZSBjb25kaXRpb25hbHMgc3RhdGVtZW50cyBhbmQgdGhlbiB0aGUgbG9vcCBzdGF0ZW1lbnRzLgoKIyBDb25kaXRpb25hbHMKIyMgSWYgYW5kIGlmIGVsc2UKCmBgYHtyfQppZig8Y29uZGl0aW9uMT4pIHsKICAjIyBkbyBzdHVmZgp9CmBgYAoKSGVyZSBpcyBhIHNpbXBsZSBleGFtcGxlLCB0aGF0IGlzIHNlbGYtZXhwbGFuYXRvcnk6CgpgYGB7cn0KZ3JhZGUgPC0gNzAKCmlmKGdyYWRlID4gNjkpe2NhdCgiWW91IGhhdmUgcGFzc2VkIHRoaXMgY291cnNlLiBXZWxsIGRvbmUhIil9CmBgYApJbiB0aGlzIGNhc2UgdGhlIGNvbmRpdGlvbiB3aWxsIGJlIHRydWUsIHNvIHRoZSBtZXNzYWdlIHdpbGwgYmUgZGlzcGxheWVkLiBZb3UgY2FuIHRyeSBkaWZmZXJlbnQgdmFsdWVzIGZvciBncmFkZSBhbmQgcmUtcnVuIHRoaXMgY29kZSB0byBzZWUgd2hhdCBoYXBwZW5zLgoKIyMgRUxTRSBJRgpJbWFnaW5lIHRoYXQgeW91IGhhdmUgc2V2ZXJhbCBjb25kaXRpb25zLCBub3Qgb25seSBvbmUgYXMgdGhlIHByZXZpb3VzIGV4YW1wbGUuIEluIHRoaXMgY2FzZSwgeW91IG5lZWQgdG8gdXNlIHRoZSBlbHNlIGlmIHN0YXRlbWVudC4gVGhlIHN0cnVjdHVyZSBsb29rcyBsaWtlIHRoaXM6CmBgYHtyfQppZig8Y29uZGl0aW9uMT4pIHsKICAjIyBkbyBzb21ldGhpbmcKfSBlbHNlIGlmKDxjb25kaXRpb24yPikgewogICMjIGRvIHNvbWV0aGluZyBkaWZmZXJlbnQKfQpgYGAKClNvIG91ciBwcmV2aW91cyBleGFtcGxlIGNhbiBiZSB1cGdyYWRlZCBhcyBmb2xsb3dzLiBUcnkgY2hhZ2luZyB0aGUgdmFsdWVzIGluIHRoZSBpbnB1dCB2YXJpYWJsZXMuCgpgYGB7cn0KZ3JhZGVQYXJ0aWFsMSA8LSA4MApncmFkZVBhcnRpYWwyIDwtIDYwCmdyYWRlRmluYWxFeGFtIDwtIDEwMAoKRmluYWxHcmFkZSA8LSAoZ3JhZGVQYXJ0aWFsMSowLjI1ICsgZ3JhZGVQYXJ0aWFsMSowLjI1ICsgZ3JhZGVGaW5hbEV4YW0qMC41KQoKaWYoRmluYWxHcmFkZSA+IDkwKXsKICAgICJZb3UgZGlkIGFuIEV4Y2VsbGVudCBqb2IhIgogIH0gZWxzZSBpZihGaW5hbEdyYWRlID4gNjkpewogICAgIllvdSBoYXZlIHBhc3NlZCB0aGlzIGNvdXJzZS4gV2VsbCBkb25lLiIKICB9IGVsc2UgaWYoRmluYWxHcmFkZSA+IDApewogICAgIlNvcnJ5IHlvdSBoYXZlIGZhaWxlZCB0aGUgY291cnNlLiIKICB9CmBgYAoKIyMgRUxTRQoKTm93IGltYWdpbmUgdGhhdCB3ZSBoYXZlIHNldmVyYWwgY29uZGl0aW9uYWxzIGJ1dCB3ZSB3YW50IHRvIGRvIHNvbWV0aGluZyB3aXRoIHRoZSByZW1haW5pbmcgdmFyaWFibGVzIHRoYXQgZG9u4oCZdCBmdWxmaWxsIHRoZSBwcmV2aW91cyBjb25kaXRpb25hbHMsIHRoZW4gd2UgdXNlIGVsc2UuIFRoZSBzdHJ1Y3R1cmUgbG9va3MgbGlrZToKCmBgYHtyfQpncmFkZVBhcnRpYWwxIDwtIC03MApncmFkZVBhcnRpYWwyIDwtIDYwCmdyYWRlRmluYWxFeGFtIDwtIC02MAoKRmluYWxHcmFkZSA8LSAoZ3JhZGVQYXJ0aWFsMSowLjI1ICsgZ3JhZGVQYXJ0aWFsMSowLjI1ICsgZ3JhZGVGaW5hbEV4YW0qMC41KQoKaWYoRmluYWxHcmFkZSA+IDkwKXsKICAgICJZb3UgZGlkIGF3ZXNvbWUhIgogIH0gZWxzZSBpZihGaW5hbEdyYWRlID4gNjkpewogICAgIllvdSBoYXZlIHBhc3NlZCB0aGlzIGNvdXJzZS4gV2VsbCBkb25lLiIKICB9IGVsc2UgaWYoRmluYWxHcmFkZSA+IDApewogICAgIlNvcnJ5IHlvdSBoYXZlIGZhaWxlZCB0aGUgY291cnNlLiIKICB9IGVsc2UgewogICAgIllvdSBoYXZlIG5lZ2F0aXZlIGdyYWRlczsgaXQgc2hvdWxkIGJlIGFuIGVycm9yIgp9CmBgYAoKIyMgJWluJQpJbiB0aGUgbmV4dCBleGFtcGxlIHdlIHVzZSB0aGUgb3BlcmF0b3IgJWluJS4gVGhpcyBvcGVyYXRvciBjaGVja3Mgd2hldGhlciBhIHZhbHVlIGV4aXN0cyBpbnNpZGUgYSB2ZWN0b3IuIEZvciBlYWNoIGVsZW1lbnQgb2YgdGhlIHZlY3RvciBpdCByZXR1cm5zIFRSVUUgaWYgdGhlIHZhbHVlIGlzIGNvbnRhaW5lZCBpbiB0aGUgdmVyY3RvciBhbmQgMCBvdGhlcndpc2U6CgpgYGB7cn0KIyBCb3RoIGVsZW1lbnRzIGluIHRoZSBmaXJzdCB2ZWN0b3IgYXBwZWFycyBpbiB0aGUgc2Vjb25kIHZlY3RvcgpjKDEsMikgJWluJSBjKDYsNCw4LDMsMiwxKQpgYGAKCmBgYHtyfQojIE9ubHkgdGhlIGxhc3QgdHdvIGVsZW1lbnRzIG9mIHRoZSBmaXJzdCB2ZXJjdG9yIGFwcGVhciBpbiB0aGUgc2Vjb25kCmMoNiw0LDgsMywyLDEpICVpbiUgYygxLDIpCmBgYAoKIyMgRm9yIExvb3AKQXMgeW91IHNlZSwgdGhlIHJlc3VsdCBvZiB1c2luZyB0aGUgJWluJSBvcGVyYXRvciBpcyBhIHZlY3RvciBvZiBCb29sZWFuIHZhbHVlcyAoVFJVRSBPUiBGQUxTRSkuIElmIHRoZSBmaXJzdCBlbGVtZW50IGlzIFRSVUUsIGl0IG1lYW5zIHRoYXQgdGhlIGZpcnN0IG51bWJlciBvZiB0aGUgZmlyc3QgdmVjdG9yIGlzIGluc2lkZSB0aGUgc2Vjb25kIHZlY3Rvci4KCmBgYHtyfQpzdHVkZW50czwtYygiUGVkcm8iLCJMYXVyYSIsIkJyeWFuIikKCmZvcihuYW1lIGluIHN0dWRlbnRzKXsKICAjI0luc3RlYWQgb2YgbmFtZSB5b3UgY2FuIHdyaXRlIGFueSB2YXJpYWJsZSBqdXN0IGNoYW5nZSBpdCBpbnNpZGUgdGhlIGxvb3AKICBjYXQoIkhpLCBteSBuYW1lIGlzIixuYW1lKQp9CmBgYApJbiB0aGUgbmV4dCBleGFtcGxlIHdlIHdpbGwgdXNlIHRoZSBxdWFudG1vZCBsaWJyYXJ5IHRvIGRvd25sb2FkIHNvbWUgZmluYW5jaWFsIGRhdGEgZnJvbSBvbmxpbmUgZGF0YSBzb3VyY2VzIHN1Y2ggYXMgWWFob28gZmluYW5jZSBhbmQgR29vZ2xlIEZpbmFuY2UuIE91ciBpbml0aWFsIHZlY3RvciBpbmRpY2F0ZSB0aGUgdGlja2VycyB0byBkb3dubG9hZCwgaW4gdGhpcyBjYXNlIEFBUEwsSlBNIGFuZCBHRS4KCllvdSBoYXZlIHRvIGluc3RhbGwgdGhlIHBhY2thZ2UgaW4gdGhlIFBhY2thZ2UgdGFiIG9mIHRoZSBib3R0b20tcmlnaHQgd2luZG93cyBvZiBSU3R1ZGlvLgoKT25jZSB5b3UgaW5zdGFsbCB0aGUgY29tbWFuZCwgeW91IGhhdmUgdG8gbG9hZCBpdCB3aXRoIHRoZSBsaWJyYXJ5IGZ1bmN0aW9uLiBUaGlzIHF1YW50bW9kIGxpYnJhcnkgaGFzIHRoZSBnZXRTeW1ib2xzIGZ1bmN0aW9uIHRoYXQgaXMgdXNlZCB0byBkb3dubG9hZCBvbmxpbmUgZGF0YSBmcm9tIHRoZSB3ZWI6CgpgYGB7cn0KbGlicmFyeShxdWFudG1vZCkKCiNWZWN0b3Igb2YgdGlja2Vycwp0aWNrZXJzIDwtYygiQUFQTCIsIkpQTSIsIkdFIikKCmZvcihpIGluIHRpY2tlcnMpewogICAgZ2V0U3ltYm9scyhpKQogICAgY2F0KCJ0aGUgcHJpY2VzIG9mIHRoZSB0aWNrZXIiLGksImhhdmUgYmVlbiBkb3dubG9hZGVkIikKfQpgYGAKCkluIHRoZSBuZXh0IGV4YW1wbGUgd2UgZG8gYSBzaW1pbGFyIHByb2Nlc3MgZm9yIGEgZGlmZmVyZW50IHRpY2tlciBsaXN0LiBJbiB0aGUgY2FzZSBvZiBHRSBhbmQgQUFQTCB3ZSBhcmUgZ29pbmcgdG8gZG93bmxvYWQgdGhlIGRhdGEgZnJvbSB5YWhvbywgd2hpbGUgSU5UR1NUTVhNMTkzTiBmcm9tIHRoZSBGRUQuIFdoYXQgaGFwcGVucyB3aXRoIHRoZSByZW1haW5uaW5nIHRpY2tlcnM/CgpgYGB7cn0KdGlja2VycyA8LSBjKCJBQVBMIiwiR00iLCJJTlRHU1RNWE0xOTNOIiwiR0UiLCJKUE0iKQoKZm9yKGkgaW4gdGlja2Vycyl7CiAgaWYoaSAlaW4lIGMoIkFBUEwiLCJHRSIpKXsKICAgIGdldFN5bWJvbHMoaSxzcmMgPSAieWFob28iKQogICAgY2F0KCJ0aGUgcHJpY2VzIG9mIHRoZSB0aWNrZXIiLGksImhhdmUgYmVlbiBkb3dubG9hZGVkIGZyb20geWFob28iKQogIH0KICBlbHNlIGlmKGk9PSJJTlRHU1RNWE0xOTNOIil7CiAgICBnZXRTeW1ib2xzKGksc3JjID0gIkZSRUQiKQogICAgI05vdGUgdGhhdCB0aGUgc291cmNlIGZvciB0aGUgRkVEIGlzIGNhbGxlZCBGUkVECiAgICBjYXQoInRoZSBkYXRhIG9mIHRoZSB0aWNrZXIiLGksImhhdmUgYmVlbiBkb3dubG9hZGVkIGZyb20gdGhlIEZFRCAoRmVkZXJhbCBVUyBCYW5rKSAiKQogIH0KfQpgYGAKCgpXZSBhcmUgZ29pbmcgdG8gdXNlIHRoZSBwcmV2aW91cyBleGFtcGxlLCBidXQgaW4gdGhpcyBjYXNlIHdlIHdhbnQgYWxzbyB0byBhZGQgYSBjb25kaXRpb24gdG8gcHJpbnQgdGhlIHRpY2tlcnMgdGhhdCBoYXZlIE5PVCBiZWVuIGRvd25sb2FkZWQuCgoKYGBge3J9CnRpY2tlcnMgPC0gYygiQUFQTCIsIkdNIiwiSU5UR1NUTVhNMTkzTiIsIkdFIiwiSlBNIikKCmZvcihpIGluIHRpY2tlcnMpewogIAogIGlmKGkgJWluJSBjKCJBQVBMIiwiR0UiKSl7CiAgICBnZXRTeW1ib2xzKGksc3JjID0gInlhaG9vIikKICAgIGNhdCgidGhlIHByaWNlcyBvZiB0aGUgdGlja2VyIixpLCJoYXZlIGJlZW4gZG93bmxvYWRlZCBmcm9tIHlhaG9vIikKICB9CiAgZWxzZSBpZihpPT0iSU5UR1NUTVhNMTkzTiIpewogICAgZ2V0U3ltYm9scyhpLHNyYyA9ICJGUkVEIikKICAgIGNhdCgidGhlIGRhdGEgb2YgdGhlIHRpY2tlciIsaSwiaGF2ZSBiZWVuIGRvd25sb2FkZWQgZnJvbSB0aGUgRkVEIChGZWRlcmFsIFVTIEJhbmspICIpCiAgfQogIGVsc2UgewogICAgY2F0KCJUaGUgdGlja2VyIixpLCJoYXMgbm90IGJlZW4gZG93bmxvYWRlZCIpCiAgfQp9CmBgYAoKCiMjIFdISUxFIEFORCBSRVBFQVQgVE9PTFMKCkluIGEgc2ltaWxhciBtYW5uZXIgdGhhbiB0aGUgZm9yIGxvb3AsIGl0IGlzIHBvc3NpYmxlIHRvIHByb2dyYW0gYSBsb29wIHdpdGggd2hpbGUgYW5kIHJlcGVhdCBjb250cm9sLWZsb3cgc3RhdGVtZW50cy4gVGhlIG1haW4gZGlmZmVyZW5jZSBpcyB0aGF0IGluIGJvdGggeW91IG5lZWQgdG8gc3BlY2lmeSB3aGF0IGlzIHRoZSBleGl0IGNvbmRpdGlvbiwgYW5kIGl0IG1heSBiZSBwb3NzaWJsZSB0aGF0IE5PVCBhbGwgdGhlIGl0ZXJlYXRpb25zIGhhcyB0byBiZSBwZXJmb3JtZWQgKGxpa2UgaW4gdGhlIGZvciBjYXNlKS4KCkZvciB0aGUgd2hpbGUgeW91IG5lZWQgdG8gc3BlY2lmeSB0aGUgY29uZGl0aW9uIGF0IHRoZSBiZWdpbm5pbmcuIEhlcmUgYW4gZXhhbXBsZS4gSWYgeW91IHdhbnQgdG8ga25vdyBob3cgbWFueSB5ZWFycyB5b3UgbmVlZCB0byBrZWVwIGFuIGludmVzdG1lbnQgd2l0aCBhIGZpeGVkIGludGVyZXN0IHJhdGUgaW4gb3JkZXIgdG8gZHVwbGljYXRlIHlvdXIgaW5pdGlhbCBpbnZlc3RtZW50OgoKYGBge3J9CiBBUFI8LTAuMTAKICAjIEkgZGVmaW5lIEFubnVhbCBQZXJjZW50YWdlIFJhdGUgdG8gYmUgZXF1YWwgdG8gMTAlCiAgSU5WPC0xMDAKICAjIEluaXRpYWwgaW52ZXN0bWVudCBlcXVhbCB0byAkMTAwCiAgTVVMVElQTEU8LTIKICAjIE11bHRpcGxlID0gMiB0byBjaGVjayB3aGVuIHRoZSBpbnZlc3RtZW50IGRvdWJsZQogIEJBTEFOQ0U8LUlOVgogICMgSSBzdGFydCBhc3NpZ25pbmcgdGhlIGJhbGFuY2UgZXF1YWwgdG8gdGhlIGluaXRpYWwgaW52ZXN0bWVudAogIHllYXI8LTAKICAjIEkgc3RhcnQgd2l0aCB5ZWFyIGVxdWFsIHRvIHplcm8KICB3aGlsZSAoQkFMQU5DRTxNVUxUSVBMRSpJTlYpIHsKICAgICMgdGhlIGV4aXQgY29uZGl0aW9uIG1lYW5zIHRoYXQgd2hpbGUgdGhlIGJhbGFuY2UgaXMgbGVzcyB0aGFuIHRoZSBpbml0aWFsIGludmVzdG1lbnQKICAgICMgICAgbXVsdGlwbGllZCBieSB0aGUgbXVsdGlwbGUsIHRoZW4gY29udGludWUgd2l0aCB0aGUgaXRlcmF0aW9ucyBvZiB0aGUgbG9vcAogICAgeWVhcjwteWVhcisxIAogICAgIyBJIGluY3JlYXNlIHRoZSB2YWx1ZSBvZiB5ZWFyIGJ5IDEKICAgIEJBTEFOQ0U8LUJBTEFOQ0UqKDErQVBSKSAKICAgICMgSSBtdWx0aXBseSB0aGUgY3VycmVudCBiYWxhbmNlIHRpbWVzIHRoZSBncm93dGggZmFjdG9yICgxK0FQUikgdXNpbmcgdG8gdGhlIAogICAgIyAgIEFubnVhbCBQZXJjZW50YWdlIFJhdGUKICB9CiAgY2F0KAogICAgICJUbyBtdWx0aXBseSB5b3VyIGludmVzdG1lbnQgdGltZXMgIiwgTVVMVElQTEUsICJ5b3UgbmVlZCAiLCB5ZWFyLCAiIHllYXJzLiIpCmBgYAoKYGBge3J9CmNhdCgKICAgICAiWW91ciBiYWxhbmNlIGFmdGVyICIsIHllYXIsICIgeWVhcnMgd2lsbCBiZSAkIixCQUxBTkNFKQpgYGAKVW5saWtlIHRoZSB3aGlsZSBzdGF0ZW1lbnQsIHlvdSBjYW4gdXNlIHRoZSByZXBlYXQgc3RhdGVtZW50IHRvIGRvIGEgbG9vcCwgYnV0IGluIHRoZSBjYXNlIG9mIHJlcGVhdCwgeW91IGhhdmUgdG8gc3BlY2lmeSB0aGUgZXhpdCBjb25kaXRpb24gdXNpbmcgaWYgYW5kIHRoZSBicmVhayBzdGF0ZW1lbnQgYW55IHBsYWNlIHdpdGhpbiB0aGUgbG9vcC4gSGVyZSBpcyB0aGUgc2FtZSBsb29wIHdlIGRpZCBhYm92ZSBidXQgdXNpbmcgcmVwZWF0OgoKCmBgYHtyfQogQVBSPC0wLjEwCiAgIyBJIGRlZmluZSBBbm51YWwgUGVyY2VudGFnZSBSYXRlIHRvIGJlIGVxdWFsIHRvIDEwJQogIElOVjwtMTAwCiAgIyBJbml0aWFsIGludmVzdG1lbnQgZXF1YWwgdG8gJDEwMAogIE1VTFRJUExFPC0yCiAgIyBNdWx0aXBsZSA9IDIgdG8gY2hlY2sgd2hlbiB0aGUgaW52ZXN0bWVudCBkb3VibGUKICBCQUxBTkNFPC1JTlYKICAjIEkgc3RhcnQgYXNzaWduaW5nIHRoZSBiYWxhbmNlIGVxdWFsIHRvIHRoZSBpbml0aWFsIGludmVzdG1lbnQKICB5ZWFyPC0wCiAgIyBJIHN0YXJ0IHdpdGggeWVhciBlcXVhbCB0byB6ZXJvCiAgcmVwZWF0ICB7CiAgICB5ZWFyPC15ZWFyKzEgCiAgICAjIEkgaW5jcmVhc2UgdGhlIHZhbHVlIG9mIHllYXIgYnkgMQogICAgQkFMQU5DRTwtQkFMQU5DRSooMStBUFIpIAogICAgIyBJIG11bHRpcGx5IHRoZSBjdXJyZW50IGJhbGFuY2UgdGltZXMgdGhlIGdyb3d0aCBmYWN0b3IgKDErQVBSKSB1c2luZyB0byB0aGUgCiAgICAjICAgQW5udWFsIFBlcmNlbnRhZ2UgUmF0ZQogICAgaWYgKEJBTEFOQ0U+PU1VTFRJUExFKklOVikgewogICAgICBicmVhawogICAgfQogICAgIyBJZiB0aGUgYmFsYW5jZSBpcyBncmVhdGVyIHRoYW4gdGhlIG11bHRpcGxlIHRpbWVzIHRoZSBpbnZlc3RtZW50LCB0aGVuCiAgICAjICAgdGhlIGJyZWFrIHN0YXRlbWVudCBpcyBleGVjdXRlZCwgc28gdGhlIHByb2dyYW0gc3RvcHMgdGhlIGludGVyYXRpb25zCiAgfQogIGNhdCgKICAgICAiVG8gbXVsdGlwbHkgeW91ciBpbnZlc3RtZW50IHRpbWVzICIsIE1VTFRJUExFLCAieW91IG5lZWQgIiwgeWVhciwgIiB5ZWFycy4iKQpgYGAKCmBgYHtyfQogIGNhdCgKICAgICAiWW91ciBiYWxhbmNlIGFmdGVyICIsIHllYXIsICIgeWVhcnMgd2lsbCBiZSAkIixCQUxBTkNFKQpgYGAKNS40IExvb3BpbmcgdnMgUi12ZWN0b3JpemF0aW9uCk1vc3QgUiBwcm9ncmFtbWVycyBiZWxpZXZlIHRoYXQgbG9vcHMgbXVzdCBiZSBBVk9JREVEISBUaGlzIGlzIHdpZXJkIHNpbmNlIG1vc3Qgb2YgdGhlIHRpbWUgcHJvZ3JhbW1pbmcgcmVxdWlyZXMgdG8gZG8gcmVwZXRpdGl2ZSB0YXNrcy4gSG93ZXZlciwgaW4gUiwgdW5saWtlIG90aGVyIHRyYWRpdGlvbmFsIGNvbXB1dGVyIGxhbmd1YWdlcyBzdWNoIGFzIEMsIHRoZXJlIGlzIGFuIGFsdGVybmF0aXZlIHdheSB0byBkbyBsb29wcyB3aXRob3V0IHdyaXRpbmcgbG9vcHMhCgoKYGBge3J9CkEgPC1jKDMsMyw0LDYsOCkgCiAgQiA8LWMoLTIsLTMsLTEsMyw1KQogICMgQSBhbmQgQiBhcmUgdmVjdG9ycyB3aXRoIHRoZSBhbm51YWwgZnJlZSBjYXNoIGZsb3dzIG9mIGVhY2ggcHJvZHVjdCAKICBzdW1jYXNoZmxvd3M8LXZlY3RvcihsZW5ndGg9NSkKICBmb3IgKGkgaW4gMTpsZW5ndGgoQSkpIHsKICAgIHN1bWNhc2hmbG93c1tpXTwtQVtpXSArIEJbaV0KICAgICMgV2Ugc3VtIHRoZSBlbGVtZW50IGkgb2YgYm90aCB2ZWN0b3JzIGFuZCBsZWF2ZSB0aGUgcmVzdWx0CiAgICAjICAgaW4gdGhlIHBvc2l0aW9uIGkgb2YgdGhlIHZlY3RvciBzdW1jYXNoZmxvd3MKICB9CiAgc3VtY2FzaGZsb3dzCmBgYAoKYGBge3J9CiAgQSA8LWMoMywzLDQsNiw4KSAKICBCIDwtYygtMiwtMywtMSwzLDUpCiAgc3VtY2FzaGZsb3dzPC1BK0IKICAjIFdlIGp1c3Qgc3VtIGJvdGggdmVjdG9ycyBhcyBpZiB0aGV5IHdlcmUgbnVtYmVycwogIHN1bWNhc2hmbG93cwpgYGAKCjUuNSBBcHBsaWNhdGlvbjogUHJlc2VudCB2YWx1ZSBvZiBmdXR1cmUgY2FzaCBmbG93cwpOb3csIGhvdyBjYW4geW91IGNhbGN1bGF0ZSB0aGUgUHJlc2VudCBWYWx1ZSBvZiB0aGVzZSBjYXNoIGZsb3dzPyBZb3UgaGF2ZSB0byByZW1lbWJlciB0aGUgYmFzaWNzIG9mIHRpbWUgdmFsdWUgb2YgbW9uZXkuIFRvIGNhbGN1bGF0ZSB0aGUgcHJlc2VudCB2YWx1ZSAoUFYwKSBvZiBhIHNlcXVlbmNlIG9mIGNhc2ggZmxvd3MgaW4gdGhlIGZ1dHVyZSwgeW91IGp1c3QgaGF2ZSB0byBhcHBseSB0aGUgZm9sbG93aW5nIGZvcm11bGEgZm9yIHRoZSBzZXF1ZW5jZSBvZiBjYXNoIGZsb3dzOgoKY29uIGxvb3AKCmBgYHtyfQogICMgSSBhc3NpZ24gMCB0aGUgdGhlIHZhcmlhYmxlIFBWLCBwcmVzZW50IHZhbHVlCiAgUFYgPC0gMAogICMgSSBkZWZpbmVkIHRoZSBkaXNjb3VudCByYXRlIGFzIFI6CiAgUiA8LSAwLjE1IAogIGZvciAoaSBpbiAxOmxlbmd0aChzdW1jYXNoZmxvd3MpKSB7CiAgICAjIEkgY2FsY3VsYXRlIHRoZSBwcmVzZW50IHZhbHVlIG9mIGVhY2ggY2FzaCBmbG93IGk6CiAgICBQVkNGIDwtIHN1bWNhc2hmbG93c1tpXSAvICgxICsgUileaQogICAjIEkgc3VtIGVhY2ggY29ycmVzcG9uZGluZyBjYXNoIGZsb3cgaSB0byB0aGUgY3VtdWxhdGl2ZSB2YXJpYWJsZSBQViAgICAKICAgIFBWIDwtIFBWICsgUFZDRgogIH0KICMgVGhlIGxvb3AgaXRlcmF0ZXMgNSB0aW1lcywgb25lIGZvciBlYWNoIGNhc2ggZmxvdyBhbmQgd2lsbCBlbmRzIHdpdGggdGhlIHN1bSBvZiBhbGwgCiAgY2F0KCJUaGUgUHJlc2VudCBWYWx1ZSBvZiBhbGwgY2FzaCBmbG93cyBpcyAiLCBQVikKYGBgCgpzaW4gbG9vcAoKYGBge3J9CiAjIEkgYXNzaWduIGEgc2VxdWVuY2UgZnJvbSAxIHRvIDUsIGZvciB0aGUgZXhwb25lbnRzIG9mIHRoZSBmb3JtdWxhIG9mIHByZXNlbnQgdmFsdWUgCiAgIyAgIGZvciBlYWNoIGNhc2ggZm93CiAgZXhwb25lbnRzIDwtIHNlcSgxLDUpCiAgIyBUaGUgc2VxIGlzIGEgZnVuY3Rpb24gdGhhdCBnZW5lcmF0ZXMgYSBzZXF1ZW5jZS4gSGVyZSBJIHNwZWNpZmllZCB0byBzdGFydCB0aGUgCiAgIyAgIHNlcXVlbmNlIGluIDEgYW5kIGZpbmlzaCBpbiA1CiAgIyBJIGNhbGN1bGF0ZSBhIHZlY3RvciB3aXRoIHRoZSBwcmVzZW50IHZhbHVlIGZvciBlYWNoIGNhc2ggZmxvdy4gSSB1c2UgdmVjdG9yaXphdGlvbjoKICBQVnZlY3RvciA8LSBzdW1jYXNoZmxvd3MgLyAoMSArIFIpXmV4cG9uZW50cwogICMgTm90ZSB0aGF0IHRoaXMgbWF0aGVtYXRpY2FsIGV4cHJlc3Npb24gYXBwbGllcyB0byBlYWNoIG9mIHRoZSBlbGVtZW50IG9mIHRoZSB2ZWN0b3IuIAogICMgICBBbHNvLCBlYWNoIHZlY3RvciBoYXMgdGhlIHNhbWUgZGltZW5zaW9uLgogICMgSSBmaW5hbGx5IHN1bSBhbGwgZWxlbWVudHMgb2YgdGhlIHZlY3RvciB1c2luZyB0aGUgZnVuY3Rpb24gc3VtOgogIFBWPC1zdW0oUFZ2ZWN0b3IpCiAgY2F0KCJUaGUgUHJlc2VudCBWYWx1ZSBvZiBhbGwgY2FzaCBmbG93cyBpcyAiLCBQVikKYGBgCiMjNyBDSEFMTEVOR0UgMQpZb3UgaGF2ZSB0byB3cml0ZSBhIHByb2dyYW0gdG8gY2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgbW9udGhzIG5lZWRlZCB0byBmaW5pc2ggcGF5aW5nIGEgbW9ydGdhZ2UgbG9hbi4gVGhlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBsb2FuIGlzIHRoZSBmb2xsb3dpbmc6CgpMb2FuIGFtb3VudCA9ICQzLDAwMCwwMDAuMDAgcGVzb3MKCkFQUiAoQW5udWFsICUgcmF0ZSkgPSAxMSUgKGNvbXBvdW5kZWQgbW9udGhseSkKCk1vbnRobHkgRml4ZWQgUGF5bWVudCA9ICQ0MCwwMDAuMDAgKGluY2x1ZGVzIGludGVyZXN0cyBhbmQgY2FwaXRhbCkKCllvdXIgcHJvZ3JhbSBoYXMgdG8gcHJvdmlkZSAyIHJlc3VsdHM6IHRoZSBudW1iZXIgb2YgbW9udGhzIG5lZWRlZCB0byBmaW5pc2ggcGF5aW5nIHRoZSBsb2FuLCBhbmQgdGhlIGFtb3VudCBvZiB0aGUgbGFzdCBwYXltZW50IGlmIHRoZSBwYXltZW50IGlzIGxlc3MgdGhhbiB0aGUgZml4ZWQgcGF5bWVudCBhbW91bnQuIFlvdXIgcHJvZ3JhbSBoYXMgdG8gYmUgYWJsZSB0byBydW4gd2l0aCBhbnkgY2hhbmdlIGluIGFueSBvZiB0aGUgdmFsdWVzIG9mIHRoZSBhYm92ZSB2YXJpYWJsZXMuCgpUaGlzIGlzIGEgcXVpdGUgY2hhbGxlbmdpbmcgZXhlcmNpc2UhCgpIaW50OiBpZiB5b3UgYXJlIGZhbWlsaWFyIHdpdGggRXhjZWwsIHN0YXJ0IHNvbHZpbmcgdGhlIHByb2JsZW0gaW4gRXhjZWwsIGFuZCB0aGVuIHRyeSB0byB3cml0ZSB5b3VyIHByb2dyYW0gaW4gUi4KCiMjOCBDSEFMTEVOR0UgMgpXcml0ZSBhIHByb2dyYW0gdGhhdCBjYWxjdWxhdGVzIHRoZSBwcmljZSBvZiB0aGUgZm9sbG93aW5nIGJvbmQgaXNzdWVkIGJ5IHRoZSBjb21wYW55IEFCQy4gQUJDIG5lZWRzIHRvIGZpbmFuY2UgYW4gaW1wb3J0YW50IHByb2plY3QgdG8gZGV2ZWxvcCBhIG5ldyB0ZWNobm9sb2dpY2FsIGRldmljZS4KClRvIGdldCB0aGUgbW9uZXksIEFCQyBpc3N1ZWQgYSBib25kIHdpdGggdGhlIGZvbGxvd2luZyBjaGFyYWN0ZXJpc3RpY3M6CgpQcmluY2lwYWw6ICQzLDAwMCwwMDAKVGltZSB0byBtYXR1cml0eTogMjAgeWVhcnMKQ291cG9uIHJhdGU6IDExJSAoYW5udWFsKQpjb3Vwb25zIGFyZSBwYXllZCBlYWNoIDYgbW9udGhzCkNhbGN1bGF0ZSB0aGUgcHJpY2Ugb2YgdGhpcyBib25kIGZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgYW5udWFsIGludGVyZXN0IHJhdGVzOgoKOCUKMTElCjEzJQpZb3UgaGF2ZSB0byBnZXQgdGhlIHByaWNlIGZvciB0aGUgYm9uZCBmb3IgZWFjaCBvZiB0aGVzZSAzIGludGVyZXN0IHJhdGVzLgoKUmVtZW1iZXIgdGhhdCB0aGUgcHJpY2Ugb2YgYSBib25kIGlzIHRoZSBwcmVzZW50IHZhbHVlIG9mIGl0cyBmdXR1cmUgY2FzaCBmbG93cy4KCgojIENIQUxMRU5HRSAxCgpZb3UgaGF2ZSB0byB3cml0ZSBhIHByb2dyYW0gdG8gY2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgbW9udGhzIG5lZWRlZCB0byBmaW5pc2ggcGF5aW5nIGEgbW9ydGdhZ2UgbG9hbi4gVGhlIGluZm9ybWF0aW9uIGFib3V0IHRoZSBsb2FuIGlzIHRoZSBmb2xsb3dpbmc6CgpMb2FuIGFtb3VudCA9ICQzLDAwMCwwMDAuMDAgcGVzb3MKCkFQUiAoQW5udWFsICUgcmF0ZSkgPSAxMSUgKGNvbXBvdW5kZWQgbW9udGhseSkKCk1vbnRobHkgRml4ZWQgUGF5bWVudCA9ICQ0MCwwMDAuMDAgKGluY2x1ZGVzIGludGVyZXN0cyBhbmQgY2FwaXRhbCkKCllvdXIgcHJvZ3JhbSBoYXMgdG8gcHJvdmlkZSAyIHJlc3VsdHM6IHRoZSBudW1iZXIgb2YgbW9udGhzIG5lZWRlZCB0byBmaW5pc2ggcGF5aW5nIHRoZSBsb2FuLCBhbmQgdGhlIGFtb3VudCBvZiB0aGUgbGFzdCBwYXltZW50IGlmIHRoZSBwYXltZW50IGlzIGxlc3MgdGhhbiB0aGUgZml4ZWQgcGF5bWVudCBhbW91bnQuIFlvdXIgcHJvZ3JhbSBoYXMgdG8gYmUgYWJsZSB0byBydW4gd2l0aCBhbnkgY2hhbmdlIGluIGFueSBvZiB0aGUgdmFsdWVzIG9mIHRoZSBhYm92ZSB2YXJpYWJsZXMuCgpUaGlzIGlzIGEgcXVpdGUgY2hhbGxlbmdpbmcgZXhlcmNpc2UhCgpIaW50OiBpZiB5b3UgYXJlIGZhbWlsaWFyIHdpdGggRXhjZWwsIHN0YXJ0IHNvbHZpbmcgdGhlIHByb2JsZW0gaW4gRXhjZWwsIGFuZCB0aGVuIHRyeSB0byB3cml0ZSB5b3VyIHByb2dyYW0gaW4gUi4KCmBgYHtyfQpGaW5hbmNpYWxNYXRoOjphbW9ydC5wZXJpb2QoTG9hbiA9IDMwMDAwMDAsIHBtdCA9IDQwMDAwLCBpID0gLjExLCBuID0gTkEpCmBgYAoKCgojIENIQUxMRU5HRSAyCgpXcml0ZSBhIHByb2dyYW0gdGhhdCBjYWxjdWxhdGVzIHRoZSBwcmljZSBvZiB0aGUgZm9sbG93aW5nIGJvbmQgaXNzdWVkIGJ5IHRoZSBjb21wYW55IEFCQy4gQUJDIG5lZWRzIHRvIGZpbmFuY2UgYW4gaW1wb3J0YW50IHByb2plY3QgdG8gZGV2ZWxvcCBhIG5ldyB0ZWNobm9sb2dpY2FsIGRldmljZS4KClRvIGdldCB0aGUgbW9uZXksIEFCQyBpc3N1ZWQgYSBib25kIHdpdGggdGhlIGZvbGxvd2luZyBjaGFyYWN0ZXJpc3RpY3M6CgpQcmluY2lwYWw6ICQzLDAwMCwwMDAKVGltZSB0byBtYXR1cml0eTogMjAgeWVhcnMKQ291cG9uIHJhdGU6IDExJSAoYW5udWFsKQpjb3Vwb25zIGFyZSBwYXllZCBlYWNoIDYgbW9udGhzCkNhbGN1bGF0ZSB0aGUgcHJpY2Ugb2YgdGhpcyBib25kIGZvciBlYWNoIG9mIHRoZSBmb2xsb3dpbmcgYW5udWFsIGludGVyZXN0IHJhdGVzOgoKOCUKMTElCjEzJQpZb3UgaGF2ZSB0byBnZXQgdGhlIHByaWNlIGZvciB0aGUgYm9uZCBmb3IgZWFjaCBvZiB0aGVzZSAzIGludGVyZXN0IHJhdGVzLgoKUmVtZW1iZXIgdGhhdCB0aGUgcHJpY2Ugb2YgYSBib25kIGlzIHRoZSBwcmVzZW50IHZhbHVlIG9mIGl0cyBmdXR1cmUgY2FzaCBmbG93cy4KCmBgYHtyfQpGaW5hbmNpYWxNYXRoOjpib25kKHQgPSBOQSwgZiA9IDMwMDAwMDAsIHIgPSAyMCwgbiA9IDExLCBpID0gLjA4LCBjID0gMSkKYGBgCihJIHRoaW5rPykKCmBgYHtyfQpGaW5hbmNpYWxNYXRoOjpib25kKHQgPSBOQSwgZiA9IDMwMDAwMDAsIHIgPSAyMCwgbiA9IDExLCBpID0gLjExLCBjID0gMSkKYGBgCgpgYGB7cn0KRmluYW5jaWFsTWF0aDo6Ym9uZCh0ID0gTkEsIGYgPSAzMDAwMDAwLCByID0gMjAsIG4gPSAxMywgaSA9IC4xMSwgYyA9IDEpCmBgYAoK