Associated Material
Zoom Notes: Zoom Notes 08 - Repeating
Code
Readings:
Introduction
In the previous module we learned to make our code more
modular by organising it into functions, each of which
encapsulates some logically distinct task. By repeatedly calling a
function, we can execute the same code many times, while only having to
type it out once. This is code reuse and is an
important goal in efficient software development.
We can also achieve code reuse through iteration.
Iterative constructs (more casually called loops) allow
us to write a code block once, then instruct R to execute it a specified
number of times. The number of iterations can be made to vary depending
on the state. (Recall that state is
the set of values of all the variables in the environment when a command
is executed.) For example, we can write a loop that iterates as many
times as there are rows in a data frame that we read from a file before
the loop starts.
In R, as in most modern programming languages, there are different
types of loops, with subtle differences in behaviour. We begin with the
most general kind of loop – the for loop.
Syntax
In R a for loop has the following structure:
for (variable_name
in some_kind_of_sequence)
{
Code block to be repeated. Can be as long as
required.
}
The keywords for and in are
required, as are the round brackets in the loop header,
and the curly brackets that delineate the code body.
The some_kind_of sequence is usually a vector. The code body
is executed as many times as there are elements in the vector.
We will discuss the role of the variable_name element later
in the module.
(It is also syntactically acceptable to place the opening curly
bracket on the same line as the for loop header, after the closing round
bracket, separated by a space.)
Basic for loop
A popular cheer in Australian sports is “Aussie!, Aussie!, Aussie!”.
Assume that (for some inexplicable reason) you wished to print this
cheer. That is, you want to print “Aussie!” to the console three times.
Using only sequential code you would write:
print("Aussie!")
print("Aussie!")
print("Aussie!")
You are executing the identical line of code three times. Having to
type the same line of code multiple times is boring, and increases the
number of opportunities for typos and bugs to sneak in. (In this toy
example, we are only repeating one line of code three times; in a real
computational situation we might need to repeat dozens of lines of code
hundreds of times.) Using a for loop, we can achieve
the same output while only typing the command once.
for (cheer in c(1,2,3))
{
print("Aussie")
}
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
Match the parts of this loop to the schematic, noting the position of
the keywords for and in, the round
brackets, and the curly brackets. Note the
some_kind_of_sequence element which, in this case, is the
vector created by c(1,2,3)
. Since there are three elements
in the vector, the code body is executed three times.
Vector sequences
If we wanted to print “Aussie!” 5 times, we could increase the length
of the vector to 5. If we wanted to print it 100 times (could happen) we
could increase the length of the vector to 100, but using function
c()
for this is too cumbersome. In R, we have an
alternative for generating a sequence of numbers – the :
operator.
small_seq <- 1:5
small_seq
#> [1] 1 2 3 4 5
big_seq <- 1:50
big_seq
#> [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
#> [26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
There are more powerful R functions for generating sequences (see,
for example seq
and rep
) but for basic for
loops, the :
operator is sufficient. We can extend our
cheer-printing for loop:
for (cheer in 1:10)
{
print("Aussie")
}
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
#> [1] "Aussie"
The Loop Driver
Recall the schematic for a for loop in R:
for (variable_name
in some_kind_of_sequence)
{
Code to be repeated. Can be as long as required.
}
The variable_name element can be any legal R variable name.
This element is called the loop driver. Inside the code
body of the for loop, the loop driver variable is always
available. For example, in our “Aussie!, Aussie! Aussie!”
example, our loop driver was called cheer. In our code body we
could have referred to variable cheer
.
As discussed above, the for loop code body is executed as many times
as there are elements in the sequence in the header. At each pass
through the loop, the loop driver variable automatically takes on
the value of the corresponding element of the sequence.
That is, in the first pass of the loop, the loop driver holds the value
of the first element of the sequence; in the second pass of the loop,
the loop driver holds the value of the second element of the sequence,
and so on.
We illustrate this by extending our previous example to print the
value of loop driver cheer
inside the code body:
for (cheer in 1:3)
{
print("Aussie")
print(cheer)
}
#> [1] "Aussie"
#> [1] 1
#> [1] "Aussie"
#> [1] 2
#> [1] "Aussie"
#> [1] 3
Note that you never assign a value to the loop
driver – it takes on its values automatically as the for loop
runs.
In all our examples so far, the sequence in the for loop header has
been numbers from 1 to n. In R, the sequence can be a vector of
any type, and the loop driver will take on whatever values the sequence
contains. For example, we can drive a for loop with a vector of
string:
sports <- c("Rugby", "Cycling", "Ice Skating")
for (current_sport in sports)
{
# Print the sport name
print(current_sport)
# Compute the number of characters in the sport name
print(nchar(current_sport))
}
#> [1] "Rugby"
#> [1] 5
#> [1] "Cycling"
#> [1] 7
#> [1] "Ice Skating"
#> [1] 11
Loop driver as index
Throughout the course we have seen that R relies heavily on managing
data in ordered collections (vectors, lists, and data frames). We select
elements from those collections using the selection operator
[]
, providing the ordinal position of the element of
interest. Since loop driver variables take on each value in their
sequence, we can use a for loop to step through each element of a
collection in turn.
For example, assume you have a data frame containing one student’s
internal and exam marks for the papers taken in one semester:
paper_codes <- c("HUBS192", "ECOL212", "STAT260")
internal_marks <- c(87, 85, 62)
exam_marks <- c(93, 84, 85)
marks_df <- data.frame(PaperCode = paper_codes,
InternalMark = as.numeric(internal_marks),
ExamMark = as.numeric(exam_marks))
marks_df
#> PaperCode InternalMark ExamMark
#> 1 HUBS192 87 93
#> 2 ECOL212 85 84
#> 3 STAT260 62 85
We know that we can select all columns from a single row in that data
frame using the syntax [row number, ]
# Select and print row 2
selected_row <- marks_df[2, ]
print(selected_row)
#> PaperCode InternalMark ExamMark
#> 2 ECOL212 85 84
With a for loop, we can use the loop driver to iterate over all the
rows, processing each in turn:
for (index in 1:3)
{
# Use the loop driver to select a row from the data frame
selected_row <- marks_df[index, ]
# Process the row (just printing in this example)
print(selected_row)
}
#> PaperCode InternalMark ExamMark
#> 1 HUBS192 87 93
#> PaperCode InternalMark ExamMark
#> 2 ECOL212 85 84
#> PaperCode InternalMark ExamMark
#> 3 STAT260 62 85
Note that if we made our data frame longer than three rows by adding
more papers to it, the preceding for loop would not
print all the rows; the sequence in that example is always
1, 2, 3
so we see only rows 1, 2, and 3. We can make the
loop more general by determining the for loop sequence
dynamically using function nrow
, which
accepts a data frame as an argument, and returns the number of rows in
the data frame:
# Display all rows
for (index in 1:nrow(marks_df))
{
# Use the loop driver to index into the data frame
selected_row <- marks_df[index, ]
print(selected_row)
}
#> PaperCode InternalMark ExamMark
#> 1 HUBS192 87 93
#> PaperCode InternalMark ExamMark
#> 2 ECOL212 85 84
#> PaperCode InternalMark ExamMark
#> 3 STAT260 62 85
# Add a row to the data frame
marks_df <- rbind(marks_df, data.frame(PaperCode = "ZOOL316",
InternalMark = 83,
ExamMark = 90))
# Repeat the loop -- see four rows
for (index in 1:nrow(marks_df))
{
# Use the loop driver to index into the data frame
selected_row <- marks_df[index, ]
print(selected_row)
}
#> PaperCode InternalMark ExamMark
#> 1 HUBS192 87 93
#> PaperCode InternalMark ExamMark
#> 2 ECOL212 85 84
#> PaperCode InternalMark ExamMark
#> 3 STAT260 62 85
#> PaperCode InternalMark ExamMark
#> 4 ZOOL316 83 90
Exercise
- Write a for loop that iterates over marks_df printing each
column in turn.
- Your final mark in each paper is computed as 40% of your internal
mark plus 60% of your exam mark. Using the technique of your choice, add
a new column to data frame marks_df which contains the computed final
mark for each paper.
- Run your for loop again and confirm that it displays all
the columns, including the new one.
# Display all columns
for (index in 1:ncol(marks_df))
{
# Use the loop driver to index into the data frame
selected_col <- marks_df[ , index]
print(selected_col)
}
#> [1] "HUBS192" "ECOL212" "STAT260" "ZOOL316"
#> [1] 87 85 62 83
#> [1] 93 84 85 90
# Add a new column
marks_df$TotalMark <- (0.40 * marks_df$InternalMark) + (0.60 * marks_df$ExamMark)
# Confirm that we display all four columns
for (index in 1:ncol(marks_df))
{
# Use the loop driver to index into the data frame
selected_col <- marks_df[ , index]
print(selected_col)
}
#> [1] "HUBS192" "ECOL212" "STAT260" "ZOOL316"
#> [1] 87 85 62 83
#> [1] 93 84 85 90
#> [1] 90.6 84.4 75.8 87.2
Nested for loops
In the preceding examples, we have iterated over a data frame
processing complete rows, or complete columns. Frequently, it is
necessary to iterate over a data frame (or matrix) processing each
individual cell in turn. That is, instead of using the
[, col]
or [row, ]
forms of selection, we need
to specify both a row index and a column index
(i.e. [row, col]
). This is very common processing technique
in simulation, computer graphics, artificial intelligence, and
computational problems requiring matrix algebra.
We iterate over tabular date in an orderly fashion. For example, if
we have a 3x3 matrix or data frame we would process the cells in the
first row from left to right ([1,1], [1,2], [1,3]), then the cells in
the second row ([2,1], [2,2], [2,3]), and finally the cells in the third
row ([3,1], [3,1], [3,3]). You can view this pattern as using
two loop drivers, one for the row index and one for the
column index. While the row driver is 1, we want the column driver to
loop through values 1, 2, and 3. Then, we want the row driver to take on
2, and again want the column driver to loop through 1, 2, and 3. Finally
we want the row driver to be 3, and the column driver to loop again. We
can achieve this by nesting a for loop for columns
inside a for loop for rows, as shown below. Note that
each for loop has its own loop driver, its own sequence and its own
round and curly brackets. The style of indenting the inner for
loop is important for maintaining code readability.
# Outer loop.
for (row_index in 1:nrow(marks_df))
{
# Inner loop -- makes all iterations for each pass through outer loop
for (col_index in 1:ncol(marks_df))
{
# Use both loop drivers to select
cell_value <- marks_df[row_index, col_index]
print(cell_value)
}
}
#> [1] "HUBS192"
#> [1] 87
#> [1] 93
#> [1] 90.6
#> [1] "ECOL212"
#> [1] 85
#> [1] 84
#> [1] 84.4
#> [1] "STAT260"
#> [1] 62
#> [1] 85
#> [1] 75.8
#> [1] "ZOOL316"
#> [1] 83
#> [1] 90
#> [1] 87.2
Exercise
The preceding example prints row-wise. That is, it prints
all the values for each row (i.e. for a single paper) before moving to
the next row (paper). Modify the code to print column-wise.
That is, print down the columns: all the paper names, then all the
internal marks, then all the exam marks, then all the final marks.
# Outer loop.
for (col_index in 1:ncol(marks_df))
{
# Inner loop -- makes all iterations for each pass through outer loop
for (row_index in 1:nrow(marks_df))
{
# Use both loop drivers to select
cell_value <- marks_df[row_index, col_index]
print(cell_value)
}
}
#> [1] "HUBS192"
#> [1] "ECOL212"
#> [1] "STAT260"
#> [1] "ZOOL316"
#> [1] 87
#> [1] 85
#> [1] 62
#> [1] 83
#> [1] 93
#> [1] 84
#> [1] 85
#> [1] 90
#> [1] 90.6
#> [1] 84.4
#> [1] 75.8
#> [1] 87.2
CAUTION
Using a nested for loop to visit every cell in a table is a very
common, and very powerful code pattern. However, be aware that it can be
computationally expensive (i.e. it can take a long time to run). If your
outer loop runs n
passes and your inner loop runs
m
passes, you make a total of n * m
passes.
When processing a 1000 row x 1000 column table with a nested for loop,
the code body of the inner loop is executed one million times, which may
be intractable. If you have large tabular data sets that take a long
time to process, you should consider leveraging R’s advanced vector
processing techniques that can be more efficient than an interior for
loop. See, for example, https://rstudio-pubs-static.s3.amazonaws.com/72295_692737b667614d369bd87cb0f51c9a4b.html
or http://www.john-ros.com/Rcourse/memory.html for
discussions.
While loop
The for loop is used when you want to execute a code
body a specific number of times, or iterate over a specific sequence of
values. An alternative loop structure – the while loop
repeats as long as a given condition evaluates to true.
The schematic for a while
loop is as follows:
while (condition)
{
# Loop body
}
In an earlier module, we used function rnorm
to randomly
select a value from a normal distribution with a known mean and standard
deviation. Imagine that you want to explore the probability of randomly
selecting a number from such a distribution that is more than two
standard deviations above the mean (i.e. has a z-score of 2 or more).
You could estimate this by repeatedly selecting a number until you
achieved the criterion, and counting the number of times you had to
select. We wish to loop repeatedly over some logic (selecting and
counting), but we don’t know exactly how many times the loop should run,
so a for loop is not appropriate. In this situation, we use a
while loop.
Before looking at the code sample below, try to work out what
the while loop condition will be.
# Define the parameters
distribution_mean <- 100
distribution_sd <- 10
# Prepare a variable to count the passes
count <- 0
# Make your first selection so the loop condition to be evaluated
# on the first pass
rand_value <- rnorm(1, distribution_mean, distribution_sd)
# The loop. Note the condition. We continue running the loop
# as long as our selected value is less than mean + 2*sd.
# While loops run as long as the loop condition is true.
while (rand_value < distribution_mean + (2 * distribution_sd))
{
# increment the count because the loop condition was true
count <- count + 1
# Select again
rand_value <- rnorm(1, distribution_mean, distribution_sd)
} # end of while loop
# Display the result
output <- paste(count, "values were chosen before z-score > 1")
print(output)
#> [1] "8 values were chosen before z-score > 1"
Here is an example of a while
loop to count how many
iterations it takes to obtain 3 heads in a row:
## Example from R for Data Science - 21.3.4 ##
# Function to simulate head or tail as the result of a coin flip
flip <- function(){
sample(c("T", "H"), 1)
}
# variables to keep track of key results
flips <- 0
nheads <- 0
# flip a coin until there are three heads and count how many flips were performed.
while (nheads < 3) {
if (flip() == "H") {
nheads <- nheads + 1
} else {
nheads <- 0
}
flips <- flips + 1
}
flips
#> [1] 15
Infinite while loops
NB: It is essential that your while loop condition will
eventually evaluate to false. Consider the following
code sample (which we will not run).
# Set a starting value so we can check the condition on the first pass
x <- 10
# The loop
while (x > 0)
{
# The code body
x <- x + 1
}
The variable x is initialised to 10, and incremented at each pass
through the code body. Its value will therefore always be greater than
or equal to 10. The loop condition is x > 0
. Since x
starts at 10 and increases at each pass, it will always be greater than
0, so the loop condition will always be true, and the loop will never
stop. This is an infinite loop. When your code is in an
infinite loop, the only way to stop it is to forcibly terminate the
program (assuming you recognise what has occurred). In R you can usually
do this by clicking the red stop sign in the top right corner of the
console window. An infinite loop that produces a lot of variables can
consume memory to the point where the machine will crash. This is bad.
Always check that your loop condition is guaranteed to eventually
evaluate to false before running code with a while loop.
Map
In the package purrr
(part of package tidyverse), there
are a collection of map
functions which iterate over a
vector or list, applying a function to each element. This is a very
succinct syntax, which achieves the same result as calling the function
inside a for loop, without the overhead of writing out the loop
structure.
library(purrr)
farenheit_to_celcius <- function(temp_f){
temp_c <- (temp_f - 32) * 5/9
return(temp_c)
}
my_temps_f <- c(90, 78, 88, 89, 77)
# map applies the function (2nd argument) to each element of the vector (1st argument)
# and returns the results as a list.
my_temps_c_list <- map(my_temps_f, farenheit_to_celcius)
my_temps_c_list
#> [[1]]
#> [1] 32.22222
#>
#> [[2]]
#> [1] 25.55556
#>
#> [[3]]
#> [1] 31.11111
#>
#> [[4]]
#> [1] 31.66667
#>
#> [[5]]
#> [1] 25
The map
argument names are .x
and
.f
, so the call to map
above could also be
written as
my_temps_c_list <- map(.x = my_temps_f, .f = farenheit_to_celcius)
Note that when providing a function as an argument, give only
the function name. Do not follow the function name with () as
for a function call.
Map and friends
The basic form of map
above, returns the results in a
list. There are suffix versions of map
that return the
results as a specific data type.
map()
makes a list.
map_lgl()
makes a logical vector.
map_int()
makes an integer vector.
map_dbl()
makes a double vector.
map_chr()
makes a character vector.
These suffix versions will give an error if the data type of the
results doesn’t match the intended return type. This is useful because
you can write code to process the results further, confident that they
are of a specific data type.
Apply
Base R has a set of built in functions that duplicate the behaviour
of purrr::map
and its suffix functions. These are the
apply family: apply
, lapply
,
sapply
, mapply
, and tapply
. The
functions differ primarily in the structure of the data they return.
See, for example, http://adv-r.had.co.nz/Functionals.html for more
detail.
Function lapply
is analogous to
purrr::map()
:
farenheit_to_celcius <- function(temp_f){
temp_c <- (temp_f -32) * 5/9
return(temp_c)
}
my_temps_f <- c(90, 78, 88, 89, 77)
# lapply example
lapply_my_temps_c <- lapply(X = my_temps_f, FUN = farenheit_to_celcius)
lapply_my_temps_c
#> [[1]]
#> [1] 32.22222
#>
#> [[2]]
#> [1] 25.55556
#>
#> [[3]]
#> [1] 31.11111
#>
#> [[4]]
#> [1] 31.66667
#>
#> [[5]]
#> [1] 25
Note that some of the apply family return different data structures
depending on the type of the input data. This can make it challenging to
know beforehand what the output is going to look like - unlike the
suffix versions of purrr::map
Conclusion
In this module we covered using for and while loops to repeat code
fragments efficiently. We saw that functions in the map and apply
families provide an equivalent, yet more succinct syntax, when the
repeated code is a single function. Combining loops with functions and
conditional flow of control from last week’s session, you can create
code that is modular, reusable, and maintainable.
What’s Next
Next week we conclude the formal content of R4SSP with a discussion
of R workflows, including project structure, incremental development,
and effective debugging techniques.
Please fill in the module feedback form https://tinyurl.com/r4ssp-module-fb.
LS0tCnRpdGxlOiAiUmVwZWF0aW5nIENvZGUiCmRhdGU6ICJTZW1lc3RlciAyLCAyMDIyIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfZGVwdGg6IDMKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQoKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNvbW1lbnQgPSAiIz4iLAogIGZpZy5wYXRoID0gImZpZ3VyZXMvMDgvIiwgIyB1c2Ugb25seSBmb3Igc2luZ2xlIFJtZCBmaWxlcwogIGNvbGxhcHNlID0gVFJVRSwKICBlY2hvID0gVFJVRQopCgojIGtlZXAgdGhlIHJlc3VsdGluZyBodG1sIHRoZSBzYW1lIHNpbmNlIHNhbXBsaW5nIGlzIHVzZWQgbGF0ZXIgb24gaW4gdGhlIGxlc3NvbgpzZXQuc2VlZCg0MikKCmBgYAoKPiAjIyMjIEFzc29jaWF0ZWQgTWF0ZXJpYWwKPgo+IFpvb20gTm90ZXM6IFtab29tIE5vdGVzIDA4IC0gUmVwZWF0aW5nIENvZGVdKHpvb21fbm90ZXNfMDguaHRtbCkKPgo+IFJlYWRpbmdzOgo+Cj4gLSBbUiBmb3IgRGF0YSBTY2llbmNlIC0gQ2hhcHRlciAyMV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei9pdGVyYXRpb24uaHRtbCkKClwKCiMgSW50cm9kdWN0aW9uCgpJbiB0aGUgcHJldmlvdXMgbW9kdWxlIHdlIGxlYXJuZWQgdG8gbWFrZSBvdXIgY29kZSBtb3JlICoqbW9kdWxhcioqIGJ5IG9yZ2FuaXNpbmcgaXQgaW50byBmdW5jdGlvbnMsIGVhY2ggb2Ygd2hpY2ggZW5jYXBzdWxhdGVzIHNvbWUgbG9naWNhbGx5IGRpc3RpbmN0IHRhc2suIEJ5IHJlcGVhdGVkbHkgY2FsbGluZyBhIGZ1bmN0aW9uLCB3ZSBjYW4gZXhlY3V0ZSB0aGUgc2FtZSBjb2RlIG1hbnkgdGltZXMsIHdoaWxlIG9ubHkgaGF2aW5nIHRvIHR5cGUgaXQgb3V0IG9uY2UuIFRoaXMgaXMgKipjb2RlIHJldXNlKiogYW5kIGlzIGFuIGltcG9ydGFudCBnb2FsIGluIGVmZmljaWVudCBzb2Z0d2FyZSBkZXZlbG9wbWVudC4KCldlIGNhbiBhbHNvIGFjaGlldmUgY29kZSByZXVzZSB0aHJvdWdoICoqaXRlcmF0aW9uKiouIEl0ZXJhdGl2ZSBjb25zdHJ1Y3RzIChtb3JlIGNhc3VhbGx5IGNhbGxlZCAqKmxvb3BzKiopIGFsbG93IHVzIHRvIHdyaXRlIGEgY29kZSBibG9jayBvbmNlLCB0aGVuIGluc3RydWN0IFIgdG8gZXhlY3V0ZSBpdCBhIHNwZWNpZmllZCBudW1iZXIgb2YgdGltZXMuIFRoZSBudW1iZXIgb2YgaXRlcmF0aW9ucyBjYW4gYmUgbWFkZSB0byB2YXJ5IGRlcGVuZGluZyBvbiB0aGUgKipzdGF0ZSoqLiAoUmVjYWxsIHRoYXQgKipzdGF0ZSoqIGlzIHRoZSBzZXQgb2YgdmFsdWVzIG9mIGFsbCB0aGUgdmFyaWFibGVzIGluIHRoZSBlbnZpcm9ubWVudCB3aGVuIGEgY29tbWFuZCBpcyBleGVjdXRlZC4pIEZvciBleGFtcGxlLCB3ZSBjYW4gd3JpdGUgYSBsb29wIHRoYXQgaXRlcmF0ZXMgYXMgbWFueSB0aW1lcyBhcyB0aGVyZSBhcmUgcm93cyBpbiBhIGRhdGEgZnJhbWUgdGhhdCB3ZSByZWFkIGZyb20gYSBmaWxlIGJlZm9yZSB0aGUgbG9vcCBzdGFydHMuCgpJbiBSLCBhcyBpbiBtb3N0IG1vZGVybiBwcm9ncmFtbWluZyBsYW5ndWFnZXMsIHRoZXJlIGFyZSBkaWZmZXJlbnQgdHlwZXMgb2YgbG9vcHMsIHdpdGggc3VidGxlIGRpZmZlcmVuY2VzIGluIGJlaGF2aW91ci4gV2UgYmVnaW4gd2l0aCB0aGUgbW9zdCBnZW5lcmFsIGtpbmQgb2YgbG9vcCAtLSB0aGUgKipmb3IgbG9vcCoqLgoKCiMgU3ludGF4CgpJbiBSIGEgKipmb3IgbG9vcCoqIGhhcyB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZToKCgp8ICoqZm9yKiogKCp2YXJpYWJsZV9uYW1lKiAqKmluKiogKnNvbWVfa2luZF9vZl9zZXF1ZW5jZSopCnwgewp8ICAgICAqQ29kZSBibG9jayB0byBiZSByZXBlYXRlZC4gQ2FuIGJlIGFzIGxvbmcgYXMgcmVxdWlyZWQuKgp8IH0KClwKClRoZSBrZXl3b3JkcyAqKmZvcioqIGFuZCAqKmluKiogYXJlIHJlcXVpcmVkLCBhcyBhcmUgdGhlIHJvdW5kIGJyYWNrZXRzIGluIHRoZSAqKmxvb3AgaGVhZGVyKiosIGFuZCB0aGUgY3VybHkgYnJhY2tldHMgdGhhdCBkZWxpbmVhdGUgdGhlIGNvZGUgYm9keS4KClRoZSAqc29tZV9raW5kX29mIHNlcXVlbmNlKiBpcyB1c3VhbGx5IGEgdmVjdG9yLiBUaGUgY29kZSBib2R5IGlzIGV4ZWN1dGVkIGFzIG1hbnkgdGltZXMgYXMgdGhlcmUgYXJlIGVsZW1lbnRzIGluIHRoZSB2ZWN0b3IuCgpXZSB3aWxsIGRpc2N1c3MgdGhlIHJvbGUgb2YgdGhlICp2YXJpYWJsZV9uYW1lKiBlbGVtZW50IGxhdGVyIGluIHRoZSBtb2R1bGUuCgooSXQgaXMgYWxzbyBzeW50YWN0aWNhbGx5IGFjY2VwdGFibGUgdG8gcGxhY2UgdGhlIG9wZW5pbmcgY3VybHkgYnJhY2tldCBvbiB0aGUgc2FtZSBsaW5lIGFzIHRoZSBmb3IgbG9vcCBoZWFkZXIsIGFmdGVyIHRoZSBjbG9zaW5nIHJvdW5kIGJyYWNrZXQsIHNlcGFyYXRlZCBieSBhIHNwYWNlLikKCgojIEJhc2ljIGZvciBsb29wCgpBIHBvcHVsYXIgY2hlZXIgaW4gQXVzdHJhbGlhbiBzcG9ydHMgaXMgIkF1c3NpZSEsIEF1c3NpZSEsIEF1c3NpZSEiLiBBc3N1bWUgdGhhdCAoZm9yIHNvbWUgaW5leHBsaWNhYmxlIHJlYXNvbikgeW91IHdpc2hlZCB0byBwcmludCB0aGlzIGNoZWVyLiBUaGF0IGlzLCB5b3Ugd2FudCB0byBwcmludCAiQXVzc2llISIgdG8gdGhlIGNvbnNvbGUgdGhyZWUgdGltZXMuIFVzaW5nIG9ubHkgc2VxdWVudGlhbCBjb2RlIHlvdSB3b3VsZCB3cml0ZToKCmBgYHtyIHNlcXVlbnRpYWwsIGV2YWw9RkFMU0V9CnByaW50KCJBdXNzaWUhIikKcHJpbnQoIkF1c3NpZSEiKQpwcmludCgiQXVzc2llISIpCmBgYAoKWW91IGFyZSBleGVjdXRpbmcgdGhlIGlkZW50aWNhbCBsaW5lIG9mIGNvZGUgdGhyZWUgdGltZXMuIEhhdmluZyB0byB0eXBlIHRoZSBzYW1lIGxpbmUgb2YgY29kZSBtdWx0aXBsZSB0aW1lcyBpcyBib3JpbmcsIGFuZCBpbmNyZWFzZXMgdGhlIG51bWJlciBvZiBvcHBvcnR1bml0aWVzIGZvciB0eXBvcyBhbmQgYnVncyB0byBzbmVhayBpbi4gKEluIHRoaXMgdG95IGV4YW1wbGUsIHdlIGFyZSBvbmx5IHJlcGVhdGluZyBvbmUgbGluZSBvZiBjb2RlIHRocmVlIHRpbWVzOyBpbiBhIHJlYWwgY29tcHV0YXRpb25hbCBzaXR1YXRpb24gd2UgbWlnaHQgbmVlZCB0byByZXBlYXQgZG96ZW5zIG9mIGxpbmVzIG9mIGNvZGUgaHVuZHJlZHMgb2YgdGltZXMuKSBVc2luZyBhICoqZm9yIGxvb3AqKiwgd2UgY2FuIGFjaGlldmUgdGhlIHNhbWUgb3V0cHV0IHdoaWxlIG9ubHkgdHlwaW5nIHRoZSBjb21tYW5kIG9uY2UuCgpgYGB7ciBiYXNpYyBsb29wfQpmb3IgKGNoZWVyIGluIGMoMSwyLDMpKQp7CiAgcHJpbnQoIkF1c3NpZSIpCn0KYGBgCgpNYXRjaCB0aGUgcGFydHMgb2YgdGhpcyBsb29wIHRvIHRoZSBzY2hlbWF0aWMsIG5vdGluZyB0aGUgcG9zaXRpb24gb2YgdGhlIGtleXdvcmRzICoqZm9yKiogYW5kICoqaW4qKiwgdGhlIHJvdW5kIGJyYWNrZXRzLCBhbmQgdGhlIGN1cmx5IGJyYWNrZXRzLiBOb3RlIHRoZSAqc29tZV9raW5kX29mX3NlcXVlbmNlKiBlbGVtZW50IHdoaWNoLCBpbiB0aGlzIGNhc2UsIGlzIHRoZSB2ZWN0b3IgY3JlYXRlZCBieSBgYygxLDIsMylgLiBTaW5jZSB0aGVyZSBhcmUgdGhyZWUgZWxlbWVudHMgaW4gdGhlIHZlY3RvciwgdGhlIGNvZGUgYm9keSBpcyBleGVjdXRlZCB0aHJlZSB0aW1lcy4gCgojIyBWZWN0b3Igc2VxdWVuY2VzCgpJZiB3ZSB3YW50ZWQgdG8gcHJpbnQgIkF1c3NpZSEiIDUgdGltZXMsIHdlIGNvdWxkIGluY3JlYXNlIHRoZSBsZW5ndGggb2YgdGhlIHZlY3RvciB0byA1LiBJZiB3ZSB3YW50ZWQgdG8gcHJpbnQgaXQgMTAwIHRpbWVzIChjb3VsZCBoYXBwZW4pIHdlIGNvdWxkIGluY3JlYXNlIHRoZSBsZW5ndGggb2YgdGhlIHZlY3RvciB0byAxMDAsIGJ1dCB1c2luZyBmdW5jdGlvbiBgYygpYCBmb3IgdGhpcyBpcyB0b28gY3VtYmVyc29tZS4gSW4gUiwgd2UgaGF2ZSBhbiBhbHRlcm5hdGl2ZSBmb3IgZ2VuZXJhdGluZyBhIHNlcXVlbmNlIG9mIG51bWJlcnMgLS0gdGhlIGA6YCBvcGVyYXRvci4KCmBgYHtyIHNlcSB9CnNtYWxsX3NlcSA8LSAxOjUKc21hbGxfc2VxCgpiaWdfc2VxIDwtIDE6NTAKYmlnX3NlcQpgYGAKClRoZXJlIGFyZSBtb3JlIHBvd2VyZnVsIFIgZnVuY3Rpb25zIGZvciBnZW5lcmF0aW5nIHNlcXVlbmNlcyAoc2VlLCBmb3IgZXhhbXBsZSBgc2VxYCBhbmQgYHJlcGApIGJ1dCBmb3IgYmFzaWMgZm9yIGxvb3BzLCB0aGUgYDpgIG9wZXJhdG9yIGlzIHN1ZmZpY2llbnQuIFdlIGNhbiBleHRlbmQgb3VyIGNoZWVyLXByaW50aW5nIGZvciBsb29wOgoKYGBge3IgbG9uZyBjaGVlcn0KZm9yIChjaGVlciBpbiAxOjEwKQp7CiAgcHJpbnQoIkF1c3NpZSIpCn0KYGBgCgpcCgojIFRoZSBMb29wIERyaXZlcgoKUmVjYWxsIHRoZSBzY2hlbWF0aWMgZm9yIGEgZm9yIGxvb3AgaW4gUjoKCnwgKipmb3IqKiAoKnZhcmlhYmxlX25hbWUqICoqaW4qKiAqc29tZV9raW5kX29mX3NlcXVlbmNlKikKfCB7CnwgICAgICpDb2RlIHRvIGJlIHJlcGVhdGVkLiBDYW4gYmUgYXMgbG9uZyBhcyByZXF1aXJlZC4qCnwgfQoKXApUaGUgKnZhcmlhYmxlX25hbWUqIGVsZW1lbnQgY2FuIGJlIGFueSBsZWdhbCBSIHZhcmlhYmxlIG5hbWUuIFRoaXMgZWxlbWVudCBpcyBjYWxsZWQgdGhlICoqbG9vcCBkcml2ZXIqKi4gSW5zaWRlIHRoZSBjb2RlIGJvZHkgb2YgdGhlIGZvciBsb29wLCB0aGUgbG9vcCBkcml2ZXIgdmFyaWFibGUgKippcyBhbHdheXMgYXZhaWxhYmxlKiouIEZvciBleGFtcGxlLCBpbiBvdXIgIkF1c3NpZSEsIEF1c3NpZSEgQXVzc2llISIgZXhhbXBsZSwgb3VyIGxvb3AgZHJpdmVyIHdhcyBjYWxsZWQgKmNoZWVyKi4gSW4gb3VyIGNvZGUgYm9keSB3ZSBjb3VsZCBoYXZlIHJlZmVycmVkIHRvIHZhcmlhYmxlIGBjaGVlcmAuIAoKQXMgZGlzY3Vzc2VkIGFib3ZlLCB0aGUgZm9yIGxvb3AgY29kZSBib2R5IGlzIGV4ZWN1dGVkIGFzIG1hbnkgdGltZXMgYXMgdGhlcmUgYXJlIGVsZW1lbnRzIGluIHRoZSBzZXF1ZW5jZSBpbiB0aGUgaGVhZGVyLiBBdCBlYWNoIHBhc3MgdGhyb3VnaCB0aGUgbG9vcCwgdGhlIGxvb3AgZHJpdmVyIHZhcmlhYmxlIGF1dG9tYXRpY2FsbHkgdGFrZXMgb24gKip0aGUgdmFsdWUgb2YgdGhlIGNvcnJlc3BvbmRpbmcgZWxlbWVudCBvZiB0aGUgc2VxdWVuY2UqKi4gVGhhdCBpcywgaW4gdGhlIGZpcnN0IHBhc3Mgb2YgdGhlIGxvb3AsIHRoZSBsb29wIGRyaXZlciBob2xkcyB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IGVsZW1lbnQgb2YgdGhlIHNlcXVlbmNlOyBpbiB0aGUgc2Vjb25kIHBhc3Mgb2YgdGhlIGxvb3AsIHRoZSBsb29wIGRyaXZlciBob2xkcyB0aGUgdmFsdWUgb2YgdGhlIHNlY29uZCBlbGVtZW50IG9mIHRoZSBzZXF1ZW5jZSwgYW5kIHNvIG9uLgoKV2UgaWxsdXN0cmF0ZSB0aGlzIGJ5IGV4dGVuZGluZyBvdXIgcHJldmlvdXMgZXhhbXBsZSB0byBwcmludCB0aGUgdmFsdWUgb2YgbG9vcCBkcml2ZXIgYGNoZWVyYCBpbnNpZGUgdGhlIGNvZGUgYm9keToKCmBgYHtyIGxvbmcgY2hlZXIgMn0KZm9yIChjaGVlciBpbiAxOjMpCnsKICBwcmludCgiQXVzc2llIikKICBwcmludChjaGVlcikKfQpgYGAKCk5vdGUgdGhhdCB5b3UgKipuZXZlciBhc3NpZ24gYSB2YWx1ZSB0byB0aGUgbG9vcCBkcml2ZXIqKiAtLSBpdCB0YWtlcyBvbiBpdHMgdmFsdWVzIGF1dG9tYXRpY2FsbHkgYXMgdGhlIGZvciBsb29wIHJ1bnMuCgpJbiBhbGwgb3VyIGV4YW1wbGVzIHNvIGZhciwgdGhlIHNlcXVlbmNlIGluIHRoZSBmb3IgbG9vcCBoZWFkZXIgaGFzIGJlZW4gbnVtYmVycyBmcm9tIDEgdG8gKm4qLiBJbiBSLCB0aGUgc2VxdWVuY2UgY2FuIGJlIGEgdmVjdG9yIG9mIGFueSB0eXBlLCBhbmQgdGhlIGxvb3AgZHJpdmVyIHdpbGwgdGFrZSBvbiB3aGF0ZXZlciB2YWx1ZXMgdGhlIHNlcXVlbmNlIGNvbnRhaW5zLiBGb3IgZXhhbXBsZSwgd2UgY2FuIGRyaXZlIGEgZm9yIGxvb3Agd2l0aCBhIHZlY3RvciBvZiBzdHJpbmc6CgpgYGB7ciBzZXEgb2Ygc3RyaW5nfQpzcG9ydHMgPC0gYygiUnVnYnkiLCAiQ3ljbGluZyIsICJJY2UgU2thdGluZyIpCmZvciAoY3VycmVudF9zcG9ydCBpbiBzcG9ydHMpCnsKICAjIFByaW50IHRoZSBzcG9ydCBuYW1lCiAgcHJpbnQoY3VycmVudF9zcG9ydCkKICAKICAjIENvbXB1dGUgdGhlIG51bWJlciBvZiBjaGFyYWN0ZXJzIGluIHRoZSBzcG9ydCBuYW1lCiAgcHJpbnQobmNoYXIoY3VycmVudF9zcG9ydCkpCn0KICAKYGBgCgpcCgojIyBMb29wIGRyaXZlciBhcyBpbmRleAoKVGhyb3VnaG91dCB0aGUgY291cnNlIHdlIGhhdmUgc2VlbiB0aGF0IFIgcmVsaWVzIGhlYXZpbHkgb24gbWFuYWdpbmcgZGF0YSBpbiBvcmRlcmVkIGNvbGxlY3Rpb25zICh2ZWN0b3JzLCBsaXN0cywgYW5kIGRhdGEgZnJhbWVzKS4gV2Ugc2VsZWN0IGVsZW1lbnRzIGZyb20gdGhvc2UgY29sbGVjdGlvbnMgdXNpbmcgdGhlIHNlbGVjdGlvbiBvcGVyYXRvciBgW11gLCBwcm92aWRpbmcgdGhlIG9yZGluYWwgcG9zaXRpb24gb2YgdGhlIGVsZW1lbnQgb2YgaW50ZXJlc3QuIFNpbmNlIGxvb3AgZHJpdmVyIHZhcmlhYmxlcyB0YWtlIG9uIGVhY2ggdmFsdWUgaW4gdGhlaXIgc2VxdWVuY2UsIHdlIGNhbiB1c2UgYSBmb3IgbG9vcCB0byBzdGVwIHRocm91Z2ggZWFjaCBlbGVtZW50IG9mIGEgY29sbGVjdGlvbiBpbiB0dXJuLgoKRm9yIGV4YW1wbGUsIGFzc3VtZSB5b3UgaGF2ZSBhIGRhdGEgZnJhbWUgY29udGFpbmluZyBvbmUgc3R1ZGVudCdzIGludGVybmFsIGFuZCBleGFtIG1hcmtzIGZvciB0aGUgcGFwZXJzIHRha2VuIGluIG9uZSBzZW1lc3RlcjogCgpgYGB7ciBtYWtlIGRhdGEgZnJhbWV9CnBhcGVyX2NvZGVzIDwtIGMoIkhVQlMxOTIiLCAiRUNPTDIxMiIsICJTVEFUMjYwIikKaW50ZXJuYWxfbWFya3MgPC0gYyg4NywgODUsIDYyKQpleGFtX21hcmtzIDwtIGMoOTMsIDg0LCA4NSkKCm1hcmtzX2RmIDwtIGRhdGEuZnJhbWUoUGFwZXJDb2RlID0gcGFwZXJfY29kZXMsCiAgICAgICAgICAgICAgICAgICAgICAgSW50ZXJuYWxNYXJrID0gYXMubnVtZXJpYyhpbnRlcm5hbF9tYXJrcyksCiAgICAgICAgICAgICAgICAgICAgICAgRXhhbU1hcmsgPSBhcy5udW1lcmljKGV4YW1fbWFya3MpKQoKbWFya3NfZGYKCmBgYAoKV2Uga25vdyB0aGF0IHdlIGNhbiBzZWxlY3QgYWxsIGNvbHVtbnMgZnJvbSBhIHNpbmdsZSByb3cgaW4gdGhhdCBkYXRhIGZyYW1lIHVzaW5nIHRoZSBzeW50YXggWypyb3cgbnVtYmVyKiwgIF0KCmBgYHtyIHNlbGVjdCByb3d9CiMgU2VsZWN0IGFuZCBwcmludCByb3cgMgpzZWxlY3RlZF9yb3cgPC0gbWFya3NfZGZbMiwgXQpwcmludChzZWxlY3RlZF9yb3cpCgpgYGAKCldpdGggYSBmb3IgbG9vcCwgd2UgY2FuIHVzZSB0aGUgbG9vcCBkcml2ZXIgdG8gaXRlcmF0ZSBvdmVyIGFsbCB0aGUgcm93cywgcHJvY2Vzc2luZyBlYWNoIGluIHR1cm46CgpgYGB7ciBzaW1wbGUgZHJpdmVyIGFzIGluZGV4fQpmb3IgKGluZGV4IGluIDE6MykKewogICMgVXNlIHRoZSBsb29wIGRyaXZlciB0byBzZWxlY3QgYSByb3cgZnJvbSB0aGUgZGF0YSBmcmFtZQogIHNlbGVjdGVkX3JvdyA8LSBtYXJrc19kZltpbmRleCwgXQogIAogICMgUHJvY2VzcyB0aGUgcm93IChqdXN0IHByaW50aW5nIGluIHRoaXMgZXhhbXBsZSkKICBwcmludChzZWxlY3RlZF9yb3cpCn0KCmBgYAoKTm90ZSB0aGF0IGlmIHdlIG1hZGUgb3VyIGRhdGEgZnJhbWUgbG9uZ2VyIHRoYW4gdGhyZWUgcm93cyBieSBhZGRpbmcgbW9yZSBwYXBlcnMgdG8gaXQsIHRoZSBwcmVjZWRpbmcgZm9yIGxvb3AgKip3b3VsZCBub3QqKiBwcmludCBhbGwgdGhlIHJvd3M7IHRoZSBzZXF1ZW5jZSBpbiB0aGF0IGV4YW1wbGUgaXMgYWx3YXlzIGAxLCAyLCAzYCBzbyB3ZSBzZWUgb25seSByb3dzIDEsIDIsIGFuZCAzLiBXZSBjYW4gbWFrZSB0aGUgbG9vcCBtb3JlIGdlbmVyYWwgYnkgZGV0ZXJtaW5pbmcgdGhlIGZvciBsb29wIHNlcXVlbmNlICoqZHluYW1pY2FsbHkqKiB1c2luZyBmdW5jdGlvbiBgbnJvd2AsIHdoaWNoIGFjY2VwdHMgYSBkYXRhIGZyYW1lIGFzIGFuIGFyZ3VtZW50LCBhbmQgcmV0dXJucyB0aGUgbnVtYmVyIG9mIHJvd3MgaW4gdGhlIGRhdGEgZnJhbWU6CgpgYGB7ciB1c2luZyBucm93fQojIERpc3BsYXkgYWxsIHJvd3MKZm9yIChpbmRleCBpbiAxOm5yb3cobWFya3NfZGYpKQp7CiAgIyBVc2UgdGhlIGxvb3AgZHJpdmVyIHRvIGluZGV4IGludG8gdGhlIGRhdGEgZnJhbWUKICBzZWxlY3RlZF9yb3cgPC0gbWFya3NfZGZbaW5kZXgsIF0KICBwcmludChzZWxlY3RlZF9yb3cpCn0KCiMgQWRkIGEgcm93IHRvIHRoZSBkYXRhIGZyYW1lCm1hcmtzX2RmIDwtIHJiaW5kKG1hcmtzX2RmLCBkYXRhLmZyYW1lKFBhcGVyQ29kZSA9ICJaT09MMzE2IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEludGVybmFsTWFyayA9IDgzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXhhbU1hcmsgPSA5MCkpCgoKIyBSZXBlYXQgdGhlIGxvb3AgLS0gc2VlIGZvdXIgcm93cwpmb3IgKGluZGV4IGluIDE6bnJvdyhtYXJrc19kZikpCnsKICAjIFVzZSB0aGUgbG9vcCBkcml2ZXIgdG8gaW5kZXggaW50byB0aGUgZGF0YSBmcmFtZQogIHNlbGVjdGVkX3JvdyA8LSBtYXJrc19kZltpbmRleCwgXQogIHByaW50KHNlbGVjdGVkX3JvdykKfQpgYGAKClwKCiMgRXhlcmNpc2UKCjEuIFdyaXRlIGEgZm9yIGxvb3AgdGhhdCBpdGVyYXRlcyBvdmVyIG1hcmtzX2RmIHByaW50aW5nICoqZWFjaCBjb2x1bW4qKiBpbiB0dXJuLgoyLiBZb3VyIGZpbmFsIG1hcmsgaW4gZWFjaCBwYXBlciBpcyBjb21wdXRlZCBhcyA0MCUgb2YgeW91ciBpbnRlcm5hbCBtYXJrIHBsdXMgNjAlIG9mIHlvdXIgZXhhbSBtYXJrLiBVc2luZyB0aGUgdGVjaG5pcXVlIG9mIHlvdXIgY2hvaWNlLCBhZGQgYSBuZXcgY29sdW1uIHRvIGRhdGEgZnJhbWUgbWFya3NfZGYgd2hpY2ggY29udGFpbnMgdGhlIGNvbXB1dGVkIGZpbmFsIG1hcmsgZm9yIGVhY2ggcGFwZXIuCjMuIFJ1biB5b3VyIGZvciBsb29wIGFnYWluIGFuZCBjb25maXJtIHRoYXQgaXQgZGlzcGxheXMgKmFsbCogdGhlIGNvbHVtbnMsIGluY2x1ZGluZyB0aGUgbmV3IG9uZS4KCmBgYHtyIGV4IDEgc29sdXRpb259CiMgRGlzcGxheSBhbGwgY29sdW1ucwpmb3IgKGluZGV4IGluIDE6bmNvbChtYXJrc19kZikpCnsKICAjIFVzZSB0aGUgbG9vcCBkcml2ZXIgdG8gaW5kZXggaW50byB0aGUgZGF0YSBmcmFtZQogIHNlbGVjdGVkX2NvbCA8LSBtYXJrc19kZlsgLCBpbmRleF0KICBwcmludChzZWxlY3RlZF9jb2wpCn0KCgojIEFkZCBhIG5ldyBjb2x1bW4KbWFya3NfZGYkVG90YWxNYXJrIDwtICgwLjQwICogbWFya3NfZGYkSW50ZXJuYWxNYXJrKSArICgwLjYwICogbWFya3NfZGYkRXhhbU1hcmspIAoKCiMgQ29uZmlybSB0aGF0IHdlIGRpc3BsYXkgYWxsIGZvdXIgY29sdW1ucwpmb3IgKGluZGV4IGluIDE6bmNvbChtYXJrc19kZikpCnsKICAjIFVzZSB0aGUgbG9vcCBkcml2ZXIgdG8gaW5kZXggaW50byB0aGUgZGF0YSBmcmFtZQogIHNlbGVjdGVkX2NvbCA8LSBtYXJrc19kZlsgLCBpbmRleF0KICBwcmludChzZWxlY3RlZF9jb2wpCn0KYGBgCgpcCgojIE5lc3RlZCBmb3IgbG9vcHMKCkluIHRoZSBwcmVjZWRpbmcgZXhhbXBsZXMsIHdlIGhhdmUgaXRlcmF0ZWQgb3ZlciBhIGRhdGEgZnJhbWUgcHJvY2Vzc2luZyBjb21wbGV0ZSByb3dzLCBvciBjb21wbGV0ZSBjb2x1bW5zLiBGcmVxdWVudGx5LCBpdCBpcyBuZWNlc3NhcnkgdG8gaXRlcmF0ZSBvdmVyIGEgZGF0YSBmcmFtZSAob3IgbWF0cml4KSBwcm9jZXNzaW5nIGVhY2ggKmluZGl2aWR1YWwgY2VsbCogaW4gdHVybi4gVGhhdCBpcywgaW5zdGVhZCBvZiB1c2luZyB0aGUgYFssIGNvbF1gIG9yIGBbcm93LCBdYCBmb3JtcyBvZiBzZWxlY3Rpb24sIHdlIG5lZWQgdG8gc3BlY2lmeSBib3RoIGEgcm93IGluZGV4IGFuZCBhIGNvbHVtbiBpbmRleCAoaS5lLiBgW3JvdywgY29sXWApLiBUaGlzIGlzIHZlcnkgY29tbW9uIHByb2Nlc3NpbmcgdGVjaG5pcXVlIGluIHNpbXVsYXRpb24sIGNvbXB1dGVyIGdyYXBoaWNzLCBhcnRpZmljaWFsIGludGVsbGlnZW5jZSwgYW5kIGNvbXB1dGF0aW9uYWwgcHJvYmxlbXMgcmVxdWlyaW5nIG1hdHJpeCBhbGdlYnJhLgoKV2UgaXRlcmF0ZSBvdmVyIHRhYnVsYXIgZGF0ZSBpbiBhbiBvcmRlcmx5IGZhc2hpb24uIEZvciBleGFtcGxlLCBpZiB3ZSBoYXZlIGEgM3gzIG1hdHJpeCBvciBkYXRhIGZyYW1lIHdlIHdvdWxkIHByb2Nlc3MgdGhlIGNlbGxzIGluIHRoZSBmaXJzdCByb3cgZnJvbSBsZWZ0IHRvIHJpZ2h0IChbMSwxXSwgWzEsMl0sIFsxLDNdKSwgdGhlbiB0aGUgY2VsbHMgaW4gdGhlIHNlY29uZCByb3cgKFsyLDFdLCBbMiwyXSwgWzIsM10pLCBhbmQgZmluYWxseSB0aGUgY2VsbHMgaW4gdGhlIHRoaXJkIHJvdyAoWzMsMV0sIFszLDFdLCBbMywzXSkuIFlvdSBjYW4gdmlldyB0aGlzIHBhdHRlcm4gYXMgdXNpbmcgKip0d28gbG9vcCBkcml2ZXJzKiosIG9uZSBmb3IgdGhlIHJvdyBpbmRleCBhbmQgb25lIGZvciB0aGUgY29sdW1uIGluZGV4LiBXaGlsZSB0aGUgcm93IGRyaXZlciBpcyAxLCB3ZSB3YW50IHRoZSBjb2x1bW4gZHJpdmVyIHRvIGxvb3AgdGhyb3VnaCB2YWx1ZXMgMSwgMiwgYW5kIDMuIFRoZW4sIHdlIHdhbnQgdGhlIHJvdyBkcml2ZXIgdG8gdGFrZSBvbiAyLCBhbmQgYWdhaW4gd2FudCB0aGUgY29sdW1uIGRyaXZlciB0byBsb29wIHRocm91Z2ggMSwgMiwgYW5kIDMuIEZpbmFsbHkgd2Ugd2FudCB0aGUgcm93IGRyaXZlciB0byBiZSAzLCBhbmQgdGhlIGNvbHVtbiBkcml2ZXIgdG8gbG9vcCBhZ2Fpbi4gV2UgY2FuIGFjaGlldmUgdGhpcyBieSAqKm5lc3RpbmcqKiBhIGZvciBsb29wIGZvciBjb2x1bW5zICoqaW5zaWRlKiogYSBmb3IgbG9vcCBmb3Igcm93cywgYXMgc2hvd24gYmVsb3cuIE5vdGUgdGhhdCBlYWNoIGZvciBsb29wIGhhcyBpdHMgb3duIGxvb3AgZHJpdmVyLCBpdHMgb3duIHNlcXVlbmNlIGFuZCBpdHMgb3duIHJvdW5kIGFuZCBjdXJseSBicmFja2V0cy4gVGhlIHN0eWxlIG9mIGluZGVudGluZyB0aGUgKippbm5lciBmb3IgbG9vcCoqIGlzIGltcG9ydGFudCBmb3IgbWFpbnRhaW5pbmcgY29kZSByZWFkYWJpbGl0eS4KCmBgYHtyIG5lc3RlZCBmb3Igcm93LXdpc2V9CiMgT3V0ZXIgbG9vcC4KZm9yIChyb3dfaW5kZXggaW4gMTpucm93KG1hcmtzX2RmKSkKewogICMgSW5uZXIgbG9vcCAtLSBtYWtlcyBhbGwgaXRlcmF0aW9ucyBmb3IgZWFjaCBwYXNzIHRocm91Z2ggb3V0ZXIgbG9vcAogIGZvciAoY29sX2luZGV4IGluIDE6bmNvbChtYXJrc19kZikpCiAgewogICAgIyBVc2UgYm90aCBsb29wIGRyaXZlcnMgdG8gc2VsZWN0CiAgICBjZWxsX3ZhbHVlIDwtIG1hcmtzX2RmW3Jvd19pbmRleCwgY29sX2luZGV4XQogICAgcHJpbnQoY2VsbF92YWx1ZSkKICB9Cn0KYGBgCgpcCgojIyBFeGVyY2lzZQpUaGUgcHJlY2VkaW5nIGV4YW1wbGUgcHJpbnRzICpyb3ctd2lzZSouIFRoYXQgaXMsIGl0IHByaW50cyBhbGwgdGhlIHZhbHVlcyBmb3IgZWFjaCByb3cgKGkuZS4gZm9yIGEgc2luZ2xlIHBhcGVyKSBiZWZvcmUgbW92aW5nIHRvIHRoZSBuZXh0IHJvdyAocGFwZXIpLiBNb2RpZnkgdGhlIGNvZGUgdG8gcHJpbnQgKmNvbHVtbi13aXNlKi4gVGhhdCBpcywgcHJpbnQgZG93biB0aGUgY29sdW1uczogYWxsIHRoZSBwYXBlciBuYW1lcywgdGhlbiBhbGwgdGhlIGludGVybmFsIG1hcmtzLCB0aGVuIGFsbCB0aGUgZXhhbSBtYXJrcywgdGhlbiBhbGwgdGhlIGZpbmFsIG1hcmtzLgoKYGBge3IgbmVzdGVkIGZvciBjb2wtd2lzZX0KIyBPdXRlciBsb29wLgpmb3IgKGNvbF9pbmRleCBpbiAxOm5jb2wobWFya3NfZGYpKQp7CiAgIyBJbm5lciBsb29wIC0tIG1ha2VzIGFsbCBpdGVyYXRpb25zIGZvciBlYWNoIHBhc3MgdGhyb3VnaCBvdXRlciBsb29wCiAgZm9yIChyb3dfaW5kZXggaW4gMTpucm93KG1hcmtzX2RmKSkKICB7CiAgICAjIFVzZSBib3RoIGxvb3AgZHJpdmVycyB0byBzZWxlY3QKICAgIGNlbGxfdmFsdWUgPC0gbWFya3NfZGZbcm93X2luZGV4LCBjb2xfaW5kZXhdCiAgICBwcmludChjZWxsX3ZhbHVlKQogIH0KfQpgYGAKClwKCiMjIyBDQVVUSU9OCgpVc2luZyBhIG5lc3RlZCBmb3IgbG9vcCB0byB2aXNpdCBldmVyeSBjZWxsIGluIGEgdGFibGUgaXMgYSB2ZXJ5IGNvbW1vbiwgYW5kIHZlcnkgcG93ZXJmdWwgY29kZSBwYXR0ZXJuLiBIb3dldmVyLCBiZSBhd2FyZSB0aGF0IGl0IGNhbiBiZSBjb21wdXRhdGlvbmFsbHkgZXhwZW5zaXZlIChpLmUuIGl0IGNhbiB0YWtlIGEgbG9uZyB0aW1lIHRvIHJ1bikuIElmIHlvdXIgb3V0ZXIgbG9vcCBydW5zIGBuYCBwYXNzZXMgYW5kIHlvdXIgaW5uZXIgbG9vcCBydW5zIGBtYCBwYXNzZXMsIHlvdSBtYWtlIGEgdG90YWwgb2YgYG4gKiBtYCBwYXNzZXMuIFdoZW4gcHJvY2Vzc2luZyBhIDEwMDAgcm93IHggMTAwMCBjb2x1bW4gdGFibGUgd2l0aCBhIG5lc3RlZCBmb3IgbG9vcCwgdGhlIGNvZGUgYm9keSBvZiB0aGUgaW5uZXIgbG9vcCBpcyBleGVjdXRlZCBvbmUgbWlsbGlvbiB0aW1lcywgd2hpY2ggbWF5IGJlIGludHJhY3RhYmxlLiBJZiB5b3UgaGF2ZSBsYXJnZSB0YWJ1bGFyIGRhdGEgc2V0cyB0aGF0IHRha2UgYSBsb25nIHRpbWUgdG8gcHJvY2VzcywgeW91IHNob3VsZCBjb25zaWRlciBsZXZlcmFnaW5nIFIncyBhZHZhbmNlZCB2ZWN0b3IgcHJvY2Vzc2luZyB0ZWNobmlxdWVzIHRoYXQgY2FuIGJlIG1vcmUgZWZmaWNpZW50IHRoYW4gYW4gaW50ZXJpb3IgZm9yIGxvb3AuIFNlZSwgZm9yIGV4YW1wbGUsIGh0dHBzOi8vcnN0dWRpby1wdWJzLXN0YXRpYy5zMy5hbWF6b25hd3MuY29tLzcyMjk1XzY5MjczN2I2Njc2MTRkMzY5YmQ4N2NiMGY1MWM5YTRiLmh0bWwgb3IgaHR0cDovL3d3dy5qb2huLXJvcy5jb20vUmNvdXJzZS9tZW1vcnkuaHRtbCBmb3IgZGlzY3Vzc2lvbnMuCgojIFdoaWxlIGxvb3AKClRoZSAqKmZvciBsb29wKiogaXMgdXNlZCB3aGVuIHlvdSB3YW50IHRvIGV4ZWN1dGUgYSBjb2RlIGJvZHkgYSBzcGVjaWZpYyBudW1iZXIgb2YgdGltZXMsIG9yIGl0ZXJhdGUgb3ZlciBhIHNwZWNpZmljIHNlcXVlbmNlIG9mIHZhbHVlcy4gQW4gYWx0ZXJuYXRpdmUgbG9vcCBzdHJ1Y3R1cmUgLS0gdGhlICoqd2hpbGUgbG9vcCoqIHJlcGVhdHMgYXMgbG9uZyBhcyBhIGdpdmVuIGNvbmRpdGlvbiBldmFsdWF0ZXMgdG8gdHJ1ZS4KClRoZSBzY2hlbWF0aWMgZm9yIGEgYHdoaWxlYCBsb29wIGlzIGFzIGZvbGxvd3M6CgpgYGB7ciwgZXZhbCA9IEZBTFNFfQp3aGlsZSAoY29uZGl0aW9uKSAKewogICMgTG9vcCBib2R5Cn0KYGBgCgpJbiBhbiBlYXJsaWVyIG1vZHVsZSwgd2UgdXNlZCBmdW5jdGlvbiBgcm5vcm1gIHRvIHJhbmRvbWx5IHNlbGVjdCBhIHZhbHVlIGZyb20gYSBub3JtYWwgZGlzdHJpYnV0aW9uIHdpdGggYSBrbm93biBtZWFuIGFuZCBzdGFuZGFyZCBkZXZpYXRpb24uIEltYWdpbmUgdGhhdCB5b3Ugd2FudCB0byBleHBsb3JlIHRoZSBwcm9iYWJpbGl0eSBvZiByYW5kb21seSBzZWxlY3RpbmcgYSBudW1iZXIgZnJvbSBzdWNoIGEgZGlzdHJpYnV0aW9uIHRoYXQgaXMgbW9yZSB0aGFuIHR3byBzdGFuZGFyZCBkZXZpYXRpb25zIGFib3ZlIHRoZSBtZWFuIChpLmUuIGhhcyBhIHotc2NvcmUgb2YgMiBvciBtb3JlKS4gWW91IGNvdWxkIGVzdGltYXRlIHRoaXMgYnkgcmVwZWF0ZWRseSBzZWxlY3RpbmcgYSBudW1iZXIgdW50aWwgeW91IGFjaGlldmVkIHRoZSBjcml0ZXJpb24sIGFuZCBjb3VudGluZyB0aGUgbnVtYmVyIG9mIHRpbWVzIHlvdSBoYWQgdG8gc2VsZWN0LiBXZSB3aXNoIHRvIGxvb3AgcmVwZWF0ZWRseSBvdmVyIHNvbWUgbG9naWMgKHNlbGVjdGluZyBhbmQgY291bnRpbmcpLCBidXQgd2UgZG9uJ3Qga25vdyBleGFjdGx5IGhvdyBtYW55IHRpbWVzIHRoZSBsb29wIHNob3VsZCBydW4sIHNvIGEgZm9yIGxvb3AgaXMgbm90IGFwcHJvcHJpYXRlLiBJbiB0aGlzIHNpdHVhdGlvbiwgd2UgdXNlIGEgKip3aGlsZSBsb29wKiouCgoqKkJlZm9yZSBsb29raW5nIGF0IHRoZSBjb2RlIHNhbXBsZSBiZWxvdywgdHJ5IHRvIHdvcmsgb3V0IHdoYXQgdGhlIHdoaWxlIGxvb3AgY29uZGl0aW9uIHdpbGwgYmUuKioKCgpgYGB7ciB3aGlsZSBsb29vcCB3aXRoIHJub3JtfQojIERlZmluZSB0aGUgcGFyYW1ldGVycwpkaXN0cmlidXRpb25fbWVhbiA8LSAxMDAKZGlzdHJpYnV0aW9uX3NkIDwtIDEwCgojIFByZXBhcmUgYSB2YXJpYWJsZSB0byBjb3VudCB0aGUgcGFzc2VzCmNvdW50IDwtIDAKCiMgTWFrZSB5b3VyIGZpcnN0IHNlbGVjdGlvbiBzbyB0aGUgbG9vcCBjb25kaXRpb24gdG8gYmUgZXZhbHVhdGVkIAojIG9uIHRoZSBmaXJzdCBwYXNzCnJhbmRfdmFsdWUgPC0gcm5vcm0oMSwgZGlzdHJpYnV0aW9uX21lYW4sIGRpc3RyaWJ1dGlvbl9zZCkKCiMgVGhlIGxvb3AuIE5vdGUgdGhlIGNvbmRpdGlvbi4gV2UgY29udGludWUgcnVubmluZyB0aGUgbG9vcAojIGFzIGxvbmcgYXMgb3VyIHNlbGVjdGVkIHZhbHVlIGlzIGxlc3MgdGhhbiBtZWFuICsgMipzZC4KIyBXaGlsZSBsb29wcyBydW4gYXMgbG9uZyBhcyB0aGUgbG9vcCBjb25kaXRpb24gaXMgdHJ1ZS4Kd2hpbGUgKHJhbmRfdmFsdWUgPCBkaXN0cmlidXRpb25fbWVhbiArICgyICogZGlzdHJpYnV0aW9uX3NkKSkKewogICMgaW5jcmVtZW50IHRoZSBjb3VudCBiZWNhdXNlIHRoZSBsb29wIGNvbmRpdGlvbiB3YXMgdHJ1ZQogIGNvdW50IDwtIGNvdW50ICsgMQogIAogICMgU2VsZWN0IGFnYWluCiAgcmFuZF92YWx1ZSA8LSBybm9ybSgxLCBkaXN0cmlidXRpb25fbWVhbiwgZGlzdHJpYnV0aW9uX3NkKQogIAp9ICMgZW5kIG9mIHdoaWxlIGxvb3AKCiMgRGlzcGxheSB0aGUgcmVzdWx0Cm91dHB1dCA8LSBwYXN0ZShjb3VudCwgInZhbHVlcyB3ZXJlIGNob3NlbiBiZWZvcmUgei1zY29yZSA+IDEiKQpwcmludChvdXRwdXQpCgpgYGAKCkhlcmUgaXMgYW4gZXhhbXBsZSBvZiBhIGB3aGlsZWAgbG9vcCB0byBjb3VudCBob3cgbWFueSBpdGVyYXRpb25zIGl0IHRha2VzIHRvIG9idGFpbiAzIGhlYWRzIGluIGEgcm93OgoKYGBge3IsIGVjaG8gPSBUUlVFLCBldmFsID0gVFJVRX0KIyMgRXhhbXBsZSBmcm9tIFIgZm9yIERhdGEgU2NpZW5jZSAtIDIxLjMuNCAjIwoKIyBGdW5jdGlvbiB0byBzaW11bGF0ZSBoZWFkIG9yIHRhaWwgYXMgdGhlIHJlc3VsdCBvZiBhIGNvaW4gZmxpcApmbGlwIDwtIGZ1bmN0aW9uKCl7CiAgc2FtcGxlKGMoIlQiLCAiSCIpLCAxKQp9CgojIHZhcmlhYmxlcyB0byBrZWVwIHRyYWNrIG9mIGtleSByZXN1bHRzCmZsaXBzIDwtIDAKbmhlYWRzIDwtIDAKCiMgZmxpcCBhIGNvaW4gdW50aWwgdGhlcmUgYXJlIHRocmVlIGhlYWRzIGFuZCBjb3VudCBob3cgbWFueSBmbGlwcyB3ZXJlIHBlcmZvcm1lZC4Kd2hpbGUgKG5oZWFkcyA8IDMpIHsKICBpZiAoZmxpcCgpID09ICJIIikgewogICAgbmhlYWRzIDwtIG5oZWFkcyArIDEKICB9IGVsc2UgewogICAgbmhlYWRzIDwtIDAKICB9CiAgZmxpcHMgPC0gZmxpcHMgKyAxCn0KZmxpcHMKCmBgYAoKXAoKIyMgSW5maW5pdGUgd2hpbGUgbG9vcHMKCk5COiBJdCBpcyBlc3NlbnRpYWwgdGhhdCB5b3VyIHdoaWxlIGxvb3AgY29uZGl0aW9uIHdpbGwgKipldmVudHVhbGx5IGV2YWx1YXRlIHRvIGZhbHNlKiouIENvbnNpZGVyIHRoZSBmb2xsb3dpbmcgY29kZSBzYW1wbGUgKHdoaWNoIHdlIHdpbGwgKm5vdCogcnVuKS4KCmBgYHtyIGluZmluaXRlIGxvb3AsIGV2YWwgPSBGQUxTRX0KIyBTZXQgYSBzdGFydGluZyB2YWx1ZSBzbyB3ZSBjYW4gY2hlY2sgdGhlIGNvbmRpdGlvbiBvbiB0aGUgZmlyc3QgcGFzcwp4IDwtIDEwCgojIFRoZSBsb29wCndoaWxlICh4ID4gMCkKewogICMgVGhlIGNvZGUgYm9keQogIHggPC0geCArIDEKfQoKYGBgCgpUaGUgdmFyaWFibGUgeCBpcyBpbml0aWFsaXNlZCB0byAxMCwgYW5kIGluY3JlbWVudGVkIGF0IGVhY2ggcGFzcyB0aHJvdWdoIHRoZSBjb2RlIGJvZHkuIEl0cyB2YWx1ZSB3aWxsIHRoZXJlZm9yZSBhbHdheXMgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEwLiBUaGUgbG9vcCBjb25kaXRpb24gaXMgYHggPiAwYC4gU2luY2UgeCBzdGFydHMgYXQgMTAgYW5kIGluY3JlYXNlcyBhdCBlYWNoIHBhc3MsIGl0IHdpbGwgYWx3YXlzIGJlIGdyZWF0ZXIgdGhhbiAwLCBzbyB0aGUgbG9vcCBjb25kaXRpb24gd2lsbCBhbHdheXMgYmUgdHJ1ZSwgYW5kIHRoZSBsb29wIHdpbGwgbmV2ZXIgc3RvcC4gVGhpcyBpcyBhbiAqKmluZmluaXRlIGxvb3AqKi4gV2hlbiB5b3VyIGNvZGUgaXMgaW4gYW4gaW5maW5pdGUgbG9vcCwgdGhlIG9ubHkgd2F5IHRvIHN0b3AgaXQgaXMgdG8gZm9yY2libHkgdGVybWluYXRlIHRoZSBwcm9ncmFtIChhc3N1bWluZyB5b3UgcmVjb2duaXNlIHdoYXQgaGFzIG9jY3VycmVkKS4gSW4gUiB5b3UgY2FuIHVzdWFsbHkgZG8gdGhpcyBieSBjbGlja2luZyB0aGUgcmVkIHN0b3Agc2lnbiBpbiB0aGUgdG9wIHJpZ2h0IGNvcm5lciBvZiB0aGUgY29uc29sZSB3aW5kb3cuIEFuIGluZmluaXRlIGxvb3AgdGhhdCBwcm9kdWNlcyBhIGxvdCBvZiB2YXJpYWJsZXMgY2FuIGNvbnN1bWUgbWVtb3J5IHRvIHRoZSBwb2ludCB3aGVyZSB0aGUgbWFjaGluZSB3aWxsIGNyYXNoLiBUaGlzIGlzIGJhZC4gQWx3YXlzIGNoZWNrIHRoYXQgeW91ciBsb29wIGNvbmRpdGlvbiBpcyBndWFyYW50ZWVkIHRvIGV2ZW50dWFsbHkgZXZhbHVhdGUgdG8gZmFsc2UgYmVmb3JlIHJ1bm5pbmcgY29kZSB3aXRoIGEgd2hpbGUgbG9vcC4KCiMgTWFwCgpJbiB0aGUgcGFja2FnZSBgcHVycnJgIChwYXJ0IG9mIHBhY2thZ2UgdGlkeXZlcnNlKSwgdGhlcmUgYXJlIGEgY29sbGVjdGlvbiBvZiBgbWFwYCBmdW5jdGlvbnMgd2hpY2ggaXRlcmF0ZSBvdmVyIGEgdmVjdG9yIG9yIGxpc3QsIGFwcGx5aW5nIGEgZnVuY3Rpb24gdG8gZWFjaCBlbGVtZW50LiBUaGlzIGlzIGEgdmVyeSBzdWNjaW5jdCBzeW50YXgsIHdoaWNoIGFjaGlldmVzIHRoZSBzYW1lIHJlc3VsdCBhcyBjYWxsaW5nIHRoZSBmdW5jdGlvbiBpbnNpZGUgYSBmb3IgbG9vcCwgd2l0aG91dCB0aGUgb3ZlcmhlYWQgb2Ygd3JpdGluZyBvdXQgdGhlIGxvb3Agc3RydWN0dXJlLgoKYGBge3Igc2ltcGxlIG1hcH0KbGlicmFyeShwdXJycikKCmZhcmVuaGVpdF90b19jZWxjaXVzIDwtIGZ1bmN0aW9uKHRlbXBfZil7CiAgdGVtcF9jIDwtICh0ZW1wX2YgLSAzMikgKiA1LzkKICByZXR1cm4odGVtcF9jKQp9CgpteV90ZW1wc19mIDwtIGMoOTAsIDc4LCA4OCwgODksIDc3KQoKIyBtYXAgYXBwbGllcyB0aGUgZnVuY3Rpb24gKDJuZCBhcmd1bWVudCkgdG8gZWFjaCBlbGVtZW50IG9mIHRoZSB2ZWN0b3IgKDFzdCBhcmd1bWVudCkgCiMgYW5kIHJldHVybnMgdGhlIHJlc3VsdHMgYXMgYSBsaXN0LiAKbXlfdGVtcHNfY19saXN0IDwtIG1hcChteV90ZW1wc19mLCBmYXJlbmhlaXRfdG9fY2VsY2l1cykKbXlfdGVtcHNfY19saXN0CgpgYGAKClRoZSBgbWFwYCBhcmd1bWVudCBuYW1lcyBhcmUgYC54YCBhbmQgYC5mYCwgc28gdGhlIGNhbGwgdG8gYG1hcGAgYWJvdmUgY291bGQgYWxzbyBiZSB3cml0dGVuIGFzIGBteV90ZW1wc19jX2xpc3QgPC0gbWFwKC54ID0gbXlfdGVtcHNfZiwgLmYgPSBmYXJlbmhlaXRfdG9fY2VsY2l1cylgCgpOb3RlIHRoYXQgd2hlbiBwcm92aWRpbmcgYSBmdW5jdGlvbiBhcyBhbiBhcmd1bWVudCwgZ2l2ZSAqKm9ubHkgdGhlIGZ1bmN0aW9uIG5hbWUqKi4gRG8gbm90IGZvbGxvdyB0aGUgZnVuY3Rpb24gbmFtZSB3aXRoICgpIGFzIGZvciBhIGZ1bmN0aW9uIGNhbGwuCgoKIyMgTWFwIGFuZCBmcmllbmRzCgpUaGUgYmFzaWMgZm9ybSBvZiBgbWFwYCBhYm92ZSwgcmV0dXJucyB0aGUgcmVzdWx0cyBpbiBhIGxpc3QuIFRoZXJlIGFyZSBzdWZmaXggdmVyc2lvbnMgb2YgYG1hcGAgdGhhdCByZXR1cm4gdGhlIHJlc3VsdHMgYXMgYSBzcGVjaWZpYyBkYXRhIHR5cGUuCgotIGBtYXAoKWAgbWFrZXMgYSBsaXN0LgotIGBtYXBfbGdsKClgIG1ha2VzIGEgbG9naWNhbCB2ZWN0b3IuCi0gYG1hcF9pbnQoKWAgbWFrZXMgYW4gaW50ZWdlciB2ZWN0b3IuCi0gYG1hcF9kYmwoKWAgbWFrZXMgYSBkb3VibGUgdmVjdG9yLgotIGBtYXBfY2hyKClgIG1ha2VzIGEgY2hhcmFjdGVyIHZlY3Rvci4KClRoZXNlIHN1ZmZpeCB2ZXJzaW9ucyB3aWxsIGdpdmUgYW4gZXJyb3IgaWYgdGhlIGRhdGEgdHlwZSBvZiB0aGUgcmVzdWx0cyBkb2Vzbid0IG1hdGNoIHRoZSBpbnRlbmRlZCByZXR1cm4gdHlwZS4gVGhpcyBpcyB1c2VmdWwgYmVjYXVzZSB5b3UgY2FuIHdyaXRlIGNvZGUgdG8gcHJvY2VzcyB0aGUgcmVzdWx0cyBmdXJ0aGVyLCBjb25maWRlbnQgdGhhdCB0aGV5IGFyZSBvZiBhIHNwZWNpZmljIGRhdGEgdHlwZS4gCgojIEFwcGx5CgpCYXNlIFIgaGFzIGEgc2V0IG9mIGJ1aWx0IGluIGZ1bmN0aW9ucyB0aGF0IGR1cGxpY2F0ZSB0aGUgYmVoYXZpb3VyIG9mIGBwdXJycjo6bWFwYCBhbmQgaXRzIHN1ZmZpeCBmdW5jdGlvbnMuIFRoZXNlIGFyZSB0aGUgKiphcHBseSBmYW1pbHkqKjogYGFwcGx5YCwgYGxhcHBseWAsIGBzYXBwbHlgLCBgbWFwcGx5YCwgYW5kIGB0YXBwbHlgLiBUaGUgZnVuY3Rpb25zIGRpZmZlciBwcmltYXJpbHkgaW4gdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YSB0aGV5IHJldHVybi4gU2VlLCBmb3IgZXhhbXBsZSwgaHR0cDovL2Fkdi1yLmhhZC5jby5uei9GdW5jdGlvbmFscy5odG1sIGZvciBtb3JlIGRldGFpbC4KCkZ1bmN0aW9uIGBsYXBwbHlgIGlzIGFuYWxvZ291cyB0byBgcHVycnI6Om1hcCgpYDoKCmBgYHtyfQpmYXJlbmhlaXRfdG9fY2VsY2l1cyA8LSBmdW5jdGlvbih0ZW1wX2YpewogIHRlbXBfYyA8LSAodGVtcF9mIC0zMikgKiA1LzkKICByZXR1cm4odGVtcF9jKQp9CgpteV90ZW1wc19mIDwtIGMoOTAsIDc4LCA4OCwgODksIDc3KQoKIyBsYXBwbHkgZXhhbXBsZQpsYXBwbHlfbXlfdGVtcHNfYyA8LSBsYXBwbHkoWCA9IG15X3RlbXBzX2YsIEZVTiA9IGZhcmVuaGVpdF90b19jZWxjaXVzKQpsYXBwbHlfbXlfdGVtcHNfYwoKYGBgCgpOb3RlIHRoYXQgc29tZSBvZiB0aGUgYXBwbHkgZmFtaWx5IHJldHVybiBkaWZmZXJlbnQgZGF0YSBzdHJ1Y3R1cmVzIGRlcGVuZGluZyBvbiB0aGUgdHlwZSBvZiB0aGUgaW5wdXQgZGF0YS4gVGhpcyBjYW4gbWFrZSBpdCBjaGFsbGVuZ2luZyB0byBrbm93IGJlZm9yZWhhbmQgd2hhdCB0aGUgb3V0cHV0IGlzIGdvaW5nIHRvIGxvb2sgbGlrZSAtIHVubGlrZSB0aGUgc3VmZml4IHZlcnNpb25zIG9mIGBwdXJycjo6bWFwYAoKIyBDb25jbHVzaW9uCgpJbiB0aGlzIG1vZHVsZSB3ZSBjb3ZlcmVkIHVzaW5nIGZvciBhbmQgd2hpbGUgbG9vcHMgdG8gcmVwZWF0IGNvZGUgZnJhZ21lbnRzIGVmZmljaWVudGx5LiBXZSBzYXcgdGhhdCBmdW5jdGlvbnMgaW4gdGhlIG1hcCBhbmQgYXBwbHkgZmFtaWxpZXMgcHJvdmlkZSBhbiBlcXVpdmFsZW50LCB5ZXQgbW9yZSBzdWNjaW5jdCBzeW50YXgsIHdoZW4gdGhlIHJlcGVhdGVkIGNvZGUgaXMgYSBzaW5nbGUgZnVuY3Rpb24uIENvbWJpbmluZyBsb29wcyB3aXRoIGZ1bmN0aW9ucyBhbmQgY29uZGl0aW9uYWwgZmxvdyBvZiBjb250cm9sIGZyb20gbGFzdCB3ZWVrJ3Mgc2Vzc2lvbiwgeW91IGNhbiBjcmVhdGUgY29kZSB0aGF0IGlzIG1vZHVsYXIsIHJldXNhYmxlLCBhbmQgbWFpbnRhaW5hYmxlLiAKCiMgV2hhdCdzIE5leHQKTmV4dCB3ZWVrIHdlIGNvbmNsdWRlIHRoZSBmb3JtYWwgY29udGVudCBvZiBSNFNTUCB3aXRoIGEgZGlzY3Vzc2lvbiBvZiBSIHdvcmtmbG93cywgaW5jbHVkaW5nIHByb2plY3Qgc3RydWN0dXJlLCBpbmNyZW1lbnRhbCBkZXZlbG9wbWVudCwgYW5kIGVmZmVjdGl2ZSBkZWJ1Z2dpbmcgdGVjaG5pcXVlcy4KCgpQbGVhc2UgZmlsbCBpbiB0aGUgbW9kdWxlIGZlZWRiYWNrIGZvcm0gW2h0dHBzOi8vdGlueXVybC5jb20vcjRzc3AtbW9kdWxlLWZiXShodHRwczovL3Rpbnl1cmwuY29tL3I0c3NwLW1vZHVsZS1mYikuCgogCg==