1 Basics

1.1 Financial returns

Assume we have $100. During January, you make a 5% return on that money. How much do you have at the end of January? Well, we have 100% of your starting money, plus another 5%: 100% + 5% = 105%. In decimals, this is 1 + .05 = 1.05. This 1.05 is the return multiplier for January, and you multiply your original $100 by it to get the amount you have at the end of January.

105 = 100 * 1.05

Or in terms of variables:

post_jan_cash <- starting_cash * jan_ret

A quick way to get the multiplier is:

multiplier = 1 + (return / 100)
# Variables for starting_cash and 5% return during January
starting_cash <- 200
jan_ret <- 5
jan_mult <- 1 + (jan_ret / 100)

# How much money do you have at the end of January?
post_jan_cash <- starting_cash * jan_mult

# Print post_jan_cash
post_jan_cash
[1] 210
# January 10% return multiplier
jan_ret_10 <- 10
jan_mult_10 <- 1 + (jan_ret_10 / 100)

# How much money do you have at the end of January now?
post_jan_cash_10 <- starting_cash * jan_mult_10

# Print post_jan_cash_10
post_jan_cash_10
[1] 220

If, in February, we earn another 2% on your cash, how would we calculate the total amount at the end of February? We already know that the amount at the end of January is $100 * 1.05 = $105. To get from the end of January to the end of February, just use another multiplier!

$105 * 1.02 = $107.1

Which is equivalent to:

$100 * 1.05 * 1.02 = $107.1

In this last form, we see the effect of both multipliers on your original $100. In fact, this form can help you find the total return over both months. The correct way to do this is by multiplying the two multipliers together: 1.05 * 1.02 = 1.071. This means you earned 7.1% in total over the 2 month period.

# Starting cash and returns 
starting_cash <- 200
jan_ret <- 4
feb_ret <- 5

# Multipliers
jan_mult <- 1 + (jan_ret/100)
feb_mult <- 1 + (feb_ret/100)

# Total cash at the end of the two months
total_cash <- starting_cash * jan_mult * feb_mult

# Print total_cash
total_cash
[1] 218.4

2 Vectors and Matrices

2.1 What is a vector?

2.1.1 c()ombine

We create a vector using the combine function, c(), and each element you add is separated by a comma.

# Another numeric vector
ibm_stock <- c(159.82, 160.02, 159.84)

# Another character vector
finance <- c("stocks", "bonds","investments")

# A logical vector
logic <- c(TRUE, FALSE, TRUE)

2.1.2 Coerce it

It is important to remember that a vector can only be composed of one data type. This means that you cannot have both a numeric and a character in the same vector. If you attempt to do this, the lower ranking type will be coerced into the higher ranking type.

For example: c(1.5, “hello”) results in c(“1.5”, “hello”) where the numeric 1.5 has been coerced into the character data type.

The hierarchy for coercion is:

logical < integer < numeric < character

Logicals are coerced a bit differently depending on what the highest data type is. c(TRUE, 1.5) will return c(1, 1.5) where TRUE is coerced to the numeric 1 (FALSE would be converted to a 0). On the other hand, c(TRUE, “this_char”) is converted to c(“TRUE”, “this_char”).

2.1.3 Vector names()

Let’s return to the example about January and February’s returns. We can put these returns into a vector:

ret <- c(5, 2)

Now all of the returns are in one place. However, we could go one step further by adding names to each return in your vector. We do this using names(). Check this out:

names(ret) <- c("Jan", "Feb")
# Vectors of 12 months of returns, and month names
ret <- c(5, 2, 3, 7, 8, 3, 5, 9, 1, 4, 6, 3)
months <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")

# Add names to ret
names(ret) <- months

# Print out ret to see the new names!
ret
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 
  5   2   3   7   8   3   5   9   1   4   6   3 

2.1.4 Visualize your vector

The plot() function is one of the many ways to create a graph from your data in R. Passing in a vector will add its values to the y-axis of the graph, and on the x-axis will be an index created from the order that your vector is in.

Inside of plot(), we can change the type of your graph using type =. The default is “p” for points, but we can also change it to “l” for line.

# Look at the data
apple_stock <- c(109.49, 109.9, 109.11, 109.95, 111.03, 112.12, 113.95, 113.3, 
115.19, 115.19, 115.82, 115.97, 116.64, 116.95, 117.06, 116.29, 
116.52, 117.26, 116.76, 116.73, 115.82)
apple_stock
 [1] 109.49 109.90 109.11 109.95 111.03 112.12 113.95 113.30 115.19 115.19
[11] 115.82 115.97 116.64 116.95 117.06 116.29 116.52 117.26 116.76 116.73
[21] 115.82
# Plot the data points
plot(apple_stock)


# Plot the data as a line graph
plot(apple_stock, type = "l")

2.2 Vector manipulation

2.2.1 Weighted average

The weighted average allows you to calculate your portfolio return over a time period.

Assume you have 40% of your cash in Apple stock, and 60% of your cash in IBM stock. If, in January, Apple earned 5% and IBM earned 7%, what was your total portfolio return?

portf_ret <- apple_ret * apple_weight + ibm_ret * ibm_weight
# Weights and returns
micr_ret <- 7
sony_ret <- 9
micr_weight <- .2
sony_weight <- .8

# Portfolio return
portf_ret <- micr_ret * micr_weight + sony_ret * sony_weight

We can use vectors

# Weights, returns, and company names
ret <- c(7, 9)
weight <- c(.2, .8)
companies <- c("Microsoft", "Sony")

# Assign company names to your vectors
names(ret) <- companies
names(weight) <- companies

# Multiply the returns and weights together 
ret_X_weight <- ret * weight

# Print ret_X_weight
ret_X_weight
Microsoft      Sony 
      1.4       7.2 
# Sum to get the total portfolio return
portf_ret <- sum(ret_X_weight)

# Print portf_ret
portf_ret
[1] 8.6

Vectors of different lengths can also be used to multiply

ret = c(Microsoft = 7, Apple = 8, Sony = 9)
# Print ret
ret
Microsoft     Apple      Sony 
        7         8         9 
# Assign 1/3 to weight
weight <- 1/3

# Create ret_X_weight
ret_X_weight <- ret * weight

# Calculate your portfolio return
portf_ret <- sum(ret_X_weight)

# Vector of length 3 * Vector of length 2?
ret * c(.2, .6)
longer object length is not a multiple of shorter object length
Microsoft     Apple      Sony 
      1.4       4.8       1.8 

Look at the warning message

2.2.2 Vector subsetting

Sometimes, we will only want to use specific pieces of your vectors, and you’ll need some way to access just those parts. To solve this, you can subset the vector using [ ].

Ret <- c(Jan = 5, Feb = 2, Mar = 3, Apr = 7, May = 8, Jun = 3, Jul = 5, 
Aug = 9, Sep = 1, Oct = 4, Nov = 6, Dec = 3)
# First 6 months of returns
ret[1:6]
Microsoft     Apple      Sony      <NA>      <NA>      <NA> 
        7         8         9        NA        NA        NA 
# Just March and May
ret[c("Mar", "May")]
<NA> <NA> 
  NA   NA 
# Omit the first month of returns
ret[-1]
Apple  Sony 
    8     9 

2.3 Matrix - a 2D vector

2.3.1 Creating a matrix

Matrices are similar to vectors, except they are in 2 dimensions! Let’s create a 2x2 matrix “by hand” using matrix().

matrix(data = c(2, 3, 4, 5), nrow = 2, ncol = 2)
     [,1] [,2]
[1,]    2    4
[2,]    3    5

Notice that the actual data for the matrix is passed in as a vector using c(), and is then converted to a matrix by specifying the number of rows and columns (also known as the dimensions).

# A vector of 9 numbers
my_vector <- c(1, 2, 3, 4, 5, 6, 7, 8, 9)

# 3x3 matrix
my_matrix <- matrix(data = my_vector, nrow = 3, ncol = 3)

# Print my_matrix
my_matrix
     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
# Filling across using byrow = TRUE
matrix(data = c(2, 3, 4, 5), nrow = 2, ncol = 2, byrow = TRUE)
     [,1] [,2]
[1,]    2    3
[2,]    4    5

2.3.2 Matrix <- bind vectors

Often, you won’t be creating vectors like we did in the last example. Instead, you will create them from multiple vectors that you want to combine together. For this, it is easiest to use the functions cbind() and rbind() (column bind and row bind respectively). To see these in action, let’s combine two vectors of Apple and IBM stock prices:

apple <- c(109.49, 109.90, 109.11, 109.95, 111.03)
ibm <- c(159.82, 160.02, 159.84, 160.35, 164.79)

cbind(apple, ibm)
      apple    ibm
[1,] 109.49 159.82
[2,] 109.90 160.02
[3,] 109.11 159.84
[4,] 109.95 160.35
[5,] 111.03 164.79
rbind(apple, ibm)
        [,1]   [,2]   [,3]   [,4]   [,5]
apple 109.49 109.90 109.11 109.95 111.03
ibm   159.82 160.02 159.84 160.35 164.79

The functions cbind() and rbind() are pretty common. They also work with data frames.

2.3.3 Visualize your matrix

We can visualize our matrix to gain some insights about the relationships in the data.

apple_micr_matrix <-  cbind(apple, ibm)
# View the data
apple_micr_matrix
      apple    ibm
[1,] 109.49 159.82
[2,] 109.90 160.02
[3,] 109.11 159.84
[4,] 109.95 160.35
[5,] 111.03 164.79
# Scatter plot of Microsoft vs Apple
plot(apple_micr_matrix)

2.3.4 cor()relation

It seems that when Apple’s stock moves up, Microsoft’s does as well. One way to capture this kind of relationship is by finding the correlation between the two stocks. Correlation is a measure of association between two things, here, stock prices, and is represented by a number from -1 to 1. A 1 represents perfect positive correlation, a -1 represents perfect negative correlation, and 0 correlation means that the stocks move independently of each other.

The cor() function will calculate the correlation between two vectors, or will create a correlation matrix when given a matrix.

cor(apple, ibm)
[1] 0.9131575
cor(apple_micr_matrix)
          apple       ibm
apple 1.0000000 0.9131575
ibm   0.9131575 1.0000000

A large correlation of .913 hints that Apple and IBM’s stock prices move closely together.

2.3.5 Matrix subsetting

Matrices can be selected from and subsetted with [ ]. The basic structure is:

my_matrix[row, col]
apple <- c(109.49, 109.90, 109.11, 109.95, 111.03)
ibm <- c(159.82, 160.02, 159.84, 160.35, 164.79)
stocks <- cbind(apple, ibm)
# Third row
stocks[3,]
 apple    ibm 
109.11 159.84 
# Fourth and fifth row of the ibm column
stocks[4:5, 2]
[1] 160.35 164.79
# ibm columns
stocks[, 2]
[1] 159.82 160.02 159.84 160.35 164.79

3 Data Frames

3.1 What is a data frame?

3.1.1 Create a data frame

Data frames are great because of their ability to hold a different type of data in each column. To get started, let’s use the data.frame() function to create a data frame of your business’s future cash flows. Here are the variables that will be in the data frame: company - The company that is paying you the cash flow (A or B). cash_flow - The amount of money a company will receive. year - The number of years from now that you receive the cash flow.

# Variables
company <- c("A", "A", "A", "B", "B", "B", "B")
cash_flow <- c(1000, 4000, 550, 1500, 1100, 750, 6000)
year <- c(1, 3, 4, 1, 2, 4, 5)

# Data frame
cash <- data.frame(company, cash_flow, year)

# Print cash
cash

3.2 Making head()s and tail()s of your data with some str()ucture

Time to introduce a few simple, but very useful functions.

  • head() - Returns the first few rows of a data frame. By default, 6. To change this, use head(cash, n = ___)
  • tail() - Returns the last few rows of a data frame. By default, 6. To change this, use tail(cash, n = ___)
  • str() - Check the structure of an object. This fantastic function will show you the data type of the object you pass in (here, data.frame), and will list each column variable along with its data type.
# Call head() for the first 4 rows
head(cash, 4)

# Call tail() for the last 3 rows
tail(cash, 3)

# Call str()
str(cash)
'data.frame':   7 obs. of  3 variables:
 $ company  : chr  "A" "A" "A" "B" ...
 $ cash_flow: num  1000 4000 550 1500 1100 750 6000
 $ year     : num  1 3 4 1 2 4 5

3.2.1 Naming your columns / rows

We can change the columns names colnames() and the row names using rownames(), but this is less common.

# Fix your column names
colnames(cash) <- c("company", "cash_flow", "year")

# Print out the column names of cash
colnames(cash)
[1] "company"   "cash_flow" "year"     

3.3 Data frame manipulation

3.3.1 Accessing and subsetting data frames

One of the ways to do this is to use [ ]. The notation is just like matrices

# Third row, second column
cash[3, 2]
[1] 550
# Fifth row of the "year" column
cash[5, "year"]
[1] 2

As you might imagine, selecting a specific column from a data frame is a common manipulation. So common, in fact, that it was given its own shortcut, the $.

# Select the year column
cash$year
[1] 1 3 4 1 2 4 5
# Select the cash_flow column and multiply by 2
cash$cash_flow * 2
[1]  2000  8000  1100  3000  2200  1500 12000
# Delete the company column
cash$company <- NULL

