Introduction to R (the Basics)

Udi Alter

2022-05-23

1 R and RStudio Installation

1.1 Step 1: Installing R (should be done before installing RStudio)

  • To install R, visit cran.r-project.org and click Download R for [your operating system]. For example, because I’m using an apple computer, I clicked on Download R for macOS.

  • Then, under ‘Latest release’, click on the first/top one. For the macOS users this should be R-4.2.0.pkg (if you don’t have apple silicone chip; usually computers older than 2) or R-4.2.0-arm64.pkg (if your apple computer has an M1 or newer silicone chip).

  • For Windows, you’ll need to click on ‘base’ (or ‘install R for the first time,’ same thing) to download the most recent version of R. To finish installing R on your computer, all that is left to do is to run the .exe file.

1.2 Step 2: Installing R studio (should be done after installing R)

  • Once R is installed, you can proceed to install the RStudio at www.rstudio.com/products/rstudio/download/#download. Under ‘Download RStudio Desktop’, click on ’DOWNLOAD RSTUDIO FOR [your operating system].

  • For Windows: Run the .exe file to finish installing RStudio on your computer.

  • To access R from here on, you only need to open RStudio. Feel free to explore it. But, don’t worry about this too much, I will explain RStudio when we first meet.

  • Here’s a brief video with R and RStudio installation instructions for your reference.

  • If you’re unable to install R and RStudio before class, you can use RStudio Cloud instead: rstudio.cloud. RStudio Cloud is a cloud-based solution that allows anyone to use R and RStudio without any prior installation. Signing up is free! After you log-in, all you need to do is go to New Project > New RStudio Project. You can save, share, and download all R projects created in your workspace henceforth.

Note: If you run into any issues with the installation process or have any questions before we start, please feel free to e-mail me at .

2 Firing Up RStudio

2.0.1 Before a new data analysis:

  • Create a folder for each data analysis project.
  • Open Rstudio.
  • Go to File > New Project > Existing Directory
  • Navigate to the folder you created
  • Click Create Project. A “.Rproj” file will be created in the folder. Next time, simply double click this file to open your project.
  • Go to File > New File > R Script and click OK.
  • Save the new R Script file.

3 Basic Operations

  • Hashtags # are used to comment

3.1 Math Operations

1+2
[1] 3
2-3
[1] -1
5*6
[1] 30
1/6
[1] 0.1666667
3^2 # to the power of 2
[1] 9
(2+3)*5 #BEDMAS
[1] 25

3.2 Logical Operations

1>2 # greater than
[1] FALSE
2<17 # less than
[1] TRUE
2==7 # equals
[1] FALSE
2<=7 # less or equal to
[1] TRUE
7>=6 # greater or equal to
[1] TRUE
2*2 != 3 # does not equal
[1] TRUE
(2 | 3) < 7 # or
[1] TRUE
(2 & 3) == 3 # and
[1] FALSE

4 Functions

Functions are little programs. Almost everything we do in R requires functions. Functions can import data, manipulate/clean our data, and export our data to use elsewhere. They are the fundamental building blocks within R. We can use functions by typing them directly into the Console pane or into script file. Here are a few of examples of functions in R:
NOTE: spaces do not matter, but R is case sensitive

sqrt(9) # square root of 9
[1] 3
factorial(3) # 3 factorial - 3! e.g., 3*2*1
[1] 6
seq(1,5) # sequence of numbers from 1 to 5 e.g., 1, 2, 3, 4, 5
[1] 1 2 3 4 5
class(1)
[1] "numeric"
class(2>=3)
[1] "logical"
#' You can even combine functions:
seq(1,3)*factorial(2) # multiply each number in the sequence of 1-3 by 2!
[1] 2 4 6
#' or incorporate them into one another:
factorial(sqrt(9)) # the factorial of the square root of 9
[1] 6
seq(1,sqrt(9)) # sequence from 1 to 3 (square root of 9)
[1] 1 2 3
# Functions' arguments
seq(from = 1, to = 5, by=1)
[1] 1 2 3 4 5
seq(from = 1, to = 5, by=2)
[1] 1 3 5
plot(x=1:10, y=11:20) # spaces do not matter, but R is case sensitive

5 Getting Help with Functions

?mean # single ? searches within loaded environement
?seq
??neg.reg 
# double ??, same as search bar in Help tab, looks for function/package on CRAN
# Try the search box in Help tab, and look at what's inside the {}, that's the package name!

5.0.1 Google is programmers’ best friend!

It’s True!

R Help is not considered great, but as you get more familiar with R you will find yourself using it… Even expert R users often look for help, nobody knows and/or remembers all commands, functions, and packages (not to mention that these change and evolve all the time). The R Documentation is a bit dry and you will often find more comprehensive explanations and examples online.

Ask anyone, looking up code (including stuff that you know and tried before) is the bread an butter of R (and other software) users!

6 Objects

In R, we temporary save the results of operations or function inside an object. Think of objects as bins containing what you need. To create a bin, you should name it first. It is SO helpful (both for you and others) to select meaningful names for your bins so that they would intuitively reveal their content. It is also helpful to define (or know) what is the type of content in your object, e.g., data frame, vector, integer, list, etc.

6.0.1 Assignment Operator <-

R uses a special operator for creating objects to hold our results: <- It frequently is read as “gets” or “assign.”
NOTE: You cannot start your object name with a number (but in the middle/end name, you can)

meow <- 1 # NOT a good name, why?

variable <- c(1,2,3,4,5, NA) # How about this?

calc_results <- 2*3 # Good object name!

# Also good name:
data <- data.frame(x=1:10, y=11:20) # creating an object called data that will be a dataframe with variables x and y

Take a look at the Environment tab! Remember that R is case sensitive, so calc_results will NOT be the same as Calc_Results. You can use either “snake case” e.g., calc_results or “CamelCase,” e.g., CalcResults, or “dot case,” e.g., calc.results.

You can call on the object to see its content, for example:

calc_results
[1] 6

7 Udi’s Recommendation Corner

  • Use # to comment on your code as much as you can. Think of comments as little post-its you are leaving for others and your future self! The better your comments, the easier it will be for you and others to understand your code.
  • Always, pick object names that are meaningful. An object name should be a good hint about what results are saved inside an object. It is worth the time you spend now choosing an appropriate object name compared to the time you will likely spend later trying to figure out which object is which.

8 Packages

You can think of a package as a collection of functions, data and help files collated into a well defined standard structure which you can download and install in R. These packages can be downloaded from a variety of sources but the most popular are CRAN, Bioconductor and GitHub. The base installation of R comes with many useful packages as standard. These packages will contain many of the functions you will use on a daily basis. However, as you start using R for more diverse projects (and as your own use of R evolves) you will find that there comes a time when you will need to extend R’s capabilities. Fortunately, many thousands of R users have developed useful code and shared this code as installable packages - this is what is meant by open-source!

To use functions from a package, you must first:

8.0.1 Install the package:

install.packages("car")

But, make sure to remove the install.package() line (or make it a comment) before saving. You can also install packages from the Packages tab.

8.0.2 Load the package:

library(car)

8.0.3 Use any of the functions from this package:

Example:

data <- data.frame(x=1:10, y=11:20) # creating an object called data that will be a dataframe with variables x and y
scatterplotMatrix(data)

9 Types of Data & Data Structure

9.1 Atomic (Data) Types

There are 6 atomic types of data in R, but, for now you only need to know (and use) 4 of them:

9.1.1 Logical (TRUE/FALSE)

