Associated Material
Zoom notes: Zoom notes 08 -
Functions and Choices
Readings:
Introduction
As the work you do in R becomes more complex, your R scripts will get
longer, and may become difficult to manage. You may find that it is
difficult to locate particular bits of code, or that you seem to be
writing the same, or very similar bits of code, over and over again. If
you want to modify those bits, there are multiple place in the script
you have to edit, typos start to creep in, and the whole process becomes
unpleasant.
To prevent this, large programs need to be organised into
logical modules. Sections of code that perform a
clearly delineated task can be enacapsulated and named. The encapsulated
code can be invoked simply by typing the name – no need to cut and
paste, no need to modify multiple copies. Scripts are shorter and easier
to manage. Code that is organised this way is said to be
modular. Modular code is better code.
In R, the main code module is the function. We have
already used many functions, like read.csv
and
sqrt
and ggplot
. We invoke them in our code as
single commands, but each of these commands actually ecapsulates many,
many (add another “many” for ggplot) lines of code. We call the function
by name, and all the associated code is executed.
Many functions in R will display their code in the console. Type the
function name without the () into the console, and the
encapsulated commands will be shown. (Look at the code for function
filter
.)
To make our own code modular, we can define our own functions. We
write the code for a function somewhere in our script file. We can then
call the function by name anywhere else in our script
file, and all the code is executed. Just as with built-in functions, we
can pass data into our function, and it can operate on those data. We
can also arrange for our function to return a result
that we can store in a variable.
Function Declaration Syntax
A function in R is comprised of four parts:
- a name
- the body (the code that does something)
- (optionally) input data
- (optionally) an output that can be stored
Creating a function
We will begin with the simplest function, one that accepts no input
data, and returns no result. We declare the function
using keyword function
. Schematically, a user-defined
function is created as:
name_of_function <- function()
{
Code Body
}
The curly braces enclose the code body.
Subesquently we call the function as:
name_of_function()
When the call is executed, all the commands in the code body are
run.
For example, in the current public health situation, we often see
discussions of what body temperature constitutes a fever. We might want
to be able to translate that temperature from Celsius to Fahrenheit (as
used in the North American literature). This is a logically
well-delineated computation, so we would encapsulate it in a
function.
# Declare/define the function
fever_in_fahrenheit <- function()
{
fever_in_celsius <- 37.5
converted_to_fahrenheit <-(fever_in_celsius*9/5) + 32
print(converted_to_fahrenheit)
}
# Call a user-defined function by name
fever_in_fahrenheit()
#> [1] 99.5
Some things to note:
- Typing out the function declaration is not enough to make the
function available for calling. The declaration code (from the start of
the name to the closing curly bracket, inclusive) must first be
executed. Execute this code in a script as we always do, by
selecting all the code (with the mouse) and typing ctrl-Enter (Windows)
or cmd-Enter (Mac). This is called sourcing the
function.
- When you source a function, nothing happens. In our
example, you will not see the output of the print statement when you
execute the declaration code. Sourcing a function declaration
does not run the code body. It simply parses
the code body and, if there are no errors, stores it in the environment.
Effectively, it informs RStudio that a function with this name exists,
and defines the code which it encapsulates, so it can be called
later.
- To execute the code body, state the name of the function followed by
(), with no intervening spaces. This calls the
function; we think of () as the call operator. Whether
the code body contains 1 line or 1,000 lines, or more, calling the
function by name runs all the encapsulated code.
In R a function cannot be called until after the function
has been sourced. Consider the following example:
# If you try to call the function before it is declared and sourced
fever_in_fahrenheit()
#> Error in fever_in_fahrenheit(): could not find function "fever_in_fahrenheit"
fever_in_fahrenheit <- function()
{
fever_in_celsius <- 37.5
converted_to_fahrenheit <-(fever_in_celsius*9/5) + 32
print(converted_to_fahrenheit)
}
There are more advanced techniques that allow us to call functions
contained in other script files where we cannot directly select and
execute the declaration code. See the reading for discussion.
Providing data to a function
Consider the following function, which demonstrates how to compute
BMI (body mass index) in R, using the given values for height (in
metres) and weight (in kg):
# Declare function calc_BMI
calc_BMI <- function()
{
weight <- 73
height <- 1.68
bmi <- weight/height^2 # ^ is the exponentiation operator
print(bmi)
}
# Call function calc_BMI
calc_BMI()
#> [1] 25.86451
This function contains nice tidy code and is mathematically correct,
but unless we happen to want the BMI of a person with exactly this
height and weight, it is of no use to us. A useful function defines the
computation (in this case taking the ratio of weight to height squared),
and accepts the data values when it is called.
We have seen this many times when writing R code, when we call a
function repeatedly on different input values:
sqrt(14)
#> [1] 3.741657
sqrt(820)
#> [1] 28.63564
sqrt(0.65)
#> [1] 0.8062258
To declare a function that can accept input arguments, perform these
steps:
- Between the round brackets that follow the keyword
function
, place a variable name for each
piece of data you wish to input when the function is called.
- In the function body refer to the input variables by the
name you placed between the round brackets. You DO NOT need to
initialise the variables inside the code body – in fact you MUST NOT do
so. Variables with those names are automatically created for you when
the function is called.
- When calling the function, provide a value for each
input variable. You do not need to repeat the variable name, just
provide values, separated by commas, in the same order as the variables
are listed in the declatration.
- When the function is called, the system creates the input variables,
assigns them the corresponding values from the call statement, and
executes the code body, using those variables.
We can modify our calc_BMI
function to accept weight and
height as input variables, as shown. Compare this version to the earlier
version. Note that we do not declare and initialise weight and
height inside the code body.
# Declare function calc_BMI
calc_BMI <- function(weight, height)
{
# Use input arguments weight and height. DON'T initialise them.
bmi <- weight/height^2
print(bmi)
}
# Call function calc_BMI
calc_BMI(73, 1.68)
#> [1] 25.86451
Following the rules
Declaring a function with inputs defines the required
interface of the function. That is, it defines what you
have to provide if you want to call the function. If the caller violates
the interface, the code is not guaranteed to work. For example, function
calc_bmi
is declared with two input arguments. Therefore,
all of these calls violate the interface.
calc_BMI()
#> Error in calc_BMI(): argument "weight" is missing, with no default
calc_BMI(16)
#> Error in calc_BMI(16): argument "height" is missing, with no default
calc_BMI(73, 168, 42)
#> Error in calc_BMI(73, 168, 42): unused argument (42)
In some programming languages, one is required to specify the data
type (e.g. number, string, data frame, etc.) of each input argument.
Code that tries to pass in the wrong type of data will not compile. In R
this is not required. R will try to run your code no matter what sort of
data it gets. However, if it tries to operate on the wrong type of data,
it will throw an error:
calc_BMI(42, "fred")
#> Error in height^2: non-numeric argument to binary operator
Naturally, R doesn’t understand how to apply the exponentiation
operator to “fred”, and it is telling you so.
More on the rules
Consider the following code:
# Declare the function
compute_area <- function(width)
{
area <- width * height
print(area)
}
# Call the function
compute_area(35)
The function compute_area
is defined with one argument.
Therefore, when it is called, we must provide one value between the
round brackets. In the call, we have correctly provided one argument, of
the correct data type. Will the call compute_area(35)
work
correctly, or will it throw an error? What error will it throw?
# Declare the function
compute_area <- function(width)
{
area <- width * height
print(area)
}
# Call the function
compute_area(35)
#> Error in compute_area(35): object 'height' not found
When compute_area(35)
is executed, it produces an error
message: ...object 'height' not found
. In the code body of
compute_area
, we refer to an entity height
.
Since that entity is not surrounded by double-quotes, R expects to find
a variable named height existing in the environment,
and no such variable exists, because we have neither created one
directly (with an assignment statement) nor passed one in as an argument
to the function.
In the same line of code, we also refer to an entity
width
. Note that R does not complain about being unable to
find width
. That is because we defined an input argument
called width.
- How would you modify function
compute_area
to eliminate
the error?
- How would this change the form of the call to
compute_area
?
Taking your time
Traditionally, new programmers find the syntax of argument passing
extremely confusing. There are too many interacting parts: we
have variable names in the declaration, variables used in the code body,
and values passed in the call. At first exposure, it can be unclear how
all these parts work together. If this is the first time you have seen
this syntax, take some time to experiment with it to solidify your
understanding. Make up some simple user defined functions of your own to
practice managing input data.
Getting output from a function
In all of our examples so far, we have used a print statement to show
the result of the function’s computation. This is, of course, not
adequate in real programming, as a print statement simply writes to the
console. The computed value is not available for use later in our
script. We want to be able to save the result of a function into a
variable, as we have done with the built-in functions we have used
earlier in the course. For example, we have said
x <- sqrt(22)
, creating a variable called x
that stores the square root of 22. We could then use x
in
subsequent computations, as needed.
When a function makes its result available for storage, we say it is
returning its result. The command sqrt(22)
returns the square root of 22, and we can store it in a
variable using the assignment statement.
We can make our user-defined function behave in the same way, by
using return
instead of print
. For example, we
can modify calc_bmi
:
# Declare function calc_BMI
calc_BMI <- function(weight, height)
{
bmi <- weight/height^2 # ^ is the exponentiation operator
return(bmi)
}
With this change to the function, we can store the result of the BMI
computation in a variable for later use.
# Save the return value in a variable.
bmi_result <- calc_BMI(75, 1.75)
# Display by name, as we always can do in R with variables
bmi_result
#> [1] 24.4898
CAUTION
In R, the return
keyword is actually optional. By
default, R functions just return the value of their last line of code.
So technically, you can write the function above like this without
changing its behaviour:
# Declare function calc_BMI
calc_BMI <- function(weight, height)
{
bmi <- weight/height^2 # ^ is the exponentiation operator
# Omitting the explicit call to return. Don't do this.
bmi
}
You will see this shortcut used in R code in the wild. However, it is
an old-fashioned syntax, and it can lead to subtle errors in complex R
programs. We suggest that you avoid it. Make the behaviour of your
functions clear by explicitly identifying the return value with function
return
.
Function exercise
Returning to the Palmers Penguins data, and using the techniques we
have seen for performing descriptive statistics, consider the following
code, which computes summaries of the body mass measure (i.e. the
dependent variable in this summary is column body_mass_g).
library(palmerpenguins)
dv_vector <- penguins$body_mass_g
mean_dv <- mean(dv_vector, na.rm = TRUE)
sd_dv <- sd(dv_vector, na.rm = TRUE)
min_dv <- min(dv_vector, na.rm = TRUE)
max_dv <- max(dv_vector, na.rm = TRUE)
This code fragment creates four new variables that we could use in
later computations, or in generating reports.
Imagine that we wish to do the same summary for flipper length. We
could copy and paste the code, changing the line where we assign
variable dv_vector
. Then if we wanted to do the same
summary on bill length, we could copy and paste the code again, and
again change the assignment to dv_vector
. By now, we are
bored of this, and our script is getting needlessly big and messy. If we
later decide we need to include the median, we will need to go back and
add the median
command multiple times, greatly increasing
the chance of errors (and also being boring).
Computing this set of descriptive stats is a logically delineated
task, and we should therefore encapsulate it into a user defined
function. Each time we do this summary, the computation (the four calls
to mean
, sd
, min
and
max
) remains the same, but the data we wish to process
changes. Each time we call the function, we want to be able to provide
it with the data to process. We must therefore pass the data in as an
input argument.
Get output from the function
As discussed earlier, displaying function output via print statements
is of limited utility; it is preferable to return the results of a
function, so it can be stored in a variable. We would like, therefore,
to return the output of function desc_stats
. Unfortunately,
a function in R can only return a single data object
and our function computes four values.
To resolve this, we can bundle up our four computed values into a
single data object, called a list. An R
list is like a vector, except that each element has a
name as well as an ordinal position, and elements can be retrieved
(using the [] operator) either by name or position. Consider this
example:
# Create a list
character_list <- list(Name = "Snoopy", Breed = "Beagle", Owner = "Charlie Brown")
# Display the entire list
character_list
#> $Name
#> [1] "Snoopy"
#>
#> $Breed
#> [1] "Beagle"
#>
#> $Owner
#> [1] "Charlie Brown"
# Some examples of selection from the list
character_list["Name"]
#> $Name
#> [1] "Snoopy"
character_list["Breed"]
#> $Breed
#> [1] "Beagle"
character_list[2]
#> $Breed
#> [1] "Beagle"
character_list[3]
#> $Owner
#> [1] "Charlie Brown"
character_list$Name
#> [1] "Snoopy"
character_list$Owner
#> [1] "Charlie Brown"
A list is considered a single data object, so it can be returned from
a function via a return
statement. Modify function
desc_stats
to return its four outputs,
rather than printing them. Call your function and use any of the
syntactic options above to explore the contents of the returned
object.
My solution is:
# Modify the function to return a list
desc_stats <- function(dv_vector)
{
mean_dv <- mean(dv_vector, na.rm = TRUE)
sd_dv <- sd(dv_vector, na.rm = TRUE)
min_dv <- min(dv_vector, na.rm = TRUE)
max_dv <- max(dv_vector, na.rm = TRUE)
result_list <- list(Mean = mean_dv,
Sd = sd_dv,
Min = min_dv,
Max = max_dv)
return(result_list)
}
flipper_desc_stats <- desc_stats(penguins$flipper_length_mm)
flipper_desc_stats$Mean
#> [1] 200.9152
flipper_desc_stats[2]
#> $Sd
#> [1] 14.06171
min_max <- c(flipper_desc_stats["Min"], flipper_desc_stats["Max"])
print(min_max)
#> $Min
#> [1] 172
#>
#> $Max
#> [1] 231
Scope
When you specify a variable in R it will start trying to find
something with that name within the global environment (displayed in the
Environment tab in RStudio). In the case of functions, any
variable defined in the function (including through its arguments) stays
within the function (a separate local environment specific to the
function). If however in the body of the function you refer to a
variable that hasn’t been defined in the function, R will start looking
at the global environment and if it finds a variable of the same name
you’ve created outside of the function, it will use the value that is
stored within it. This behaviour can cause issues.
Here is an example, where the function needs a value for
n
but it hasn’t been supplied as an argument and there is
no default value.
# multiplies the number x by the number n
multiply_by_n <- function(x){
x * n
}
multiply_by_n(x = 3)
#> Error in multiply_by_n(x = 3): object 'n' not found
In the function body we referred to n
which wasn’t
defined anywhere so we got an error.
Let’s use the same function again but define n
outside
the function:
# multiplies the number x by the number n
multiply_by_n <- function(x){
x * n
}
# define n in the global environment
n <- 10
multiply_by_n(x = 3)
#> [1] 30
This time R looks for n
inside the body but doesn’t find
it and when it looks into the global environment it finds a variable
named n
and so uses that value.
This time we’re going to modify the function to take a second
argument called n
, and also have n
defined in
the global environment:
# multiplies the number x by the number n
multiply_by_n <- function(x, n){
x * n
}
# define n in the global environment
n <- 10
multiply_by_n(x = 3, n = 2)
#> [1] 6
The value of n
that was used was the value supplied as
the argument, rather than the version that was defined in the global
environment. Thus a function will use a locally defined variable when
one exists, but if it can’t find one, it will look in the global
environment.
This behaviour can lead to subtle errors in your code. For example,
earlier in this module we wrote a version of user-defined function
calc_area
that tried to reference variable
height
without having passed it in as an argument. When R
was unable to find height
, it alerted us with an error
message, and we were able to identify and correct the error in the code
(the missing input argument height
). If, at that point, we
had already created a variable height
outside the function
(for any reason), R would have happily used that existing
variable when executing the function code body and we would not
have realised there was an error. Of course, if we ever called the bad
function when we hadn’t previously created height
, our
program would crash. Some programmers use special variable coding styles
– for example prefixing all input arguents with underscore – to prevent
confusion between local and global variables. It is very important, when
working in R to be constantly aware of which variables exist in the
global environment. Keep your eye on the Environment tab as you write
functions.
Complex Program Behaviour
In very simple programs, we write a set of commands which are
executed in sequence – first statement, second statement, third
statement, etc. Each time we run the code, the exact same set of
commands are executed, in the exact same sequence.
However, as computational problems become more complex, the behaviour
of our code solutions must also become more complex. We may have
sections of code that we want to repeat some varying number times
depending on our data, or sections of code that we only want to execute
under certain conditions.
The specific time course of program execution is called flow
of control, and R provides many syntactic features that allow
us to manage it. Flow of control generally depends on the program’s
state – the specific set of variables and their values
at each point during program execution.
For example, when we import a csv file into a data frame, that data
frame is part of the state. We may want to execute a function once for
each row in the data frame. If we import a data frame with 53 rows, we
want the function to be called 53 times. Thus the number of times the
function is called (the flow of control) depends on the state.
Similarly, when we write a function that accepts data input arguments,
the value of those arguments passed in at function call are part of the
state, and can be different each time the function is called. Frequently
we will want to take different actions in the function depending on that
state.
We have described the three primary flow of control constructs:
- Sequential execution: Statements are executed in order
- Iteration: A set of statements is repeated a number of times
- Conditional execution: A set of statements may or may not be
executed, depending on the state.
We have already seen, and written, code that contains only sequential
exection. We will now look at the syntactic tools for conditional
execution. In our next module, we will cover iteration, which is
syntactically more complex.
If statements
All modern programming languages allow you to wrap a block of code in
an if statement. If statements contain a
condition, which is an expression which evaluates to
either true or false. At runtime, the condition is evaluated. If it is
true, the block of code is executed; if it is false, the block of code
is not executed. Conditional code blocks in R are delineated with curly
brackets. The conditional expression is delineated with round
brackets.
Schematically:
if (condition) {
# code here is only run if condition was TRUE
}
Consider this toy example:
did_I_pass_the_paper <- function(my_mark)
{
if (my_mark > 50) {
print("You passed!")
}
}
# This call generates no output
did_I_pass_the_paper(14)
# This call generates output
did_I_pass_the_paper(73)
#> [1] "You passed!"
Adding an alternative with else
Frequently we wish to define two behaviours for a conditional
expression – one for when it is true and another for when it is false.
In R we do this with the keyword else
if (condition) {
# code here is only run if condition was TRUE
} else {
# code here is only run if condition was FALSE
}
For example:
did_I_pass_the_paper <- function(my_mark)
{
if (my_mark > 50) {
print("You passed! :)")
} else {
print("Sorry, you didn't pass. :(")
}
}
# This call runs the else block
did_I_pass_the_paper(14)
#> [1] "Sorry, you didn't pass. :("
# This call runs the if block
did_I_pass_the_paper(73)
#> [1] "You passed! :)"
NB: Pay careful attention to the placement of the curly brackets for
both the if block and the else block. The first curly bracket must
sit on the same line as the if statement. The else
keyword must be on the same line as the closing curly bracket of the
if
block, and must be followed, on that same line, by the
opening curly bracket of the else
block. It is a known
peculiarity of the R language that it is extremely
fussy about this rule. No use fighting it; just follow the
rule.
An extension of else
is the else if
construct that lets you link a series of conditions. The conditions are
tested one at a time from the top and the first condition that evaluates
to TRUE
is the only code block that gets run. For
example:
bmi_category <- function(bmi)
{
if(bmi > 30){
print("obese")
} else if (bmi > 25){
print("overweight")
} else if (bmi > 20){
print("healthy")
} else {
print("underweight")
}
}
bmi_category(22)
#> [1] "healthy"
bmi_category(18)
#> [1] "underweight"
Conditional statements can be nested. That is, inside the
if
or else
block, you can have more
conditional statements, each of which can have if
and
else
blocks, each of which can in turn have nested
conditional statements, and so on. For complex computations, the
conditional logic can become very elaborate, and needs to be approached
carefully. I find it helpful in these cases to sketch out a flow chart
showing all the different outcomes based on state, and use that as a
pattern for writing and arranging the various code blocks.
Complex conditional expressions
In our previous examples, we wrote conditional expressions using the
> (greater than) operator. The expression
my_mark > 50
evaluates to either true or false (i.e. a
boolean value). If variable my_mark
is
greater than 50, the expression returns true, otherwise it returns
false. Greater than is a comparison operator. The R
comparison operators are:
== |
equal to |
!= |
not equal to |
< |
less than |
<= |
less than or equal to |
> |
greater than |
>= |
greater than or equal to |
The Boolean logic operators can be used in to modify
or combine conditional expressions.
For example, the following function might be used to check that a
value entered as a penguin body mass was within the expected weight
range for the species.
# Chinstrap penguins weight between 3 and 5 kg
check_chinstrap_weight <- function(weight_to_check)
{
if ((weight_to_check >= 3000) & (weight_to_check <= 5000)) {
print("Weight ok")
} else {
print("That's probably a typo")
}
}
check_chinstrap_weight(4100)
#> [1] "Weight ok"
check_chinstrap_weight(410)
#> [1] "That's probably a typo"
The result of the NOT, AND, and OR are shown in the logic table:
!TRUE |
FALSE |
|
|
!FALSE |
TRUE |
|
|
TRUE & TRUE |
TRUE |
|
|
TRUE & FALSE |
FALSE |
|
|
FALSE & TRUE |
FALSE |
|
|
FALSE & FALSE |
FALSE |
|
|
TRUE | TRUE |
TRUE |
|
|
TRUE | FALSE |
TRUE |
|
|
FALSE | TRUE |
TRUE |
|
|
FALSE | FALSE |
FALSE |
|
|
Conditional exercise
Write and test a function that determines whether a student receives
a passing grade on an assessment. The function should accept two input
args: the number of marks earned, and the total number of marks possible
for the assessment. The student must earn 50% of the available marks in
order to pass. For example, if a student earns 18 marks on a 20 mark
assessment they pass, but if they earn only 8 marks, they fail. Your
function should print “Pass” or “Fail” as appropriate based on the input
data.
pass_check <- function(earned, possible)
{
mark <- earned/possible
if (mark > 0.5){
print("Pass")
} else {
print("Fail")
}
}
pass_check(18, 20)
#> [1] "Pass"
pass_check(8,20)
#> [1] "Fail"
pass_check(18,100)
#> [1] "Fail"
pass_check(8,10)
#> [1] "Pass"
Function Error Checking
We can use conditional control statements to provide error checking
in user-defined functions.
Failing
One of the sayings in programming is “if it’s going to fail, it’s
best to fail early”. That is, if we know that our function requires a
specific input data type, we want to program
defensively so that our function “fails” before it
encounters the error. As part of our defensive programming we can
provide informative error messages, rather than rely on R’s generic
ones.
In the following example, we check that the data coming into our
function is numeric. If it is not, we use function stop
, to
exit the function, displaying our informative message.
# Returns the provided number doubled
double_number <- function(x) {
if( !is.numeric(x) ){
stop("x needs to be a number.")
}
x * 2
}
double_number(4)
#> [1] 8
double_number("a")
#> Error in double_number("a"): x needs to be a number.
N.B. Check the appendix for more on data types.
Conclusion
This document has presented an introduction to creating your own
functions and implementing conditional flow of control. For more detail,
see the free online books Advanced
R and R packages.
Appendix
Data types
Not all data are created equal, in R this concept is captured by
data types. For a vector, all values must be of a single data
type.
The main data types that you will encounter in R are:
- Logical (
c(TRUE, FALSE)
)
- Numeric - also called Real or Double
(Numbers that have a floating point (decimal) representation
e.g.
c(1, 3.6, 1e3)
)
- Character - also called String (anything inside
matching opening and closing quotes (single or double)
e.g.
c("a", "some words", "animal"
))
There are 3 other less common:
- Integer (integers
c(1L, 4L, -3L)
)
- Complex (Complex numbers
e.g.
c(0+3i, 4i, -2-5i)
)
- Raw (the bytes of a file)
Each data type is known in R as an atomic vector. R has
built in functions to be able to determine the data type of a vector,
typeof()
is the best one to use, but others such as
str()
and class()
can be used.
There is also a series of functions that let us do explicit checking
for a data type which will return TRUE
or
FALSE
:
is.logical()
is.numeric()
or is.double()
is.character()
is.integer()
is.complex()
is.raw()
Data Type Coercion
In R, when doing operations on multiple vectors, they all need to be
the same data type - but how can this work if we have for example a
numeric vector and a character vector? Coercion is how R deals
with trying to operate on two vectors of different data types. What this
means in practice is that R will convert the data type of a vector in a
defined manner such that we end up will all of the same type and follows
a “lowest common data type” approach. Using the 3 main data types from
above, the following is the order in which they will be coerced into the
next data type: logical -> numeric ->
character.
This principle applies when you try to create a vector of mixed data
types too, R will coerce everything until it is a single data type.
See if you can predict what data type the result will be (you can
check by using typeof()
:
# logical and numeric
c(4, TRUE, 5)
# numeric and character
c(1, 3, "A")
# logical and character
c(FALSE, "cat","frog")
# mixed
c("see", TRUE, 4.8)
# tricky
c("1.3", "4", TRUE)
We can also explicitly force coercion into a particular data type by
using the following:
as.logical()
as.numeric()
as.character()
The other data types also have similarly named functions. When going
against the normal direction of coercion, it is important to realise
that if your data doesn’t have a representation in that data type, it
will become NA (missing).
LS0tCnRpdGxlOiAiRnVuY3Rpb25zIGFuZCBDaG9pY2VzIgpkYXRlOiAiU2VtZXN0ZXIgMiwgMjAyMyIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2RlcHRoOiAzCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IHNob3cKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShrbml0cikKCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBjb21tZW50ID0gIiM+IiwKICBmaWcucGF0aCA9ICJmaWd1cmVzLzA4LyIsICMgdXNlIG9ubHkgZm9yIHNpbmdsZSBSbWQgZmlsZXMKICBjb2xsYXBzZSA9IFRSVUUsCiAgZWNobyA9IFRSVUUKKQoKCmBgYAoKPiAjIyMjIEFzc29jaWF0ZWQgTWF0ZXJpYWwKPgo+IFpvb20gbm90ZXM6IFtab29tIG5vdGVzIDA4IC0gRnVuY3Rpb25zIGFuZCBDaG9pY2VzXSh6b29tX25vdGVzXzA4X2Z1bmN0aW9ucy5odG1sKQo+IAo+IFJlYWRpbmdzOgo+Cj4gLSBbUiBmb3IgRGF0YSBTY2llbmNlIC0gQ2hhcHRlciAxOV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei9mdW5jdGlvbnMuaHRtbCkKClwKCiMgSW50cm9kdWN0aW9uCgpBcyB0aGUgd29yayB5b3UgZG8gaW4gUiBiZWNvbWVzIG1vcmUgY29tcGxleCwgeW91ciBSIHNjcmlwdHMgd2lsbCBnZXQgbG9uZ2VyLCBhbmQgbWF5IGJlY29tZSBkaWZmaWN1bHQgdG8gbWFuYWdlLiBZb3UgbWF5IGZpbmQgdGhhdCBpdCBpcyBkaWZmaWN1bHQgdG8gbG9jYXRlIHBhcnRpY3VsYXIgYml0cyBvZiBjb2RlLCBvciB0aGF0IHlvdSBzZWVtIHRvIGJlIHdyaXRpbmcgdGhlIHNhbWUsIG9yIHZlcnkgc2ltaWxhciBiaXRzIG9mIGNvZGUsIG92ZXIgYW5kIG92ZXIgYWdhaW4uIElmIHlvdSB3YW50IHRvIG1vZGlmeSB0aG9zZSBiaXRzLCB0aGVyZSBhcmUgbXVsdGlwbGUgcGxhY2UgaW4gdGhlIHNjcmlwdCB5b3UgaGF2ZSB0byBlZGl0LCB0eXBvcyBzdGFydCB0byBjcmVlcCBpbiwgYW5kIHRoZSB3aG9sZSBwcm9jZXNzIGJlY29tZXMgdW5wbGVhc2FudC4KClRvIHByZXZlbnQgdGhpcywgbGFyZ2UgcHJvZ3JhbXMgbmVlZCB0byBiZSBvcmdhbmlzZWQgaW50byAqKmxvZ2ljYWwgbW9kdWxlcyoqLiBTZWN0aW9ucyBvZiBjb2RlIHRoYXQgcGVyZm9ybSBhIGNsZWFybHkgZGVsaW5lYXRlZCB0YXNrIGNhbiBiZSBlbmFjYXBzdWxhdGVkIGFuZCBuYW1lZC4gVGhlIGVuY2Fwc3VsYXRlZCBjb2RlIGNhbiBiZSBpbnZva2VkIHNpbXBseSBieSB0eXBpbmcgdGhlIG5hbWUgLS0gbm8gbmVlZCB0byBjdXQgYW5kIHBhc3RlLCBubyBuZWVkIHRvIG1vZGlmeSBtdWx0aXBsZSBjb3BpZXMuIFNjcmlwdHMgYXJlIHNob3J0ZXIgYW5kIGVhc2llciB0byBtYW5hZ2UuIENvZGUgdGhhdCBpcyBvcmdhbmlzZWQgdGhpcyB3YXkgaXMgc2FpZCB0byBiZSAqKm1vZHVsYXIqKi4gTW9kdWxhciBjb2RlIGlzIGJldHRlciBjb2RlLgoKSW4gUiwgdGhlIG1haW4gY29kZSBtb2R1bGUgaXMgdGhlICoqZnVuY3Rpb24qKi4gV2UgaGF2ZSBhbHJlYWR5IHVzZWQgbWFueSBmdW5jdGlvbnMsIGxpa2UgYHJlYWQuY3N2YCBhbmQgYHNxcnRgIGFuZCBgZ2dwbG90YC4gV2UgaW52b2tlIHRoZW0gaW4gb3VyIGNvZGUgYXMgc2luZ2xlIGNvbW1hbmRzLCBidXQgZWFjaCBvZiB0aGVzZSBjb21tYW5kcyBhY3R1YWxseSBlY2Fwc3VsYXRlcyBtYW55LCBtYW55IChhZGQgYW5vdGhlciAibWFueSIgZm9yIGdncGxvdCkgbGluZXMgb2YgY29kZS4gV2UgY2FsbCB0aGUgZnVuY3Rpb24gYnkgbmFtZSwgYW5kIGFsbCB0aGUgYXNzb2NpYXRlZCBjb2RlIGlzIGV4ZWN1dGVkLgoKTWFueSBmdW5jdGlvbnMgaW4gUiB3aWxsIGRpc3BsYXkgdGhlaXIgY29kZSBpbiB0aGUgY29uc29sZS4gVHlwZSB0aGUgZnVuY3Rpb24gbmFtZSAqKndpdGhvdXQgdGhlICgpKiogaW50byB0aGUgY29uc29sZSwgYW5kIHRoZSBlbmNhcHN1bGF0ZWQgY29tbWFuZHMgd2lsbCBiZSBzaG93bi4gKExvb2sgYXQgdGhlIGNvZGUgZm9yIGZ1bmN0aW9uIGBmaWx0ZXJgLikKClRvIG1ha2Ugb3VyIG93biBjb2RlIG1vZHVsYXIsIHdlIGNhbiBkZWZpbmUgb3VyIG93biBmdW5jdGlvbnMuIFdlIHdyaXRlIHRoZSBjb2RlIGZvciBhIGZ1bmN0aW9uIHNvbWV3aGVyZSBpbiBvdXIgc2NyaXB0IGZpbGUuIFdlIGNhbiB0aGVuICoqY2FsbCoqIHRoZSBmdW5jdGlvbiBieSBuYW1lIGFueXdoZXJlIGVsc2UgaW4gb3VyIHNjcmlwdCBmaWxlLCBhbmQgYWxsIHRoZSBjb2RlIGlzIGV4ZWN1dGVkLiBKdXN0IGFzIHdpdGggYnVpbHQtaW4gZnVuY3Rpb25zLCB3ZSBjYW4gcGFzcyBkYXRhIGludG8gb3VyIGZ1bmN0aW9uLCBhbmQgaXQgY2FuIG9wZXJhdGUgb24gdGhvc2UgZGF0YS4gV2UgY2FuIGFsc28gYXJyYW5nZSBmb3Igb3VyIGZ1bmN0aW9uIHRvICoqcmV0dXJuIGEgcmVzdWx0KiogdGhhdCB3ZSBjYW4gc3RvcmUgaW4gYSB2YXJpYWJsZS4gCgoKIyBGdW5jdGlvbiBEZWNsYXJhdGlvbiBTeW50YXgKCkEgZnVuY3Rpb24gaW4gUiBpcyBjb21wcmlzZWQgb2YgZm91ciBwYXJ0czoKCjEuIGEgbmFtZQoyLiB0aGUgYm9keSAodGhlIGNvZGUgdGhhdCBkb2VzIHNvbWV0aGluZykKMy4gKG9wdGlvbmFsbHkpIGlucHV0IGRhdGEKNC4gKG9wdGlvbmFsbHkpIGFuIG91dHB1dCB0aGF0IGNhbiBiZSBzdG9yZWQKCgojIyBDcmVhdGluZyBhIGZ1bmN0aW9uCgpXZSB3aWxsIGJlZ2luIHdpdGggdGhlIHNpbXBsZXN0IGZ1bmN0aW9uLCBvbmUgdGhhdCBhY2NlcHRzIG5vIGlucHV0IGRhdGEsIGFuZCByZXR1cm5zIG5vIHJlc3VsdC4gV2UgKipkZWNsYXJlKiogdGhlIGZ1bmN0aW9uIHVzaW5nIGtleXdvcmQgYGZ1bmN0aW9uYC4gU2NoZW1hdGljYWxseSwgYSB1c2VyLWRlZmluZWQgZnVuY3Rpb24gaXMgY3JlYXRlZCBhczoKCmBgYApuYW1lX29mX2Z1bmN0aW9uIDwtIGZ1bmN0aW9uKCkKewogICBDb2RlIEJvZHkKfQpgYGAgCgpUaGUgY3VybHkgYnJhY2VzIGVuY2xvc2UgdGhlIGNvZGUgYm9keS4KCgpTdWJlc3F1ZW50bHkgd2UgKipjYWxsKiogdGhlIGZ1bmN0aW9uIGFzOgoKKm5hbWVfb2ZfZnVuY3Rpb24qKCkKCldoZW4gdGhlIGNhbGwgaXMgZXhlY3V0ZWQsIGFsbCB0aGUgY29tbWFuZHMgaW4gdGhlIGNvZGUgYm9keSBhcmUgcnVuLgoKRm9yIGV4YW1wbGUsIGluIHRoZSBjdXJyZW50IHB1YmxpYyBoZWFsdGggc2l0dWF0aW9uLCB3ZSBvZnRlbiBzZWUgZGlzY3Vzc2lvbnMgb2Ygd2hhdCBib2R5IHRlbXBlcmF0dXJlIGNvbnN0aXR1dGVzIGEgZmV2ZXIuIFdlIG1pZ2h0IHdhbnQgdG8gYmUgYWJsZSB0byB0cmFuc2xhdGUgdGhhdCB0ZW1wZXJhdHVyZSBmcm9tIENlbHNpdXMgdG8gRmFocmVuaGVpdCAoYXMgdXNlZCBpbiB0aGUgTm9ydGggQW1lcmljYW4gbGl0ZXJhdHVyZSkuIFRoaXMgaXMgYSBsb2dpY2FsbHkgd2VsbC1kZWxpbmVhdGVkIGNvbXB1dGF0aW9uLCBzbyB3ZSB3b3VsZCBlbmNhcHN1bGF0ZSBpdCBpbiBhIGZ1bmN0aW9uLgoKYGBge3IgZGVjbGFyZSBhIGZ1bmN0aW9ufQojIERlY2xhcmUvZGVmaW5lIHRoZSBmdW5jdGlvbgpmZXZlcl9pbl9mYWhyZW5oZWl0IDwtIGZ1bmN0aW9uKCkKewogIGZldmVyX2luX2NlbHNpdXMgPC0gMzcuNQogIGNvbnZlcnRlZF90b19mYWhyZW5oZWl0IDwtKGZldmVyX2luX2NlbHNpdXMqOS81KSArIDMyCiAgcHJpbnQoY29udmVydGVkX3RvX2ZhaHJlbmhlaXQpCn0KYGBgCgpgYGB7ciBjYWxsfQojIENhbGwgYSB1c2VyLWRlZmluZWQgZnVuY3Rpb24gYnkgbmFtZQpmZXZlcl9pbl9mYWhyZW5oZWl0KCkKYGBgCgpTb21lIHRoaW5ncyB0byBub3RlOgoKLSAgVHlwaW5nIG91dCB0aGUgZnVuY3Rpb24gZGVjbGFyYXRpb24gaXMgbm90IGVub3VnaCB0byBtYWtlIHRoZSBmdW5jdGlvbiBhdmFpbGFibGUgZm9yIGNhbGxpbmcuIFRoZSBkZWNsYXJhdGlvbiBjb2RlIChmcm9tIHRoZSBzdGFydCBvZiB0aGUgbmFtZSB0byB0aGUgY2xvc2luZyBjdXJseSBicmFja2V0LCBpbmNsdXNpdmUpICoqbXVzdCBmaXJzdCBiZSBleGVjdXRlZCoqLiBFeGVjdXRlIHRoaXMgY29kZSBpbiBhIHNjcmlwdCBhcyB3ZSBhbHdheXMgZG8sIGJ5IHNlbGVjdGluZyBhbGwgdGhlIGNvZGUgKHdpdGggdGhlIG1vdXNlKSBhbmQgdHlwaW5nIGN0cmwtRW50ZXIgKFdpbmRvd3MpIG9yIGNtZC1FbnRlciAoTWFjKS4gVGhpcyBpcyBjYWxsZWQgKipzb3VyY2luZyoqIHRoZSBmdW5jdGlvbi4KLSBXaGVuIHlvdSBzb3VyY2UgYSBmdW5jdGlvbiwgKipub3RoaW5nIGhhcHBlbnMqKi4gSW4gb3VyIGV4YW1wbGUsIHlvdSB3aWxsIG5vdCBzZWUgdGhlIG91dHB1dCBvZiB0aGUgcHJpbnQgc3RhdGVtZW50IHdoZW4geW91IGV4ZWN1dGUgdGhlIGRlY2xhcmF0aW9uIGNvZGUuIFNvdXJjaW5nIGEgZnVuY3Rpb24gZGVjbGFyYXRpb24gKipkb2VzIG5vdCBydW4gdGhlIGNvZGUgYm9keSoqLiBJdCBzaW1wbHkgKnBhcnNlcyogdGhlIGNvZGUgYm9keSBhbmQsIGlmIHRoZXJlIGFyZSBubyBlcnJvcnMsIHN0b3JlcyBpdCBpbiB0aGUgZW52aXJvbm1lbnQuIEVmZmVjdGl2ZWx5LCBpdCBpbmZvcm1zIFJTdHVkaW8gdGhhdCBhIGZ1bmN0aW9uIHdpdGggdGhpcyBuYW1lIGV4aXN0cywgYW5kIGRlZmluZXMgdGhlIGNvZGUgd2hpY2ggaXQgZW5jYXBzdWxhdGVzLCBzbyBpdCBjYW4gYmUgY2FsbGVkIGxhdGVyLgotIFRvIGV4ZWN1dGUgdGhlIGNvZGUgYm9keSwgc3RhdGUgdGhlIG5hbWUgb2YgdGhlIGZ1bmN0aW9uIGZvbGxvd2VkIGJ5ICgpLCB3aXRoIG5vIGludGVydmVuaW5nIHNwYWNlcy4gVGhpcyAqKmNhbGxzKiogdGhlIGZ1bmN0aW9uOyB3ZSB0aGluayBvZiAoKSBhcyB0aGUgKipjYWxsIG9wZXJhdG9yKiouIFdoZXRoZXIgdGhlIGNvZGUgYm9keSBjb250YWlucyAxIGxpbmUgb3IgMSwwMDAgbGluZXMsIG9yIG1vcmUsIGNhbGxpbmcgdGhlIGZ1bmN0aW9uIGJ5IG5hbWUgcnVucyBhbGwgdGhlIGVuY2Fwc3VsYXRlZCBjb2RlLgoKCkluIFIgYSBmdW5jdGlvbiBjYW5ub3QgYmUgY2FsbGVkIHVudGlsICphZnRlciogdGhlIGZ1bmN0aW9uIGhhcyBiZWVuIHNvdXJjZWQuIENvbnNpZGVyIHRoZSBmb2xsb3dpbmcgZXhhbXBsZToKCmBgYHtyIGNsZWFyLCBlY2hvPUZBTFNFfQpybShsaXN0ID0gbHMoKSkKYGBgCgpgYGB7ciB3cm9uZyBvcmRlciwgZXJyb3I9VFJVRX0KCiMgSWYgeW91IHRyeSB0byBjYWxsIHRoZSBmdW5jdGlvbiBiZWZvcmUgaXQgaXMgZGVjbGFyZWQgYW5kIHNvdXJjZWQKZmV2ZXJfaW5fZmFocmVuaGVpdCgpCgpmZXZlcl9pbl9mYWhyZW5oZWl0IDwtIGZ1bmN0aW9uKCkKewogIGZldmVyX2luX2NlbHNpdXMgPC0gMzcuNQogIGNvbnZlcnRlZF90b19mYWhyZW5oZWl0IDwtKGZldmVyX2luX2NlbHNpdXMqOS81KSArIDMyCiAgcHJpbnQoY29udmVydGVkX3RvX2ZhaHJlbmhlaXQpCn0KCmBgYAoKVGhlcmUgYXJlIG1vcmUgYWR2YW5jZWQgdGVjaG5pcXVlcyB0aGF0IGFsbG93IHVzIHRvIGNhbGwgZnVuY3Rpb25zIGNvbnRhaW5lZCBpbiBvdGhlciBzY3JpcHQgZmlsZXMgd2hlcmUgd2UgY2Fubm90IGRpcmVjdGx5IHNlbGVjdCBhbmQgZXhlY3V0ZSB0aGUgZGVjbGFyYXRpb24gY29kZS4gU2VlIHRoZSByZWFkaW5nIGZvciBkaXNjdXNzaW9uLgoKCiMjIFByb3ZpZGluZyBkYXRhIHRvIGEgZnVuY3Rpb24KCkNvbnNpZGVyIHRoZSBmb2xsb3dpbmcgZnVuY3Rpb24sIHdoaWNoIGRlbW9uc3RyYXRlcyBob3cgdG8gY29tcHV0ZSBCTUkgKGJvZHkgbWFzcyBpbmRleCkgaW4gUiwgdXNpbmcgdGhlIGdpdmVuIHZhbHVlcyBmb3IgaGVpZ2h0IChpbiBtZXRyZXMpIGFuZCB3ZWlnaHQgKGluIGtnKToKCmBgYHtyIGNhbGMgQk1JfQoKIyBEZWNsYXJlIGZ1bmN0aW9uIGNhbGNfQk1JCmNhbGNfQk1JIDwtIGZ1bmN0aW9uKCkKewogIHdlaWdodCA8LSA3MwogIGhlaWdodCA8LSAxLjY4CiAgYm1pIDwtIHdlaWdodC9oZWlnaHReMiAjIF4gaXMgdGhlIGV4cG9uZW50aWF0aW9uIG9wZXJhdG9yCiAgCiAgcHJpbnQoYm1pKQp9CgojIENhbGwgZnVuY3Rpb24gY2FsY19CTUkKY2FsY19CTUkoKQoKYGBgClRoaXMgZnVuY3Rpb24gY29udGFpbnMgbmljZSB0aWR5IGNvZGUgYW5kIGlzIG1hdGhlbWF0aWNhbGx5IGNvcnJlY3QsIGJ1dCB1bmxlc3Mgd2UgaGFwcGVuIHRvIHdhbnQgdGhlIEJNSSBvZiBhIHBlcnNvbiB3aXRoIGV4YWN0bHkgdGhpcyBoZWlnaHQgYW5kIHdlaWdodCwgaXQgaXMgb2Ygbm8gdXNlIHRvIHVzLiBBIHVzZWZ1bCBmdW5jdGlvbiBkZWZpbmVzIHRoZSBjb21wdXRhdGlvbiAoaW4gdGhpcyBjYXNlIHRha2luZyB0aGUgcmF0aW8gb2Ygd2VpZ2h0IHRvIGhlaWdodCBzcXVhcmVkKSwgYW5kICoqYWNjZXB0cyB0aGUgZGF0YSB2YWx1ZXMqKiB3aGVuIGl0IGlzIGNhbGxlZC4KCldlIGhhdmUgc2VlbiB0aGlzIG1hbnkgdGltZXMgd2hlbiB3cml0aW5nIFIgY29kZSwgd2hlbiB3ZSBjYWxsIGEgZnVuY3Rpb24gcmVwZWF0ZWRseSBvbiBkaWZmZXJlbnQgaW5wdXQgdmFsdWVzOgoKYGBge3IgYnVpbHQgaW4gaW5wdXRzfQoKc3FydCgxNCkKCnNxcnQoODIwKQoKc3FydCgwLjY1KQoKYGBgCgpUbyBkZWNsYXJlIGEgZnVuY3Rpb24gdGhhdCBjYW4gYWNjZXB0IGlucHV0IGFyZ3VtZW50cywgcGVyZm9ybSB0aGVzZSBzdGVwczoKCjEuIEJldHdlZW4gdGhlIHJvdW5kIGJyYWNrZXRzIHRoYXQgZm9sbG93IHRoZSBrZXl3b3JkIGBmdW5jdGlvbmAsIHBsYWNlIGEgKip2YXJpYWJsZSBuYW1lKiogZm9yIGVhY2ggcGllY2Ugb2YgZGF0YSB5b3Ugd2lzaCB0byBpbnB1dCB3aGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQuCjIuIEluIHRoZSBmdW5jdGlvbiBib2R5IHJlZmVyIHRvIHRoZSBpbnB1dCB2YXJpYWJsZXMgKipieSB0aGUgbmFtZSB5b3UgcGxhY2VkIGJldHdlZW4gdGhlIHJvdW5kIGJyYWNrZXRzKiouIFlvdSBETyBOT1QgbmVlZCB0byBpbml0aWFsaXNlIHRoZSB2YXJpYWJsZXMgaW5zaWRlIHRoZSBjb2RlIGJvZHkgLS0gaW4gZmFjdCB5b3UgTVVTVCBOT1QgZG8gc28uIFZhcmlhYmxlcyB3aXRoIHRob3NlIG5hbWVzIGFyZSBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQgZm9yIHlvdSB3aGVuIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQuIAozLiBXaGVuIGNhbGxpbmcgdGhlIGZ1bmN0aW9uLCBwcm92aWRlICoqYSB2YWx1ZSoqIGZvciBlYWNoIGlucHV0IHZhcmlhYmxlLiBZb3UgZG8gbm90IG5lZWQgdG8gcmVwZWF0IHRoZSB2YXJpYWJsZSBuYW1lLCBqdXN0IHByb3ZpZGUgdmFsdWVzLCBzZXBhcmF0ZWQgYnkgY29tbWFzLCBpbiB0aGUgc2FtZSBvcmRlciBhcyB0aGUgdmFyaWFibGVzIGFyZSBsaXN0ZWQgaW4gdGhlIGRlY2xhdHJhdGlvbi4KNC4gV2hlbiB0aGUgZnVuY3Rpb24gaXMgY2FsbGVkLCB0aGUgc3lzdGVtIGNyZWF0ZXMgdGhlIGlucHV0IHZhcmlhYmxlcywgYXNzaWducyB0aGVtIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcyBmcm9tIHRoZSBjYWxsIHN0YXRlbWVudCwgYW5kIGV4ZWN1dGVzIHRoZSBjb2RlIGJvZHksIHVzaW5nIHRob3NlIHZhcmlhYmxlcy4KCldlIGNhbiBtb2RpZnkgb3VyIGBjYWxjX0JNSWAgZnVuY3Rpb24gdG8gYWNjZXB0IHdlaWdodCBhbmQgaGVpZ2h0IGFzIGlucHV0IHZhcmlhYmxlcywgYXMgc2hvd24uIENvbXBhcmUgdGhpcyB2ZXJzaW9uIHRvIHRoZSBlYXJsaWVyIHZlcnNpb24uIE5vdGUgdGhhdCB3ZSAqZG8gbm90KiBkZWNsYXJlIGFuZCBpbml0aWFsaXNlIHdlaWdodCBhbmQgaGVpZ2h0IGluc2lkZSB0aGUgY29kZSBib2R5LgoKYGBge3IgaW5wdXRzfQojIERlY2xhcmUgZnVuY3Rpb24gY2FsY19CTUkKY2FsY19CTUkgPC0gZnVuY3Rpb24od2VpZ2h0LCBoZWlnaHQpCnsKICAjIFVzZSBpbnB1dCBhcmd1bWVudHMgd2VpZ2h0IGFuZCBoZWlnaHQuIERPTidUIGluaXRpYWxpc2UgdGhlbS4KICBibWkgPC0gd2VpZ2h0L2hlaWdodF4yCiAgCiAgcHJpbnQoYm1pKQp9CgojIENhbGwgZnVuY3Rpb24gY2FsY19CTUkKY2FsY19CTUkoNzMsIDEuNjgpCgpgYGAKCiMjIyBGb2xsb3dpbmcgdGhlIHJ1bGVzCgpEZWNsYXJpbmcgYSBmdW5jdGlvbiB3aXRoIGlucHV0cyBkZWZpbmVzIHRoZSByZXF1aXJlZCAqKmludGVyZmFjZSoqIG9mIHRoZSBmdW5jdGlvbi4gVGhhdCBpcywgaXQgZGVmaW5lcyB3aGF0IHlvdSBoYXZlIHRvIHByb3ZpZGUgaWYgeW91IHdhbnQgdG8gY2FsbCB0aGUgZnVuY3Rpb24uIElmIHRoZSBjYWxsZXIgdmlvbGF0ZXMgdGhlIGludGVyZmFjZSwgdGhlIGNvZGUgaXMgbm90IGd1YXJhbnRlZWQgdG8gd29yay4gRm9yIGV4YW1wbGUsIGZ1bmN0aW9uIGBjYWxjX2JtaWAgaXMgZGVjbGFyZWQgd2l0aCB0d28gaW5wdXQgYXJndW1lbnRzLiBUaGVyZWZvcmUsIGFsbCBvZiB0aGVzZSBjYWxscyB2aW9sYXRlIHRoZSBpbnRlcmZhY2UuCgpgYGB7ciBiYWQgYXJncyAxLCBlcnJvcj1UUlVFfQpjYWxjX0JNSSgpCmBgYAoKYGBge3IgYmFkX2FyZ3MgMiwgZXJyb3I9VFJVRX0KY2FsY19CTUkoMTYpCmBgYAoKYGBge3IgYmFkIGFyZ3MgMywgZXJyb3I9VFJVRX0KY2FsY19CTUkoNzMsIDE2OCwgNDIpCmBgYAoKSW4gc29tZSBwcm9ncmFtbWluZyBsYW5ndWFnZXMsIG9uZSBpcyByZXF1aXJlZCB0byBzcGVjaWZ5IHRoZSBkYXRhIHR5cGUgKGUuZy4gbnVtYmVyLCBzdHJpbmcsIGRhdGEgZnJhbWUsIGV0Yy4pIG9mIGVhY2ggaW5wdXQgYXJndW1lbnQuIENvZGUgdGhhdCB0cmllcyB0byBwYXNzIGluIHRoZSB3cm9uZyB0eXBlIG9mIGRhdGEgd2lsbCBub3QgY29tcGlsZS4gSW4gUiB0aGlzIGlzIG5vdCByZXF1aXJlZC4gUiB3aWxsIHRyeSB0byBydW4geW91ciBjb2RlIG5vIG1hdHRlciB3aGF0IHNvcnQgb2YgZGF0YSBpdCBnZXRzLiBIb3dldmVyLCBpZiBpdCB0cmllcyB0byBvcGVyYXRlIG9uIHRoZSB3cm9uZyB0eXBlIG9mIGRhdGEsIGl0IHdpbGwgdGhyb3cgYW4gZXJyb3I6CgoKYGBge3IgYmFkIGFyZ3MgNCwgZXJyb3I9VFJVRX0KY2FsY19CTUkoNDIsICJmcmVkIikKYGBgCgpOYXR1cmFsbHksIFIgZG9lc24ndCB1bmRlcnN0YW5kIGhvdyB0byBhcHBseSB0aGUgZXhwb25lbnRpYXRpb24gb3BlcmF0b3IgdG8gImZyZWQiLCBhbmQgaXQgaXMgdGVsbGluZyB5b3Ugc28uCgojIyMgTW9yZSBvbiB0aGUgcnVsZXMKCkNvbnNpZGVyIHRoZSBmb2xsb3dpbmcgY29kZToKCmBgYHtyIGFyZ3MgMmEsIGV2YWwgPSBGQUxTRX0KIyBEZWNsYXJlIHRoZSBmdW5jdGlvbgpjb21wdXRlX2FyZWEgPC0gZnVuY3Rpb24od2lkdGgpCnsKICBhcmVhIDwtIHdpZHRoICogaGVpZ2h0CiAgcHJpbnQoYXJlYSkKfQoKIyBDYWxsIHRoZSBmdW5jdGlvbgpjb21wdXRlX2FyZWEoMzUpCmBgYAoKClRoZSBmdW5jdGlvbiBgY29tcHV0ZV9hcmVhYCBpcyBkZWZpbmVkIHdpdGggb25lIGFyZ3VtZW50LiBUaGVyZWZvcmUsIHdoZW4gaXQgaXMgY2FsbGVkLCB3ZSBtdXN0IHByb3ZpZGUgb25lIHZhbHVlIGJldHdlZW4gdGhlIHJvdW5kIGJyYWNrZXRzLiBJbiB0aGUgY2FsbCwgd2UgaGF2ZSBjb3JyZWN0bHkgcHJvdmlkZWQgb25lIGFyZ3VtZW50LCBvZiB0aGUgY29ycmVjdCBkYXRhIHR5cGUuIFdpbGwgdGhlIGNhbGwgYGNvbXB1dGVfYXJlYSgzNSlgIHdvcmsgY29ycmVjdGx5LCBvciB3aWxsIGl0IHRocm93IGFuIGVycm9yPyBXaGF0IGVycm9yIHdpbGwgaXQgdGhyb3c/CgpgYGB7ciBhcmdzIDJiLCBlcnJvciA9IFRSVUV9CiMgRGVjbGFyZSB0aGUgZnVuY3Rpb24KY29tcHV0ZV9hcmVhIDwtIGZ1bmN0aW9uKHdpZHRoKQp7CiAgYXJlYSA8LSB3aWR0aCAqIGhlaWdodAogIHByaW50KGFyZWEpCn0KCiMgQ2FsbCB0aGUgZnVuY3Rpb24KY29tcHV0ZV9hcmVhKDM1KQpgYGAKCldoZW4gYGNvbXB1dGVfYXJlYSgzNSlgIGlzIGV4ZWN1dGVkLCBpdCBwcm9kdWNlcyBhbiBlcnJvciBtZXNzYWdlOiBgLi4ub2JqZWN0ICdoZWlnaHQnIG5vdCBmb3VuZGAuIEluIHRoZSBjb2RlIGJvZHkgb2YgYGNvbXB1dGVfYXJlYWAsIHdlIHJlZmVyIHRvIGFuIGVudGl0eSBgaGVpZ2h0YC4gU2luY2UgdGhhdCBlbnRpdHkgaXMgbm90IHN1cnJvdW5kZWQgYnkgZG91YmxlLXF1b3RlcywgUiBleHBlY3RzIHRvIGZpbmQgYSB2YXJpYWJsZSBuYW1lZCAqKmhlaWdodCoqIGV4aXN0aW5nIGluIHRoZSBlbnZpcm9ubWVudCwgYW5kIG5vIHN1Y2ggdmFyaWFibGUgZXhpc3RzLCBiZWNhdXNlIHdlIGhhdmUgbmVpdGhlciBjcmVhdGVkIG9uZSBkaXJlY3RseSAod2l0aCBhbiBhc3NpZ25tZW50IHN0YXRlbWVudCkgbm9yIHBhc3NlZCBvbmUgaW4gYXMgYW4gYXJndW1lbnQgdG8gdGhlIGZ1bmN0aW9uLiAKCkluIHRoZSBzYW1lIGxpbmUgb2YgY29kZSwgd2UgYWxzbyByZWZlciB0byBhbiBlbnRpdHkgYHdpZHRoYC4gTm90ZSB0aGF0IFIgZG9lcyBub3QgY29tcGxhaW4gYWJvdXQgYmVpbmcgdW5hYmxlIHRvIGZpbmQgYHdpZHRoYC4gVGhhdCBpcyBiZWNhdXNlIHdlIGRlZmluZWQgYW4gaW5wdXQgYXJndW1lbnQgY2FsbGVkICoqd2lkdGgqKi4gCgoxLiBIb3cgd291bGQgeW91IG1vZGlmeSBmdW5jdGlvbiBgY29tcHV0ZV9hcmVhYCB0byBlbGltaW5hdGUgdGhlIGVycm9yPwoyLiBIb3cgd291bGQgdGhpcyBjaGFuZ2UgdGhlIGZvcm0gb2YgdGhlIGNhbGwgdG8gYGNvbXB1dGVfYXJlYWA/CgoKIyMjIFRha2luZyB5b3VyIHRpbWUKClRyYWRpdGlvbmFsbHksIG5ldyBwcm9ncmFtbWVycyBmaW5kIHRoZSBzeW50YXggb2YgYXJndW1lbnQgcGFzc2luZyAqZXh0cmVtZWx5KiBjb25mdXNpbmcuIFRoZXJlIGFyZSB0b28gbWFueSBpbnRlcmFjdGluZyBwYXJ0czogd2UgaGF2ZSB2YXJpYWJsZSBuYW1lcyBpbiB0aGUgZGVjbGFyYXRpb24sIHZhcmlhYmxlcyB1c2VkIGluIHRoZSBjb2RlIGJvZHksIGFuZCB2YWx1ZXMgcGFzc2VkIGluIHRoZSBjYWxsLiBBdCBmaXJzdCBleHBvc3VyZSwgaXQgY2FuIGJlIHVuY2xlYXIgaG93IGFsbCB0aGVzZSBwYXJ0cyB3b3JrIHRvZ2V0aGVyLiBJZiB0aGlzIGlzIHRoZSBmaXJzdCB0aW1lIHlvdSBoYXZlIHNlZW4gdGhpcyBzeW50YXgsIHRha2Ugc29tZSB0aW1lIHRvIGV4cGVyaW1lbnQgd2l0aCBpdCB0byBzb2xpZGlmeSB5b3VyIHVuZGVyc3RhbmRpbmcuIE1ha2UgdXAgc29tZSBzaW1wbGUgdXNlciBkZWZpbmVkIGZ1bmN0aW9ucyBvZiB5b3VyIG93biB0byBwcmFjdGljZSBtYW5hZ2luZyBpbnB1dCBkYXRhLgoKCiMjIEdldHRpbmcgb3V0cHV0IGZyb20gYSBmdW5jdGlvbgoKSW4gYWxsIG9mIG91ciBleGFtcGxlcyBzbyBmYXIsIHdlIGhhdmUgdXNlZCBhIHByaW50IHN0YXRlbWVudCB0byBzaG93IHRoZSByZXN1bHQgb2YgdGhlIGZ1bmN0aW9uJ3MgY29tcHV0YXRpb24uIFRoaXMgaXMsIG9mIGNvdXJzZSwgbm90IGFkZXF1YXRlIGluIHJlYWwgcHJvZ3JhbW1pbmcsIGFzIGEgcHJpbnQgc3RhdGVtZW50IHNpbXBseSB3cml0ZXMgdG8gdGhlIGNvbnNvbGUuIFRoZSBjb21wdXRlZCB2YWx1ZSBpcyBub3QgYXZhaWxhYmxlIGZvciB1c2UgbGF0ZXIgaW4gb3VyIHNjcmlwdC4gV2Ugd2FudCB0byBiZSBhYmxlIHRvIHNhdmUgdGhlIHJlc3VsdCBvZiBhIGZ1bmN0aW9uIGludG8gYSB2YXJpYWJsZSwgYXMgd2UgaGF2ZSBkb25lIHdpdGggdGhlIGJ1aWx0LWluIGZ1bmN0aW9ucyB3ZSBoYXZlIHVzZWQgZWFybGllciBpbiB0aGUgY291cnNlLiBGb3IgZXhhbXBsZSwgd2UgaGF2ZSBzYWlkIGB4IDwtIHNxcnQoMjIpYCwgY3JlYXRpbmcgYSB2YXJpYWJsZSBjYWxsZWQgKngqIHRoYXQgc3RvcmVzIHRoZSBzcXVhcmUgcm9vdCBvZiAyMi4gV2UgY291bGQgdGhlbiB1c2UgYHhgIGluIHN1YnNlcXVlbnQgY29tcHV0YXRpb25zLCBhcyBuZWVkZWQuCgpXaGVuIGEgZnVuY3Rpb24gbWFrZXMgaXRzIHJlc3VsdCBhdmFpbGFibGUgZm9yIHN0b3JhZ2UsIHdlIHNheSBpdCBpcyAqKnJldHVybmluZyoqIGl0cyByZXN1bHQuIFRoZSBjb21tYW5kIGBzcXJ0KDIyKWAgKipyZXR1cm5zKiogdGhlIHNxdWFyZSByb290IG9mIDIyLCBhbmQgd2UgY2FuIHN0b3JlIGl0IGluIGEgdmFyaWFibGUgdXNpbmcgdGhlIGFzc2lnbm1lbnQgc3RhdGVtZW50LgoKV2UgY2FuIG1ha2Ugb3VyIHVzZXItZGVmaW5lZCBmdW5jdGlvbiBiZWhhdmUgaW4gdGhlIHNhbWUgd2F5LCBieSB1c2luZyBgcmV0dXJuYCBpbnN0ZWFkIG9mIGBwcmludGAuIEZvciBleGFtcGxlLCB3ZSBjYW4gbW9kaWZ5IGBjYWxjX2JtaWA6CgpgYGB7ciByZXR1cm59CiMgRGVjbGFyZSBmdW5jdGlvbiBjYWxjX0JNSQpjYWxjX0JNSSA8LSBmdW5jdGlvbih3ZWlnaHQsIGhlaWdodCkKewogIGJtaSA8LSB3ZWlnaHQvaGVpZ2h0XjIgIyBeIGlzIHRoZSBleHBvbmVudGlhdGlvbiBvcGVyYXRvcgogIAogIHJldHVybihibWkpCn0KYGBgCgpXaXRoIHRoaXMgY2hhbmdlIHRvIHRoZSBmdW5jdGlvbiwgd2UgY2FuIHN0b3JlIHRoZSByZXN1bHQgb2YgdGhlIEJNSSBjb21wdXRhdGlvbiBpbiBhIHZhcmlhYmxlIGZvciBsYXRlciB1c2UuCgpgYGB7ciBzYXZpbmcgYSByZXR1cm59CgojIFNhdmUgdGhlIHJldHVybiB2YWx1ZSBpbiBhIHZhcmlhYmxlLgpibWlfcmVzdWx0IDwtIGNhbGNfQk1JKDc1LCAxLjc1KQoKIyBEaXNwbGF5IGJ5IG5hbWUsIGFzIHdlIGFsd2F5cyBjYW4gZG8gaW4gUiB3aXRoIHZhcmlhYmxlcwpibWlfcmVzdWx0CmBgYAoKIyMjIENBVVRJT04KCkluIFIsIHRoZSBgcmV0dXJuYCBrZXl3b3JkIGlzIGFjdHVhbGx5IG9wdGlvbmFsLiBCeSBkZWZhdWx0LCBSIGZ1bmN0aW9ucyBqdXN0IHJldHVybiB0aGUgdmFsdWUgb2YgdGhlaXIgbGFzdCBsaW5lIG9mIGNvZGUuIFNvIHRlY2huaWNhbGx5LCB5b3UgY2FuIHdyaXRlIHRoZSBmdW5jdGlvbiBhYm92ZSBsaWtlIHRoaXMgd2l0aG91dCBjaGFuZ2luZyBpdHMgYmVoYXZpb3VyOgoKYGBge3IgYmxhbmsgcmV0dXJufQojIERlY2xhcmUgZnVuY3Rpb24gY2FsY19CTUkKY2FsY19CTUkgPC0gZnVuY3Rpb24od2VpZ2h0LCBoZWlnaHQpCnsKICBibWkgPC0gd2VpZ2h0L2hlaWdodF4yICMgXiBpcyB0aGUgZXhwb25lbnRpYXRpb24gb3BlcmF0b3IKICAKICAjIE9taXR0aW5nIHRoZSBleHBsaWNpdCBjYWxsIHRvIHJldHVybi4gRG9uJ3QgZG8gdGhpcy4KICBibWkKfQpgYGAKCllvdSB3aWxsIHNlZSB0aGlzIHNob3J0Y3V0IHVzZWQgaW4gUiBjb2RlIGluIHRoZSB3aWxkLiBIb3dldmVyLCBpdCBpcyBhbiBvbGQtZmFzaGlvbmVkIHN5bnRheCwgYW5kIGl0IGNhbiBsZWFkIHRvIHN1YnRsZSBlcnJvcnMgaW4gY29tcGxleCBSIHByb2dyYW1zLiBXZSBzdWdnZXN0IHRoYXQgeW91IGF2b2lkIGl0LiBNYWtlIHRoZSBiZWhhdmlvdXIgb2YgeW91ciBmdW5jdGlvbnMgY2xlYXIgYnkgZXhwbGljaXRseSBpZGVudGlmeWluZyB0aGUgcmV0dXJuIHZhbHVlIHdpdGggZnVuY3Rpb24gYHJldHVybmAuCgoKIyMgRnVuY3Rpb24gZXhlcmNpc2UKClJldHVybmluZyB0byB0aGUgUGFsbWVycyBQZW5ndWlucyBkYXRhLCBhbmQgdXNpbmcgdGhlIHRlY2huaXF1ZXMgd2UgaGF2ZSBzZWVuIGZvciBwZXJmb3JtaW5nIGRlc2NyaXB0aXZlIHN0YXRpc3RpY3MsIGNvbnNpZGVyIHRoZSBmb2xsb3dpbmcgY29kZSwgd2hpY2ggY29tcHV0ZXMgc3VtbWFyaWVzIG9mIHRoZSBib2R5IG1hc3MgbWVhc3VyZSAoaS5lLiB0aGUgZGVwZW5kZW50IHZhcmlhYmxlIGluIHRoaXMgc3VtbWFyeSBpcyAgY29sdW1uICpib2R5X21hc3NfZyopLgoKYGBge3Igc3VtbWFyaXNpbmcsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkocGFsbWVycGVuZ3VpbnMpCgpkdl92ZWN0b3IgPC0gcGVuZ3VpbnMkYm9keV9tYXNzX2cKCm1lYW5fZHYgPC0gbWVhbihkdl92ZWN0b3IsIG5hLnJtID0gVFJVRSkKc2RfZHYgPC0gc2QoZHZfdmVjdG9yLCBuYS5ybSA9IFRSVUUpCm1pbl9kdiA8LSBtaW4oZHZfdmVjdG9yLCBuYS5ybSA9IFRSVUUpCm1heF9kdiA8LSBtYXgoZHZfdmVjdG9yLCBuYS5ybSA9IFRSVUUpCgpgYGAKCgpUaGlzIGNvZGUgZnJhZ21lbnQgY3JlYXRlcyBmb3VyIG5ldyB2YXJpYWJsZXMgdGhhdCB3ZSBjb3VsZCB1c2UgaW4gbGF0ZXIgY29tcHV0YXRpb25zLCBvciBpbiBnZW5lcmF0aW5nIHJlcG9ydHMuIAoKSW1hZ2luZSB0aGF0IHdlIHdpc2ggdG8gZG8gdGhlIHNhbWUgc3VtbWFyeSBmb3IgZmxpcHBlciBsZW5ndGguIFdlIGNvdWxkIGNvcHkgYW5kIHBhc3RlIHRoZSBjb2RlLCBjaGFuZ2luZyB0aGUgbGluZSB3aGVyZSB3ZSBhc3NpZ24gdmFyaWFibGUgYGR2X3ZlY3RvcmAuIFRoZW4gaWYgd2Ugd2FudGVkIHRvIGRvIHRoZSBzYW1lIHN1bW1hcnkgb24gYmlsbCBsZW5ndGgsIHdlIGNvdWxkIGNvcHkgYW5kIHBhc3RlIHRoZSBjb2RlIGFnYWluLCBhbmQgYWdhaW4gY2hhbmdlIHRoZSBhc3NpZ25tZW50IHRvIGBkdl92ZWN0b3JgLiBCeSBub3csIHdlIGFyZSBib3JlZCBvZiB0aGlzLCBhbmQgb3VyIHNjcmlwdCBpcyBnZXR0aW5nIG5lZWRsZXNzbHkgYmlnIGFuZCBtZXNzeS4gSWYgd2UgbGF0ZXIgZGVjaWRlIHdlIG5lZWQgdG8gaW5jbHVkZSB0aGUgbWVkaWFuLCB3ZSB3aWxsIG5lZWQgdG8gZ28gYmFjayBhbmQgYWRkIHRoZSBgbWVkaWFuYCBjb21tYW5kIG11bHRpcGxlIHRpbWVzLCBncmVhdGx5IGluY3JlYXNpbmcgdGhlIGNoYW5jZSBvZiBlcnJvcnMgKGFuZCBhbHNvIGJlaW5nIGJvcmluZykuCgpDb21wdXRpbmcgdGhpcyBzZXQgb2YgZGVzY3JpcHRpdmUgc3RhdHMgaXMgYSBsb2dpY2FsbHkgZGVsaW5lYXRlZCB0YXNrLCBhbmQgd2Ugc2hvdWxkIHRoZXJlZm9yZSBlbmNhcHN1bGF0ZSBpdCBpbnRvIGEgdXNlciBkZWZpbmVkIGZ1bmN0aW9uLiBFYWNoIHRpbWUgd2UgZG8gdGhpcyBzdW1tYXJ5LCB0aGUgY29tcHV0YXRpb24gKHRoZSBmb3VyIGNhbGxzIHRvIGBtZWFuYCwgYHNkYCwgYG1pbmAgYW5kIGBtYXhgKSByZW1haW5zIHRoZSBzYW1lLCBidXQgdGhlIGRhdGEgd2Ugd2lzaCB0byBwcm9jZXNzIGNoYW5nZXMuIEVhY2ggdGltZSB3ZSBjYWxsIHRoZSBmdW5jdGlvbiwgd2Ugd2FudCB0byBiZSBhYmxlIHRvIHByb3ZpZGUgaXQgd2l0aCB0aGUgZGF0YSB0byBwcm9jZXNzLiBXZSBtdXN0IHRoZXJlZm9yZSBwYXNzIHRoZSBkYXRhIGluIGFzIGFuIGlucHV0IGFyZ3VtZW50LgoKIyMjIE1ha2UgYSBmdW5jdGlvbiB3aXRoIGlucHV0IGFyZ3VtZW50cwoKQ29udmVydCB0aGlzIGNvZGUgaW50byBhIGZ1bmN0aW9uIHRoYXQgYWNjZXB0cyBhIHNpbmdsZSBpbnB1dCBhcmd1bWVudCwgd2hpY2ggd2lsbCBiZSB0aGUgdmVjdG9yIG9mIGRhdGEgdG8gYmUgYW5hbHlzZWQuIEZvciBub3csIHVzZSBwcmludCBzdGF0ZW1lbnRzIHRvIGRpc3BsYXkgdGhlIHJlc3VsdHMsIG5vdCByZXR1cm4gc3RhdGVtZW50cywgc28gd2UgY2FuIGNvbmNlbnRyYXRlIG9uIGdldHRpbmcgdGhlIGRhdGEgaW4uIENhbGwgeW91ciBmdW5jdGlvbiBgZGVzY19zdGF0c2AuCgpgYGB7ciBzdW1tYXJpc2luZyBmdW5jdGlvbn0KbGlicmFyeShwYWxtZXJwZW5ndWlucykKCmRlc2Nfc3RhdHMgPC0gZnVuY3Rpb24oZHZfdmVjdG9yKQp7CiAgbWVhbl9kdiA8LSBtZWFuKGR2X3ZlY3RvciwgbmEucm0gPSBUUlVFKQogIHNkX2R2IDwtIHNkKGR2X3ZlY3RvciwgbmEucm0gPSBUUlVFKQogIG1pbl9kdiA8LSBtaW4oZHZfdmVjdG9yLCBuYS5ybSA9IFRSVUUpCiAgbWF4X2R2IDwtIG1heChkdl92ZWN0b3IsIG5hLnJtID0gVFJVRSkKCiAgcHJpbnQobWVhbl9kdikKICBwcmludChzZF9kdikKICBwcmludChtaW5fZHYpCiAgcHJpbnQobWF4X2R2KQp9ICAKYGBgCgpTb3VyY2UgdGhlIGZ1bmN0aW9uIGJ5IHNlbGVjdGluZyBhbGwgdGhlIGNvZGUgKGZyb20gYmVmb3JlIGBkZXNjX3N0YXRzYCBkb3duIHRvIGFuZCBpbmNsdWRpbmcgdGhlIGNsb3NpbmcgY3VybHkgYnJhY2tldCkgYW5kIHR5cGluZyBjdHJsLUVudGVyIG9yIGNtZC1FbnRlci4gVGVzdCB5b3VyIGZ1bmN0aW9uIGJ5IGNhbGxpbmcgaXQgb24gdGhlIGJvZHkgbWFzcyBkYXRhLCB0aGUgZmxpcHBlciBsZW5ndGggZGF0YSwgYW5kIHRoZSBiaWxsIGxlbmd0aCBkYXRhLgoKYGBge3IgY2FsbGluZ30KZGVzY19zdGF0cyhwZW5ndWlucyRib2R5X21hc3NfZykKZGVzY19zdGF0cyhwZW5ndWlucyRmbGlwcGVyX2xlbmd0aF9tbSkKZGVzY19zdGF0cyhwZW5ndWlucyRiaWxsX2xlbmd0aF9tbSkKYGBgCgpTdG9wIHRvIGFkbWlyZSBob3cgdGlkeSBhbmQgc3VjY2luY3QgeW91ciBjb2RlIGlzLiBOb3RlIHRoYXQgaWYgeW91IG5vdyBkZWNpZGUgdG8gYWRkIHRoZSBtZWRpYW4sIHlvdSBvbmx5IG5lZWQgdG8gbWFrZSB0aGUgY2hhbmdlIGluIG9uZSBwbGFjZSAtLSBpbiB0aGUgZnVuY3Rpb24gZGVjbGFyYXRpb24gaXRzZWxmIC0tIHJlZ2FyZGxlc3Mgb2YgaG93IG1hbnkgZGlmZmVyZW50IGRhdGEgc2V0cyB5b3UgaGF2ZSBwcm9jZXNzZWQuCgoqKk5COiBJZiB5b3UgZG8gY2hhbmdlIHRoZSBmdW5jdGlvbiwgeW91IG11c3Qgc291cmNlIHRoZSBmdW5jdGlvbiBhZ2FpbiAoaS5lLiB5b3UgbXVzdCByZXBlYXQgdGhlICJzZWxlY3QgYWxsIHRoZSBmdW5jdGlvbiBjb2RlIGFuZCB0eXBlIGN0cmwtZW50ZXIiIHN0ZXApIHRvIHVwZGF0ZSBSJ3Mgc3RvcmVkIGNvcHkgb2YgdGhlIGZ1bmN0aW9uLiBZb3Ugd2lsbCBub3Qgc2VlIGFueSBjaGFuZ2UgaW4gYmVoYXZpb3VyIHVudGlsIHRoZSBtb2RpZmllZCBmdW5jdGlvbiBjb2RlIGlzIHNvdXJjZWQuKioKCiMjIyBHZXQgb3V0cHV0IGZyb20gdGhlIGZ1bmN0aW9uCgpBcyBkaXNjdXNzZWQgZWFybGllciwgZGlzcGxheWluZyBmdW5jdGlvbiBvdXRwdXQgdmlhIHByaW50IHN0YXRlbWVudHMgaXMgb2YgbGltaXRlZCB1dGlsaXR5OyBpdCBpcyBwcmVmZXJhYmxlIHRvIHJldHVybiB0aGUgcmVzdWx0cyBvZiBhIGZ1bmN0aW9uLCBzbyBpdCBjYW4gYmUgc3RvcmVkIGluIGEgdmFyaWFibGUuIFdlIHdvdWxkIGxpa2UsIHRoZXJlZm9yZSwgdG8gcmV0dXJuIHRoZSBvdXRwdXQgb2YgZnVuY3Rpb24gYGRlc2Nfc3RhdHNgLiBVbmZvcnR1bmF0ZWx5LCBhIGZ1bmN0aW9uIGluIFIgKipjYW4gb25seSByZXR1cm4gYSBzaW5nbGUgZGF0YSBvYmplY3QqKiBhbmQgb3VyIGZ1bmN0aW9uIGNvbXB1dGVzICpmb3VyKiB2YWx1ZXMuCgpUbyByZXNvbHZlIHRoaXMsIHdlIGNhbiBidW5kbGUgdXAgb3VyIGZvdXIgY29tcHV0ZWQgdmFsdWVzIGludG8gYSBzaW5nbGUgZGF0YSBvYmplY3QsIGNhbGxlZCBhICoqbGlzdCoqLiBBbiBSICoqbGlzdCoqIGlzIGxpa2UgYSB2ZWN0b3IsIGV4Y2VwdCB0aGF0IGVhY2ggZWxlbWVudCBoYXMgYSBuYW1lIGFzIHdlbGwgYXMgYW4gb3JkaW5hbCBwb3NpdGlvbiwgYW5kIGVsZW1lbnRzIGNhbiBiZSByZXRyaWV2ZWQgKHVzaW5nIHRoZSBbXSBvcGVyYXRvcikgZWl0aGVyIGJ5IG5hbWUgb3IgcG9zaXRpb24uIENvbnNpZGVyIHRoaXMgZXhhbXBsZToKCmBgYHtyIGxpc3R9CiMgQ3JlYXRlIGEgbGlzdApjaGFyYWN0ZXJfbGlzdCA8LSBsaXN0KE5hbWUgPSAiU25vb3B5IiwgQnJlZWQgPSAiQmVhZ2xlIiwgT3duZXIgPSAiQ2hhcmxpZSBCcm93biIpCgojIERpc3BsYXkgdGhlIGVudGlyZSBsaXN0CmNoYXJhY3Rlcl9saXN0CgojIFNvbWUgZXhhbXBsZXMgb2Ygc2VsZWN0aW9uIGZyb20gdGhlIGxpc3QKY2hhcmFjdGVyX2xpc3RbIk5hbWUiXQpjaGFyYWN0ZXJfbGlzdFsiQnJlZWQiXQoKY2hhcmFjdGVyX2xpc3RbMl0KY2hhcmFjdGVyX2xpc3RbM10KCmNoYXJhY3Rlcl9saXN0JE5hbWUKY2hhcmFjdGVyX2xpc3QkT3duZXIKYGBgCgpBIGxpc3QgaXMgY29uc2lkZXJlZCBhIHNpbmdsZSBkYXRhIG9iamVjdCwgc28gaXQgY2FuIGJlIHJldHVybmVkIGZyb20gYSBmdW5jdGlvbiB2aWEgYSBgcmV0dXJuYCBzdGF0ZW1lbnQuCk1vZGlmeSBmdW5jdGlvbiBgZGVzY19zdGF0c2AgdG8gKipyZXR1cm4qKiBpdHMgZm91ciBvdXRwdXRzLCByYXRoZXIgdGhhbiBwcmludGluZyB0aGVtLiBDYWxsIHlvdXIgZnVuY3Rpb24gYW5kIHVzZSBhbnkgb2YgdGhlIHN5bnRhY3RpYyBvcHRpb25zIGFib3ZlIHRvIGV4cGxvcmUgdGhlIGNvbnRlbnRzIG9mIHRoZSByZXR1cm5lZCBvYmplY3QuIAoKTXkgc29sdXRpb24gaXM6CgpgYGB7ciBvdXRwdXQgbXVsdGlwbGUgaXRlbXN9CiMgTW9kaWZ5IHRoZSBmdW5jdGlvbiB0byByZXR1cm4gYSBsaXN0CmRlc2Nfc3RhdHMgPC0gZnVuY3Rpb24oZHZfdmVjdG9yKQp7CiAgbWVhbl9kdiA8LSBtZWFuKGR2X3ZlY3RvciwgbmEucm0gPSBUUlVFKQogIHNkX2R2IDwtIHNkKGR2X3ZlY3RvciwgbmEucm0gPSBUUlVFKQogIG1pbl9kdiA8LSBtaW4oZHZfdmVjdG9yLCBuYS5ybSA9IFRSVUUpCiAgbWF4X2R2IDwtIG1heChkdl92ZWN0b3IsIG5hLnJtID0gVFJVRSkKCiAgcmVzdWx0X2xpc3QgPC0gbGlzdChNZWFuID0gbWVhbl9kdiwKICAgICAgICAgICAgICAgICAgICAgIFNkID0gc2RfZHYsCiAgICAgICAgICAgICAgICAgICAgICBNaW4gPSBtaW5fZHYsCiAgICAgICAgICAgICAgICAgICAgICBNYXggPSBtYXhfZHYpCiAgCiAgcmV0dXJuKHJlc3VsdF9saXN0KQp9CgoKZmxpcHBlcl9kZXNjX3N0YXRzIDwtIGRlc2Nfc3RhdHMocGVuZ3VpbnMkZmxpcHBlcl9sZW5ndGhfbW0pCgpmbGlwcGVyX2Rlc2Nfc3RhdHMkTWVhbgoKZmxpcHBlcl9kZXNjX3N0YXRzWzJdCgptaW5fbWF4IDwtIGMoZmxpcHBlcl9kZXNjX3N0YXRzWyJNaW4iXSwgZmxpcHBlcl9kZXNjX3N0YXRzWyJNYXgiXSkKCnByaW50KG1pbl9tYXgpCgoKYGBgCgoKIyBTY29wZQoKV2hlbiB5b3Ugc3BlY2lmeSBhIHZhcmlhYmxlIGluIFIgaXQgd2lsbCBzdGFydCB0cnlpbmcgdG8gZmluZCBzb21ldGhpbmcgd2l0aCB0aGF0IG5hbWUgd2l0aGluIHRoZSBnbG9iYWwgZW52aXJvbm1lbnQgKGRpc3BsYXllZCBpbiB0aGUgX0Vudmlyb25tZW50XyB0YWIgaW4gUlN0dWRpbykuIEluIHRoZSBjYXNlIG9mIGZ1bmN0aW9ucywgYW55IHZhcmlhYmxlIGRlZmluZWQgaW4gdGhlIGZ1bmN0aW9uIChpbmNsdWRpbmcgdGhyb3VnaCBpdHMgYXJndW1lbnRzKSBzdGF5cyB3aXRoaW4gdGhlIGZ1bmN0aW9uIChhIHNlcGFyYXRlIGxvY2FsIGVudmlyb25tZW50IHNwZWNpZmljIHRvIHRoZSBmdW5jdGlvbikuIElmIGhvd2V2ZXIgaW4gdGhlIGJvZHkgb2YgdGhlIGZ1bmN0aW9uIHlvdSByZWZlciB0byBhIHZhcmlhYmxlIHRoYXQgaGFzbid0IGJlZW4gZGVmaW5lZCBpbiB0aGUgZnVuY3Rpb24sIFIgd2lsbCBzdGFydCBsb29raW5nIGF0IHRoZSBnbG9iYWwgZW52aXJvbm1lbnQgYW5kIGlmIGl0IGZpbmRzIGEgdmFyaWFibGUgb2YgdGhlIHNhbWUgbmFtZSB5b3UndmUgY3JlYXRlZCBvdXRzaWRlIG9mIHRoZSBmdW5jdGlvbiwgaXQgd2lsbCB1c2UgdGhlIHZhbHVlIHRoYXQgaXMgc3RvcmVkIHdpdGhpbiBpdC4gVGhpcyBiZWhhdmlvdXIgY2FuIGNhdXNlIGlzc3Vlcy4KCgpIZXJlIGlzIGFuIGV4YW1wbGUsIHdoZXJlIHRoZSBmdW5jdGlvbiBuZWVkcyBhIHZhbHVlIGZvciBgbmAgYnV0IGl0IGhhc24ndCBiZWVuIHN1cHBsaWVkIGFzIGFuIGFyZ3VtZW50IGFuZCB0aGVyZSBpcyBubyBkZWZhdWx0IHZhbHVlLgoKYGBge3IsIGVycm9yPVRSVUV9CiMgbXVsdGlwbGllcyB0aGUgbnVtYmVyIHggYnkgdGhlIG51bWJlciBuCm11bHRpcGx5X2J5X24gPC0gZnVuY3Rpb24oeCl7CiAgeCAqIG4KfQoKbXVsdGlwbHlfYnlfbih4ID0gMykKYGBgCgpJbiB0aGUgZnVuY3Rpb24gYm9keSB3ZSByZWZlcnJlZCB0byBgbmAgd2hpY2ggd2Fzbid0IGRlZmluZWQgYW55d2hlcmUgc28gd2UgZ290IGFuIGVycm9yLgoKCkxldCdzIHVzZSB0aGUgc2FtZSBmdW5jdGlvbiBhZ2FpbiBidXQgZGVmaW5lIGBuYCBvdXRzaWRlIHRoZSBmdW5jdGlvbjoKYGBge3J9CiMgbXVsdGlwbGllcyB0aGUgbnVtYmVyIHggYnkgdGhlIG51bWJlciBuCm11bHRpcGx5X2J5X24gPC0gZnVuY3Rpb24oeCl7CiAgeCAqIG4KfQoKIyBkZWZpbmUgbiBpbiB0aGUgZ2xvYmFsIGVudmlyb25tZW50IApuIDwtIDEwCgptdWx0aXBseV9ieV9uKHggPSAzKQpgYGAKVGhpcyB0aW1lIFIgbG9va3MgZm9yIGBuYCBpbnNpZGUgdGhlIGJvZHkgYnV0IGRvZXNuJ3QgZmluZCBpdCBhbmQgd2hlbiBpdCBsb29rcyBpbnRvIHRoZSBnbG9iYWwgZW52aXJvbm1lbnQgaXQgZmluZHMgYSB2YXJpYWJsZSBuYW1lZCBgbmAgYW5kIHNvIHVzZXMgdGhhdCB2YWx1ZS4KIAogVGhpcyB0aW1lIHdlJ3JlIGdvaW5nIHRvIG1vZGlmeSB0aGUgZnVuY3Rpb24gdG8gdGFrZSBhIHNlY29uZCBhcmd1bWVudCBjYWxsZWQgYG5gLCBhbmQgYWxzbyBoYXZlIGBuYCBkZWZpbmVkIGluIHRoZSBnbG9iYWwgZW52aXJvbm1lbnQ6CmBgYHtyfQojIG11bHRpcGxpZXMgdGhlIG51bWJlciB4IGJ5IHRoZSBudW1iZXIgbgptdWx0aXBseV9ieV9uIDwtIGZ1bmN0aW9uKHgsIG4pewogIHggKiBuCn0KCiMgZGVmaW5lIG4gaW4gdGhlIGdsb2JhbCBlbnZpcm9ubWVudApuIDwtIDEwCgptdWx0aXBseV9ieV9uKHggPSAzLCBuID0gMikKYGBgCiAKVGhlIHZhbHVlIG9mIGBuYCB0aGF0IHdhcyB1c2VkIHdhcyB0aGUgdmFsdWUgc3VwcGxpZWQgYXMgdGhlIGFyZ3VtZW50LCByYXRoZXIgdGhhbiB0aGUgdmVyc2lvbiB0aGF0IHdhcyBkZWZpbmVkIGluIHRoZSBnbG9iYWwgZW52aXJvbm1lbnQuIFRodXMgYSBmdW5jdGlvbiB3aWxsIHVzZSBhIGxvY2FsbHkgZGVmaW5lZCB2YXJpYWJsZSB3aGVuIG9uZSBleGlzdHMsIGJ1dCBpZiBpdCBjYW4ndCBmaW5kIG9uZSwgaXQgd2lsbCBsb29rIGluIHRoZSBnbG9iYWwgZW52aXJvbm1lbnQuCgpUaGlzIGJlaGF2aW91ciBjYW4gbGVhZCB0byBzdWJ0bGUgZXJyb3JzIGluIHlvdXIgY29kZS4gRm9yIGV4YW1wbGUsIGVhcmxpZXIgaW4gdGhpcyBtb2R1bGUgd2Ugd3JvdGUgYSB2ZXJzaW9uIG9mIHVzZXItZGVmaW5lZCBmdW5jdGlvbiBgY2FsY19hcmVhYCB0aGF0IHRyaWVkIHRvIHJlZmVyZW5jZSB2YXJpYWJsZSBgaGVpZ2h0YCB3aXRob3V0IGhhdmluZyBwYXNzZWQgaXQgaW4gYXMgYW4gYXJndW1lbnQuIFdoZW4gUiB3YXMgdW5hYmxlIHRvIGZpbmQgYGhlaWdodGAsIGl0IGFsZXJ0ZWQgdXMgd2l0aCBhbiBlcnJvciBtZXNzYWdlLCBhbmQgd2Ugd2VyZSBhYmxlIHRvIGlkZW50aWZ5IGFuZCBjb3JyZWN0IHRoZSBlcnJvciBpbiB0aGUgY29kZSAodGhlIG1pc3NpbmcgaW5wdXQgYXJndW1lbnQgYGhlaWdodGApLiBJZiwgYXQgdGhhdCBwb2ludCwgd2UgaGFkIGFscmVhZHkgY3JlYXRlZCBhIHZhcmlhYmxlIGBoZWlnaHRgIG91dHNpZGUgdGhlIGZ1bmN0aW9uIChmb3IgYW55IHJlYXNvbiksIFIgd291bGQgaGF2ZSBoYXBwaWx5ICoqdXNlZCB0aGF0IGV4aXN0aW5nIHZhcmlhYmxlIHdoZW4gZXhlY3V0aW5nIHRoZSBmdW5jdGlvbiBjb2RlIGJvZHkqKiBhbmQgd2Ugd291bGQgbm90IGhhdmUgcmVhbGlzZWQgdGhlcmUgd2FzIGFuIGVycm9yLiBPZiBjb3Vyc2UsIGlmIHdlIGV2ZXIgY2FsbGVkIHRoZSBiYWQgZnVuY3Rpb24gd2hlbiB3ZSBoYWRuJ3QgcHJldmlvdXNseSBjcmVhdGVkIGBoZWlnaHRgLCBvdXIgcHJvZ3JhbSB3b3VsZCBjcmFzaC4gU29tZSBwcm9ncmFtbWVycyB1c2Ugc3BlY2lhbCB2YXJpYWJsZSBjb2Rpbmcgc3R5bGVzIC0tIGZvciBleGFtcGxlIHByZWZpeGluZyBhbGwgaW5wdXQgYXJndWVudHMgd2l0aCB1bmRlcnNjb3JlIC0tIHRvIHByZXZlbnQgY29uZnVzaW9uIGJldHdlZW4gbG9jYWwgYW5kIGdsb2JhbCB2YXJpYWJsZXMuIEl0IGlzIHZlcnkgaW1wb3J0YW50LCB3aGVuIHdvcmtpbmcgaW4gUiB0byBiZSBjb25zdGFudGx5IGF3YXJlIG9mIHdoaWNoIHZhcmlhYmxlcyBleGlzdCBpbiB0aGUgZ2xvYmFsIGVudmlyb25tZW50LiBLZWVwIHlvdXIgZXllIG9uIHRoZSBFbnZpcm9ubWVudCB0YWIgYXMgeW91IHdyaXRlIGZ1bmN0aW9ucy4KCgoKIyBDb21wbGV4IFByb2dyYW0gQmVoYXZpb3VyCgpJbiB2ZXJ5IHNpbXBsZSBwcm9ncmFtcywgd2Ugd3JpdGUgYSBzZXQgb2YgY29tbWFuZHMgd2hpY2ggYXJlIGV4ZWN1dGVkIGluIHNlcXVlbmNlIC0tIGZpcnN0IHN0YXRlbWVudCwgc2Vjb25kIHN0YXRlbWVudCwgdGhpcmQgc3RhdGVtZW50LCBldGMuIEVhY2ggdGltZSB3ZSBydW4gdGhlIGNvZGUsIHRoZSBleGFjdCBzYW1lIHNldCBvZiBjb21tYW5kcyBhcmUgZXhlY3V0ZWQsIGluIHRoZSBleGFjdCBzYW1lIHNlcXVlbmNlLiAKCkhvd2V2ZXIsIGFzIGNvbXB1dGF0aW9uYWwgcHJvYmxlbXMgYmVjb21lIG1vcmUgY29tcGxleCwgdGhlIGJlaGF2aW91ciBvZiBvdXIgY29kZSBzb2x1dGlvbnMgbXVzdCBhbHNvIGJlY29tZSBtb3JlIGNvbXBsZXguIFdlIG1heSBoYXZlIHNlY3Rpb25zIG9mIGNvZGUgdGhhdCB3ZSB3YW50IHRvIHJlcGVhdCBzb21lIHZhcnlpbmcgbnVtYmVyIHRpbWVzIGRlcGVuZGluZyBvbiBvdXIgZGF0YSwgb3Igc2VjdGlvbnMgb2YgY29kZSB0aGF0IHdlIG9ubHkgd2FudCB0byBleGVjdXRlIHVuZGVyIGNlcnRhaW4gY29uZGl0aW9ucy4KClRoZSBzcGVjaWZpYyB0aW1lIGNvdXJzZSBvZiBwcm9ncmFtIGV4ZWN1dGlvbiBpcyBjYWxsZWQgKipmbG93IG9mIGNvbnRyb2wqKiwgYW5kIFIgcHJvdmlkZXMgbWFueSBzeW50YWN0aWMgZmVhdHVyZXMgdGhhdCBhbGxvdyB1cyB0byBtYW5hZ2UgaXQuIEZsb3cgb2YgY29udHJvbCBnZW5lcmFsbHkgZGVwZW5kcyBvbiB0aGUgcHJvZ3JhbSdzICoqc3RhdGUqKiAtLSB0aGUgc3BlY2lmaWMgc2V0IG9mIHZhcmlhYmxlcyBhbmQgdGhlaXIgdmFsdWVzIGF0IGVhY2ggcG9pbnQgZHVyaW5nIHByb2dyYW0gZXhlY3V0aW9uLiAKCkZvciBleGFtcGxlLCB3aGVuIHdlIGltcG9ydCBhIGNzdiBmaWxlIGludG8gYSBkYXRhIGZyYW1lLCB0aGF0IGRhdGEgZnJhbWUgaXMgcGFydCBvZiB0aGUgc3RhdGUuIFdlIG1heSB3YW50IHRvIGV4ZWN1dGUgYSBmdW5jdGlvbiBvbmNlIGZvciBlYWNoIHJvdyBpbiB0aGUgZGF0YSBmcmFtZS4gSWYgd2UgaW1wb3J0IGEgZGF0YSBmcmFtZSB3aXRoIDUzIHJvd3MsIHdlIHdhbnQgdGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCA1MyB0aW1lcy4gVGh1cyB0aGUgbnVtYmVyIG9mIHRpbWVzIHRoZSBmdW5jdGlvbiBpcyBjYWxsZWQgKHRoZSBmbG93IG9mIGNvbnRyb2wpIGRlcGVuZHMgb24gdGhlIHN0YXRlLiBTaW1pbGFybHksIHdoZW4gd2Ugd3JpdGUgYSBmdW5jdGlvbiB0aGF0IGFjY2VwdHMgZGF0YSBpbnB1dCBhcmd1bWVudHMsIHRoZSB2YWx1ZSBvZiB0aG9zZSBhcmd1bWVudHMgcGFzc2VkIGluIGF0IGZ1bmN0aW9uIGNhbGwgYXJlIHBhcnQgb2YgdGhlIHN0YXRlLCBhbmQgY2FuIGJlIGRpZmZlcmVudCBlYWNoIHRpbWUgdGhlIGZ1bmN0aW9uIGlzIGNhbGxlZC4gRnJlcXVlbnRseSB3ZSB3aWxsIHdhbnQgdG8gdGFrZSBkaWZmZXJlbnQgYWN0aW9ucyBpbiB0aGUgZnVuY3Rpb24gZGVwZW5kaW5nIG9uIHRoYXQgc3RhdGUuIAoKV2UgaGF2ZSBkZXNjcmliZWQgdGhlIHRocmVlIHByaW1hcnkgZmxvdyBvZiBjb250cm9sIGNvbnN0cnVjdHM6CgotICBTZXF1ZW50aWFsIGV4ZWN1dGlvbjogU3RhdGVtZW50cyBhcmUgZXhlY3V0ZWQgaW4gb3JkZXIKLSAgSXRlcmF0aW9uOiBBIHNldCBvZiBzdGF0ZW1lbnRzIGlzIHJlcGVhdGVkIGEgbnVtYmVyIG9mIHRpbWVzCi0gIENvbmRpdGlvbmFsIGV4ZWN1dGlvbjogQSBzZXQgb2Ygc3RhdGVtZW50cyBtYXkgb3IgbWF5IG5vdCBiZSBleGVjdXRlZCwgZGVwZW5kaW5nIG9uIHRoZSBzdGF0ZS4KCldlIGhhdmUgYWxyZWFkeSBzZWVuLCBhbmQgd3JpdHRlbiwgY29kZSB0aGF0IGNvbnRhaW5zIG9ubHkgc2VxdWVudGlhbCBleGVjdGlvbi4gV2Ugd2lsbCBub3cgbG9vayBhdCB0aGUgc3ludGFjdGljIHRvb2xzIGZvciBjb25kaXRpb25hbCBleGVjdXRpb24uIEluIG91ciBuZXh0IG1vZHVsZSwgd2Ugd2lsbCBjb3ZlciBpdGVyYXRpb24sIHdoaWNoIGlzIHN5bnRhY3RpY2FsbHkgbW9yZSBjb21wbGV4LgoKIyMgSWYgc3RhdGVtZW50cwoKQWxsIG1vZGVybiBwcm9ncmFtbWluZyBsYW5ndWFnZXMgYWxsb3cgeW91IHRvIHdyYXAgYSBibG9jayBvZiBjb2RlIGluIGFuICoqaWYgc3RhdGVtZW50KiouIElmIHN0YXRlbWVudHMgY29udGFpbiBhICoqY29uZGl0aW9uKiosIHdoaWNoIGlzIGFuIGV4cHJlc3Npb24gd2hpY2ggZXZhbHVhdGVzIHRvIGVpdGhlciB0cnVlIG9yIGZhbHNlLiBBdCBydW50aW1lLCB0aGUgY29uZGl0aW9uIGlzIGV2YWx1YXRlZC4gSWYgaXQgaXMgdHJ1ZSwgdGhlIGJsb2NrIG9mIGNvZGUgaXMgZXhlY3V0ZWQ7IGlmIGl0IGlzIGZhbHNlLCB0aGUgYmxvY2sgb2YgY29kZSBpcyBub3QgZXhlY3V0ZWQuIENvbmRpdGlvbmFsIGNvZGUgYmxvY2tzIGluIFIgYXJlIGRlbGluZWF0ZWQgd2l0aCBjdXJseSBicmFja2V0cy4gVGhlIGNvbmRpdGlvbmFsIGV4cHJlc3Npb24gaXMgZGVsaW5lYXRlZCB3aXRoIHJvdW5kIGJyYWNrZXRzLgoKU2NoZW1hdGljYWxseToKCmBgYHtyIGNvbmRpdGlvbmFsIHBhdHRlcm4sIGV2YWwgPSBGQUxTRX0KaWYgKGNvbmRpdGlvbikgewogICMgY29kZSBoZXJlIGlzIG9ubHkgcnVuIGlmIGNvbmRpdGlvbiB3YXMgVFJVRQp9CmBgYAoKQ29uc2lkZXIgdGhpcyB0b3kgZXhhbXBsZToKCmBgYHtyIHNpbXBsZSBpZn0KZGlkX0lfcGFzc190aGVfcGFwZXIgPC0gZnVuY3Rpb24obXlfbWFyaykKewogIGlmIChteV9tYXJrID4gNTApIHsKICAgIHByaW50KCJZb3UgcGFzc2VkISIpCiAgfQp9CgojIFRoaXMgY2FsbCBnZW5lcmF0ZXMgbm8gb3V0cHV0CmRpZF9JX3Bhc3NfdGhlX3BhcGVyKDE0KQoKIyBUaGlzIGNhbGwgZ2VuZXJhdGVzIG91dHB1dApkaWRfSV9wYXNzX3RoZV9wYXBlcig3MykKYGBgCgoKIyMgQWRkaW5nIGFuIGFsdGVybmF0aXZlIHdpdGggYGVsc2VgCgpGcmVxdWVudGx5IHdlIHdpc2ggdG8gZGVmaW5lIHR3byBiZWhhdmlvdXJzIGZvciBhIGNvbmRpdGlvbmFsIGV4cHJlc3Npb24gLS0gb25lIGZvciB3aGVuIGl0IGlzIHRydWUgYW5kIGFub3RoZXIgZm9yIHdoZW4gaXQgaXMgZmFsc2UuIEluIFIgd2UgZG8gdGhpcyB3aXRoIHRoZSBrZXl3b3JkIGBlbHNlYAoKYGBge3IgaWYgZWxzZSBwYXR0ZXJuLCBldmFsID0gRkFMU0V9CmlmIChjb25kaXRpb24pIHsKICAjIGNvZGUgaGVyZSBpcyBvbmx5IHJ1biBpZiBjb25kaXRpb24gd2FzIFRSVUUKfSBlbHNlIHsKICAjIGNvZGUgaGVyZSBpcyBvbmx5IHJ1biBpZiBjb25kaXRpb24gd2FzIEZBTFNFCn0KCgpgYGAKCkZvciBleGFtcGxlOgpgYGB7ciBpZiBlbHNlfQpkaWRfSV9wYXNzX3RoZV9wYXBlciA8LSBmdW5jdGlvbihteV9tYXJrKQp7CiAgaWYgKG15X21hcmsgPiA1MCkgewogICAgcHJpbnQoIllvdSBwYXNzZWQhIDopIikKICB9IGVsc2UgewogICAgcHJpbnQoIlNvcnJ5LCB5b3UgZGlkbid0IHBhc3MuIDooIikKICB9Cn0KCiMgVGhpcyBjYWxsIHJ1bnMgdGhlIGVsc2UgYmxvY2sKZGlkX0lfcGFzc190aGVfcGFwZXIoMTQpCgojIFRoaXMgY2FsbCBydW5zIHRoZSBpZiBibG9jawpkaWRfSV9wYXNzX3RoZV9wYXBlcig3MykKYGBgCgoKTkI6IFBheSBjYXJlZnVsIGF0dGVudGlvbiB0byB0aGUgcGxhY2VtZW50IG9mIHRoZSBjdXJseSBicmFja2V0cyBmb3IgYm90aCB0aGUgaWYgYmxvY2sgYW5kIHRoZSBlbHNlIGJsb2NrLiBUaGUgZmlyc3QgY3VybHkgYnJhY2tldCAqbXVzdCBzaXQgb24gdGhlIHNhbWUgbGluZSBhcyB0aGUgaWYgc3RhdGVtZW50Ki4gVGhlIGBlbHNlYCBrZXl3b3JkIG11c3QgYmUgb24gdGhlIHNhbWUgbGluZSBhcyB0aGUgY2xvc2luZyBjdXJseSBicmFja2V0IG9mIHRoZSBgaWZgIGJsb2NrLCBhbmQgbXVzdCBiZSBmb2xsb3dlZCwgb24gdGhhdCBzYW1lIGxpbmUsIGJ5IHRoZSBvcGVuaW5nIGN1cmx5IGJyYWNrZXQgb2YgdGhlIGBlbHNlYCBibG9jay4gSXQgaXMgYSBrbm93biBwZWN1bGlhcml0eSBvZiB0aGUgUiBsYW5ndWFnZSB0aGF0IGl0IGlzICoqZXh0cmVtZWx5IGZ1c3N5KiogYWJvdXQgdGhpcyBydWxlLiBObyB1c2UgZmlnaHRpbmcgaXQ7IGp1c3QgZm9sbG93IHRoZSBydWxlLgoKQW4gZXh0ZW5zaW9uIG9mIGBlbHNlYCBpcyB0aGUgYGVsc2UgaWZgIGNvbnN0cnVjdCB0aGF0IGxldHMgeW91IGxpbmsgYSBzZXJpZXMgb2YgY29uZGl0aW9ucy4gVGhlIGNvbmRpdGlvbnMgYXJlIHRlc3RlZCBvbmUgYXQgYSB0aW1lIGZyb20gdGhlIHRvcCBhbmQgdGhlIGZpcnN0IGNvbmRpdGlvbiB0aGF0IGV2YWx1YXRlcyB0byBgVFJVRWAgaXMgdGhlIG9ubHkgY29kZSBibG9jayB0aGF0IGdldHMgcnVuLiBGb3IgZXhhbXBsZToKCgpgYGB7ciBlbHNlIGlmfQpibWlfY2F0ZWdvcnkgPC0gZnVuY3Rpb24oYm1pKQp7CiAgICBpZihibWkgPiAzMCl7CiAgICAgIHByaW50KCJvYmVzZSIpCiAgICB9IGVsc2UgaWYgKGJtaSA+IDI1KXsKICAgICAgcHJpbnQoIm92ZXJ3ZWlnaHQiKQogICAgfSBlbHNlIGlmIChibWkgPiAyMCl7CiAgICAgIHByaW50KCJoZWFsdGh5IikKICAgIH0gZWxzZSB7CiAgICAgIHByaW50KCJ1bmRlcndlaWdodCIpCiAgfQp9CgoKYm1pX2NhdGVnb3J5KDIyKQoKYm1pX2NhdGVnb3J5KDE4KQpgYGAKCkNvbmRpdGlvbmFsIHN0YXRlbWVudHMgY2FuIGJlIG5lc3RlZC4gVGhhdCBpcywgaW5zaWRlIHRoZSBgaWZgIG9yIGBlbHNlYCBibG9jaywgeW91IGNhbiBoYXZlIG1vcmUgY29uZGl0aW9uYWwgc3RhdGVtZW50cywgZWFjaCBvZiB3aGljaCBjYW4gaGF2ZSBgaWZgIGFuZCBgZWxzZWAgYmxvY2tzLCBlYWNoIG9mIHdoaWNoIGNhbiBpbiB0dXJuIGhhdmUgbmVzdGVkIGNvbmRpdGlvbmFsIHN0YXRlbWVudHMsIGFuZCBzbyBvbi4gRm9yIGNvbXBsZXggY29tcHV0YXRpb25zLCB0aGUgY29uZGl0aW9uYWwgbG9naWMgY2FuIGJlY29tZSB2ZXJ5IGVsYWJvcmF0ZSwgYW5kIG5lZWRzIHRvIGJlIGFwcHJvYWNoZWQgY2FyZWZ1bGx5LiBJIGZpbmQgaXQgaGVscGZ1bCBpbiB0aGVzZSBjYXNlcyB0byBza2V0Y2ggb3V0IGEgZmxvdyBjaGFydCBzaG93aW5nIGFsbCB0aGUgZGlmZmVyZW50IG91dGNvbWVzIGJhc2VkIG9uIHN0YXRlLCBhbmQgdXNlIHRoYXQgYXMgYSBwYXR0ZXJuIGZvciB3cml0aW5nIGFuZCBhcnJhbmdpbmcgdGhlIHZhcmlvdXMgY29kZSBibG9ja3MuCgoKIyMgQ29tcGxleCBjb25kaXRpb25hbCBleHByZXNzaW9ucwoKSW4gb3VyIHByZXZpb3VzIGV4YW1wbGVzLCB3ZSB3cm90ZSBjb25kaXRpb25hbCBleHByZXNzaW9ucyB1c2luZyB0aGUgPiAoZ3JlYXRlciB0aGFuKSBvcGVyYXRvci4gVGhlIGV4cHJlc3Npb24gYG15X21hcmsgPiA1MGAgZXZhbHVhdGVzIHRvIGVpdGhlciB0cnVlIG9yIGZhbHNlIChpLmUuIGEgKipib29sZWFuIHZhbHVlKiopLiBJZiB2YXJpYWJsZSBgbXlfbWFya2AgaXMgZ3JlYXRlciB0aGFuIDUwLCB0aGUgZXhwcmVzc2lvbiByZXR1cm5zIHRydWUsIG90aGVyd2lzZSBpdCByZXR1cm5zIGZhbHNlLiBHcmVhdGVyIHRoYW4gaXMgYSAqKmNvbXBhcmlzb24gb3BlcmF0b3IqKi4gVGhlIFIgY29tcGFyaXNvbiBvcGVyYXRvcnMgYXJlOgoKT3BlcmF0b3IgfCBNZWFuaW5nCi0tLS0tLS0tLXwtLS0tLS0tLS0KYD09YCB8IGVxdWFsIHRvCmAhPWAgfCBub3QgZXF1YWwgdG8KYDxgIHwgbGVzcyB0aGFuCmA8PWAgfCBsZXNzIHRoYW4gb3IgZXF1YWwgdG8KYD5gIHwgZ3JlYXRlciB0aGFuCmA+PWAgfCBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8KCgpUaGUgKipCb29sZWFuIGxvZ2ljIG9wZXJhdG9ycyoqIGNhbiBiZSB1c2VkIGluIHRvIG1vZGlmeSBvciBjb21iaW5lIGNvbmRpdGlvbmFsIGV4cHJlc3Npb25zLgoKCkJvb2xlYW4gT3BlcmF0aW9uIHwgU3ltYm9sIGluIFIKLS0tfC0tLQpOT1QgfCAhCk9SIHwgXHwKQU5EIHwgJgoKCkZvciBleGFtcGxlLCB0aGUgZm9sbG93aW5nIGZ1bmN0aW9uIG1pZ2h0IGJlIHVzZWQgdG8gY2hlY2sgdGhhdCBhIHZhbHVlIGVudGVyZWQgYXMgYSBwZW5ndWluIGJvZHkgbWFzcyB3YXMgd2l0aGluIHRoZSBleHBlY3RlZCB3ZWlnaHQgcmFuZ2UgZm9yIHRoZSBzcGVjaWVzLgoKYGBge3IgY29tcG91bmQgY29uZGl0aW9uYWx9CiMgQ2hpbnN0cmFwIHBlbmd1aW5zIHdlaWdodCBiZXR3ZWVuIDMgYW5kIDUga2cKCmNoZWNrX2NoaW5zdHJhcF93ZWlnaHQgPC0gZnVuY3Rpb24od2VpZ2h0X3RvX2NoZWNrKQp7CiAgaWYgKCh3ZWlnaHRfdG9fY2hlY2sgPj0gMzAwMCkgJiAod2VpZ2h0X3RvX2NoZWNrIDw9IDUwMDApKSB7CiAgICBwcmludCgiV2VpZ2h0IG9rIikKICB9IGVsc2UgewogICAgcHJpbnQoIlRoYXQncyBwcm9iYWJseSBhIHR5cG8iKQogIH0KfQoKCmNoZWNrX2NoaW5zdHJhcF93ZWlnaHQoNDEwMCkKCgpjaGVja19jaGluc3RyYXBfd2VpZ2h0KDQxMCkKCmBgYAoKVGhlIHJlc3VsdCBvZiB0aGUgTk9ULCBBTkQsIGFuZCBPUiBhcmUgc2hvd24gaW4gdGhlIGxvZ2ljIHRhYmxlOgoKU3RhdGVtZW50IHwgQmVjb21lcwotLS18LS0tfC0tLXwtLS0KICAhVFJVRSB8IGByICFUUlVFYAogIUZBTFNFIHwgYHIgIUZBTFNFYCAKVFJVRSAmIFRSVUUgfCBgciBUUlVFICYgVFJVRWAKVFJVRSAmIEZBTFNFIHwgYHIgVFJVRSAmIEZBTFNFYApGQUxTRSAmIFRSVUUgfCBgciBGQUxTRSAmIFRSVUVgCkZBTFNFICYgRkFMU0UgfCBgciBGQUxTRSAmIEZBTFNFYApUUlVFIFx8IFRSVUUgfCBgciBUUlVFIHwgVFJVRWAKVFJVRSBcfCBGQUxTRSB8IGByIFRSVUUgfCBGQUxTRWAKRkFMU0UgXHwgVFJVRSB8IGByIEZBTFNFIHwgVFJVRWAKRkFMU0UgXHwgRkFMU0UgfCBgciBGQUxTRSB8IEZBTFNFYAoKCgojIyBDb25kaXRpb25hbCBleGVyY2lzZQpXcml0ZSBhbmQgdGVzdCBhIGZ1bmN0aW9uIHRoYXQgZGV0ZXJtaW5lcyB3aGV0aGVyIGEgc3R1ZGVudCByZWNlaXZlcyBhIHBhc3NpbmcgZ3JhZGUgb24gYW4gYXNzZXNzbWVudC4gVGhlIGZ1bmN0aW9uIHNob3VsZCBhY2NlcHQgdHdvIGlucHV0IGFyZ3M6IHRoZSBudW1iZXIgb2YgbWFya3MgZWFybmVkLCBhbmQgdGhlIHRvdGFsIG51bWJlciBvZiBtYXJrcyBwb3NzaWJsZSBmb3IgdGhlIGFzc2Vzc21lbnQuIFRoZSBzdHVkZW50IG11c3QgZWFybiA1MCUgb2YgdGhlIGF2YWlsYWJsZSBtYXJrcyBpbiBvcmRlciB0byBwYXNzLiBGb3IgZXhhbXBsZSwgaWYgYSBzdHVkZW50IGVhcm5zIDE4IG1hcmtzIG9uIGEgMjAgbWFyayBhc3Nlc3NtZW50IHRoZXkgcGFzcywgYnV0IGlmIHRoZXkgZWFybiBvbmx5IDggbWFya3MsIHRoZXkgZmFpbC4gWW91ciBmdW5jdGlvbiBzaG91bGQgcHJpbnQgIlBhc3MiIG9yICJGYWlsIiBhcyBhcHByb3ByaWF0ZSBiYXNlZCBvbiB0aGUgaW5wdXQgZGF0YS4gCgpgYGB7ciBleGVyY2lzZSBzb2x1dGlvbn0KCnBhc3NfY2hlY2sgPC0gZnVuY3Rpb24oZWFybmVkLCBwb3NzaWJsZSkKewogIG1hcmsgPC0gZWFybmVkL3Bvc3NpYmxlCiAgCiAgaWYgKG1hcmsgPiAwLjUpewogICAgcHJpbnQoIlBhc3MiKQogIH0gZWxzZSB7CiAgICBwcmludCgiRmFpbCIpCiAgfQogIAp9CgoKcGFzc19jaGVjaygxOCwgMjApCnBhc3NfY2hlY2soOCwyMCkKcGFzc19jaGVjaygxOCwxMDApCnBhc3NfY2hlY2soOCwxMCkKCmBgYAoKCiMgRnVuY3Rpb24gRXJyb3IgQ2hlY2tpbmcKCldlIGNhbiB1c2UgY29uZGl0aW9uYWwgY29udHJvbCBzdGF0ZW1lbnRzIHRvIHByb3ZpZGUgZXJyb3IgY2hlY2tpbmcgaW4gdXNlci1kZWZpbmVkIGZ1bmN0aW9ucy4KCiMjIEZhaWxpbmcKCk9uZSBvZiB0aGUgc2F5aW5ncyBpbiBwcm9ncmFtbWluZyBpcyAiaWYgaXQncyBnb2luZyB0byBmYWlsLCBpdCdzIGJlc3QgdG8gZmFpbCBlYXJseSIuIFRoYXQgaXMsIGlmIHdlIGtub3cgdGhhdCBvdXIgZnVuY3Rpb24gcmVxdWlyZXMgYSBzcGVjaWZpYyBpbnB1dCBkYXRhIHR5cGUsIHdlIHdhbnQgdG8gcHJvZ3JhbSAqKmRlZmVuc2l2ZWx5Kiogc28gdGhhdCBvdXIgZnVuY3Rpb24gImZhaWxzIiBiZWZvcmUgaXQgZW5jb3VudGVycyB0aGUgZXJyb3IuIEFzIHBhcnQgb2Ygb3VyIGRlZmVuc2l2ZSBwcm9ncmFtbWluZyB3ZSBjYW4gcHJvdmlkZSBpbmZvcm1hdGl2ZSBlcnJvciBtZXNzYWdlcywgcmF0aGVyIHRoYW4gcmVseSBvbiBSJ3MgZ2VuZXJpYyBvbmVzLgoKCkluIHRoZSBmb2xsb3dpbmcgZXhhbXBsZSwgd2UgY2hlY2sgdGhhdCB0aGUgZGF0YSBjb21pbmcgaW50byBvdXIgZnVuY3Rpb24gaXMgbnVtZXJpYy4gSWYgaXQgaXMgbm90LCB3ZSB1c2UgZnVuY3Rpb24gYHN0b3BgLCB0byBleGl0IHRoZSBmdW5jdGlvbiwgZGlzcGxheWluZyBvdXIgaW5mb3JtYXRpdmUgbWVzc2FnZS4KCgpgYGB7ciwgZXJyb3I9VFJVRX0KIyBSZXR1cm5zIHRoZSBwcm92aWRlZCBudW1iZXIgZG91YmxlZApkb3VibGVfbnVtYmVyIDwtIGZ1bmN0aW9uKHgpIHsKICBpZiggIWlzLm51bWVyaWMoeCkgKXsKICAgIHN0b3AoInggbmVlZHMgdG8gYmUgYSBudW1iZXIuIikKICB9CiAgeCAqIDIKfQoKCmRvdWJsZV9udW1iZXIoNCkKCmRvdWJsZV9udW1iZXIoImEiKQpgYGAKCk4uQi4gQ2hlY2sgdGhlIGFwcGVuZGl4IGZvciBtb3JlIG9uIGRhdGEgdHlwZXMuCgojIENvbmNsdXNpb24KVGhpcyBkb2N1bWVudCBoYXMgcHJlc2VudGVkIGFuIGludHJvZHVjdGlvbiB0byBjcmVhdGluZyB5b3VyIG93biBmdW5jdGlvbnMgYW5kIGltcGxlbWVudGluZyBjb25kaXRpb25hbCBmbG93IG9mIGNvbnRyb2wuIEZvciBtb3JlIGRldGFpbCwgc2VlIHRoZSBmcmVlIG9ubGluZSBib29rcyBbQWR2YW5jZWQgUl0oaHR0cHM6Ly9hZHYtci5oYWRsZXkubnopIGFuZCBbUiBwYWNrYWdlc10oaHR0cHM6Ly9yLXBrZ3Mub3JnKS4KCgojIFdoYXQncyBOZXh0CgoKTmV4dCBtb3ZlIG9udG8gW1IgZm9yIERhdGEgU2NpZW5jZSBDaGFwdGVyIDIxIC0gSXRlcmF0aW9uIChodHRwczovL3I0ZHMuaGFkLmNvLm56L2l0ZXJhdGlvbi5odG1sKV0oaHR0cHM6Ly9yNGRzLmhhZC5jby5uei9pdGVyYXRpb24uaHRtbCkgdG8gbGVhcm4gYWJvdXQgaG93IHdlIGNhbiByZWR1Y2UgY29kZSBkdXBsaWNhdGlvbiwgYnkgcmVwZWF0aW5nIGNvZGUgZWZmaWNpZW50bHkgdGhyb3VnaCBpdGVyYXRpb24gb3IgJ2xvb3BzJy4gQXMgYWx3YXlzLCBpZiB5b3UgcnVuIGludG8gdHJvdWJsZSwgbGV0IHVzIGtub3cuCgojIEFwcGVuZGl4CgojIyBEYXRhIHR5cGVzCgpOb3QgYWxsIGRhdGEgYXJlIGNyZWF0ZWQgZXF1YWwsIGluIFIgdGhpcyBjb25jZXB0IGlzIGNhcHR1cmVkIGJ5IF9kYXRhIHR5cGVzXy4gRm9yIGEgdmVjdG9yLCBhbGwgdmFsdWVzIG11c3QgYmUgb2YgYSBzaW5nbGUgZGF0YSB0eXBlLgoKVGhlIG1haW4gZGF0YSB0eXBlcyB0aGF0IHlvdSB3aWxsIGVuY291bnRlciBpbiBSIGFyZToKCi0gX0xvZ2ljYWxfICggYGMoVFJVRSwgRkFMU0UpYCkKLSBfTnVtZXJpY18gLSBhbHNvIGNhbGxlZCBfUmVhbF8gb3IgX0RvdWJsZV8gKE51bWJlcnMgdGhhdCBoYXZlIGEgZmxvYXRpbmcgcG9pbnQgKGRlY2ltYWwpIHJlcHJlc2VudGF0aW9uIGUuZy4gYGMoMSwgMy42LCAxZTMpYCkKLSBfQ2hhcmFjdGVyXyAtIGFsc28gY2FsbGVkIF9TdHJpbmdfIChhbnl0aGluZyBpbnNpZGUgbWF0Y2hpbmcgb3BlbmluZyBhbmQgY2xvc2luZyBxdW90ZXMgKHNpbmdsZSBvciBkb3VibGUpIGUuZy4gYGMoImEiLCAic29tZSB3b3JkcyIsICJhbmltYWwiYCkpCgpUaGVyZSBhcmUgMyBvdGhlciBsZXNzIGNvbW1vbjoKCi0gX0ludGVnZXJfIChpbnRlZ2VycyBgYygxTCwgNEwsIC0zTClgKQotIF9Db21wbGV4XyAoQ29tcGxleCBudW1iZXJzIGUuZy4gYGMoMCszaSwgNGksIC0yLTVpKWApCi0gX1Jhd18gKHRoZSBieXRlcyBvZiBhIGZpbGUpCgoKRWFjaCBkYXRhIHR5cGUgaXMga25vd24gaW4gUiBhcyBhbiBfYXRvbWljXyB2ZWN0b3IuIFIgaGFzIGJ1aWx0IGluIGZ1bmN0aW9ucyB0byBiZSBhYmxlIHRvIGRldGVybWluZSB0aGUgZGF0YSB0eXBlIG9mIGEgdmVjdG9yLCBgdHlwZW9mKClgIGlzIHRoZSBiZXN0IG9uZSB0byB1c2UsIGJ1dCBvdGhlcnMgc3VjaCBhcyBgc3RyKClgIGFuZCBgY2xhc3MoKWAgY2FuIGJlIHVzZWQuCgpUaGVyZSBpcyBhbHNvIGEgc2VyaWVzIG9mIGZ1bmN0aW9ucyB0aGF0IGxldCB1cyBkbyBleHBsaWNpdCBjaGVja2luZyBmb3IgYSBkYXRhIHR5cGUgd2hpY2ggd2lsbCByZXR1cm4gYFRSVUVgIG9yIGBGQUxTRWA6CgotIGBpcy5sb2dpY2FsKClgCi0gYGlzLm51bWVyaWMoKWAgb3IgYGlzLmRvdWJsZSgpYAotIGBpcy5jaGFyYWN0ZXIoKWAKLSBgaXMuaW50ZWdlcigpYAotIGBpcy5jb21wbGV4KClgCi0gYGlzLnJhdygpYAoKCgojIyMgRGF0YSBUeXBlIENvZXJjaW9uCgpJbiBSLCB3aGVuIGRvaW5nIG9wZXJhdGlvbnMgb24gbXVsdGlwbGUgdmVjdG9ycywgdGhleSBhbGwgbmVlZCB0byBiZSB0aGUgc2FtZSBkYXRhIHR5cGUgLSBidXQgaG93IGNhbiB0aGlzIHdvcmsgaWYgd2UgaGF2ZSBmb3IgZXhhbXBsZSBhIG51bWVyaWMgdmVjdG9yIGFuZCBhIGNoYXJhY3RlciB2ZWN0b3I/IF9Db2VyY2lvbl8gaXMgaG93IFIgZGVhbHMgd2l0aCB0cnlpbmcgdG8gb3BlcmF0ZSBvbiB0d28gdmVjdG9ycyBvZiBkaWZmZXJlbnQgZGF0YSB0eXBlcy4gV2hhdCB0aGlzIG1lYW5zIGluIHByYWN0aWNlIGlzIHRoYXQgUiB3aWxsIGNvbnZlcnQgdGhlIGRhdGEgdHlwZSBvZiBhIHZlY3RvciBpbiBhIGRlZmluZWQgbWFubmVyIHN1Y2ggdGhhdCB3ZSBlbmQgdXAgd2lsbCBhbGwgb2YgdGhlIHNhbWUgdHlwZSBhbmQgZm9sbG93cyBhICJsb3dlc3QgY29tbW9uIGRhdGEgdHlwZSIKIGFwcHJvYWNoLiBVc2luZyB0aGUgMyBtYWluIGRhdGEgdHlwZXMgZnJvbSBhYm92ZSwgdGhlIGZvbGxvd2luZyBpcyB0aGUgb3JkZXIgaW4gd2hpY2ggdGhleSB3aWxsIGJlIGNvZXJjZWQgaW50byB0aGUgbmV4dCBkYXRhIHR5cGU6IF9sb2dpY2FsXyAtPiBfbnVtZXJpY18gLT4gX2NoYXJhY3Rlcl8uCiAKVGhpcyBwcmluY2lwbGUgYXBwbGllcyB3aGVuIHlvdSB0cnkgdG8gY3JlYXRlIGEgdmVjdG9yIG9mIG1peGVkIGRhdGEgdHlwZXMgdG9vLCBSIHdpbGwgY29lcmNlIGV2ZXJ5dGhpbmcgdW50aWwgaXQgaXMgYSBzaW5nbGUgZGF0YSB0eXBlLgogCgpTZWUgaWYgeW91IGNhbiBwcmVkaWN0IHdoYXQgZGF0YSB0eXBlIHRoZSByZXN1bHQgd2lsbCBiZSAoeW91IGNhbiBjaGVjayBieSB1c2luZyBgdHlwZW9mKClgOiAKYGBge3IsIGV2YWwgPSBGQUxTRX0KIyBsb2dpY2FsIGFuZCBudW1lcmljCmMoNCwgVFJVRSwgNSkKCiMgbnVtZXJpYyBhbmQgY2hhcmFjdGVyCmMoMSwgMywgIkEiKQoKIyBsb2dpY2FsIGFuZCBjaGFyYWN0ZXIKYyhGQUxTRSwgImNhdCIsImZyb2ciKQoKIyBtaXhlZApjKCJzZWUiLCBUUlVFLCA0LjgpCgojIHRyaWNreQpjKCIxLjMiLCAiNCIsIFRSVUUpCmBgYAoKV2UgY2FuIGFsc28gZXhwbGljaXRseSBmb3JjZSBjb2VyY2lvbiBpbnRvIGEgcGFydGljdWxhciBkYXRhIHR5cGUgYnkgdXNpbmcgdGhlIGZvbGxvd2luZzoKCi0gYGFzLmxvZ2ljYWwoKWAKLSBgYXMubnVtZXJpYygpYAotIGBhcy5jaGFyYWN0ZXIoKWAKClRoZSBvdGhlciBkYXRhIHR5cGVzIGFsc28gaGF2ZSBzaW1pbGFybHkgbmFtZWQgZnVuY3Rpb25zLiBXaGVuIGdvaW5nIGFnYWluc3QgdGhlIG5vcm1hbCBkaXJlY3Rpb24gb2YgY29lcmNpb24sIGl0IGlzIGltcG9ydGFudCB0byByZWFsaXNlIHRoYXQgaWYgeW91ciBkYXRhIGRvZXNuJ3QgaGF2ZSBhIHJlcHJlc2VudGF0aW9uIGluIHRoYXQgZGF0YSB0eXBlLCBpdCB3aWxsIGJlY29tZSBfTkFfIChtaXNzaW5nKS4K