# Print cash again
cash

What if you are only interested in the cash flows from company A? For more flexibility, try subset()

subset(cash, company == "A")

There are a few important things happening here:

  • The first argument you pass to subset() is the name of your data frame, cash.Notice that you shouldn’t put company in quotes.
  • The == is the equality operator. It tests to find where two things are equal, and returns a logical vector.
# Rows about company B
subset(cash, company == "B")

# Rows with cash flows due in 1 year

subset(cash, year == 1)

3.3.2 Adding new columns

Creating new columns in your data frame is as simple as assigning the new information to data_frame$new_column. Often, the newly created column is some transformation of existing columns, so the $ operator really comes in handy here.

# Quarter cash flow scenario
cash$quarter_cash <- cash$cash_flow * .25

# Double year scenario
cash$double_year <- cash$year * 2

3.4 Present value

3.4.1 Present value of projected cash flows

If you expect a cash flow of $100 to be received 1 year from now, what is the present value of that cash flow at a 5% interest rate? To calculate this, you discount the cash flow to get it in terms of today’s dollars. The general formula for this is:

present_value <- cash_flow * (1 + interest / 100) ^ -year
95.238 = 100 * (1.05) ^ -1
# Present value of $4000, in 3 years, at 5%
present_value_4k <- 4000 * (1.05)^-3

# Present value of all cash flows
cash$present_value <- cash$cash_flow * (1.05)^-cash$year

# Print out cash
cash

We now have a column for present_value, but we want to report the total amount of that column to your board members. Calculating this part is easy, use the sum() function you learned earlier to add up the elements of cash$present_value.

However, we also want to know how much company A and company B individually contribute to the total present value.

# Total present value of cash
total_pv <- sum(cash$present_value)

# Company B information
cash_B <- subset(cash, company == "B")

# Total present value of cash_B
total_pv_B <- sum(cash_B$present_value)

4 Factor

4.1 What is a factor?

4.1.1 Create a factor

Bond credit ratings are common in the fixed income side of the finance world as a simple measure of how “risky” a certain bond might be. Here, riskiness can be defined as the probability of default, which means an inability to pay back your debts. The Standard and Poor’s and Fitch credit rating agency has defined the following ratings, from least likely to default to most likely: AAA, AA, A, BBB, BB, B, CCC, CC, C, D This is a perfect example of a factor! It is a categorical variable that takes on a limited number of levels.

To create a factor in R, use the factor() function, and pass in a vector that you want to be converted into a factor.

# credit_rating character vector
credit_rating <- c("BB", "AAA", "AA", "CCC", "AA", "AAA", "B", "BB")

# Create a factor from credit_rating
credit_factor <- factor(credit_rating)

# Print out your new factor
credit_factor
[1] BB  AAA AA  CCC AA  AAA B   BB 
Levels: AA AAA B BB CCC
# Call str() on credit_rating
str(credit_rating)
 chr [1:8] "BB" "AAA" "AA" "CCC" "AA" "AAA" "B" "BB"
# Call str() on credit_factor
str(credit_factor)
 Factor w/ 5 levels "AA","AAA","B",..: 4 2 1 5 1 2 3 4

4.1.2 Factor levels

Accessing the unique levels of your factor is simple enough by using the levels() function. You can also use this to rename your factor levels

# Identify unique levels
levels(credit_factor)
[1] "AA"  "AAA" "B"   "BB"  "CCC"
# Rename the levels of credit_factor
levels(credit_factor)  <- c("2A", "3A", "1B", "2B", "3C")

# Print credit_factor
credit_factor
[1] 2B 3A 2A 3C 2A 3A 1B 2B
Levels: 2A 3A 1B 2B 3C

4.1.3 Factor summary

As any good bond investor would do, you would like to keep track of how many bonds you are holding of each credit rating. A way to present a table of the counts of each bond credit rating would be great! Luckily for you, the summary() function for factors can help you with that.

# Summarize the character vector, credit_rating
summary(credit_rating)
   Length     Class      Mode 
        8 character character 
# Summarize the factor, credit_factor
summary(credit_factor)
2A 3A 1B 2B 3C 
 2  2  1  2  1 

4.1.4 Visualize your factor

We can also visualize the table that you created in the last example by using a bar chart. A bar chart is a type of graph that displays groups of data using rectangular bars where the height of each bar represents the number of counts in that group.

The plot() function can again take care of all of the magic for us. We are creating the plot from a factor and not a character vector. R will throw an error if you try and plot a character vector!

# Visualize your factor!
plot(credit_factor)

4.1.5 Bucketing a numeric variable into a factor

Your old friend Dan sent you a list of 50 AAA rated bonds called AAA_rank, with each bond having an additional number from 1-100 describing how profitable he thinks that bond will be (100 being the most profitable). You are interested in doing further analysis on his suggestions, but first it would be nice if the bonds were bucketed by their ranking somehow. This would help you create groups of bonds, from least profitable to most profitable, to more easily analyze them.

AAA_rank <- c(31L, 48L, 100L, 53L, 85L, 73L, 62L, 74L, 42L, 38L, 97L, 61L, 
48L, 86L, 44L, 9L, 43L, 18L, 62L, 38L, 23L, 37L, 54L, 80L, 78L, 
93L, 47L, 100L, 22L, 22L, 18L, 26L, 81L, 17L, 98L, 4L, 83L, 5L, 
6L, 52L, 29L, 44L, 50L, 2L, 25L, 19L, 15L, 42L, 30L, 27L)

This is a great example of creating a factor from a numeric vector. The easiest way to do this is to use cut().

Note that the ( in the factor levels means we do not include the number beside it in that group, and the ] means that we do include that number in the group.

In the cut() function, using breaks = allows you to specify the groups that you want R to bucket your data by!

# Create 4 buckets for AAA_rank using cut()
AAA_factor <- cut(x = AAA_rank, breaks = c(0, 25, 50, 75, 100))

# Rename the levels 
levels(AAA_factor) <- c("low", "medium", "high", "very_high")

# Print AAA_factor
AAA_factor
 [1] medium    medium    very_high high      very_high high      high     
 [8] high      medium    medium    very_high high      medium    very_high
[15] medium    low       medium    low       high      medium    low      
[22] medium    high      very_high very_high very_high medium    very_high
[29] low       low       low       medium    very_high low       very_high
[36] low       very_high low       low       high      medium    medium   
[43] medium    low       low       low       low       medium    medium   
[50] medium   
Levels: low medium high very_high
# Plot AAA_factor
plot(AAA_factor)

4.2 Ordering and subsetting factors

4.2.1 Create an ordered factor

To order your factor, there are two options.

When creating a factor, specify ordered = TRUE and add unique levels in order from least to greatest:

credit_rating <- c("AAA", "AA", "A", "BBB", "AA", "BBB", "A")

credit_factor_ordered <- factor(credit_rating, ordered = TRUE, 
                                levels = c("AAA", "AA", "A", "BBB"))

For an existing unordered factor like credit_factor, use the ordered() function:

ordered(credit_factor, levels = c("AAA", "AA", "A", "BBB"))
[1] <NA> <NA> <NA> <NA> <NA> <NA> <NA> <NA>
Levels: AAA < AA < A < BBB
credit_factor_ordered
[1] AAA AA  A   BBB AA  BBB A  
Levels: AAA < AA < A < BBB

Notice the < specifying the order of the levels.

# Use unique() to find unique words
unique(credit_rating)
[1] "AAA" "AA"  "A"   "BBB"
# Create an ordered factor
credit_factor_ordered <- factor(credit_rating, ordered = TRUE, levels = c("CCC", "B", "BB", "AA", "AAA"))

# Plot credit_factor_ordered
plot(credit_factor_ordered)

Ordered factors are great for plotting or creating tables with a predefined order.

4.2.2 Subsetting a factor

You can subset factors in a similar way that you subset vectors. As usual, [ ] is the key! Also, you can add drop = TRUE so the levels are updated in line with your new vector.

# Remove the A bonds at positions 3 and 7. Don't drop the A level.
keep_level <- credit_factor_ordered[c(-3, -7)]

# Plot keep_level
plot(keep_level)


# Remove the A bonds at positions 3 and 7. Drop the A level.
drop_level <- keep_level <- credit_factor_ordered[c(-3, -7), drop = TRUE]

# Plot drop_level
plot(keep_level)

The drop argument will help you get rid of those pesky factor levels that stick around.

4.2.3 stringsAsFactors

R’s default behavior when creating data frames is to convert all characters into factors. This has caused countless novice R users a headache trying to figure out why their character columns are not working properly

To turn off this behavior:

cash <- data.frame(company, cash_flow, year, stringsAsFactors = FALSE)

str(cash)
'data.frame':   7 obs. of  3 variables:
 $ company  : chr  "A" "A" "A" "B" ...
 $ cash_flow: num  1000 4000 550 1500 1100 750 6000
 $ year     : num  1 3 4 1 2 4 5
# Variables
credit_rating <- c("AAA", "A", "BB")
bond_owners <- c("Dan", "Tom", "Joe")

# Create the data frame of character vectors, bonds
bonds <- data.frame(credit_rating, bond_owners, stringsAsFactors = FALSE)

# Use str() on bonds
str(bonds)
'data.frame':   3 obs. of  2 variables:
 $ credit_rating: chr  "AAA" "A" "BB"
 $ bond_owners  : chr  "Dan" "Tom" "Joe"
# Create a factor column in bonds called credit_factor from credit_rating
bonds$credit_factor <- factor(bonds$credit_rating, ordered = TRUE, levels = c("BB", "A", "AAA"))

# Use str() on bonds again
str(bonds)
'data.frame':   3 obs. of  3 variables:
 $ credit_rating: chr  "AAA" "A" "BB"
 $ bond_owners  : chr  "Dan" "Tom" "Joe"
 $ credit_factor: Ord.factor w/ 3 levels "BB"<"A"<"AAA": 3 2 1

5 Lists

5.1 What is a list?

5.1.1 Create a list

Lists in R can be used to hold together items of different data types. Creating a list is as simple as using the list() function.

# List components
name <- "Apple and IBM"
apple <- c(109.49, 109.90, 109.11, 109.95, 111.03)
ibm <- c(159.82, 160.02, 159.84, 160.35, 164.79)
cor_matrix <- cor(cbind(apple, ibm))

# Create a list
portfolio <- list(name, apple, ibm, cor_matrix)

# View your first list
portfolio
[[1]]
[1] "Apple and IBM"

[[2]]
[1] 109.49 109.90 109.11 109.95 111.03

[[3]]
[1] 159.82 160.02 159.84 160.35 164.79

[[4]]
          apple       ibm
apple 1.0000000 0.9131575
ibm   0.9131575 1.0000000

5.1.2 Named lists

You could name the elements as you create the list with the form name = value. Or, if the list was already created, you could use names().

# Add names to your portfolio
names(portfolio) <- c("portfolio_name", "apple", "ibm", "correlation")

# Print portfolio
portfolio
$portfolio_name
[1] "Apple and IBM"

$apple
[1] 109.49 109.90 109.11 109.95 111.03

$ibm
[1] 159.82 160.02 159.84 160.35 164.79

$correlation
          apple       ibm
apple 1.0000000 0.9131575
ibm   0.9131575 1.0000000

5.1.3 Access elements in a list

Subsetting a list is similar to subsetting a vector or data frame, with one extra useful operation.

To access the elements in the list, use [ ]. This will always return another list.

To pull out the data inside each element of your list, use [[ ]].

# Second and third elements of portfolio
portfolio[c(2,3)]
$apple
[1] 109.49 109.90 109.11 109.95 111.03

$ibm
[1] 159.82 160.02 159.84 160.35 164.79
# Use $ to get the correlation data
portfolio$correlation
          apple       ibm
apple 1.0000000 0.9131575
ibm   0.9131575 1.0000000

5.1.4 Adding to a list

We can add new elements to it. You can do so using $. We could have also used c() to add another element to the list: c(my_list, dans_movie = “StaR Wars”). This can be useful if we want to add multiple elements to your list at once.

# Add weight: 20% Apple, 80% IBM
portfolio$weight <- c(apple = 0.2, ibm = 0.8)

# Print portfolio
portfolio
$portfolio_name
[1] "Apple and IBM"

$apple
[1] 109.49 109.90 109.11 109.95 111.03

$ibm
[1] 159.82 160.02 159.84 160.35 164.79

$correlation
          apple       ibm
apple 1.0000000 0.9131575
ibm   0.9131575 1.0000000

$weight
apple   ibm 
  0.2   0.8 
# Change the weight variable: 30% Apple, 70% IBM
portfolio$weight <- c(apple = 0.3, ibm = 0.7)

# Print portfolio to see the changes
portfolio
$portfolio_name
[1] "Apple and IBM"

$apple
[1] 109.49 109.90 109.11 109.95 111.03

$ibm
[1] 159.82 160.02 159.84 160.35 164.79

$correlation
          apple       ibm
apple 1.0000000 0.9131575
ibm   0.9131575 1.0000000

$weight
apple   ibm 
  0.3   0.7 

5.1.5 Removing from a list

Using NULL is the easiest way to remove an element from your list. We can also remove elements by position using my_list[1] <- NULL or my_list[[1]] <- NULL.

# Take a look at portfolio
portfolio
$portfolio_name
[1] "Apple and IBM"