1 > 2
[1] FALSE
2 > 1
[1] TRUE

9.1.2 Integer

e.g., 1, 96, NA, 78910

9.1.3 Numeric

e.g., 2, 4.67, pi

9.1.4 Character

e.g., “hello”, “34”

"I like a lot pulp in my organge juice"
[1] "I like a lot pulp in my organge juice"

9.2 Data Structures

Data structures are ways which R stores data. Just like the name implies, a data structure tells us exactly how our data is structured or organized within R. R, like most programming languages, uses a variety of data structures. The most common of which are:

9.2.1 Vectors

A series of data which must have the same data type. Vectors can be any of the basic data types, e.g., logical, integer, numeric, character

vector_example1 <- 1:5
vector_example2 <- c(1,2,3,4,5) # c function is meant to **combine** values to form a vector
vector_example3 <- c(T, F, T, F, T) # T and F is the same as TRUE and FALSE
vector_example4 <- c("My", "mom", "is", "a", "teacher")

9.2.2 Matrices

Must be 2 dimensional. Must be of the same data type.

(matrix_example <- matrix(1:10, 1:10))
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    2    3    4    5    6    7    8    9    10

9.2.3 Arrays

Similar to matrices, but they can be more than 2 dimensions

(array_exaple <- array(dim = c(3,4,5)))
, , 1

     [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   NA   NA   NA   NA
[3,]   NA   NA   NA   NA

, , 2

     [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   NA   NA   NA   NA
[3,]   NA   NA   NA   NA

, , 3

     [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   NA   NA   NA   NA
[3,]   NA   NA   NA   NA

, , 4

     [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   NA   NA   NA   NA
[3,]   NA   NA   NA   NA

, , 5

     [,1] [,2] [,3] [,4]
[1,]   NA   NA   NA   NA
[2,]   NA   NA   NA   NA
[3,]   NA   NA   NA   NA

9.2.4 Lists

A list can have mixed data types, but they can be a bit trickier to use.

list_example <- list("cat", 3, TRUE)

9.2.5 Data frames

Used for tabular data, think of them as a basic spreadsheet, but each column is a vector.

(dataframe_example <- data.frame(x=1:10, y=11:20))
    x  y
1   1 11
2   2 12
3   3 13
4   4 14
5   5 15
6   6 16
7   7 17
8   8 18
9   9 19
10 10 20
(dataframe_example2 <- data.frame(eyecolour= c("blue", "brown", "grey"),
                                 hight = c(1.75, 2.1, 1.56),
                                 registered = c(T,F, T)))
  eyecolour hight registered
1      blue  1.75       TRUE
2     brown  2.10      FALSE
3      grey  1.56       TRUE

9.2.6 Tibbles

Similar to data frames with a few differences. Tibbles are the standard data structures within the tidyverse.

(tibble_example <- tibble(x=letters, y=1:length(letters)))
# A tibble: 26 × 2
   x         y
   <chr> <int>
 1 a         1
 2 b         2
 3 c         3
 4 d         4
 5 e         5
 6 f         6
 7 g         7
 8 h         8
 9 i         9
10 j        10
# … with 16 more rows

If you are not sure what type of data or data structure an object (or value) is, you can check using:

class(dataframe_example)
[1] "data.frame"
class(1.34)
[1] "numeric"
class(TRUE)
[1] "logical"
class(list_example)
[1] "list"
class(dataframe_example[1,2]) # dataframe_example[1,2] means the value in the 1st row, 2nd column
[1] "integer"
# It is always: [Rows, Columns]

dataframe_example
    x  y
1   1 11
2   2 12
3   3 13
4   4 14
5   5 15
6   6 16
7   7 17
8   8 18
9   9 19
10 10 20
dataframe_example[1,2]
[1] 11

10 Importing Data

R is very flexible and can import many data formats. RStudio will help you with that, using necessary packages. In this workshop I will show you how to do it through RStudio and also through R script. One thing to notice is that if you have a RStudio project in the same folder where your data sets are, you don’t need to specify path addresses to import your data. R will by default import and save anything on that folder.

10.0.1 R allows you to read in data from many different formats:

  • SPSS
  • Excel
  • SAS
  • .csv
  • .txt
  • .dat

The easiest way to get started with reading data into R is go to the environment tab and click on the import dataset button and then read in the data accordingly (note that csv files are a type of text file).

Let’s start by importing an SPSS dataset (.sav) using the read_sav() function in the haven package:

10.0.2 Install the haven package

install.packages("haven")

10.0.3 Load the haven package

library(haven)

10.0.4 Use read_sav()

You want to make sure the file is saved in the same workspace as your R Script, or set the path to where the data is. And, don’t forget to store the data in an object!

aggression_data <- read_sav("aggression.sav")

class(aggression_data) # what data structure is the dataset 
[1] "tbl_df"     "tbl"        "data.frame"
str(aggression_data) # structure, variables and their data type and structure
tibble [275 × 8] (S3: tbl_df/tbl/data.frame)
 $ age    : num [1:275] 18 18 20 17 17 17 17 17 17 17 ...
  ..- attr(*, "format.spss")= chr "F2.0"
 $ BPAQ   : num [1:275] 2.62 2.24 2.72 1.93 2.72 ...
  ..- attr(*, "label")= chr "Aggression total score"
  ..- attr(*, "format.spss")= chr "F12.10"
  ..- attr(*, "display_width")= int 14
 $ AISS   : num [1:275] 2.65 2.85 3.05 2.65 2.95 1.95 2.55 2.3 2 2.15 ...
  ..- attr(*, "label")= chr "sensation seeking total score"
  ..- attr(*, "format.spss")= chr "F4.2"
 $ alcohol: num [1:275] 28 NA 80 28 10 12 21 3 21 0 ...
  ..- attr(*, "label")= chr "alcohol consumption (in drinks)"
  ..- attr(*, "format.spss")= chr "F2.0"
 $ BIS    : num [1:275] 2.15 3.08 3 1.85 2.08 ...
  ..- attr(*, "label")= chr "Impulsivity total score"
  ..- attr(*, "format.spss")= chr "F12.10"
  ..- attr(*, "display_width")= int 14
 $ NEOc   : num [1:275] 2.83 2.5 2.75 3.42 3.58 ...
  ..- attr(*, "label")= chr "Conscientiousness total score"
  ..- attr(*, "format.spss")= chr "F12.10"
  ..- attr(*, "display_width")= int 14
 $ gender : dbl+lbl [1:275] 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, ...
   ..@ label      : chr "biological sex of participant"
   ..@ format.spss: chr "F1.0"
   ..@ labels     : Named num [1:2] 0 1
   .. ..- attr(*, "names")= chr [1:2] "male" "female"
 $ NEOo   : num [1:275] 2.92 4.17 3.92 4.17 3.5 ...
  ..- attr(*, "label")= chr "openness to experience total score"
  ..- attr(*, "format.spss")= chr "F12.10"
  ..- attr(*, "display_width")= int 14
head(aggression_data) # inspect the top 6 (head) of the data
# A tibble: 6 × 8
    age  BPAQ  AISS alcohol   BIS  NEOc     gender  NEOo
  <dbl> <dbl> <dbl>   <dbl> <dbl> <dbl>  <dbl+lbl> <dbl>
1    18  2.62  2.65      28  2.15  2.83 1 [female]  2.92
2    18  2.24  2.85      NA  3.08  2.5  1 [female]  4.17
3    20  2.72  3.05      80  3     2.75 1 [female]  3.92
4    17  1.93  2.65      28  1.85  3.42 1 [female]  4.17
5    17  2.72  2.95      10  2.08  3.58 0 [male]    3.5 
6    17  2.45  1.95      12  2.62  3.83 1 [female]  3.25
names(aggression_data) # variable/column names
[1] "age"     "BPAQ"    "AISS"    "alcohol" "BIS"     "NEOc"    "gender" 
[8] "NEOo"   

10.0.5 finding the value located in the 2nd row, 3rd column

aggression_data[2,3]
# A tibble: 1 × 1
   AISS
  <dbl>
1  2.85

10.0.6 looking only at the age variable/column

aggression_data$age
 [1] 18 18 20 17 17 17 17 17 17 17 17 17 17 18 18 18 18 18 18 18 18 18 18 18 18
[26] 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18
[51] 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18
 [ reached getOption("max.print") -- omitted 200 entries ]
attr(,"format.spss")
[1] "F2.0"

10.0.7 finding the age of the 3rd participant

aggression_data$age[3]
[1] 20

10.0.8 finding the mean age of all participants

mean(aggression_data$age)
[1] 20.21091

10.0.9 finding the standard deviation of age

sd(aggression_data$age)
[1] 4.960342

10.0.10 finding the median of age

median(aggression_data$age)
[1] 18

10.0.11 find how many values in age

length(aggression_data$age)
[1] 275
nrow(aggression_data)
[1] 275

10.0.12 plotting age vs. alcohol

plot(aggression_data$age, aggression_data$alcohol)

10.1 CONGRATULATIONS! You are now officially an R user! Next week, we will learn more about data exploration and manipulation!

LS0tCnRpdGxlOiAiSW50cm9kdWN0aW9uIHRvIFIgKHRoZSBCYXNpY3MpIgphdXRob3I6ICJVZGkgQWx0ZXIiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIHJtZGZvcm1hdHM6OmRvd25jdXRlOgogICAgdGhlbWU6IGZsYXRseQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBoaWdobGlnaHQ6IHRhbmdvCiAgICBzb2NpYWw6IHRydWUKLS0tCgoKYGBge3Igc2V0dXAsIGVjaG89RkFMU0UsIGNhY2hlPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KHJtZGZvcm1hdHMpCmxpYnJhcnkodGlkeXZlcnNlKQojIyBHbG9iYWwgb3B0aW9ucwpvcHRpb25zKG1heC5wcmludD0iNzUiKQpvcHRzX2NodW5rJHNldChlY2hvPVRSVUUsCgkgICAgICAgICAgICAgY2FjaGU9VFJVRSwKICAgICAgICAgICAgICAgcHJvbXB0PUZBTFNFLAogICAgICAgICAgICAgICB0aWR5PVRSVUUsCiAgICAgICAgICAgICAgIGNvbW1lbnQ9TkEsCiAgICAgICAgICAgICAgIG1lc3NhZ2U9RkFMU0UsCiAgICAgICAgICAgICAgIHdhcm5pbmc9RkFMU0UpCm9wdHNfa25pdCRzZXQod2lkdGg9NzUpCmBgYAoKIyBSIGFuZCBSU3R1ZGlvIEluc3RhbGxhdGlvbiAKCgojIyBTdGVwIDE6IEluc3RhbGxpbmcgUiAoc2hvdWxkIGJlIGRvbmUgYmVmb3JlIGluc3RhbGxpbmcgUlN0dWRpbykKCiAqIFRvIGluc3RhbGwgUiwgdmlzaXQgW2NyYW4uci1wcm9qZWN0Lm9yZ10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvKSBhbmQgY2xpY2sgRG93bmxvYWQgUiBmb3IgW3lvdXIgb3BlcmF0aW5nIHN5c3RlbV0uIEZvciBleGFtcGxlLCBiZWNhdXNlIEnigJltIHVzaW5nIGFuIGFwcGxlIGNvbXB1dGVyLCBJIGNsaWNrZWQgb24gRG93bmxvYWQgUiBmb3IgbWFjT1MuICAKIAoqIFRoZW4sIHVuZGVyIOKAmExhdGVzdCByZWxlYXNl4oCZLCBjbGljayBvbiB0aGUgZmlyc3QvdG9wIG9uZS4gRm9yIHRoZSBtYWNPUyB1c2VycyB0aGlzIHNob3VsZCBiZSBSLTQuMi4wLnBrZyAoaWYgeW91IGRvbuKAmXQgaGF2ZSBhcHBsZSBzaWxpY29uZSBjaGlwOyB1c3VhbGx5IGNvbXB1dGVycyBvbGRlciB0aGFuIDIpIG9yIFItNC4yLjAtYXJtNjQucGtnIChpZiB5b3VyIGFwcGxlIGNvbXB1dGVyIGhhcyBhbiBNMSBvciBuZXdlciBzaWxpY29uZSBjaGlwKS4gIAogCiAqIEZvciBXaW5kb3dzLCB5b3XigJlsbCBuZWVkIHRvIGNsaWNrIG9uIOKAmGJhc2XigJkgKG9yIOKAmGluc3RhbGwgUiBmb3IgdGhlIGZpcnN0IHRpbWUs4oCZIHNhbWUgdGhpbmcpIHRvIGRvd25sb2FkIHRoZSBtb3N0IHJlY2VudCB2ZXJzaW9uIG9mIFIuIFRvIGZpbmlzaCBpbnN0YWxsaW5nIFIgb24geW91ciBjb21wdXRlciwgYWxsIHRoYXQgaXMgbGVmdCB0byBkbyBpcyB0byBydW4gdGhlIC5leGUgZmlsZS4gIAogCiMjIFN0ZXAgMjogSW5zdGFsbGluZyBSIHN0dWRpbyAoc2hvdWxkIGJlIGRvbmUgYWZ0ZXIgaW5zdGFsbGluZyBSKQogCiAqIE9uY2UgUiBpcyBpbnN0YWxsZWQsIHlvdSBjYW4gcHJvY2VlZCB0byBpbnN0YWxsIHRoZSBSU3R1ZGlvIGF0IFt3d3cucnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC8jZG93bmxvYWRdKGh0dHBzOi8vd3d3LnJzdHVkaW8uY29tL3Byb2R1Y3RzL3JzdHVkaW8vZG93bmxvYWQvI2Rvd25sb2FkKS4gVW5kZXIg4oCYRG93bmxvYWQgUlN0dWRpbyBEZXNrdG9w4oCZLCBjbGljayBvbiDigJhET1dOTE9BRCBSU1RVRElPIEZPUiBbeW91ciBvcGVyYXRpbmcgc3lzdGVtXS4gCgogKiBGb3IgV2luZG93czogUnVuIHRoZSAuZXhlIGZpbGUgdG8gZmluaXNoIGluc3RhbGxpbmcgUlN0dWRpbyBvbiB5b3VyIGNvbXB1dGVyLiAgCiAKICogVG8gYWNjZXNzIFIgZnJvbSBoZXJlIG9uLCB5b3Ugb25seSBuZWVkIHRvIG9wZW4gUlN0dWRpby4gRmVlbCBmcmVlIHRvIGV4cGxvcmUgaXQuIEJ1dCwgZG9u4oCZdCB3b3JyeSBhYm91dCB0aGlzIHRvbyBtdWNoLCBJIHdpbGwgZXhwbGFpbiBSU3R1ZGlvIHdoZW4gd2UgZmlyc3QgbWVldC4gCiAKICogSGVyZeKAmXMgYSBbYnJpZWYgdmlkZW8gd2l0aCBSIGFuZCBSU3R1ZGlvIGluc3RhbGxhdGlvbiBpbnN0cnVjdGlvbnNdKGh0dHBzOi8vdmltZW8uY29tLzQxNTUwMTI4ND9lbWJlZGRlZD10cnVlJnNvdXJjZT12aWRlb190aXRsZSZvd25lcj0xMTQ3OTMzOTUpIGZvciB5b3VyIHJlZmVyZW5jZS4KIAogKiBJZiB5b3XigJlyZSB1bmFibGUgdG8gaW5zdGFsbCBSIGFuZCBSU3R1ZGlvIGJlZm9yZSBjbGFzcywgeW91IGNhbiB1c2UgUlN0dWRpbyBDbG91ZCBpbnN0ZWFkOiBbcnN0dWRpby5jbG91ZF0oaHR0cHM6Ly9yc3R1ZGlvLmNsb3VkLykuIFJTdHVkaW8gQ2xvdWQgaXMgYSBjbG91ZC1iYXNlZCBzb2x1dGlvbiB0aGF0IGFsbG93cyBhbnlvbmUgdG8gdXNlIFIgYW5kIFJTdHVkaW8gd2l0aG91dCBhbnkgcHJpb3IgaW5zdGFsbGF0aW9uLiBTaWduaW5nIHVwIGlzIGZyZWUhIEFmdGVyIHlvdSBsb2ctaW4sIGFsbCB5b3UgbmVlZCB0byBkbyBpcyBnbyB0byAqKk5ldyBQcm9qZWN0ID4gTmV3IFJTdHVkaW8gUHJvamVjdCoqLiBZb3UgY2FuIHNhdmUsIHNoYXJlLCBhbmQgZG93bmxvYWQgYWxsIFIgcHJvamVjdHMgY3JlYXRlZCBpbiB5b3VyIHdvcmtzcGFjZSBoZW5jZWZvcnRoLiAgCgoKKipOb3RlOioqIElmIHlvdSBydW4gaW50byBhbnkgaXNzdWVzIHdpdGggdGhlIGluc3RhbGxhdGlvbiBwcm9jZXNzIG9yIGhhdmUgYW55IHF1ZXN0aW9ucyBiZWZvcmUgd2Ugc3RhcnQsIHBsZWFzZSBmZWVsIGZyZWUgdG8gZS1tYWlsIG1lIGF0IHVkaWFsdGVyQHlvcmt1LmNhLiAgCgoKIyBGaXJpbmcgVXAgUlN0dWRpbwoKIyMjIEJlZm9yZSBhIG5ldyBkYXRhIGFuYWx5c2lzOgoKICogQ3JlYXRlIGEgZm9sZGVyIGZvciBlYWNoIGRhdGEgYW5hbHlzaXMgcHJvamVjdC4gCiAqIE9wZW4gUnN0dWRpby4KICogR28gdG8gKipGaWxlID4gTmV3IFByb2plY3QgPiBFeGlzdGluZyBEaXJlY3RvcnkqKgogKiBOYXZpZ2F0ZSB0byB0aGUgZm9sZGVyIHlvdSBjcmVhdGVkCiAqIENsaWNrIENyZWF0ZSBQcm9qZWN0LiBBIOKAnC5ScHJvauKAnSBmaWxlIHdpbGwgYmUgY3JlYXRlZCBpbiB0aGUgZm9sZGVyLiAgTmV4dCB0aW1lLCBzaW1wbHkgZG91YmxlIGNsaWNrIHRoaXMgZmlsZSB0byBvcGVuIHlvdXIgcHJvamVjdC4KICogR28gdG8gKipGaWxlID4gTmV3IEZpbGUgPiBSIFNjcmlwdCoqICBhbmQgY2xpY2sgT0suCiAqIFNhdmUgdGhlIG5ldyBSIFNjcmlwdCBmaWxlLgoKIyBCYXNpYyBPcGVyYXRpb25zCiAqIEhhc2h0YWdzICMgYXJlIHVzZWQgdG8gY29tbWVudAoKIyMgTWF0aCBPcGVyYXRpb25zCgpgYGB7ciBtYXRoIG9wZXJhdGlvbnN9CjErMgoyLTMKNSo2CjEvNgozXjIgIyB0byB0aGUgcG93ZXIgb2YgMgooMiszKSo1ICNCRURNQVMKYGBgCgojIyBMb2dpY2FsIE9wZXJhdGlvbnMKYGBge3IgbG9naWNhbCBvcGVyYXRpb25zfQoxPjIgIyBncmVhdGVyIHRoYW4KMjwxNyAjIGxlc3MgdGhhbgoyPT03ICMgZXF1YWxzCjI8PTcgIyBsZXNzIG9yIGVxdWFsIHRvCjc+PTYgIyBncmVhdGVyIG9yIGVxdWFsIHRvCjIqMiAhPSAzICMgZG9lcyBub3QgZXF1YWwKKDIgfCAzKSA8IDcgIyBvcgooMiAmIDMpID09IDMgIyBhbmQKYGBgCgojIEZ1bmN0aW9ucwpGdW5jdGlvbnMgYXJlIGxpdHRsZSBwcm9ncmFtcy4gQWxtb3N0IGV2ZXJ5dGhpbmcgd2UgZG8gaW4gUiByZXF1aXJlcyBmdW5jdGlvbnMuIApGdW5jdGlvbnMgY2FuIGltcG9ydCBkYXRhLCBtYW5pcHVsYXRlL2NsZWFuIG91ciBkYXRhLCBhbmQgZXhwb3J0IG91ciBkYXRhIHRvIHVzZSBlbHNld2hlcmUuIApUaGV5IGFyZSB0aGUgZnVuZGFtZW50YWwgYnVpbGRpbmcgYmxvY2tzIHdpdGhpbiBSLiAKV2UgY2FuIHVzZSBmdW5jdGlvbnMgYnkgdHlwaW5nIHRoZW0gZGlyZWN0bHkgaW50byB0aGUgQ29uc29sZSBwYW5lIG9yIGludG8gc2NyaXB0IGZpbGUuIApIZXJlIGFyZSBhIGZldyBvZiBleGFtcGxlcyBvZiBmdW5jdGlvbnMgaW4gUjogPGJyPgoqKk5PVEU6Kiogc3BhY2VzIGRvIG5vdCBtYXR0ZXIsIGJ1dCBSIGlzIGNhc2Ugc2Vuc2l0aXZlCgpgYGB7ciBmdW5jdGlvbnN9CnNxcnQoOSkgIyBzcXVhcmUgcm9vdCBvZiA5CmZhY3RvcmlhbCgzKSAjIDMgZmFjdG9yaWFsIC0gMyEgZS5nLiwgMyoyKjEKc2VxKDEsNSkgIyBzZXF1ZW5jZSBvZiBudW1iZXJzIGZyb20gMSB0byA1IGUuZy4sIDEsIDIsIDMsIDQsIDUKY2xhc3MoMSkKY2xhc3MoMj49MykKCiMnIFlvdSBjYW4gZXZlbiBjb21iaW5lIGZ1bmN0aW9uczoKc2VxKDEsMykqZmFjdG9yaWFsKDIpICMgbXVsdGlwbHkgZWFjaCBudW1iZXIgaW4gdGhlIHNlcXVlbmNlIG9mIDEtMyBieSAyIQoKIycgb3IgaW5jb3Jwb3JhdGUgdGhlbSBpbnRvIG9uZSBhbm90aGVyOgpmYWN0b3JpYWwoc3FydCg5KSkgIyB0aGUgZmFjdG9yaWFsIG9mIHRoZSBzcXVhcmUgcm9vdCBvZiA5CnNlcSgxLHNxcnQoOSkpICMgc2VxdWVuY2UgZnJvbSAxIHRvIDMgKHNxdWFyZSByb290IG9mIDkpCgojIEZ1bmN0aW9ucycgYXJndW1lbnRzCnNlcShmcm9tID0gMSwgdG8gPSA1LCBieT0xKQpzZXEoZnJvbSA9IDEsIHRvID0gNSwgYnk9MikKcGxvdCh4PTE6MTAsIHk9MTE6MjApICMgc3BhY2VzIGRvIG5vdCBtYXR0ZXIsIGJ1dCBSIGlzIGNhc2Ugc2Vuc2l0aXZlCmBgYAoKIyBHZXR0aW5nIEhlbHAgd2l0aCBGdW5jdGlvbnMKCmBgYHtyIGhlbHAgZnVuY3Rpb259Cj9tZWFuICMgc2luZ2xlID8gc2VhcmNoZXMgd2l0aGluIGxvYWRlZCBlbnZpcm9uZW1lbnQKP3NlcQo/P25lZy5yZWcgCiMgZG91YmxlID8/LCBzYW1lIGFzIHNlYXJjaCBiYXIgaW4gSGVscCB0YWIsIGxvb2tzIGZvciBmdW5jdGlvbi9wYWNrYWdlIG9uIENSQU4KIyBUcnkgdGhlIHNlYXJjaCBib3ggaW4gSGVscCB0YWIsIGFuZCBsb29rIGF0IHdoYXQncyBpbnNpZGUgdGhlIHt9LCB0aGF0J3MgdGhlIHBhY2thZ2UgbmFtZSEKYGBgCgojIyMgR29vZ2xlIGlzIHByb2dyYW1tZXJzJyBiZXN0IGZyaWVuZCEgCgpJdCdzIFRydWUhIDxicj4KClIgSGVscCBpcyBub3QgY29uc2lkZXJlZCBncmVhdCwgYnV0IGFzIHlvdSBnZXQgbW9yZSBmYW1pbGlhciB3aXRoIFIgeW91IHdpbGwgZmluZCB5b3Vyc2VsZiB1c2luZyBpdC4uLgpFdmVuIGV4cGVydCBSIHVzZXJzIG9mdGVuIGxvb2sgZm9yIGhlbHAsIG5vYm9keSBrbm93cyBhbmQvb3IgcmVtZW1iZXJzIGFsbCBjb21tYW5kcywgZnVuY3Rpb25zLCBhbmQgcGFja2FnZXMgKG5vdCB0byBtZW50aW9uIHRoYXQgdGhlc2UgY2hhbmdlIGFuZCBldm9sdmUgYWxsIHRoZSB0aW1lKS4gVGhlIFIgRG9jdW1lbnRhdGlvbiBpcyBhIGJpdCBkcnkgYW5kIHlvdSB3aWxsIG9mdGVuIGZpbmQgbW9yZSBjb21wcmVoZW5zaXZlIGV4cGxhbmF0aW9ucyBhbmQgZXhhbXBsZXMgb25saW5lLgoKQXNrIGFueW9uZSwgbG9va2luZyB1cCBjb2RlIChpbmNsdWRpbmcgc3R1ZmYgdGhhdCB5b3Uga25vdyBhbmQgdHJpZWQgYmVmb3JlKSBpcyB0aGUgYnJlYWQgYW4gYnV0dGVyIG9mIFIgKGFuZCBvdGhlciBzb2Z0d2FyZSkgdXNlcnMhIAoKIyBPYmplY3RzCgoKSW4gUiwgd2UgdGVtcG9yYXJ5IHNhdmUgdGhlIHJlc3VsdHMgb2Ygb3BlcmF0aW9ucyBvciBmdW5jdGlvbiBpbnNpZGUgYW4gb2JqZWN0LiAKVGhpbmsgb2Ygb2JqZWN0cyBhcyBiaW5zIGNvbnRhaW5pbmcgd2hhdCB5b3UgbmVlZC4gVG8gY3JlYXRlIGEgYmluLCB5b3Ugc2hvdWxkIG5hbWUgaXQgZmlyc3QuIApJdCBpcyAqU08qIGhlbHBmdWwgKGJvdGggZm9yIHlvdSBhbmQgb3RoZXJzKSB0byBzZWxlY3QgbWVhbmluZ2Z1bCBuYW1lcyBmb3IgeW91ciBiaW5zIHNvIHRoYXQgIHRoZXkgd291bGQgaW50dWl0aXZlbHkgcmV2ZWFsIHRoZWlyIGNvbnRlbnQuIEl0IGlzIGFsc28gaGVscGZ1bCB0byBkZWZpbmUgKG9yIGtub3cpIHdoYXQgaXMgdGhlIHR5cGUgb2YgY29udGVudCBpbiB5b3VyIG9iamVjdCwgZS5nLiwgZGF0YSBmcmFtZSwgdmVjdG9yLCBpbnRlZ2VyLCBsaXN0LCBldGMuCgojIyMgQXNzaWdubWVudCBPcGVyYXRvciBgPC1gClIgdXNlcyBhIHNwZWNpYWwgb3BlcmF0b3IgZm9yIGNyZWF0aW5nIG9iamVjdHMgdG8gaG9sZCBvdXIgcmVzdWx0czogYDwtYApJdCBmcmVxdWVudGx5IGlzIHJlYWQgYXMg4oCcZ2V0c+KAnSBvciAiYXNzaWduLiIgPGJyPgoqKk5PVEU6KiogWW91IGNhbm5vdCBzdGFydCB5b3VyIG9iamVjdCBuYW1lIHdpdGggYSBudW1iZXIgKGJ1dCBpbiB0aGUgbWlkZGxlL2VuZCBuYW1lLCB5b3UgY2FuKQoKYGBge3Igb2JqZWN0c30KbWVvdyA8LSAxICMgTk9UIGEgZ29vZCBuYW1lLCB3aHk/Cgp2YXJpYWJsZSA8LSBjKDEsMiwzLDQsNSwgTkEpICMgSG93IGFib3V0IHRoaXM/CgpjYWxjX3Jlc3VsdHMgPC0gMiozICMgR29vZCBvYmplY3QgbmFtZSEKCiMgQWxzbyBnb29kIG5hbWU6CmRhdGEgPC0gZGF0YS5mcmFtZSh4PTE6MTAsIHk9MTE6MjApICMgY3JlYXRpbmcgYW4gb2JqZWN0IGNhbGxlZCBkYXRhIHRoYXQgd2lsbCBiZSBhIGRhdGFmcmFtZSB3aXRoIHZhcmlhYmxlcyB4IGFuZCB5CmBgYAogClRha2UgYSBsb29rIGF0IHRoZSBFbnZpcm9ubWVudCB0YWIhIFJlbWVtYmVyIHRoYXQgUiBpcyBjYXNlIHNlbnNpdGl2ZSwgc28gYGNhbGNfcmVzdWx0c2Agd2lsbCBOT1QgYmUgdGhlIHNhbWUgYXMgYENhbGNfUmVzdWx0c2AuIFlvdSBjYW4gdXNlIGVpdGhlciAic25ha2UgY2FzZSIgZS5nLiwgYGNhbGNfcmVzdWx0c2Agb3IgIkNhbWVsQ2FzZSwiIGUuZy4sIGBDYWxjUmVzdWx0c2AsIG9yICJkb3QgY2FzZSwiIGUuZy4sIGBjYWxjLnJlc3VsdHNgLiA8YnI+CiAKWW91IGNhbiBjYWxsIG9uIHRoZSBvYmplY3QgdG8gc2VlIGl0cyBjb250ZW50LCBmb3IgZXhhbXBsZToKYGBge3IgY2FsbCBvYmplY3RzfQpjYWxjX3Jlc3VsdHMKYGBgCgojIFVkaSdzIFJlY29tbWVuZGF0aW9uIENvcm5lcgoKICogKipVc2UgIyB0byBjb21tZW50IG9uIHlvdXIgY29kZSBhcyBtdWNoIGFzIHlvdSBjYW4qKi4gVGhpbmsgb2YgY29tbWVudHMgYXMgbGl0dGxlIHBvc3QtaXRzIHlvdSBhcmUgbGVhdmluZyBmb3Igb3RoZXJzICphbmQqIHlvdXIgZnV0dXJlIHNlbGYhIFRoZSBiZXR0ZXIgeW91ciBjb21tZW50cywgdGhlIGVhc2llciBpdCB3aWxsIGJlIGZvciB5b3UgYW5kIG90aGVycyB0byB1bmRlcnN0YW5kIHlvdXIgY29kZS4gCiAqICoqQWx3YXlzLCBwaWNrIG9iamVjdCBuYW1lcyB0aGF0IGFyZSBtZWFuaW5nZnVsKiouIEFuIG9iamVjdCBuYW1lIHNob3VsZCBiZSBhIGdvb2QgaGludCBhYm91dCB3aGF0IHJlc3VsdHMgYXJlIHNhdmVkIGluc2lkZSBhbiBvYmplY3QuIEl0IGlzIHdvcnRoIHRoZSB0aW1lIHlvdSBzcGVuZCBub3cgY2hvb3NpbmcgYW4gYXBwcm9wcmlhdGUgb2JqZWN0IG5hbWUgY29tcGFyZWQgdG8gdGhlIHRpbWUgeW91IHdpbGwgbGlrZWx5IHNwZW5kIGxhdGVyIHRyeWluZyB0byBmaWd1cmUgb3V0IHdoaWNoIG9iamVjdCBpcyB3aGljaC4KCgojIFBhY2thZ2VzCllvdSBjYW4gdGhpbmsgb2YgYSBwYWNrYWdlIGFzIGEgY29sbGVjdGlvbiBvZiBmdW5jdGlvbnMsIGRhdGEgYW5kIGhlbHAgZmlsZXMgY29sbGF0ZWQgaW50byBhIHdlbGwgZGVmaW5lZCBzdGFuZGFyZCBzdHJ1Y3R1cmUgd2hpY2ggeW91IGNhbiBkb3dubG9hZCBhbmQgaW5zdGFsbCBpbiBSLiBUaGVzZSBwYWNrYWdlcyBjYW4gYmUgZG93bmxvYWRlZCBmcm9tIGEgdmFyaWV0eSBvZiBzb3VyY2VzIGJ1dCB0aGUgbW9zdCBwb3B1bGFyIGFyZSBDUkFOLCBCaW9jb25kdWN0b3IgYW5kIEdpdEh1Yi4gVGhlIGJhc2UgaW5zdGFsbGF0aW9uIG9mIFIgY29tZXMgd2l0aCBtYW55IHVzZWZ1bCBwYWNrYWdlcyBhcyBzdGFuZGFyZC4gVGhlc2UgcGFja2FnZXMgd2lsbCBjb250YWluIG1hbnkgb2YgdGhlIGZ1bmN0aW9ucyB5b3Ugd2lsbCB1c2Ugb24gYSBkYWlseSBiYXNpcy4gSG93ZXZlciwgYXMgeW91IHN0YXJ0IHVzaW5nIFIgZm9yIG1vcmUgZGl2ZXJzZSBwcm9qZWN0cyAoYW5kIGFzIHlvdXIgb3duIHVzZSBvZiBSIGV2b2x2ZXMpIHlvdSB3aWxsIGZpbmQgdGhhdCB0aGVyZSBjb21lcyBhIHRpbWUgd2hlbiB5b3Ugd2lsbCBuZWVkIHRvIGV4dGVuZCBS4oCZcyBjYXBhYmlsaXRpZXMuIEZvcnR1bmF0ZWx5LCBtYW55IHRob3VzYW5kcyBvZiBSIHVzZXJzIGhhdmUgZGV2ZWxvcGVkIHVzZWZ1bCBjb2RlIGFuZCBzaGFyZWQgdGhpcyBjb2RlIGFzIGluc3RhbGxhYmxlIHBhY2thZ2VzIC0gKnRoaXMgaXMgd2hhdCBpcyBtZWFudCBieSBvcGVuLXNvdXJjZSohIDxicj4KClRvIHVzZSBmdW5jdGlvbnMgZnJvbSBhIHBhY2thZ2UsIHlvdSBtdXN0IGZpcnN0OiAKCgojIyMgSW5zdGFsbCB0aGUgcGFja2FnZToKCgoKYGBge3IgaW5zdGFsbCBwYWNrYWdlcywgZXZhbD1GQUxTRX0KaW5zdGFsbC5wYWNrYWdlcygiY2FyIikKYGBgCgoKCkJ1dCwgbWFrZSBzdXJlIHRvIHJlbW92ZSB0aGUgYGluc3RhbGwucGFja2FnZSgpYCBsaW5lIChvciBtYWtlIGl0IGEgY29tbWVudCkgYmVmb3JlIHNhdmluZy4gWW91IGNhbiBhbHNvIGluc3RhbGwgcGFja2FnZXMgZnJvbSB0aGUgUGFja2FnZXMgdGFiLgoKCgojIyMgTG9hZCB0aGUgcGFja2FnZToKCgoKCgpgYGB7ciBsb2FkIHBhY2thZ2V9CmxpYnJhcnkoY2FyKQpgYGAKCgoKIyMjIFVzZSBhbnkgb2YgdGhlIGZ1bmN0aW9ucyBmcm9tIHRoaXMgcGFja2FnZToKCgoKCgoKRXhhbXBsZTogCgpgYGB7ciB1c2UgcGFja2FnZX0KZGF0YSA8LSBkYXRhLmZyYW1lKHg9MToxMCwgeT0xMToyMCkgIyBjcmVhdGluZyBhbiBvYmplY3QgY2FsbGVkIGRhdGEgdGhhdCB3aWxsIGJlIGEgZGF0YWZyYW1lIHdpdGggdmFyaWFibGVzIHggYW5kIHkKc2NhdHRlcnBsb3RNYXRyaXgoZGF0YSkKYGBgCgojIFR5cGVzIG9mIERhdGEgJiBEYXRhIFN0cnVjdHVyZQoKCgojIyBBdG9taWMgKERhdGEpIFR5cGVzCgoKClRoZXJlIGFyZSA2IGF0b21pYyB0eXBlcyBvZiBkYXRhIGluIFIsIGJ1dCwgZm9yIG5vdyB5b3Ugb25seSBuZWVkIHRvIGtub3cgKGFuZCB1c2UpIDQgb2YgdGhlbToKCiMjIyBMb2dpY2FsIChUUlVFL0ZBTFNFKQoKCgoKCmBgYHtyIGxvZ2ljYWx9CjEgPiAyCjIgPiAxCmBgYAoKCiMjIyBJbnRlZ2VyCgoKCgoKZS5nLiwgMSwgOTYsIE5BLCA3ODkxMAoKCiMjIyBOdW1lcmljCgoKCgoKCmUuZy4sICAyLCA0LjY3LCBwaQoKCgojIyMgQ2hhcmFjdGVyIAoKCgoKCmUuZy4sIOKAnGhlbGxv4oCdLCAiMzQiCgoKYGBge3IgY2hhcmFjdGVyfQoiSSBsaWtlIGEgbG90IHB1bHAgaW4gbXkgb3JnYW5nZSBqdWljZSIKYGBgCgoKIyMgRGF0YSBTdHJ1Y3R1cmVzCgoKCkRhdGEgc3RydWN0dXJlcyBhcmUgd2F5cyB3aGljaCBSIHN0b3JlcyBkYXRhLiBKdXN0IGxpa2UgdGhlIG5hbWUgaW1wbGllcywgYSBkYXRhIHN0cnVjdHVyZSB0ZWxscyB1cyBleGFjdGx5IGhvdyBvdXIgZGF0YSBpcyBzdHJ1Y3R1cmVkIG9yIG9yZ2FuaXplZCB3aXRoaW4gUi4gUiwgbGlrZSBtb3N0IHByb2dyYW1taW5nIGxhbmd1YWdlcywgdXNlcyBhIHZhcmlldHkgb2YgZGF0YSBzdHJ1Y3R1cmVzLiBUaGUgbW9zdCBjb21tb24gb2Ygd2hpY2ggYXJlOgoKIyMjIFZlY3RvcnMKCgoKCkEgc2VyaWVzIG9mIGRhdGEgd2hpY2ggbXVzdCBoYXZlIHRoZSBzYW1lIGRhdGEgdHlwZS4KVmVjdG9ycyBjYW4gYmUgYW55IG9mIHRoZSBiYXNpYyBkYXRhIHR5cGVzLCBlLmcuLCBsb2dpY2FsLCBpbnRlZ2VyLCBudW1lcmljLCBjaGFyYWN0ZXIKCgpgYGB7ciB2ZWN0b3JzfQp2ZWN0b3JfZXhhbXBsZTEgPC0gMTo1CnZlY3Rvcl9leGFtcGxlMiA8LSBjKDEsMiwzLDQsNSkgIyBjIGZ1bmN0aW9uIGlzIG1lYW50IHRvICoqY29tYmluZSoqIHZhbHVlcyB0byBmb3JtIGEgdmVjdG9yCnZlY3Rvcl9leGFtcGxlMyA8LSBjKFQsIEYsIFQsIEYsIFQpICMgVCBhbmQgRiBpcyB0aGUgc2FtZSBhcyBUUlVFIGFuZCBGQUxTRQp2ZWN0b3JfZXhhbXBsZTQgPC0gYygiTXkiLCAibW9tIiwgImlzIiwgImEiLCAidGVhY2hlciIpCmBgYAoKCiMjIyBNYXRyaWNlcwoKCgoKCgpNdXN0IGJlIDIgZGltZW5zaW9uYWwuIE11c3QgYmUgb2YgdGhlIHNhbWUgZGF0YSB0eXBlLgpgYGB7ciBtYXRyaWNlc30KKG1hdHJpeF9leGFtcGxlIDwtIG1hdHJpeCgxOjEwLCAxOjEwKSkKYGBgCgoKCiMjIyBBcnJheXMKCgoKU2ltaWxhciB0byBtYXRyaWNlcywgYnV0IHRoZXkgY2FuIGJlIG1vcmUgdGhhbiAyIGRpbWVuc2lvbnMKYGBge3IgYXJyYXlzfQooYXJyYXlfZXhhcGxlIDwtIGFycmF5KGRpbSA9IGMoMyw0LDUpKSkKYGBgCgojIyMgTGlzdHMKCgoKQSBsaXN0IGNhbiBoYXZlIG1peGVkIGRhdGEgdHlwZXMsIGJ1dCB0aGV5IGNhbiBiZSBhIGJpdCB0cmlja2llciB0byB1c2UuCmBgYHtyIGxpc3R9Cmxpc3RfZXhhbXBsZSA8LSBsaXN0KCJjYXQiLCAzLCBUUlVFKQpgYGAKCiMjIyBEYXRhIGZyYW1lcwoKCgpVc2VkIGZvciB0YWJ1bGFyIGRhdGEsIHRoaW5rIG9mIHRoZW0gYXMgYSBiYXNpYyBzcHJlYWRzaGVldCwgYnV0IGVhY2ggY29sdW1uIGlzIGEgdmVjdG9yLgpgYGB7ciBkYXRhZnJhbWV9CihkYXRhZnJhbWVfZXhhbXBsZSA8LSBkYXRhLmZyYW1lKHg9MToxMCwgeT0xMToyMCkpCihkYXRhZnJhbWVfZXhhbXBsZTIgPC0gZGF0YS5mcmFtZShleWVjb2xvdXI9IGMoImJsdWUiLCAiYnJvd24iLCAiZ3JleSIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdodCA9IGMoMS43NSwgMi4xLCAxLjU2KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVnaXN0ZXJlZCA9IGMoVCxGLCBUKSkpCmBgYAojIyMgVGliYmxlcwoKCgpTaW1pbGFyIHRvIGRhdGEgZnJhbWVzIHdpdGggYSBmZXcgZGlmZmVyZW5jZXMuIFRpYmJsZXMgYXJlIHRoZSBzdGFuZGFyZCBkYXRhIHN0cnVjdHVyZXMgd2l0aGluIHRoZSBgdGlkeXZlcnNlYC4KYGBge3IgdGliYmxlc30KKHRpYmJsZV9leGFtcGxlIDwtIHRpYmJsZSh4PWxldHRlcnMsIHk9MTpsZW5ndGgobGV0dGVycykpKQpgYGAKCklmIHlvdSBhcmUgbm90IHN1cmUgd2hhdCB0eXBlIG9mIGRhdGEgb3IgZGF0YSBzdHJ1Y3R1cmUgYW4gb2JqZWN0IChvciB2YWx1ZSkgaXMsIHlvdSBjYW4gY2hlY2sgdXNpbmc6CmBgYHtyIGRhdGFmcmFtZSBjaGVja30KY2xhc3MoZGF0YWZyYW1lX2V4YW1wbGUpCmNsYXNzKDEuMzQpCmNsYXNzKFRSVUUpCmNsYXNzKGxpc3RfZXhhbXBsZSkKY2xhc3MoZGF0YWZyYW1lX2V4YW1wbGVbMSwyXSkgIyBkYXRhZnJhbWVfZXhhbXBsZVsxLDJdIG1lYW5zIHRoZSB2YWx1ZSBpbiB0aGUgMXN0IHJvdywgMm5kIGNvbHVtbgojIEl0IGlzIGFsd2F5czogW1Jvd3MsIENvbHVtbnNdCgpkYXRhZnJhbWVfZXhhbXBsZQpkYXRhZnJhbWVfZXhhbXBsZVsxLDJdCgpgYGAKCiMgSW1wb3J0aW5nIERhdGEKCgpSIGlzIHZlcnkgZmxleGlibGUgYW5kIGNhbiBpbXBvcnQgbWFueSBkYXRhIGZvcm1hdHMuIFJTdHVkaW8gd2lsbCBoZWxwIHlvdSB3aXRoIHRoYXQsIHVzaW5nIG5lY2Vzc2FyeSBwYWNrYWdlcy4gSW4gdGhpcyB3b3Jrc2hvcCBJIHdpbGwgc2hvdyB5b3UgaG93IHRvIGRvIGl0IHRocm91Z2ggUlN0dWRpbyBhbmQgYWxzbyB0aHJvdWdoIFIgc2NyaXB0LiBPbmUgdGhpbmcgdG8gbm90aWNlIGlzIHRoYXQgaWYgeW91IGhhdmUgYSBSU3R1ZGlvIHByb2plY3QgaW4gdGhlIHNhbWUgZm9sZGVyIHdoZXJlIHlvdXIgZGF0YSBzZXRzIGFyZSwgeW91IGRvbid0IG5lZWQgdG8gc3BlY2lmeSBwYXRoIGFkZHJlc3NlcyB0byBpbXBvcnQgeW91ciBkYXRhLiBSIHdpbGwgYnkgZGVmYXVsdCBpbXBvcnQgYW5kIHNhdmUgYW55dGhpbmcgb24gdGhhdCBmb2xkZXIuCgoKIyMjIFIgYWxsb3dzIHlvdSB0byByZWFkIGluIGRhdGEgZnJvbSBtYW55IGRpZmZlcmVudCBmb3JtYXRzOgoKCiAqIFNQU1MKICogRXhjZWwKICogU0FTCiAqIC5jc3YKICogLnR4dAogKiAuZGF0CgpUaGUgZWFzaWVzdCB3YXkgdG8gZ2V0IHN0YXJ0ZWQgd2l0aCByZWFkaW5nIGRhdGEgaW50byBSIGlzIGdvIHRvIHRoZSBlbnZpcm9ubWVudCB0YWIgYW5kIGNsaWNrIG9uIHRoZSBpbXBvcnQgZGF0YXNldCBidXR0b24gYW5kIHRoZW4gcmVhZCBpbiB0aGUgZGF0YSBhY2NvcmRpbmdseSAobm90ZSB0aGF0IGNzdiBmaWxlcyBhcmUgYSB0eXBlIG9mIHRleHQgZmlsZSkuIAoKCkxldCdzIHN0YXJ0IGJ5IGltcG9ydGluZyBhbiBTUFNTIGRhdGFzZXQgKC5zYXYpIHVzaW5nIHRoZSBgcmVhZF9zYXYoKWAgZnVuY3Rpb24gaW4gdGhlIGBoYXZlbmAgcGFja2FnZToKCiMjIyBJbnN0YWxsIHRoZSBgaGF2ZW5gIHBhY2thZ2UKYGBge3IgaGF2ZW4sIGV2YWw9RkFMU0V9Cmluc3RhbGwucGFja2FnZXMoImhhdmVuIikKYGBgCiMjIyBMb2FkIHRoZSBgaGF2ZW5gIHBhY2thZ2UKYGBge3IgbG9hZCBoYXZlbn0KbGlicmFyeShoYXZlbikKYGBgCgojIyMgVXNlIGByZWFkX3NhdigpYAoKWW91IHdhbnQgdG8gbWFrZSBzdXJlIHRoZSBmaWxlIGlzIHNhdmVkIGluIHRoZSBzYW1lIHdvcmtzcGFjZSBhcyB5b3VyIFIgU2NyaXB0LCBvciBzZXQgdGhlIHBhdGggdG8gd2hlcmUgdGhlIGRhdGEgaXMuIEFuZCwgZG9uJ3QgZm9yZ2V0IHRvIHN0b3JlIHRoZSBkYXRhIGluIGFuIG9iamVjdCEKYGBge3IgaW1wb3J0aW5nIGRhdGF9CmFnZ3Jlc3Npb25fZGF0YSA8LSByZWFkX3NhdigiYWdncmVzc2lvbi5zYXYiKQoKY2xhc3MoYWdncmVzc2lvbl9kYXRhKSAjIHdoYXQgZGF0YSBzdHJ1Y3R1cmUgaXMgdGhlIGRhdGFzZXQgCnN0cihhZ2dyZXNzaW9uX2RhdGEpICMgc3RydWN0dXJlLCB2YXJpYWJsZXMgYW5kIHRoZWlyIGRhdGEgdHlwZSBhbmQgc3RydWN0dXJlCmhlYWQoYWdncmVzc2lvbl9kYXRhKSAjIGluc3BlY3QgdGhlIHRvcCA2IChoZWFkKSBvZiB0aGUgZGF0YQpuYW1lcyhhZ2dyZXNzaW9uX2RhdGEpICMgdmFyaWFibGUvY29sdW1uIG5hbWVzCmBgYAoKCiMjIyBmaW5kaW5nIHRoZSB2YWx1ZSBsb2NhdGVkIGluIHRoZSAybmQgcm93LCAzcmQgY29sdW1uCmBgYHtyIH0KYWdncmVzc2lvbl9kYXRhWzIsM10KYGBgCiMjIyBsb29raW5nIG9ubHkgYXQgdGhlIGBhZ2VgIHZhcmlhYmxlL2NvbHVtbgpgYGB7ciB9CmFnZ3Jlc3Npb25fZGF0YSRhZ2UKYGBgCgojIyMgZmluZGluZyB0aGUgYGFnZWAgb2YgdGhlIDNyZCBwYXJ0aWNpcGFudApgYGB7ciB9CmFnZ3Jlc3Npb25fZGF0YSRhZ2VbM10KYGBgCgojIyMgZmluZGluZyB0aGUgbWVhbiBgYWdlYCBvZiBhbGwgcGFydGljaXBhbnRzCmBgYHtyIH0KbWVhbihhZ2dyZXNzaW9uX2RhdGEkYWdlKQpgYGAKCiMjIyBmaW5kaW5nIHRoZSBzdGFuZGFyZCBkZXZpYXRpb24gb2YgYGFnZWAKYGBge3IgfQpzZChhZ2dyZXNzaW9uX2RhdGEkYWdlKQpgYGAKCiMjIyBmaW5kaW5nIHRoZSBtZWRpYW4gb2YgYGFnZWAKYGBge3IgfQptZWRpYW4oYWdncmVzc2lvbl9kYXRhJGFnZSkKYGBgCgoKIyMjIGZpbmQgaG93IG1hbnkgdmFsdWVzIGluIGBhZ2VgCmBgYHtyIH0KbGVuZ3RoKGFnZ3Jlc3Npb25fZGF0YSRhZ2UpCm5yb3coYWdncmVzc2lvbl9kYXRhKQpgYGAKCgojIyMgcGxvdHRpbmcgYGFnZWAgdnMuIGBhbGNvaG9sYAoKYGBge3IgfQpwbG90KGFnZ3Jlc3Npb25fZGF0YSRhZ2UsIGFnZ3Jlc3Npb25fZGF0YSRhbGNvaG9sKQpgYGAKCiMjIENPTkdSQVRVTEFUSU9OUyEgWW91IGFyZSBub3cgb2ZmaWNpYWxseSBhbiBSIHVzZXIhIE5leHQgd2Vlaywgd2Ugd2lsbCBsZWFybiBtb3JlIGFib3V0IGRhdGEgZXhwbG9yYXRpb24gYW5kIG1hbmlwdWxhdGlvbiEK