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:

  1. a name
  2. the body (the code that does something)
  3. (optionally) input data
  4. (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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.

  1. How would you modify function compute_area to eliminate the error?
  2. 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.

Make a function with input arguments

Convert this code into a function that accepts a single input argument, which will be the vector of data to be analysed. For now, use print statements to display the results, not return statements, so we can concentrate on getting the data in. Call your function desc_stats.

library(palmerpenguins)

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)

  print(mean_dv)
  print(sd_dv)
  print(min_dv)
  print(max_dv)
}  

Source the function by selecting all the code (from before desc_stats down to and including the closing curly bracket) and typing ctrl-Enter or cmd-Enter. Test your function by calling it on the body mass data, the flipper length data, and the bill length data.

desc_stats(penguins$body_mass_g)
#> [1] 4201.754
#> [1] 801.9545
#> [1] 2700
#> [1] 6300
desc_stats(penguins$flipper_length_mm)
#> [1] 200.9152
#> [1] 14.06171
#> [1] 172
#> [1] 231
desc_stats(penguins$bill_length_mm)
#> [1] 43.92193
#> [1] 5.459584
#> [1] 32.1
#> [1] 59.6

Stop to admire how tidy and succinct your code is. Note that if you now decide to add the median, you only need to make the change in one place – in the function declaration itself – regardless of how many different data sets you have processed.

NB: If you do change the function, you must source the function again (i.e. you must repeat the “select all the function code and type ctrl-enter” step) to update R’s stored copy of the function. You will not see any change in behaviour until the modified function code is sourced.

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:

Operator Meaning
== 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.

Boolean Operation Symbol in R
NOT !
OR |
AND &

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:

Statement Becomes
!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.

What’s Next

Next move onto R for Data Science Chapter 21 - Iteration (https://r4ds.had.co.nz/iteration.html) to learn about how we can reduce code duplication, by repeating code efficiently through iteration or ‘loops’. As always, if you run into trouble, let us know.

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