$apple
[1] 109.49 109.90 109.11 109.95 111.03

$ibm
[1] 159.82 160.02 159.84 160.35 164.79

$correlation
          apple       ibm
apple 1.0000000 0.9131575
ibm   0.9131575 1.0000000

$weight
apple   ibm 
  0.3   0.7 
# Remove the microsoft stock prices from your portfolio
portfolio$microsoft <- NULL

5.2 A few list creating functions

5.2.1 Split it

Often, you will have data for multiple groups together in one data frame.

We can create a grouping to split on, and use split() to create a list of two data frames.

grouping <- cash$company
split_cash <- split(cash, grouping)

split_cash 
$A

$B
NA

To get your original data frame back, use:

unsplit(split_cash, grouping)
# Define grouping from year
grouping <- cash$year

# Split cash on your new grouping
split_cash <- split(cash, grouping)

# Look at your split_cash list
split_cash
$`1`

$`2`

$`3`

$`4`

$`5`
# Unsplit split_cash to get the original data back.
original_cash <- unsplit(split_cash, grouping)

# Print original_cash
original_cash

5.2.2 Split-Apply-Combine

A common data science problem is to split your data frame by a grouping, apply some transformation to each group, and then recombine those pieces back into one data frame. This is such a common class of problems in R that it has been given the name split-apply-combine.

Suppose, for the cash data frame, you are interested in doubling the cash_flow for company A, and tripling it for company B:

grouping <- cash$company
split_cash <- split(cash, grouping)

# We can access each list element's cash_flow column by:
split_cash$A$cash_flow
[1] 1000 4000  550
split_cash$A$cash_flow <- split_cash$A$cash_flow * 2
split_cash$B$cash_flow <- split_cash$B$cash_flow * 3

new_cash <- unsplit(split_cash, grouping)
new_cash
# Print the cash_flow column of B in split_cash
split_cash$B$cash_flow
[1]  4500  3300  2250 18000
# Set the cash_flow column of company A in split_cash to 0
split_cash$A$cash_flow <- 0

# Use the grouping to unsplit split_cash
cash_no_A <- unsplit(split_cash, grouping)

# Print cash_no_A
cash_no_A

5.2.3 Attributes

Attributes are a bit of extra metadata about your data structure. Some of the most common attributes are: row names and column names, dimensions, and class. You can use the attributes() function to return a list of attributes about the object you pass in. To access a specific attribute, you can use the attr() function.

# my_matrix and my_factor
my_matrix <- matrix(c(1,2,3,4,5,6), nrow = 2, ncol = 3)
rownames(my_matrix) <- c("Row1", "Row2")
colnames(my_matrix) <- c("Col1", "Col2", "Col3")

my_factor <- factor(c("A", "A", "B"), ordered = T, levels = c("A", "B"))

# attributes of my_matrix
attributes(my_matrix)
$dim
[1] 2 3

$dimnames
$dimnames[[1]]
[1] "Row1" "Row2"

$dimnames[[2]]
[1] "Col1" "Col2" "Col3"
# Just the dim attribute of my_matrix
attr(my_matrix, which = "dim")
[1] 2 3
# attributes of my_factor
attributes(my_factor)
$levels
[1] "A" "B"

$class
[1] "ordered" "factor" 
LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFIgZm9yIEZpbmFuY2UiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19jb2xsYXBzZWQ6IGZhbHNlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIAp0b2NfZGVwdGg6IDMKLS0tCgojIEJhc2ljcwoKIyMgRmluYW5jaWFsIHJldHVybnMKCkFzc3VtZSB3ZSBoYXZlIFwkMTAwLiBEdXJpbmcgSmFudWFyeSwgeW91IG1ha2UgYSA1JSByZXR1cm4gb24gdGhhdCBtb25leS4gSG93IG11Y2ggZG8geW91IGhhdmUgYXQgdGhlIGVuZCBvZiBKYW51YXJ5PyBXZWxsLCB3ZSBoYXZlIDEwMCUgb2YgeW91ciBzdGFydGluZyBtb25leSwgcGx1cyBhbm90aGVyIDUlOiAxMDAlICsgNSUgPSAxMDUlLiBJbiBkZWNpbWFscywgdGhpcyBpcyAxICsgLjA1ID0gMS4wNS4gVGhpcyAxLjA1IGlzIHRoZSByZXR1cm4gbXVsdGlwbGllciBmb3IgSmFudWFyeSwgYW5kIHlvdSBtdWx0aXBseSB5b3VyIG9yaWdpbmFsIFwkMTAwIGJ5IGl0IHRvIGdldCB0aGUgYW1vdW50IHlvdSBoYXZlIGF0IHRoZSBlbmQgb2YgSmFudWFyeS4KCiAgICAxMDUgPSAxMDAgKiAxLjA1CgpPciBpbiB0ZXJtcyBvZiB2YXJpYWJsZXM6CgogICAgcG9zdF9qYW5fY2FzaCA8LSBzdGFydGluZ19jYXNoICogamFuX3JldAoKQSBxdWljayB3YXkgdG8gZ2V0IHRoZSBtdWx0aXBsaWVyIGlzOgoKICAgIG11bHRpcGxpZXIgPSAxICsgKHJldHVybiAvIDEwMCkKCmBgYHtyfQojIFZhcmlhYmxlcyBmb3Igc3RhcnRpbmdfY2FzaCBhbmQgNSUgcmV0dXJuIGR1cmluZyBKYW51YXJ5CnN0YXJ0aW5nX2Nhc2ggPC0gMjAwCmphbl9yZXQgPC0gNQpqYW5fbXVsdCA8LSAxICsgKGphbl9yZXQgLyAxMDApCgojIEhvdyBtdWNoIG1vbmV5IGRvIHlvdSBoYXZlIGF0IHRoZSBlbmQgb2YgSmFudWFyeT8KcG9zdF9qYW5fY2FzaCA8LSBzdGFydGluZ19jYXNoICogamFuX211bHQKCiMgUHJpbnQgcG9zdF9qYW5fY2FzaApwb3N0X2phbl9jYXNoCgojIEphbnVhcnkgMTAlIHJldHVybiBtdWx0aXBsaWVyCmphbl9yZXRfMTAgPC0gMTAKamFuX211bHRfMTAgPC0gMSArIChqYW5fcmV0XzEwIC8gMTAwKQoKIyBIb3cgbXVjaCBtb25leSBkbyB5b3UgaGF2ZSBhdCB0aGUgZW5kIG9mIEphbnVhcnkgbm93Pwpwb3N0X2phbl9jYXNoXzEwIDwtIHN0YXJ0aW5nX2Nhc2ggKiBqYW5fbXVsdF8xMAoKIyBQcmludCBwb3N0X2phbl9jYXNoXzEwCnBvc3RfamFuX2Nhc2hfMTAKYGBgCklmLCBpbiBGZWJydWFyeSwgd2UgZWFybiBhbm90aGVyIDIlIG9uIHlvdXIgY2FzaCwgaG93IHdvdWxkIHdlIGNhbGN1bGF0ZSB0aGUgdG90YWwgYW1vdW50IGF0IHRoZSBlbmQgb2YgRmVicnVhcnk/IFdlIGFscmVhZHkga25vdyB0aGF0IHRoZSBhbW91bnQgYXQgdGhlIGVuZCBvZiBKYW51YXJ5IGlzIFwkMTAwICogMS4wNSA9IFwkMTA1LiBUbyBnZXQgZnJvbSB0aGUgZW5kIG9mIEphbnVhcnkgdG8gdGhlIGVuZCBvZiBGZWJydWFyeSwganVzdCB1c2UgYW5vdGhlciBtdWx0aXBsaWVyIQoKICAgICQxMDUgKiAxLjAyID0gJDEwNy4xCgpXaGljaCBpcyBlcXVpdmFsZW50IHRvOgoKICAgICQxMDAgKiAxLjA1ICogMS4wMiA9ICQxMDcuMQoKSW4gdGhpcyBsYXN0IGZvcm0sIHdlIHNlZSB0aGUgZWZmZWN0IG9mIGJvdGggbXVsdGlwbGllcnMgb24geW91ciBvcmlnaW5hbCAkMTAwLiBJbiBmYWN0LCB0aGlzIGZvcm0gY2FuIGhlbHAgeW91IGZpbmQgdGhlIHRvdGFsIHJldHVybiBvdmVyIGJvdGggbW9udGhzLiBUaGUgY29ycmVjdCB3YXkgdG8gZG8gdGhpcyBpcyBieSBtdWx0aXBseWluZyB0aGUgdHdvIG11bHRpcGxpZXJzIHRvZ2V0aGVyOiAxLjA1ICogMS4wMiA9IDEuMDcxLiBUaGlzIG1lYW5zIHlvdSBlYXJuZWQgNy4xJSBpbiB0b3RhbCBvdmVyIHRoZSAyIG1vbnRoIHBlcmlvZC4KCmBgYHtyfQojIFN0YXJ0aW5nIGNhc2ggYW5kIHJldHVybnMgCnN0YXJ0aW5nX2Nhc2ggPC0gMjAwCmphbl9yZXQgPC0gNApmZWJfcmV0IDwtIDUKCiMgTXVsdGlwbGllcnMKamFuX211bHQgPC0gMSArIChqYW5fcmV0LzEwMCkKZmViX211bHQgPC0gMSArIChmZWJfcmV0LzEwMCkKCiMgVG90YWwgY2FzaCBhdCB0aGUgZW5kIG9mIHRoZSB0d28gbW9udGhzCnRvdGFsX2Nhc2ggPC0gc3RhcnRpbmdfY2FzaCAqIGphbl9tdWx0ICogZmViX211bHQKCiMgUHJpbnQgdG90YWxfY2FzaAp0b3RhbF9jYXNoCmBgYAojIFZlY3RvcnMgYW5kIE1hdHJpY2VzCgojIyBXaGF0IGlzIGEgdmVjdG9yPwoKIyMjIGMoKW9tYmluZQoKV2UgY3JlYXRlIGEgdmVjdG9yIHVzaW5nIHRoZSBjb21iaW5lIGZ1bmN0aW9uLCBjKCksIGFuZCBlYWNoIGVsZW1lbnQgeW91IGFkZCBpcyBzZXBhcmF0ZWQgYnkgYSBjb21tYS4KYGBge3J9CiMgQW5vdGhlciBudW1lcmljIHZlY3RvcgppYm1fc3RvY2sgPC0gYygxNTkuODIsIDE2MC4wMiwgMTU5Ljg0KQoKIyBBbm90aGVyIGNoYXJhY3RlciB2ZWN0b3IKZmluYW5jZSA8LSBjKCJzdG9ja3MiLCAiYm9uZHMiLCJpbnZlc3RtZW50cyIpCgojIEEgbG9naWNhbCB2ZWN0b3IKbG9naWMgPC0gYyhUUlVFLCBGQUxTRSwgVFJVRSkKYGBgCiMjIyBDb2VyY2UgaXQKCkl0IGlzIGltcG9ydGFudCB0byByZW1lbWJlciB0aGF0IGEgdmVjdG9yIGNhbiBvbmx5IGJlIGNvbXBvc2VkIG9mIG9uZSBkYXRhIHR5cGUuIFRoaXMgbWVhbnMgdGhhdCB5b3UgY2Fubm90IGhhdmUgYm90aCBhIG51bWVyaWMgYW5kIGEgY2hhcmFjdGVyIGluIHRoZSBzYW1lIHZlY3Rvci4gSWYgeW91IGF0dGVtcHQgdG8gZG8gdGhpcywgdGhlIGxvd2VyIHJhbmtpbmcgdHlwZSB3aWxsIGJlIGNvZXJjZWQgaW50byB0aGUgaGlnaGVyIHJhbmtpbmcgdHlwZS4KCkZvciBleGFtcGxlOiBjKDEuNSwgImhlbGxvIikgcmVzdWx0cyBpbiBjKCIxLjUiLCAiaGVsbG8iKSB3aGVyZSB0aGUgbnVtZXJpYyAxLjUgaGFzIGJlZW4gY29lcmNlZCBpbnRvIHRoZSBjaGFyYWN0ZXIgZGF0YSB0eXBlLgoKVGhlIGhpZXJhcmNoeSBmb3IgY29lcmNpb24gaXM6CgogICAgbG9naWNhbCA8IGludGVnZXIgPCBudW1lcmljIDwgY2hhcmFjdGVyCgpMb2dpY2FscyBhcmUgY29lcmNlZCBhIGJpdCBkaWZmZXJlbnRseSBkZXBlbmRpbmcgb24gd2hhdCB0aGUgaGlnaGVzdCBkYXRhIHR5cGUgaXMuIGMoVFJVRSwgMS41KSB3aWxsIHJldHVybiBjKDEsIDEuNSkgd2hlcmUgVFJVRSBpcyBjb2VyY2VkIHRvIHRoZSBudW1lcmljIDEgKEZBTFNFIHdvdWxkIGJlIGNvbnZlcnRlZCB0byBhIDApLiBPbiB0aGUgb3RoZXIgaGFuZCwgYyhUUlVFLCAidGhpc19jaGFyIikgaXMgY29udmVydGVkIHRvIGMoIlRSVUUiLCAidGhpc19jaGFyIikuCgojIyMgVmVjdG9yIG5hbWVzKCkKCkxldCdzIHJldHVybiB0byB0aGUgZXhhbXBsZSBhYm91dCBKYW51YXJ5IGFuZCBGZWJydWFyeSdzIHJldHVybnMuIFdlIGNhbiBwdXQgdGhlc2UgcmV0dXJucyBpbnRvIGEgdmVjdG9yOgoKICAgIHJldCA8LSBjKDUsIDIpCgpOb3cgYWxsIG9mIHRoZSByZXR1cm5zIGFyZSBpbiBvbmUgcGxhY2UuIEhvd2V2ZXIsIHdlIGNvdWxkIGdvIG9uZSBzdGVwIGZ1cnRoZXIgYnkgYWRkaW5nIG5hbWVzIHRvIGVhY2ggcmV0dXJuIGluIHlvdXIgdmVjdG9yLiBXZSBkbyB0aGlzIHVzaW5nIG5hbWVzKCkuIENoZWNrIHRoaXMgb3V0OgoKICAgIG5hbWVzKHJldCkgPC0gYygiSmFuIiwgIkZlYiIpCgpgYGB7cn0KIyBWZWN0b3JzIG9mIDEyIG1vbnRocyBvZiByZXR1cm5zLCBhbmQgbW9udGggbmFtZXMKcmV0IDwtIGMoNSwgMiwgMywgNywgOCwgMywgNSwgOSwgMSwgNCwgNiwgMykKbW9udGhzIDwtIGMoIkphbiIsICJGZWIiLCAiTWFyIiwgIkFwciIsICJNYXkiLCAiSnVuIiwgIkp1bCIsICJBdWciLCAiU2VwIiwgIk9jdCIsICJOb3YiLCAiRGVjIikKCiMgQWRkIG5hbWVzIHRvIHJldApuYW1lcyhyZXQpIDwtIG1vbnRocwoKIyBQcmludCBvdXQgcmV0IHRvIHNlZSB0aGUgbmV3IG5hbWVzIQpyZXQKYGBgCiMjIyBWaXN1YWxpemUgeW91ciB2ZWN0b3IKClRoZSBwbG90KCkgZnVuY3Rpb24gaXMgb25lIG9mIHRoZSBtYW55IHdheXMgdG8gY3JlYXRlIGEgZ3JhcGggZnJvbSB5b3VyIGRhdGEgaW4gUi4gUGFzc2luZyBpbiBhIHZlY3RvciB3aWxsIGFkZCBpdHMgdmFsdWVzIHRvIHRoZSB5LWF4aXMgb2YgdGhlIGdyYXBoLCBhbmQgb24gdGhlIHgtYXhpcyB3aWxsIGJlIGFuIGluZGV4IGNyZWF0ZWQgZnJvbSB0aGUgb3JkZXIgdGhhdCB5b3VyIHZlY3RvciBpcyBpbi4KCkluc2lkZSBvZiBwbG90KCksIHdlIGNhbiBjaGFuZ2UgdGhlIHR5cGUgb2YgeW91ciBncmFwaCB1c2luZyB0eXBlID0uIFRoZSBkZWZhdWx0IGlzICJwIiBmb3IgcG9pbnRzLCBidXQgd2UgY2FuIGFsc28gY2hhbmdlIGl0IHRvICJsIiBmb3IgbGluZS4KYGBge3J9CiMgTG9vayBhdCB0aGUgZGF0YQphcHBsZV9zdG9jayA8LSBjKDEwOS40OSwgMTA5LjksIDEwOS4xMSwgMTA5Ljk1LCAxMTEuMDMsIDExMi4xMiwgMTEzLjk1LCAxMTMuMywgCjExNS4xOSwgMTE1LjE5LCAxMTUuODIsIDExNS45NywgMTE2LjY0LCAxMTYuOTUsIDExNy4wNiwgMTE2LjI5LCAKMTE2LjUyLCAxMTcuMjYsIDExNi43NiwgMTE2LjczLCAxMTUuODIpCmFwcGxlX3N0b2NrCgojIFBsb3QgdGhlIGRhdGEgcG9pbnRzCnBsb3QoYXBwbGVfc3RvY2spCgojIFBsb3QgdGhlIGRhdGEgYXMgYSBsaW5lIGdyYXBoCnBsb3QoYXBwbGVfc3RvY2ssIHR5cGUgPSAibCIpCmBgYAojIyBWZWN0b3IgbWFuaXB1bGF0aW9uCgojIyMgV2VpZ2h0ZWQgYXZlcmFnZQoKVGhlIHdlaWdodGVkIGF2ZXJhZ2UgYWxsb3dzIHlvdSB0byBjYWxjdWxhdGUgeW91ciBwb3J0Zm9saW8gcmV0dXJuIG92ZXIgYSB0aW1lIHBlcmlvZC4KCkFzc3VtZSB5b3UgaGF2ZSA0MCUgb2YgeW91ciBjYXNoIGluIEFwcGxlIHN0b2NrLCBhbmQgNjAlIG9mIHlvdXIgY2FzaCBpbiBJQk0gc3RvY2suIElmLCBpbiBKYW51YXJ5LCBBcHBsZSBlYXJuZWQgNSUgYW5kIElCTSBlYXJuZWQgNyUsIHdoYXQgd2FzIHlvdXIgdG90YWwgcG9ydGZvbGlvIHJldHVybj8KCiAgICBwb3J0Zl9yZXQgPC0gYXBwbGVfcmV0ICogYXBwbGVfd2VpZ2h0ICsgaWJtX3JldCAqIGlibV93ZWlnaHQKCmBgYHtyfQojIFdlaWdodHMgYW5kIHJldHVybnMKbWljcl9yZXQgPC0gNwpzb255X3JldCA8LSA5Cm1pY3Jfd2VpZ2h0IDwtIC4yCnNvbnlfd2VpZ2h0IDwtIC44CgojIFBvcnRmb2xpbyByZXR1cm4KcG9ydGZfcmV0IDwtIG1pY3JfcmV0ICogbWljcl93ZWlnaHQgKyBzb255X3JldCAqIHNvbnlfd2VpZ2h0CmBgYApXZSBjYW4gdXNlIHZlY3RvcnMKYGBge3J9CiMgV2VpZ2h0cywgcmV0dXJucywgYW5kIGNvbXBhbnkgbmFtZXMKcmV0IDwtIGMoNywgOSkKd2VpZ2h0IDwtIGMoLjIsIC44KQpjb21wYW5pZXMgPC0gYygiTWljcm9zb2Z0IiwgIlNvbnkiKQoKIyBBc3NpZ24gY29tcGFueSBuYW1lcyB0byB5b3VyIHZlY3RvcnMKbmFtZXMocmV0KSA8LSBjb21wYW5pZXMKbmFtZXMod2VpZ2h0KSA8LSBjb21wYW5pZXMKCiMgTXVsdGlwbHkgdGhlIHJldHVybnMgYW5kIHdlaWdodHMgdG9nZXRoZXIgCnJldF9YX3dlaWdodCA8LSByZXQgKiB3ZWlnaHQKCiMgUHJpbnQgcmV0X1hfd2VpZ2h0CnJldF9YX3dlaWdodAoKIyBTdW0gdG8gZ2V0IHRoZSB0b3RhbCBwb3J0Zm9saW8gcmV0dXJuCnBvcnRmX3JldCA8LSBzdW0ocmV0X1hfd2VpZ2h0KQoKIyBQcmludCBwb3J0Zl9yZXQKcG9ydGZfcmV0CmBgYApWZWN0b3JzIG9mIGRpZmZlcmVudCBsZW5ndGhzIGNhbiBhbHNvIGJlIHVzZWQgdG8gbXVsdGlwbHkKYGBge3J9CnJldCA9IGMoTWljcm9zb2Z0ID0gNywgQXBwbGUgPSA4LCBTb255ID0gOSkKIyBQcmludCByZXQKcmV0CgojIEFzc2lnbiAxLzMgdG8gd2VpZ2h0CndlaWdodCA8LSAxLzMKCiMgQ3JlYXRlIHJldF9YX3dlaWdodApyZXRfWF93ZWlnaHQgPC0gcmV0ICogd2VpZ2h0CgojIENhbGN1bGF0ZSB5b3VyIHBvcnRmb2xpbyByZXR1cm4KcG9ydGZfcmV0IDwtIHN1bShyZXRfWF93ZWlnaHQpCgojIFZlY3RvciBvZiBsZW5ndGggMyAqIFZlY3RvciBvZiBsZW5ndGggMj8KcmV0ICogYyguMiwgLjYpCmBgYApMb29rIGF0IHRoZSB3YXJuaW5nIG1lc3NhZ2UKCiMjIyBWZWN0b3Igc3Vic2V0dGluZwoKU29tZXRpbWVzLCB3ZSB3aWxsIG9ubHkgd2FudCB0byB1c2Ugc3BlY2lmaWMgcGllY2VzIG9mIHlvdXIgdmVjdG9ycywgYW5kIHlvdSdsbCBuZWVkIHNvbWUgd2F5IHRvIGFjY2VzcyBqdXN0IHRob3NlIHBhcnRzLiBUbyBzb2x2ZSB0aGlzLCB5b3UgY2FuIHN1YnNldCB0aGUgdmVjdG9yIHVzaW5nIFsgXS4KYGBge3J9ClJldCA8LSBjKEphbiA9IDUsIEZlYiA9IDIsIE1hciA9IDMsIEFwciA9IDcsIE1heSA9IDgsIEp1biA9IDMsIEp1bCA9IDUsIApBdWcgPSA5LCBTZXAgPSAxLCBPY3QgPSA0LCBOb3YgPSA2LCBEZWMgPSAzKQojIEZpcnN0IDYgbW9udGhzIG9mIHJldHVybnMKcmV0WzE6Nl0KCiMgSnVzdCBNYXJjaCBhbmQgTWF5CnJldFtjKCJNYXIiLCAiTWF5IildCgojIE9taXQgdGhlIGZpcnN0IG1vbnRoIG9mIHJldHVybnMKcmV0Wy0xXQpgYGAKIyMgTWF0cml4IC0gYSAyRCB2ZWN0b3IKCiMjIyBDcmVhdGluZyBhIG1hdHJpeAoKTWF0cmljZXMgYXJlIHNpbWlsYXIgdG8gdmVjdG9ycywgZXhjZXB0IHRoZXkgYXJlIGluIDIgZGltZW5zaW9ucyEgTGV0J3MgY3JlYXRlIGEgMngyIG1hdHJpeCAiYnkgaGFuZCIgdXNpbmcgbWF0cml4KCkuCgpgYGB7cn0KbWF0cml4KGRhdGEgPSBjKDIsIDMsIDQsIDUpLCBucm93ID0gMiwgbmNvbCA9IDIpCmBgYApOb3RpY2UgdGhhdCB0aGUgYWN0dWFsIGRhdGEgZm9yIHRoZSBtYXRyaXggaXMgcGFzc2VkIGluIGFzIGEgdmVjdG9yIHVzaW5nIGMoKSwgYW5kIGlzIHRoZW4gY29udmVydGVkIHRvIGEgbWF0cml4IGJ5IHNwZWNpZnlpbmcgdGhlIG51bWJlciBvZiByb3dzIGFuZCBjb2x1bW5zIChhbHNvIGtub3duIGFzIHRoZSBkaW1lbnNpb25zKS4KYGBge3J9CiMgQSB2ZWN0b3Igb2YgOSBudW1iZXJzCm15X3ZlY3RvciA8LSBjKDEsIDIsIDMsIDQsIDUsIDYsIDcsIDgsIDkpCgojIDN4MyBtYXRyaXgKbXlfbWF0cml4IDwtIG1hdHJpeChkYXRhID0gbXlfdmVjdG9yLCBucm93ID0gMywgbmNvbCA9IDMpCgojIFByaW50IG15X21hdHJpeApteV9tYXRyaXgKCiMgRmlsbGluZyBhY3Jvc3MgdXNpbmcgYnlyb3cgPSBUUlVFCm1hdHJpeChkYXRhID0gYygyLCAzLCA0LCA1KSwgbnJvdyA9IDIsIG5jb2wgPSAyLCBieXJvdyA9IFRSVUUpCmBgYAojIyMgTWF0cml4IDwtIGJpbmQgdmVjdG9ycwoKT2Z0ZW4sIHlvdSB3b24ndCBiZSBjcmVhdGluZyB2ZWN0b3JzIGxpa2Ugd2UgZGlkIGluIHRoZSBsYXN0IGV4YW1wbGUuIEluc3RlYWQsIHlvdSB3aWxsIGNyZWF0ZSB0aGVtIGZyb20gbXVsdGlwbGUgdmVjdG9ycyB0aGF0IHlvdSB3YW50IHRvIGNvbWJpbmUgdG9nZXRoZXIuIEZvciB0aGlzLCBpdCBpcyBlYXNpZXN0IHRvIHVzZSB0aGUgZnVuY3Rpb25zIGNiaW5kKCkgYW5kIHJiaW5kKCkgKGNvbHVtbiBiaW5kIGFuZCByb3cgYmluZCByZXNwZWN0aXZlbHkpLiBUbyBzZWUgdGhlc2UgaW4gYWN0aW9uLCBsZXQncyBjb21iaW5lIHR3byB2ZWN0b3JzIG9mIEFwcGxlIGFuZCBJQk0gc3RvY2sgcHJpY2VzOgpgYGB7cn0KYXBwbGUgPC0gYygxMDkuNDksIDEwOS45MCwgMTA5LjExLCAxMDkuOTUsIDExMS4wMykKaWJtIDwtIGMoMTU5LjgyLCAxNjAuMDIsIDE1OS44NCwgMTYwLjM1LCAxNjQuNzkpCgpjYmluZChhcHBsZSwgaWJtKQpyYmluZChhcHBsZSwgaWJtKQpgYGAKVGhlIGZ1bmN0aW9ucyBjYmluZCgpIGFuZCByYmluZCgpIGFyZSBwcmV0dHkgY29tbW9uLiBUaGV5IGFsc28gd29yayB3aXRoIGRhdGEgZnJhbWVzLgoKIyMjIFZpc3VhbGl6ZSB5b3VyIG1hdHJpeAoKV2UgY2FuIHZpc3VhbGl6ZSBvdXIgbWF0cml4IHRvIGdhaW4gc29tZSBpbnNpZ2h0cyBhYm91dCB0aGUgcmVsYXRpb25zaGlwcyBpbiB0aGUgZGF0YS4KYGBge3J9CmFwcGxlX21pY3JfbWF0cml4IDwtICBjYmluZChhcHBsZSwgaWJtKQojIFZpZXcgdGhlIGRhdGEKYXBwbGVfbWljcl9tYXRyaXgKCiMgU2NhdHRlciBwbG90IG9mIE1pY3Jvc29mdCB2cyBBcHBsZQpwbG90KGFwcGxlX21pY3JfbWF0cml4KQpgYGAKIyMjIGNvcigpcmVsYXRpb24KCkl0IHNlZW1zIHRoYXQgd2hlbiBBcHBsZSdzIHN0b2NrIG1vdmVzIHVwLCBNaWNyb3NvZnQncyBkb2VzIGFzIHdlbGwuIE9uZSB3YXkgdG8gY2FwdHVyZSB0aGlzIGtpbmQgb2YgcmVsYXRpb25zaGlwIGlzIGJ5IGZpbmRpbmcgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlIHR3byBzdG9ja3MuIENvcnJlbGF0aW9uIGlzIGEgbWVhc3VyZSBvZiBhc3NvY2lhdGlvbiBiZXR3ZWVuIHR3byB0aGluZ3MsIGhlcmUsIHN0b2NrIHByaWNlcywgYW5kIGlzIHJlcHJlc2VudGVkIGJ5IGEgbnVtYmVyIGZyb20gLTEgdG8gMS4gQSAxIHJlcHJlc2VudHMgcGVyZmVjdCBwb3NpdGl2ZSBjb3JyZWxhdGlvbiwgYSAtMSByZXByZXNlbnRzIHBlcmZlY3QgbmVnYXRpdmUgY29ycmVsYXRpb24sIGFuZCAwIGNvcnJlbGF0aW9uIG1lYW5zIHRoYXQgdGhlIHN0b2NrcyBtb3ZlIGluZGVwZW5kZW50bHkgb2YgZWFjaCBvdGhlci4KClRoZSBjb3IoKSBmdW5jdGlvbiB3aWxsIGNhbGN1bGF0ZSB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0d28gdmVjdG9ycywgb3Igd2lsbCBjcmVhdGUgYSBjb3JyZWxhdGlvbiBtYXRyaXggd2hlbiBnaXZlbiBhIG1hdHJpeC4KYGBge3J9CmNvcihhcHBsZSwgaWJtKQpjb3IoYXBwbGVfbWljcl9tYXRyaXgpCmBgYApBIGxhcmdlIGNvcnJlbGF0aW9uIG9mIC45MTMgaGludHMgdGhhdCBBcHBsZSBhbmQgSUJNJ3Mgc3RvY2sgcHJpY2VzIG1vdmUgY2xvc2VseSB0b2dldGhlci4KCiMjIyBNYXRyaXggc3Vic2V0dGluZwoKTWF0cmljZXMgY2FuIGJlIHNlbGVjdGVkIGZyb20gYW5kIHN1YnNldHRlZCB3aXRoIFsgXS4gVGhlIGJhc2ljIHN0cnVjdHVyZSBpczoKCiAgICBteV9tYXRyaXhbcm93LCBjb2xdCgpgYGB7cn0KYXBwbGUgPC0gYygxMDkuNDksIDEwOS45MCwgMTA5LjExLCAxMDkuOTUsIDExMS4wMykKaWJtIDwtIGMoMTU5LjgyLCAxNjAuMDIsIDE1OS44NCwgMTYwLjM1LCAxNjQuNzkpCnN0b2NrcyA8LSBjYmluZChhcHBsZSwgaWJtKQojIFRoaXJkIHJvdwpzdG9ja3NbMyxdCgojIEZvdXJ0aCBhbmQgZmlmdGggcm93IG9mIHRoZSBpYm0gY29sdW1uCnN0b2Nrc1s0OjUsIDJdCgojIGlibSBjb2x1bW5zCnN0b2Nrc1ssIDJdCmBgYAojIERhdGEgRnJhbWVzCgojIyBXaGF0IGlzIGEgZGF0YSBmcmFtZT8KCiMjIyBDcmVhdGUgYSBkYXRhIGZyYW1lCgpEYXRhIGZyYW1lcyBhcmUgZ3JlYXQgYmVjYXVzZSBvZiB0aGVpciBhYmlsaXR5IHRvIGhvbGQgYSBkaWZmZXJlbnQgdHlwZSBvZiBkYXRhIGluIGVhY2ggY29sdW1uLiBUbyBnZXQgc3RhcnRlZCwgbGV0J3MgdXNlIHRoZSBkYXRhLmZyYW1lKCkgZnVuY3Rpb24gdG8gY3JlYXRlIGEgZGF0YSBmcmFtZSBvZiB5b3VyIGJ1c2luZXNzJ3MgZnV0dXJlIGNhc2ggZmxvd3MuIEhlcmUgYXJlIHRoZSB2YXJpYWJsZXMgdGhhdCB3aWxsIGJlIGluIHRoZSBkYXRhIGZyYW1lOgpjb21wYW55IC0gVGhlIGNvbXBhbnkgdGhhdCBpcyBwYXlpbmcgeW91IHRoZSBjYXNoIGZsb3cgKEEgb3IgQikuCmNhc2hfZmxvdyAtIFRoZSBhbW91bnQgb2YgbW9uZXkgYSBjb21wYW55IHdpbGwgcmVjZWl2ZS4KeWVhciAtIFRoZSBudW1iZXIgb2YgeWVhcnMgZnJvbSBub3cgdGhhdCB5b3UgcmVjZWl2ZSB0aGUgY2FzaCBmbG93LgpgYGB7cn0KIyBWYXJpYWJsZXMKY29tcGFueSA8LSBjKCJBIiwgIkEiLCAiQSIsICJCIiwgIkIiLCAiQiIsICJCIikKY2FzaF9mbG93IDwtIGMoMTAwMCwgNDAwMCwgNTUwLCAxNTAwLCAxMTAwLCA3NTAsIDYwMDApCnllYXIgPC0gYygxLCAzLCA0LCAxLCAyLCA0LCA1KQoKIyBEYXRhIGZyYW1lCmNhc2ggPC0gZGF0YS5mcmFtZShjb21wYW55LCBjYXNoX2Zsb3csIHllYXIpCgojIFByaW50IGNhc2gKY2FzaApgYGAKIyMgTWFraW5nIGhlYWQoKXMgYW5kIHRhaWwoKXMgb2YgeW91ciBkYXRhIHdpdGggc29tZSBzdHIoKXVjdHVyZQoKVGltZSB0byBpbnRyb2R1Y2UgYSBmZXcgc2ltcGxlLCBidXQgdmVyeSB1c2VmdWwgZnVuY3Rpb25zLgoKLQloZWFkKCkgLSBSZXR1cm5zIHRoZSBmaXJzdCBmZXcgcm93cyBvZiBhIGRhdGEgZnJhbWUuIEJ5IGRlZmF1bHQsIDYuIFRvIGNoYW5nZSB0aGlzLCB1c2UgaGVhZChjYXNoLCBuID0gX19fKQotCXRhaWwoKSAtIFJldHVybnMgdGhlIGxhc3QgZmV3IHJvd3Mgb2YgYSBkYXRhIGZyYW1lLiBCeSBkZWZhdWx0LCA2LiBUbyBjaGFuZ2UgdGhpcywgdXNlIHRhaWwoY2FzaCwgbiA9IF9fXykKLQlzdHIoKSAtIENoZWNrIHRoZSBzdHJ1Y3R1cmUgb2YgYW4gb2JqZWN0LiBUaGlzIGZhbnRhc3RpYyBmdW5jdGlvbiB3aWxsIHNob3cgeW91IHRoZSBkYXRhIHR5cGUgb2YgdGhlIG9iamVjdCB5b3UgcGFzcyBpbiAoaGVyZSwgZGF0YS5mcmFtZSksIGFuZCB3aWxsIGxpc3QgZWFjaCBjb2x1bW4gdmFyaWFibGUgYWxvbmcgd2l0aCBpdHMgZGF0YSB0eXBlLgpgYGB7cn0KIyBDYWxsIGhlYWQoKSBmb3IgdGhlIGZpcnN0IDQgcm93cwpoZWFkKGNhc2gsIDQpCgojIENhbGwgdGFpbCgpIGZvciB0aGUgbGFzdCAzIHJvd3MKdGFpbChjYXNoLCAzKQoKIyBDYWxsIHN0cigpCnN0cihjYXNoKQpgYGAKIyMjIE5hbWluZyB5b3VyIGNvbHVtbnMgLyByb3dzCgpXZSBjYW4gY2hhbmdlIHRoZSBjb2x1bW5zIG5hbWVzIGNvbG5hbWVzKCkgYW5kIHRoZSByb3cgbmFtZXMgdXNpbmcgcm93bmFtZXMoKSwgYnV0IHRoaXMgaXMgbGVzcyBjb21tb24uCmBgYHtyfQojIEZpeCB5b3VyIGNvbHVtbiBuYW1lcwpjb2xuYW1lcyhjYXNoKSA8LSBjKCJjb21wYW55IiwgImNhc2hfZmxvdyIsICJ5ZWFyIikKCiMgUHJpbnQgb3V0IHRoZSBjb2x1bW4gbmFtZXMgb2YgY2FzaApjb2xuYW1lcyhjYXNoKQpgYGAKIyMgRGF0YSBmcmFtZSBtYW5pcHVsYXRpb24KCiMjIyBBY2Nlc3NpbmcgYW5kIHN1YnNldHRpbmcgZGF0YSBmcmFtZXMKCk9uZSBvZiB0aGUgd2F5cyB0byBkbyB0aGlzIGlzIHRvIHVzZSBbIF0uIFRoZSBub3RhdGlvbiBpcyBqdXN0IGxpa2UgbWF0cmljZXMKYGBge3J9CiMgVGhpcmQgcm93LCBzZWNvbmQgY29sdW1uCmNhc2hbMywgMl0KCiMgRmlmdGggcm93IG9mIHRoZSAieWVhciIgY29sdW1uCmNhc2hbNSwgInllYXIiXQpgYGAKQXMgeW91IG1pZ2h0IGltYWdpbmUsIHNlbGVjdGluZyBhIHNwZWNpZmljIGNvbHVtbiBmcm9tIGEgZGF0YSBmcmFtZSBpcyBhIGNvbW1vbiBtYW5pcHVsYXRpb24uIFNvIGNvbW1vbiwgaW4gZmFjdCwgdGhhdCBpdCB3YXMgZ2l2ZW4gaXRzIG93biBzaG9ydGN1dCwgdGhlIFwkLgpgYGB7cn0KIyBTZWxlY3QgdGhlIHllYXIgY29sdW1uCmNhc2gkeWVhcgoKIyBTZWxlY3QgdGhlIGNhc2hfZmxvdyBjb2x1bW4gYW5kIG11bHRpcGx5IGJ5IDIKY2FzaCRjYXNoX2Zsb3cgKiAyCgojIERlbGV0ZSB0aGUgY29tcGFueSBjb2x1bW4KY2FzaCRjb21wYW55IDwtIE5VTEwKCiMgUHJpbnQgY2FzaCBhZ2FpbgpjYXNoCmBgYApXaGF0IGlmIHlvdSBhcmUgb25seSBpbnRlcmVzdGVkIGluIHRoZSBjYXNoIGZsb3dzIGZyb20gY29tcGFueSBBPyBGb3IgbW9yZSBmbGV4aWJpbGl0eSwgdHJ5IHN1YnNldCgpCmBgYHtyfQpzdWJzZXQoY2FzaCwgY29tcGFueSA9PSAiQSIpCmBgYApUaGVyZSBhcmUgYSBmZXcgaW1wb3J0YW50IHRoaW5ncyBoYXBwZW5pbmcgaGVyZToKCi0JVGhlIGZpcnN0IGFyZ3VtZW50IHlvdSBwYXNzIHRvIHN1YnNldCgpIGlzIHRoZSBuYW1lIG9mIHlvdXIgZGF0YSBmcmFtZSwgY2FzaC5Ob3RpY2UgdGhhdCB5b3Ugc2hvdWxkbid0IHB1dCBjb21wYW55IGluIHF1b3Rlcy4KLQlUaGUgPT0gaXMgdGhlIGVxdWFsaXR5IG9wZXJhdG9yLiBJdCB0ZXN0cyB0byBmaW5kIHdoZXJlIHR3byB0aGluZ3MgYXJlIGVxdWFsLCBhbmQgcmV0dXJucyBhIGxvZ2ljYWwgdmVjdG9yLgoKCmBgYHtyfQojIFJvd3MgYWJvdXQgY29tcGFueSBCCnN1YnNldChjYXNoLCBjb21wYW55ID09ICJCIikKCiMgUm93cyB3aXRoIGNhc2ggZmxvd3MgZHVlIGluIDEgeWVhcgoKc3Vic2V0KGNhc2gsIHllYXIgPT0gMSkKYGBgCiMjIyBBZGRpbmcgbmV3IGNvbHVtbnMKCkNyZWF0aW5nIG5ldyBjb2x1bW5zIGluIHlvdXIgZGF0YSBmcmFtZSBpcyBhcyBzaW1wbGUgYXMgYXNzaWduaW5nIHRoZSBuZXcgaW5mb3JtYXRpb24gdG8gZGF0YV9mcmFtZVwkbmV3X2NvbHVtbi4gT2Z0ZW4sIHRoZSBuZXdseSBjcmVhdGVkIGNvbHVtbiBpcyBzb21lIHRyYW5zZm9ybWF0aW9uIG9mIGV4aXN0aW5nIGNvbHVtbnMsIHNvIHRoZSBcJCBvcGVyYXRvciByZWFsbHkgY29tZXMgaW4gaGFuZHkgaGVyZS4KYGBge3J9CiMgUXVhcnRlciBjYXNoIGZsb3cgc2NlbmFyaW8KY2FzaCRxdWFydGVyX2Nhc2ggPC0gY2FzaCRjYXNoX2Zsb3cgKiAuMjUKCiMgRG91YmxlIHllYXIgc2NlbmFyaW8KY2FzaCRkb3VibGVfeWVhciA8LSBjYXNoJHllYXIgKiAyCmBgYAojIyBQcmVzZW50IHZhbHVlCgojIyMgUHJlc2VudCB2YWx1ZSBvZiBwcm9qZWN0ZWQgY2FzaCBmbG93cwoKSWYgeW91IGV4cGVjdCBhIGNhc2ggZmxvdyBvZiAkMTAwIHRvIGJlIHJlY2VpdmVkIDEgeWVhciBmcm9tIG5vdywgd2hhdCBpcyB0aGUgcHJlc2VudCB2YWx1ZSBvZiB0aGF0IGNhc2ggZmxvdyBhdCBhIDUlIGludGVyZXN0IHJhdGU/IFRvIGNhbGN1bGF0ZSB0aGlzLCB5b3UgZGlzY291bnQgdGhlIGNhc2ggZmxvdyB0byBnZXQgaXQgaW4gdGVybXMgb2YgdG9kYXkncyBkb2xsYXJzLiBUaGUgZ2VuZXJhbCBmb3JtdWxhIGZvciB0aGlzIGlzOgoKICAgIHByZXNlbnRfdmFsdWUgPC0gY2FzaF9mbG93ICogKDEgKyBpbnRlcmVzdCAvIDEwMCkgXiAteWVhcgogICAgOTUuMjM4ID0gMTAwICogKDEuMDUpIF4gLTEKCmBgYHtyfQojIFByZXNlbnQgdmFsdWUgb2YgJDQwMDAsIGluIDMgeWVhcnMsIGF0IDUlCnByZXNlbnRfdmFsdWVfNGsgPC0gNDAwMCAqICgxLjA1KV4tMwoKIyBQcmVzZW50IHZhbHVlIG9mIGFsbCBjYXNoIGZsb3dzCmNhc2gkcHJlc2VudF92YWx1ZSA8LSBjYXNoJGNhc2hfZmxvdyAqICgxLjA1KV4tY2FzaCR5ZWFyCgojIFByaW50IG91dCBjYXNoCmNhc2gKYGBgCldlIG5vdyBoYXZlIGEgY29sdW1uIGZvciBwcmVzZW50X3ZhbHVlLCBidXQgd2Ugd2FudCB0byByZXBvcnQgdGhlIHRvdGFsIGFtb3VudCBvZiB0aGF0IGNvbHVtbiB0byB5b3VyIGJvYXJkIG1lbWJlcnMuIENhbGN1bGF0aW5nIHRoaXMgcGFydCBpcyBlYXN5LCB1c2UgdGhlIHN1bSgpIGZ1bmN0aW9uIHlvdSBsZWFybmVkIGVhcmxpZXIgdG8gYWRkIHVwIHRoZSBlbGVtZW50cyBvZiBjYXNoJHByZXNlbnRfdmFsdWUuCgpIb3dldmVyLCB3ZSBhbHNvIHdhbnQgdG8ga25vdyBob3cgbXVjaCBjb21wYW55IEEgYW5kIGNvbXBhbnkgQiBpbmRpdmlkdWFsbHkgY29udHJpYnV0ZSB0byB0aGUgdG90YWwgcHJlc2VudCB2YWx1ZS4KYGBge3J9CiMgVG90YWwgcHJlc2VudCB2YWx1ZSBvZiBjYXNoCnRvdGFsX3B2IDwtIHN1bShjYXNoJHByZXNlbnRfdmFsdWUpCgojIENvbXBhbnkgQiBpbmZvcm1hdGlvbgpjYXNoX0IgPC0gc3Vic2V0KGNhc2gsIGNvbXBhbnkgPT0gIkIiKQoKIyBUb3RhbCBwcmVzZW50IHZhbHVlIG9mIGNhc2hfQgp0b3RhbF9wdl9CIDwtIHN1bShjYXNoX0IkcHJlc2VudF92YWx1ZSkKYGBgCiMgRmFjdG9yCgojIyBXaGF0IGlzIGEgZmFjdG9yPwoKIyMjIENyZWF0ZSBhIGZhY3RvcgoKQm9uZCBjcmVkaXQgcmF0aW5ncyBhcmUgY29tbW9uIGluIHRoZSBmaXhlZCBpbmNvbWUgc2lkZSBvZiB0aGUgZmluYW5jZSB3b3JsZCBhcyBhIHNpbXBsZSBtZWFzdXJlIG9mIGhvdyAicmlza3kiIGEgY2VydGFpbiBib25kIG1pZ2h0IGJlLiBIZXJlLCByaXNraW5lc3MgY2FuIGJlIGRlZmluZWQgYXMgdGhlIHByb2JhYmlsaXR5IG9mIGRlZmF1bHQsIHdoaWNoIG1lYW5zIGFuIGluYWJpbGl0eSB0byBwYXkgYmFjayB5b3VyIGRlYnRzLiBUaGUgU3RhbmRhcmQgYW5kIFBvb3IncyBhbmQgRml0Y2ggY3JlZGl0IHJhdGluZyBhZ2VuY3kgaGFzIGRlZmluZWQgdGhlIGZvbGxvd2luZyByYXRpbmdzLCBmcm9tIGxlYXN0IGxpa2VseSB0byBkZWZhdWx0IHRvIG1vc3QgbGlrZWx5OgpBQUEsIEFBLCBBLCBCQkIsIEJCLCBCLCBDQ0MsIENDLCBDLCBEClRoaXMgaXMgYSBwZXJmZWN0IGV4YW1wbGUgb2YgYSBmYWN0b3IhIEl0IGlzIGEgY2F0ZWdvcmljYWwgdmFyaWFibGUgdGhhdCB0YWtlcyBvbiBhIGxpbWl0ZWQgbnVtYmVyIG9mIGxldmVscy4KClRvIGNyZWF0ZSBhIGZhY3RvciBpbiBSLCB1c2UgdGhlIGZhY3RvcigpIGZ1bmN0aW9uLCBhbmQgcGFzcyBpbiBhIHZlY3RvciB0aGF0IHlvdSB3YW50IHRvIGJlIGNvbnZlcnRlZCBpbnRvIGEgZmFjdG9yLgpgYGB7cn0KIyBjcmVkaXRfcmF0aW5nIGNoYXJhY3RlciB2ZWN0b3IKY3JlZGl0X3JhdGluZyA8LSBjKCJCQiIsICJBQUEiLCAiQUEiLCAiQ0NDIiwgIkFBIiwgIkFBQSIsICJCIiwgIkJCIikKCiMgQ3JlYXRlIGEgZmFjdG9yIGZyb20gY3JlZGl0X3JhdGluZwpjcmVkaXRfZmFjdG9yIDwtIGZhY3RvcihjcmVkaXRfcmF0aW5nKQoKIyBQcmludCBvdXQgeW91ciBuZXcgZmFjdG9yCmNyZWRpdF9mYWN0b3IKCiMgQ2FsbCBzdHIoKSBvbiBjcmVkaXRfcmF0aW5nCnN0cihjcmVkaXRfcmF0aW5nKQoKIyBDYWxsIHN0cigpIG9uIGNyZWRpdF9mYWN0b3IKc3RyKGNyZWRpdF9mYWN0b3IpCmBgYAojIyMgRmFjdG9yIGxldmVscwoKQWNjZXNzaW5nIHRoZSB1bmlxdWUgbGV2ZWxzIG9mIHlvdXIgZmFjdG9yIGlzIHNpbXBsZSBlbm91Z2ggYnkgdXNpbmcgdGhlIGxldmVscygpIGZ1bmN0aW9uLiBZb3UgY2FuIGFsc28gdXNlIHRoaXMgdG8gcmVuYW1lIHlvdXIgZmFjdG9yIGxldmVscwpgYGB7cn0KIyBJZGVudGlmeSB1bmlxdWUgbGV2ZWxzCmxldmVscyhjcmVkaXRfZmFjdG9yKQoKIyBSZW5hbWUgdGhlIGxldmVscyBvZiBjcmVkaXRfZmFjdG9yCmxldmVscyhjcmVkaXRfZmFjdG9yKSAgPC0gYygiMkEiLCAiM0EiLCAiMUIiLCAiMkIiLCAiM0MiKQoKIyBQcmludCBjcmVkaXRfZmFjdG9yCmNyZWRpdF9mYWN0b3IKYGBgCiMjIyBGYWN0b3Igc3VtbWFyeQoKQXMgYW55IGdvb2QgYm9uZCBpbnZlc3RvciB3b3VsZCBkbywgeW91IHdvdWxkIGxpa2UgdG8ga2VlcCB0cmFjayBvZiBob3cgbWFueSBib25kcyB5b3UgYXJlIGhvbGRpbmcgb2YgZWFjaCBjcmVkaXQgcmF0aW5nLiBBIHdheSB0byBwcmVzZW50IGEgdGFibGUgb2YgdGhlIGNvdW50cyBvZiBlYWNoIGJvbmQgY3JlZGl0IHJhdGluZyB3b3VsZCBiZSBncmVhdCEgTHVja2lseSBmb3IgeW91LCB0aGUgc3VtbWFyeSgpIGZ1bmN0aW9uIGZvciBmYWN0b3JzIGNhbiBoZWxwIHlvdSB3aXRoIHRoYXQuCmBgYHtyfQojIFN1bW1hcml6ZSB0aGUgY2hhcmFjdGVyIHZlY3RvciwgY3JlZGl0X3JhdGluZwpzdW1tYXJ5KGNyZWRpdF9yYXRpbmcpCgojIFN1bW1hcml6ZSB0aGUgZmFjdG9yLCBjcmVkaXRfZmFjdG9yCnN1bW1hcnkoY3JlZGl0X2ZhY3RvcikKYGBgCiMjIyBWaXN1YWxpemUgeW91ciBmYWN0b3IKCldlIGNhbiBhbHNvIHZpc3VhbGl6ZSB0aGUgdGFibGUgdGhhdCB5b3UgY3JlYXRlZCBpbiB0aGUgbGFzdCBleGFtcGxlIGJ5IHVzaW5nIGEgYmFyIGNoYXJ0LiBBIGJhciBjaGFydCBpcyBhIHR5cGUgb2YgZ3JhcGggdGhhdCBkaXNwbGF5cyBncm91cHMgb2YgZGF0YSB1c2luZyByZWN0YW5ndWxhciBiYXJzIHdoZXJlIHRoZSBoZWlnaHQgb2YgZWFjaCBiYXIgcmVwcmVzZW50cyB0aGUgbnVtYmVyIG9mIGNvdW50cyBpbiB0aGF0IGdyb3VwLgoKVGhlIHBsb3QoKSBmdW5jdGlvbiBjYW4gYWdhaW4gdGFrZSBjYXJlIG9mIGFsbCBvZiB0aGUgbWFnaWMgZm9yIHVzLiBXZSBhcmUgY3JlYXRpbmcgdGhlIHBsb3QgZnJvbSBhIGZhY3RvciBhbmQgbm90IGEgY2hhcmFjdGVyIHZlY3Rvci4gUiB3aWxsIHRocm93IGFuIGVycm9yIGlmIHlvdSB0cnkgYW5kIHBsb3QgYSBjaGFyYWN0ZXIgdmVjdG9yIQpgYGB7cn0KIyBWaXN1YWxpemUgeW91ciBmYWN0b3IhCnBsb3QoY3JlZGl0X2ZhY3RvcikKYGBgCiMjIyBCdWNrZXRpbmcgYSBudW1lcmljIHZhcmlhYmxlIGludG8gYSBmYWN0b3IKCllvdXIgb2xkIGZyaWVuZCBEYW4gc2VudCB5b3UgYSBsaXN0IG9mIDUwIEFBQSByYXRlZCBib25kcyBjYWxsZWQgQUFBX3JhbmssIHdpdGggZWFjaCBib25kIGhhdmluZyBhbiBhZGRpdGlvbmFsIG51bWJlciBmcm9tIDEtMTAwIGRlc2NyaWJpbmcgaG93IHByb2ZpdGFibGUgaGUgdGhpbmtzIHRoYXQgYm9uZCB3aWxsIGJlICgxMDAgYmVpbmcgdGhlIG1vc3QgcHJvZml0YWJsZSkuIFlvdSBhcmUgaW50ZXJlc3RlZCBpbiBkb2luZyBmdXJ0aGVyIGFuYWx5c2lzIG9uIGhpcyBzdWdnZXN0aW9ucywgYnV0IGZpcnN0IGl0IHdvdWxkIGJlIG5pY2UgaWYgdGhlIGJvbmRzIHdlcmUgYnVja2V0ZWQgYnkgdGhlaXIgcmFua2luZyBzb21laG93LiBUaGlzIHdvdWxkIGhlbHAgeW91IGNyZWF0ZSBncm91cHMgb2YgYm9uZHMsIGZyb20gbGVhc3QgcHJvZml0YWJsZSB0byBtb3N0IHByb2ZpdGFibGUsIHRvIG1vcmUgZWFzaWx5IGFuYWx5emUgdGhlbS4KYGBge3J9CkFBQV9yYW5rIDwtIGMoMzFMLCA0OEwsIDEwMEwsIDUzTCwgODVMLCA3M0wsIDYyTCwgNzRMLCA0MkwsIDM4TCwgOTdMLCA2MUwsIAo0OEwsIDg2TCwgNDRMLCA5TCwgNDNMLCAxOEwsIDYyTCwgMzhMLCAyM0wsIDM3TCwgNTRMLCA4MEwsIDc4TCwgCjkzTCwgNDdMLCAxMDBMLCAyMkwsIDIyTCwgMThMLCAyNkwsIDgxTCwgMTdMLCA5OEwsIDRMLCA4M0wsIDVMLCAKNkwsIDUyTCwgMjlMLCA0NEwsIDUwTCwgMkwsIDI1TCwgMTlMLCAxNUwsIDQyTCwgMzBMLCAyN0wpCmBgYApUaGlzIGlzIGEgZ3JlYXQgZXhhbXBsZSBvZiBjcmVhdGluZyBhIGZhY3RvciBmcm9tIGEgbnVtZXJpYyB2ZWN0b3IuIFRoZSBlYXNpZXN0IHdheSB0byBkbyB0aGlzIGlzIHRvIHVzZSBjdXQoKS4KCk5vdGUgdGhhdCB0aGUgKCBpbiB0aGUgZmFjdG9yIGxldmVscyBtZWFucyB3ZSBkbyBub3QgaW5jbHVkZSB0aGUgbnVtYmVyIGJlc2lkZSBpdCBpbiB0aGF0IGdyb3VwLCBhbmQgdGhlIF0gbWVhbnMgdGhhdCB3ZSBkbyBpbmNsdWRlIHRoYXQgbnVtYmVyIGluIHRoZSBncm91cC4KCkluIHRoZSBjdXQoKSBmdW5jdGlvbiwgdXNpbmcgYnJlYWtzID0gYWxsb3dzIHlvdSB0byBzcGVjaWZ5IHRoZSBncm91cHMgdGhhdCB5b3Ugd2FudCBSIHRvIGJ1Y2tldCB5b3VyIGRhdGEgYnkhCmBgYHtyfQojIENyZWF0ZSA0IGJ1Y2tldHMgZm9yIEFBQV9yYW5rIHVzaW5nIGN1dCgpCkFBQV9mYWN0b3IgPC0gY3V0KHggPSBBQUFfcmFuaywgYnJlYWtzID0gYygwLCAyNSwgNTAsIDc1LCAxMDApKQoKIyBSZW5hbWUgdGhlIGxldmVscyAKbGV2ZWxzKEFBQV9mYWN0b3IpIDwtIGMoImxvdyIsICJtZWRpdW0iLCAiaGlnaCIsICJ2ZXJ5X2hpZ2giKQoKIyBQcmludCBBQUFfZmFjdG9yCkFBQV9mYWN0b3IKCiMgUGxvdCBBQUFfZmFjdG9yCnBsb3QoQUFBX2ZhY3RvcikKYGBgCiMjIE9yZGVyaW5nIGFuZCBzdWJzZXR0aW5nIGZhY3RvcnMKCiMjIyBDcmVhdGUgYW4gb3JkZXJlZCBmYWN0b3IKClRvIG9yZGVyIHlvdXIgZmFjdG9yLCB0aGVyZSBhcmUgdHdvIG9wdGlvbnMuCgpXaGVuIGNyZWF0aW5nIGEgZmFjdG9yLCBzcGVjaWZ5IG9yZGVyZWQgPSBUUlVFIGFuZCBhZGQgdW5pcXVlIGxldmVscyBpbiBvcmRlciBmcm9tIGxlYXN0IHRvIGdyZWF0ZXN0OgpgYGB7cn0KY3JlZGl0X3JhdGluZyA8LSBjKCJBQUEiLCAiQUEiLCAiQSIsICJCQkIiLCAiQUEiLCAiQkJCIiwgIkEiKQoKY3JlZGl0X2ZhY3Rvcl9vcmRlcmVkIDwtIGZhY3RvcihjcmVkaXRfcmF0aW5nLCBvcmRlcmVkID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzID0gYygiQUFBIiwgIkFBIiwgIkEiLCAiQkJCIikpCmBgYApGb3IgYW4gZXhpc3RpbmcgdW5vcmRlcmVkIGZhY3RvciBsaWtlIGNyZWRpdF9mYWN0b3IsIHVzZSB0aGUgb3JkZXJlZCgpIGZ1bmN0aW9uOgpgYGB7cn0Kb3JkZXJlZChjcmVkaXRfZmFjdG9yLCBsZXZlbHMgPSBjKCJBQUEiLCAiQUEiLCAiQSIsICJCQkIiKSkKY3JlZGl0X2ZhY3Rvcl9vcmRlcmVkCmBgYApOb3RpY2UgdGhlIDwgc3BlY2lmeWluZyB0aGUgb3JkZXIgb2YgdGhlIGxldmVscy4KYGBge3J9CiMgVXNlIHVuaXF1ZSgpIHRvIGZpbmQgdW5pcXVlIHdvcmRzCnVuaXF1ZShjcmVkaXRfcmF0aW5nKQoKIyBDcmVhdGUgYW4gb3JkZXJlZCBmYWN0b3IKY3JlZGl0X2ZhY3Rvcl9vcmRlcmVkIDwtIGZhY3RvcihjcmVkaXRfcmF0aW5nLCBvcmRlcmVkID0gVFJVRSwgbGV2ZWxzID0gYygiQ0NDIiwgIkIiLCAiQkIiLCAiQUEiLCAiQUFBIikpCgojIFBsb3QgY3JlZGl0X2ZhY3Rvcl9vcmRlcmVkCnBsb3QoY3JlZGl0X2ZhY3Rvcl9vcmRlcmVkKQpgYGAKT3JkZXJlZCBmYWN0b3JzIGFyZSBncmVhdCBmb3IgcGxvdHRpbmcgb3IgY3JlYXRpbmcgdGFibGVzIHdpdGggYSBwcmVkZWZpbmVkIG9yZGVyLgoKIyMjIFN1YnNldHRpbmcgYSBmYWN0b3IKCllvdSBjYW4gc3Vic2V0IGZhY3RvcnMgaW4gYSBzaW1pbGFyIHdheSB0aGF0IHlvdSBzdWJzZXQgdmVjdG9ycy4gQXMgdXN1YWwsIFsgXSBpcyB0aGUga2V5ISBBbHNvLCB5b3UgY2FuIGFkZCBkcm9wID0gVFJVRSBzbyB0aGUgbGV2ZWxzIGFyZSB1cGRhdGVkIGluIGxpbmUgd2l0aCB5b3VyIG5ldyB2ZWN0b3IuCgpgYGB7cn0KIyBSZW1vdmUgdGhlIEEgYm9uZHMgYXQgcG9zaXRpb25zIDMgYW5kIDcuIERvbid0IGRyb3AgdGhlIEEgbGV2ZWwuCmtlZXBfbGV2ZWwgPC0gY3JlZGl0X2ZhY3Rvcl9vcmRlcmVkW2MoLTMsIC03KV0KCiMgUGxvdCBrZWVwX2xldmVsCnBsb3Qoa2VlcF9sZXZlbCkKCiMgUmVtb3ZlIHRoZSBBIGJvbmRzIGF0IHBvc2l0aW9ucyAzIGFuZCA3LiBEcm9wIHRoZSBBIGxldmVsLgpkcm9wX2xldmVsIDwtIGtlZXBfbGV2ZWwgPC0gY3JlZGl0X2ZhY3Rvcl9vcmRlcmVkW2MoLTMsIC03KSwgZHJvcCA9IFRSVUVdCgojIFBsb3QgZHJvcF9sZXZlbApwbG90KGtlZXBfbGV2ZWwpCmBgYApUaGUgZHJvcCBhcmd1bWVudCB3aWxsIGhlbHAgeW91IGdldCByaWQgb2YgdGhvc2UgcGVza3kgZmFjdG9yIGxldmVscyB0aGF0IHN0aWNrIGFyb3VuZC4KCiMjIyBzdHJpbmdzQXNGYWN0b3JzCgpSJ3MgZGVmYXVsdCBiZWhhdmlvciB3aGVuIGNyZWF0aW5nIGRhdGEgZnJhbWVzIGlzIHRvIGNvbnZlcnQgYWxsIGNoYXJhY3RlcnMgaW50byBmYWN0b3JzLiBUaGlzIGhhcyBjYXVzZWQgY291bnRsZXNzIG5vdmljZSBSIHVzZXJzIGEgaGVhZGFjaGUgdHJ5aW5nIHRvIGZpZ3VyZSBvdXQgd2h5IHRoZWlyIGNoYXJhY3RlciBjb2x1bW5zIGFyZSBub3Qgd29ya2luZyBwcm9wZXJseQoKVG8gdHVybiBvZmYgdGhpcyBiZWhhdmlvcjoKYGBge3J9CmNhc2ggPC0gZGF0YS5mcmFtZShjb21wYW55LCBjYXNoX2Zsb3csIHllYXIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCnN0cihjYXNoKQpgYGAKYGBge3J9CiMgVmFyaWFibGVzCmNyZWRpdF9yYXRpbmcgPC0gYygiQUFBIiwgIkEiLCAiQkIiKQpib25kX293bmVycyA8LSBjKCJEYW4iLCAiVG9tIiwgIkpvZSIpCgojIENyZWF0ZSB0aGUgZGF0YSBmcmFtZSBvZiBjaGFyYWN0ZXIgdmVjdG9ycywgYm9uZHMKYm9uZHMgPC0gZGF0YS5mcmFtZShjcmVkaXRfcmF0aW5nLCBib25kX293bmVycywgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQoKIyBVc2Ugc3RyKCkgb24gYm9uZHMKc3RyKGJvbmRzKQoKIyBDcmVhdGUgYSBmYWN0b3IgY29sdW1uIGluIGJvbmRzIGNhbGxlZCBjcmVkaXRfZmFjdG9yIGZyb20gY3JlZGl0X3JhdGluZwpib25kcyRjcmVkaXRfZmFjdG9yIDwtIGZhY3Rvcihib25kcyRjcmVkaXRfcmF0aW5nLCBvcmRlcmVkID0gVFJVRSwgbGV2ZWxzID0gYygiQkIiLCAiQSIsICJBQUEiKSkKCiMgVXNlIHN0cigpIG9uIGJvbmRzIGFnYWluCnN0cihib25kcykKYGBgCiMgTGlzdHMKCiMjIFdoYXQgaXMgYSBsaXN0PwoKIyMjIENyZWF0ZSBhIGxpc3QKCkxpc3RzIGluIFIgY2FuIGJlIHVzZWQgdG8gaG9sZCB0b2dldGhlciBpdGVtcyBvZiBkaWZmZXJlbnQgZGF0YSB0eXBlcy4gQ3JlYXRpbmcgYSBsaXN0IGlzIGFzIHNpbXBsZSBhcyB1c2luZyB0aGUgbGlzdCgpIGZ1bmN0aW9uLiAKYGBge3J9CiMgTGlzdCBjb21wb25lbnRzCm5hbWUgPC0gIkFwcGxlIGFuZCBJQk0iCmFwcGxlIDwtIGMoMTA5LjQ5LCAxMDkuOTAsIDEwOS4xMSwgMTA5Ljk1LCAxMTEuMDMpCmlibSA8LSBjKDE1OS44MiwgMTYwLjAyLCAxNTkuODQsIDE2MC4zNSwgMTY0Ljc5KQpjb3JfbWF0cml4IDwtIGNvcihjYmluZChhcHBsZSwgaWJtKSkKCiMgQ3JlYXRlIGEgbGlzdApwb3J0Zm9saW8gPC0gbGlzdChuYW1lLCBhcHBsZSwgaWJtLCBjb3JfbWF0cml4KQoKIyBWaWV3IHlvdXIgZmlyc3QgbGlzdApwb3J0Zm9saW8KYGBgCiMjIyBOYW1lZCBsaXN0cwoKWW91IGNvdWxkIG5hbWUgdGhlIGVsZW1lbnRzIGFzIHlvdSBjcmVhdGUgdGhlIGxpc3Qgd2l0aCB0aGUgZm9ybSBuYW1lID0gdmFsdWUuIE9yLCBpZiB0aGUgbGlzdCB3YXMgYWxyZWFkeSBjcmVhdGVkLCB5b3UgY291bGQgdXNlIG5hbWVzKCkuCmBgYHtyfQojIEFkZCBuYW1lcyB0byB5b3VyIHBvcnRmb2xpbwpuYW1lcyhwb3J0Zm9saW8pIDwtIGMoInBvcnRmb2xpb19uYW1lIiwgImFwcGxlIiwgImlibSIsICJjb3JyZWxhdGlvbiIpCgojIFByaW50IHBvcnRmb2xpbwpwb3J0Zm9saW8KYGBgCiMjIyBBY2Nlc3MgZWxlbWVudHMgaW4gYSBsaXN0CgpTdWJzZXR0aW5nIGEgbGlzdCBpcyBzaW1pbGFyIHRvIHN1YnNldHRpbmcgYSB2ZWN0b3Igb3IgZGF0YSBmcmFtZSwgd2l0aCBvbmUgZXh0cmEgdXNlZnVsIG9wZXJhdGlvbi4KClRvIGFjY2VzcyB0aGUgZWxlbWVudHMgaW4gdGhlIGxpc3QsIHVzZSBbIF0uIFRoaXMgd2lsbCBhbHdheXMgcmV0dXJuIGFub3RoZXIgbGlzdC4KClRvIHB1bGwgb3V0IHRoZSBkYXRhIGluc2lkZSBlYWNoIGVsZW1lbnQgb2YgeW91ciBsaXN0LCB1c2UgW1sgXV0uCmBgYHtyfQojIFNlY29uZCBhbmQgdGhpcmQgZWxlbWVudHMgb2YgcG9ydGZvbGlvCnBvcnRmb2xpb1tjKDIsMyldCgojIFVzZSAkIHRvIGdldCB0aGUgY29ycmVsYXRpb24gZGF0YQpwb3J0Zm9saW8kY29ycmVsYXRpb24KYGBgCiMjIyBBZGRpbmcgdG8gYSBsaXN0CgpXZSBjYW4gYWRkIG5ldyBlbGVtZW50cyB0byBpdC4gWW91IGNhbiBkbyBzbyB1c2luZyAkLiBXZSBjb3VsZCBoYXZlIGFsc28gdXNlZCBjKCkgdG8gYWRkIGFub3RoZXIgZWxlbWVudCB0byB0aGUgbGlzdDogYyhteV9saXN0LCBkYW5zX21vdmllID0gIlN0YVIgV2FycyIpLiBUaGlzIGNhbiBiZSB1c2VmdWwgaWYgd2Ugd2FudCB0byBhZGQgbXVsdGlwbGUgZWxlbWVudHMgdG8geW91ciBsaXN0IGF0IG9uY2UuCmBgYHtyfQojIEFkZCB3ZWlnaHQ6IDIwJSBBcHBsZSwgODAlIElCTQpwb3J0Zm9saW8kd2VpZ2h0IDwtIGMoYXBwbGUgPSAwLjIsIGlibSA9IDAuOCkKCiMgUHJpbnQgcG9ydGZvbGlvCnBvcnRmb2xpbwoKIyBDaGFuZ2UgdGhlIHdlaWdodCB2YXJpYWJsZTogMzAlIEFwcGxlLCA3MCUgSUJNCnBvcnRmb2xpbyR3ZWlnaHQgPC0gYyhhcHBsZSA9IDAuMywgaWJtID0gMC43KQoKIyBQcmludCBwb3J0Zm9saW8gdG8gc2VlIHRoZSBjaGFuZ2VzCnBvcnRmb2xpbwpgYGAKIyMjIFJlbW92aW5nIGZyb20gYSBsaXN0CgpVc2luZyBOVUxMIGlzIHRoZSBlYXNpZXN0IHdheSB0byByZW1vdmUgYW4gZWxlbWVudCBmcm9tIHlvdXIgbGlzdC4gV2UgY2FuIGFsc28gcmVtb3ZlIGVsZW1lbnRzIGJ5IHBvc2l0aW9uIHVzaW5nIG15X2xpc3RbMV0gPC0gTlVMTCBvciBteV9saXN0W1sxXV0gPC0gTlVMTC4KYGBge3J9CiMgVGFrZSBhIGxvb2sgYXQgcG9ydGZvbGlvCnBvcnRmb2xpbwoKIyBSZW1vdmUgdGhlIG1pY3Jvc29mdCBzdG9jayBwcmljZXMgZnJvbSB5b3VyIHBvcnRmb2xpbwpwb3J0Zm9saW8kbWljcm9zb2Z0IDwtIE5VTEwKYGBgCiMjIEEgZmV3IGxpc3QgY3JlYXRpbmcgZnVuY3Rpb25zCgojIyMgU3BsaXQgaXQKCk9mdGVuLCB5b3Ugd2lsbCBoYXZlIGRhdGEgZm9yIG11bHRpcGxlIGdyb3VwcyB0b2dldGhlciBpbiBvbmUgZGF0YSBmcmFtZS4KCldlIGNhbiBjcmVhdGUgYSBncm91cGluZyB0byBzcGxpdCBvbiwgYW5kIHVzZSBzcGxpdCgpIHRvIGNyZWF0ZSBhIGxpc3Qgb2YgdHdvIGRhdGEgZnJhbWVzLgpgYGB7cn0KZ3JvdXBpbmcgPC0gY2FzaCRjb21wYW55CnNwbGl0X2Nhc2ggPC0gc3BsaXQoY2FzaCwgZ3JvdXBpbmcpCgpzcGxpdF9jYXNoIApgYGAKVG8gZ2V0IHlvdXIgb3JpZ2luYWwgZGF0YSBmcmFtZSBiYWNrLCB1c2U6CmBgYHtyfQp1bnNwbGl0KHNwbGl0X2Nhc2gsIGdyb3VwaW5nKQpgYGAKYGBge3J9CiMgRGVmaW5lIGdyb3VwaW5nIGZyb20geWVhcgpncm91cGluZyA8LSBjYXNoJHllYXIKCiMgU3BsaXQgY2FzaCBvbiB5b3VyIG5ldyBncm91cGluZwpzcGxpdF9jYXNoIDwtIHNwbGl0KGNhc2gsIGdyb3VwaW5nKQoKIyBMb29rIGF0IHlvdXIgc3BsaXRfY2FzaCBsaXN0CnNwbGl0X2Nhc2gKCiMgVW5zcGxpdCBzcGxpdF9jYXNoIHRvIGdldCB0aGUgb3JpZ2luYWwgZGF0YSBiYWNrLgpvcmlnaW5hbF9jYXNoIDwtIHVuc3BsaXQoc3BsaXRfY2FzaCwgZ3JvdXBpbmcpCgojIFByaW50IG9yaWdpbmFsX2Nhc2gKb3JpZ2luYWxfY2FzaApgYGAKIyMjIFNwbGl0LUFwcGx5LUNvbWJpbmUKCkEgY29tbW9uIGRhdGEgc2NpZW5jZSBwcm9ibGVtIGlzIHRvIHNwbGl0IHlvdXIgZGF0YSBmcmFtZSBieSBhIGdyb3VwaW5nLCBhcHBseSBzb21lIHRyYW5zZm9ybWF0aW9uIHRvIGVhY2ggZ3JvdXAsIGFuZCB0aGVuIHJlY29tYmluZSB0aG9zZSBwaWVjZXMgYmFjayBpbnRvIG9uZSBkYXRhIGZyYW1lLiBUaGlzIGlzIHN1Y2ggYSBjb21tb24gY2xhc3Mgb2YgcHJvYmxlbXMgaW4gUiB0aGF0IGl0IGhhcyBiZWVuIGdpdmVuIHRoZSBuYW1lIHNwbGl0LWFwcGx5LWNvbWJpbmUuCgpTdXBwb3NlLCBmb3IgdGhlIGNhc2ggZGF0YSBmcmFtZSwgeW91IGFyZSBpbnRlcmVzdGVkIGluIGRvdWJsaW5nIHRoZSBjYXNoX2Zsb3cgZm9yIGNvbXBhbnkgQSwgYW5kIHRyaXBsaW5nIGl0IGZvciBjb21wYW55IEI6CmBgYHtyfQpncm91cGluZyA8LSBjYXNoJGNvbXBhbnkKc3BsaXRfY2FzaCA8LSBzcGxpdChjYXNoLCBncm91cGluZykKCiMgV2UgY2FuIGFjY2VzcyBlYWNoIGxpc3QgZWxlbWVudCdzIGNhc2hfZmxvdyBjb2x1bW4gYnk6CnNwbGl0X2Nhc2gkQSRjYXNoX2Zsb3cKCnNwbGl0X2Nhc2gkQSRjYXNoX2Zsb3cgPC0gc3BsaXRfY2FzaCRBJGNhc2hfZmxvdyAqIDIKc3BsaXRfY2FzaCRCJGNhc2hfZmxvdyA8LSBzcGxpdF9jYXNoJEIkY2FzaF9mbG93ICogMwoKbmV3X2Nhc2ggPC0gdW5zcGxpdChzcGxpdF9jYXNoLCBncm91cGluZykKbmV3X2Nhc2gKYGBgCmBgYHtyfQojIFByaW50IHRoZSBjYXNoX2Zsb3cgY29sdW1uIG9mIEIgaW4gc3BsaXRfY2FzaApzcGxpdF9jYXNoJEIkY2FzaF9mbG93CgojIFNldCB0aGUgY2FzaF9mbG93IGNvbHVtbiBvZiBjb21wYW55IEEgaW4gc3BsaXRfY2FzaCB0byAwCnNwbGl0X2Nhc2gkQSRjYXNoX2Zsb3cgPC0gMAoKIyBVc2UgdGhlIGdyb3VwaW5nIHRvIHVuc3BsaXQgc3BsaXRfY2FzaApjYXNoX25vX0EgPC0gdW5zcGxpdChzcGxpdF9jYXNoLCBncm91cGluZykKCiMgUHJpbnQgY2FzaF9ub19BCmNhc2hfbm9fQQpgYGAKIyMjIEF0dHJpYnV0ZXMKCkF0dHJpYnV0ZXMgYXJlIGEgYml0IG9mIGV4dHJhIG1ldGFkYXRhIGFib3V0IHlvdXIgZGF0YSBzdHJ1Y3R1cmUuIFNvbWUgb2YgdGhlIG1vc3QgY29tbW9uIGF0dHJpYnV0ZXMgYXJlOiByb3cgbmFtZXMgYW5kIGNvbHVtbiBuYW1lcywgZGltZW5zaW9ucywgYW5kIGNsYXNzLiBZb3UgY2FuIHVzZSB0aGUgYXR0cmlidXRlcygpIGZ1bmN0aW9uIHRvIHJldHVybiBhIGxpc3Qgb2YgYXR0cmlidXRlcyBhYm91dCB0aGUgb2JqZWN0IHlvdSBwYXNzIGluLiBUbyBhY2Nlc3MgYSBzcGVjaWZpYyBhdHRyaWJ1dGUsIHlvdSBjYW4gdXNlIHRoZSBhdHRyKCkgZnVuY3Rpb24uCmBgYHtyfQojIG15X21hdHJpeCBhbmQgbXlfZmFjdG9yCm15X21hdHJpeCA8LSBtYXRyaXgoYygxLDIsMyw0LDUsNiksIG5yb3cgPSAyLCBuY29sID0gMykKcm93bmFtZXMobXlfbWF0cml4KSA8LSBjKCJSb3cxIiwgIlJvdzIiKQpjb2xuYW1lcyhteV9tYXRyaXgpIDwtIGMoIkNvbDEiLCAiQ29sMiIsICJDb2wzIikKCm15X2ZhY3RvciA8LSBmYWN0b3IoYygiQSIsICJBIiwgIkIiKSwgb3JkZXJlZCA9IFQsIGxldmVscyA9IGMoIkEiLCAiQiIpKQoKIyBhdHRyaWJ1dGVzIG9mIG15X21hdHJpeAphdHRyaWJ1dGVzKG15X21hdHJpeCkKCiMgSnVzdCB0aGUgZGltIGF0dHJpYnV0ZSBvZiBteV9tYXRyaXgKYXR0cihteV9tYXRyaXgsIHdoaWNoID0gImRpbSIpCgojIGF0dHJpYnV0ZXMgb2YgbXlfZmFjdG9yCmF0dHJpYnV0ZXMobXlfZmFjdG9yKQpgYGAKCg==