Working directory

Before starting, you have to create a directory where you put all the files of the tutorial. The command

getwd()

indicates the directory where R works. The command setwd allows to change this directory. You can also use the menu Session -> Set Working directory -> Choose directory…

Creating objects

Numeric

An object can be created by being assigned to one of the three operators <-, ->, = and by naming

b<-41.3  # set up object b consisting of one number: 41.3 
x<-b     # b is assigned to x
x=b      # b is assigned to x
b->x     # b is assigned to x
is.numeric(b)
mode(b)

Character

x <- "La mort"
y <- "aux trousses"
paste(x,y)
is.character(x)

Logical (Boolean)

x <- TRUE
is.logical(x)
mode(x)
a <- 1
a==1
a!=1
a<0
a>0

Vector

There are different ways to define a vector:

  • collect function c
x <- c(1.2,5,9,11)
x
  • sequence operator :
1:5
  • sequence function seq
seq(1,10,by=2)
seq(0,1,length=10)
  • The rep function
rep(1,4)
rep(c(1,3),each=3)

We can also create character or logical vectors

x <- c("A","B","C")
x <- rep("A",5)
paste("X",1:5,sep="-")
substr("statistician",5,9)

Selecting part of a vector

Selections are made using the selection operator [ ]

x <- c(-4,-3,1,3,5,8,0)
x[2]
x[c(2,5)]
x>0
x[x>0]

Operations

Explain the following commands

x <- seq(-10,10,by=2)
y <- 1:length(x)
x+y
x*y
z <- x>0
x*z

Factors

Factors are particular vectors very useful when we deal with categorical variables.

V1 <- factor(c("less20years","more50years","less20years","more50years","less20years"))
V1
levels(V1)
levels(V1) <- c("Young","Old")
V1

Exercise 1

  1. Compute the mean, the sum, the median and the variance of the vector (1,3,8,9,11)

  2. Create the following vectors using the rep function:

vec1 = 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5

vec2 = 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5

vec3 = 1 1 2 2 2 3 3 3 3 4 4 4 4 4

  1. Create the following vector using the paste function:

vec4 = “A0)” “A1)” “A2)” “A3)” “A4)” “A5)” “A6)” “A7)” “A8)” “A9)” “A10)”

  1. letters is a vector containing the 26 letters of the alphabet. Find the index of the letter \(q\) and create the vector containing “a1”,“b2”,\(\dots\) until \(q\) with the index of \(q\).

Matrix

The matrix function allows to define matrices

m <- matrix(1:4,ncol=2)
m
m <- matrix(1:4,nrow=2)
m
m <- matrix(1:4,nrow=2,byrow=TRUE)
dim(m)

The position of an element within a matrix is indicated by its row and column number. Thus, to select the term in the second row and the first column, we execute

m[2,1]

We can also extract rows or columns of matrices:

m[1,] #first row
m[,2] #second column

It is easy to make classical operations on matrices

det(m) #determinant
solve(m) #inverse
t(m) #transpose
n <- matrix(5:8,nrow=2)
m+n
m*n #be carefull: Hadamart product
m%*%n #matrix product
eigen(m) #eigen decomposition

Lists

A list is a heterogeneous object. It is a set of ranked objects which do not always have the same mode or length. The objects are referred to as components of the list. For instance, we can put a vector and a matrix in a list with

mylist <- list(vector=rep(1:5),mat=matrix(1:8,nrow=2))
mylist
length(mylist)

To extract a component from the list, we can simply indicate the position of the element that we want to extract. [[ ]] are used to identify the element in the list:

mylist[[1]]

We can also use the name of the element, if it has one, which can be written in two ways:

mylist$mat
mylist[["mat"]]

Dataframe

Dataframes are special lists with components of the same length but with potentially different modes. The data tables generally used in statistics are often referred to as dataframe. Indeed, a data table is made up of quantitative and/or qualitative variables taken from the same individuals.

name <- c("Paul","Mary","Steven","Charlotte","Peter")
sex <- factor(c("M","F","M","F","M"))
size <- c(180,165,168,170,175)
data <- data.frame(name,sex,size)
summary(data)

Observe that name is character vector, sex a factor and size a numeric vector.

Extraction is similar to matrix and list

data[2,3]
data[,2]
data$sex

Some basic (and important) functions

summary(data)
summary(1:10)
x <- c(1,8,5,4)
sort(x)
order(x)
V1 <- 1:10
V2 <- seq(-20,25,length=10)
df <- data.frame(V1,V2)
apply(df,1,mean)
apply(df,2,sum)

Exercise 2

  1. Create the following matrix mat (with the column and row names, you can use rownames and colnames functions):
column 1 column 2 column 3 column 4
row-1 1 5 5 0
row-2 0 5 6 1
row-3 3 0 3 3
row-4 4 4 4 2
  1. Create a vector containing the diagonal elements of the matrix mat.

  2. Create a matrix containing the first 2 rows of mat.

  3. Create a matrix containing the last 2 columns of mat.

  4. Calculate the determinant and then invert the matrix using the appropriate functions.

Exercise 3

We consider the iris dataset available in R (use data(iris) to load it and then head(iris) to visualise the first rows).

data(iris)
head(iris)
  1. Compute the mean and the variance for the variables Sepal.Width and Petal.Length :

  2. Create a sub-dataset comprising only the data for the category versicolor of the variable species (call this new dataset iris2).

  3. Sort the data in iris2 in descending order according to the variable Sepal.Length (you can use the order function).

  4. Compute the mean of Sepal.Length for each species.

  5. Add a variable (called sum.Petal) in the dataframe iris which corresponds to the sum of Petal.Length and Petal.Width.

Exercise 4

  1. Calculate the benchmark statistics (mean, min, max, etc.) for the three variables of the ethanol dataset (available in the lattice package).

  2. Calculate the quartiles for each of the three variables. To do this, use the apply function with the quantile function.

  3. Again with the apply function, calculate all the deciles for each of the three variables using the argument probs of the quantile function.

Exercise 5

We consider the predidents dataset.

data("presidents")
df <- matrix(presidents,ncol=4,byrow=T)
  1. Is there at least one missing value in the 20th line of the dataset (you can use the any function).

  2. Which lines in the table contain at least one missing data? You can use which.

  3. Delete the rows of the table that contain at least one missing data.

LS0tCnRpdGxlOiAnVHV0byAyOiBSIG9iamVjdHMnCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIFdvcmtpbmcgZGlyZWN0b3J5CgpCZWZvcmUgc3RhcnRpbmcsIHlvdSBoYXZlIHRvIGNyZWF0ZSBhIGRpcmVjdG9yeSB3aGVyZSB5b3UgcHV0IGFsbCB0aGUgZmlsZXMgb2YgdGhlIHR1dG9yaWFsLiBUaGUgY29tbWFuZAoKYGBge3J9CmdldHdkKCkKYGBgCmluZGljYXRlcyB0aGUgZGlyZWN0b3J5IHdoZXJlICoqUioqIHdvcmtzLiBUaGUgY29tbWFuZCAqKnNldHdkKiogYWxsb3dzIHRvIGNoYW5nZSB0aGlzIGRpcmVjdG9yeS4gWW91IGNhbiBhbHNvIHVzZSB0aGUgbWVudSAqKlNlc3Npb24gLT4gU2V0IFdvcmtpbmcgZGlyZWN0b3J5IC0+IENob29zZSBkaXJlY3RvcnkuLi4qKgoKIyMgQ3JlYXRpbmcgb2JqZWN0cwoKIyMjIE51bWVyaWMKQW4gb2JqZWN0IGNhbiBiZSBjcmVhdGVkIGJ5IGJlaW5nIGFzc2lnbmVkIHRvIG9uZSBvZiB0aGUgdGhyZWUgb3BlcmF0b3JzICoqPC0qKiwgKiotPioqLCAqKj0qKiBhbmQgYnkgbmFtaW5nIAoKYGBge3J9CmI8LTQxLjMgICMgc2V0IHVwIG9iamVjdCBiIGNvbnNpc3Rpbmcgb2Ygb25lIG51bWJlcjogNDEuMyAKeDwtYiAgICAgIyBiIGlzIGFzc2lnbmVkIHRvIHgKeD1iICAgICAgIyBiIGlzIGFzc2lnbmVkIHRvIHgKYi0+eCAgICAgIyBiIGlzIGFzc2lnbmVkIHRvIHgKaXMubnVtZXJpYyhiKQptb2RlKGIpCmBgYAoKIyMjIENoYXJhY3RlcgoKYGBge3J9CnggPC0gIkxhIG1vcnQiCnkgPC0gImF1eCB0cm91c3NlcyIKcGFzdGUoeCx5KQppcy5jaGFyYWN0ZXIoeCkKYGBgCgojIyMgTG9naWNhbCAoQm9vbGVhbikKCmBgYHtyfQp4IDwtIFRSVUUKaXMubG9naWNhbCh4KQptb2RlKHgpCmEgPC0gMQphPT0xCmEhPTEKYTwwCmE+MApgYGAKCiMjIyBWZWN0b3IKClRoZXJlIGFyZSBkaWZmZXJlbnQgd2F5cyB0byBkZWZpbmUgYSB2ZWN0b3I6CgoqIGNvbGxlY3QgZnVuY3Rpb24gKipjKioKYGBge3J9CnggPC0gYygxLjIsNSw5LDExKQp4CmBgYAoKKiBzZXF1ZW5jZSBvcGVyYXRvciAqKjoqKgoKYGBge3J9CjE6NQpgYGAKCiogIHNlcXVlbmNlIGZ1bmN0aW9uICoqc2VxKioKCmBgYHtyfQpzZXEoMSwxMCxieT0yKQpzZXEoMCwxLGxlbmd0aD0xMCkKYGBgCgoqIFRoZSAqKnJlcCoqIGZ1bmN0aW9uCgpgYGB7cn0KcmVwKDEsNCkKcmVwKGMoMSwzKSxlYWNoPTMpCmBgYAoKV2UgY2FuIGFsc28gY3JlYXRlICpjaGFyYWN0ZXIqIG9yICpsb2dpY2FsKiB2ZWN0b3JzCgpgYGB7cn0KeCA8LSBjKCJBIiwiQiIsIkMiKQp4IDwtIHJlcCgiQSIsNSkKcGFzdGUoIlgiLDE6NSxzZXA9Ii0iKQpzdWJzdHIoInN0YXRpc3RpY2lhbiIsNSw5KQpgYGAKCgojIyMgU2VsZWN0aW5nIHBhcnQgb2YgYSB2ZWN0b3IKClNlbGVjdGlvbnMgYXJlIG1hZGUgdXNpbmcgdGhlIHNlbGVjdGlvbiBvcGVyYXRvciAqKlsgXSoqCgpgYGB7cn0KeCA8LSBjKC00LC0zLDEsMyw1LDgsMCkKeFsyXQp4W2MoMiw1KV0KeD4wCnhbeD4wXQpgYGAKCgojIyMgT3BlcmF0aW9ucwoKRXhwbGFpbiB0aGUgZm9sbG93aW5nIGNvbW1hbmRzCmBgYHtyfQp4IDwtIHNlcSgtMTAsMTAsYnk9MikKeSA8LSAxOmxlbmd0aCh4KQp4K3kKeCp5CnogPC0geD4wCngqegpgYGAKCiMjIEZhY3RvcnMKCkZhY3RvcnMgYXJlIHBhcnRpY3VsYXIgdmVjdG9ycyB2ZXJ5IHVzZWZ1bCB3aGVuIHdlIGRlYWwgd2l0aCBjYXRlZ29yaWNhbCB2YXJpYWJsZXMuCgpgYGB7cn0KVjEgPC0gZmFjdG9yKGMoImxlc3MyMHllYXJzIiwibW9yZTUweWVhcnMiLCJsZXNzMjB5ZWFycyIsIm1vcmU1MHllYXJzIiwibGVzczIweWVhcnMiKSkKVjEKbGV2ZWxzKFYxKQpsZXZlbHMoVjEpIDwtIGMoIllvdW5nIiwiT2xkIikKVjEKYGBgCgoKIyMjIEV4ZXJjaXNlIDEKCjEuIENvbXB1dGUgdGhlIG1lYW4sIHRoZSBzdW0sIHRoZSBtZWRpYW4gYW5kIHRoZSB2YXJpYW5jZSBvZiB0aGUgdmVjdG9yICgxLDMsOCw5LDExKQoKCjIuIENyZWF0ZSB0aGUgZm9sbG93aW5nIHZlY3RvcnMgdXNpbmcgdGhlICoqcmVwKiogZnVuY3Rpb246Cgp2ZWMxID0gMSAyIDMgNCA1IDEgMiAzIDQgNSAxIDIgMyA0IDUgCgp2ZWMyID0gMSAxIDEgMiAyIDIgMyAzIDMgNCA0IDQgNSA1IDUKCnZlYzMgPSAxIDEgMiAyIDIgMyAzIDMgMyA0IDQgNCA0IDQKCgozLiBDcmVhdGUgdGhlIGZvbGxvd2luZyB2ZWN0b3IgdXNpbmcgdGhlICoqcGFzdGUqKiBmdW5jdGlvbjoKCnZlYzQgPSAiQTApIiAiQTEpIiAiQTIpIiAiQTMpIiAiQTQpIiAiQTUpIiAiQTYpIiAiQTcpIiAiQTgpIiAiQTkpIiAiQTEwKSIKCgo0LiAqKmxldHRlcnMqKiBpcyBhIHZlY3RvciBjb250YWluaW5nIHRoZSAyNiBsZXR0ZXJzIG9mIHRoZSBhbHBoYWJldC4gRmluZCB0aGUgaW5kZXggb2YgdGhlIGxldHRlciAkcSQgYW5kIGNyZWF0ZSB0aGUgdmVjdG9yIGNvbnRhaW5pbmcgImExIiwiYjIiLCRcZG90cyQgdW50aWwgJHEkIHdpdGggdGhlIGluZGV4IG9mICRxJC4KCgoKCiMjIE1hdHJpeAoKVGhlICoqbWF0cml4KiogZnVuY3Rpb24gYWxsb3dzIHRvIGRlZmluZSBtYXRyaWNlcwpgYGB7cn0KbSA8LSBtYXRyaXgoMTo0LG5jb2w9MikKbQptIDwtIG1hdHJpeCgxOjQsbnJvdz0yKQptCm0gPC0gbWF0cml4KDE6NCxucm93PTIsYnlyb3c9VFJVRSkKZGltKG0pCmBgYAoKVGhlIHBvc2l0aW9uIG9mIGFuIGVsZW1lbnQgd2l0aGluIGEgbWF0cml4IGlzIGluZGljYXRlZCBieSBpdHMgcm93IGFuZCBjb2x1bW4gbnVtYmVyLiBUaHVzLCB0byBzZWxlY3QgdGhlIHRlcm0gaW4gdGhlIHNlY29uZCByb3cgYW5kIHRoZSBmaXJzdCBjb2x1bW4sIHdlIGV4ZWN1dGUKYGBge3J9Cm1bMiwxXQpgYGAKCldlIGNhbiBhbHNvIGV4dHJhY3Qgcm93cyBvciBjb2x1bW5zIG9mIG1hdHJpY2VzOgpgYGB7cn0KbVsxLF0gI2ZpcnN0IHJvdwptWywyXSAjc2Vjb25kIGNvbHVtbgpgYGAKCkl0IGlzIGVhc3kgdG8gbWFrZSBjbGFzc2ljYWwgb3BlcmF0aW9ucyBvbiBtYXRyaWNlcwoKYGBge3J9CmRldChtKSAjZGV0ZXJtaW5hbnQKc29sdmUobSkgI2ludmVyc2UKdChtKSAjdHJhbnNwb3NlCm4gPC0gbWF0cml4KDU6OCxucm93PTIpCm0rbgptKm4gI2JlIGNhcmVmdWxsOiBIYWRhbWFydCBwcm9kdWN0Cm0lKiVuICNtYXRyaXggcHJvZHVjdAplaWdlbihtKSAjZWlnZW4gZGVjb21wb3NpdGlvbgpgYGAKCiMjIExpc3RzCgpBIGxpc3QgaXMgYSBoZXRlcm9nZW5lb3VzIG9iamVjdC4gIEl0IGlzIGEgc2V0IG9mIHJhbmtlZCBvYmplY3RzIHdoaWNoIGRvIG5vdCBhbHdheXMgaGF2ZSB0aGUgc2FtZSBtb2RlIG9yIGxlbmd0aC4gVGhlIG9iamVjdHMgYXJlIHJlZmVycmVkIHRvIGFzIGNvbXBvbmVudHMgb2YgdGhlIGxpc3QuIEZvciBpbnN0YW5jZSwgd2UgY2FuIHB1dCBhIHZlY3RvciBhbmQgYSBtYXRyaXggaW4gYSBsaXN0IHdpdGgKCmBgYHtyfQpteWxpc3QgPC0gbGlzdCh2ZWN0b3I9cmVwKDE6NSksbWF0PW1hdHJpeCgxOjgsbnJvdz0yKSkKbXlsaXN0Cmxlbmd0aChteWxpc3QpCmBgYApUbyBleHRyYWN0IGEgY29tcG9uZW50IGZyb20gdGhlIGxpc3QsIHdlIGNhbiBzaW1wbHkgaW5kaWNhdGUgdGhlIHBvc2l0aW9uIG9mIHRoZSBlbGVtZW50IHRoYXQgd2Ugd2FudCB0byBleHRyYWN0LiAqKltbICBdXSoqIGFyZSB1c2VkIHRvIGlkZW50aWZ5IHRoZSBlbGVtZW50IGluIHRoZSBsaXN0OgoKYGBge3J9Cm15bGlzdFtbMV1dCmBgYAoKV2UgY2FuIGFsc28gdXNlIHRoZSBuYW1lIG9mIHRoZSBlbGVtZW50LCBpZiBpdCBoYXMgb25lLCB3aGljaCBjYW4gYmUgd3JpdHRlbiBpbiB0d28gd2F5czoKYGBge3J9Cm15bGlzdCRtYXQKbXlsaXN0W1sibWF0Il1dCmBgYAoKCiMjIERhdGFmcmFtZQoKRGF0YWZyYW1lcyBhcmUgc3BlY2lhbCBsaXN0cyB3aXRoIGNvbXBvbmVudHMgb2YgdGhlIHNhbWUgbGVuZ3RoIGJ1dCB3aXRoIHBvdGVudGlhbGx5IGRpZmZlcmVudCBtb2Rlcy4gVGhlIGRhdGEgdGFibGVzIGdlbmVyYWxseSB1c2VkIGluIHN0YXRpc3RpY3MgYXJlIG9mdGVuIHJlZmVycmVkIHRvIGFzIGRhdGFmcmFtZS4gSW5kZWVkLCBhIGRhdGEgdGFibGUgaXMgbWFkZSB1cCBvZiBxdWFudGl0YXRpdmUgYW5kL29yIHF1YWxpdGF0aXZlIHZhcmlhYmxlcyB0YWtlbiBmcm9tIHRoZSBzYW1lIGluZGl2aWR1YWxzLgoKYGBge3J9Cm5hbWUgPC0gYygiUGF1bCIsIk1hcnkiLCJTdGV2ZW4iLCJDaGFybG90dGUiLCJQZXRlciIpCnNleCA8LSBmYWN0b3IoYygiTSIsIkYiLCJNIiwiRiIsIk0iKSkKc2l6ZSA8LSBjKDE4MCwxNjUsMTY4LDE3MCwxNzUpCmRhdGEgPC0gZGF0YS5mcmFtZShuYW1lLHNleCxzaXplKQpzdW1tYXJ5KGRhdGEpCmBgYAoKT2JzZXJ2ZSB0aGF0ICpuYW1lKiBpcyBjaGFyYWN0ZXIgdmVjdG9yLCAqc2V4KiBhIGZhY3RvciBhbmQgKnNpemUqIGEgbnVtZXJpYyB2ZWN0b3IuCgpFeHRyYWN0aW9uIGlzIHNpbWlsYXIgdG8gbWF0cml4IGFuZCBsaXN0CgpgYGB7cn0KZGF0YVsyLDNdCmRhdGFbLDJdCmRhdGEkc2V4CmBgYAoKCiMjIFNvbWUgYmFzaWMgKGFuZCBpbXBvcnRhbnQpIGZ1bmN0aW9ucwoKKiAqKnN1bW1hcnkqKiBwcm9kdWNlcyByZXN1bHQgc3VtbWFyaWVzIG9mIGFuIG9iamVjdAoKYGBge3J9CnN1bW1hcnkoZGF0YSkKc3VtbWFyeSgxOjEwKQpgYGAKCiogbWVhbiwgc3VtLCBtZWRpYW4sIHZhciwgbWluLCBtYXguLi4gKGVhc3kgdG8gdW5kZXJzdGFuZCkKCiogKnNvcnQqLCAqb3JkZXIqCgpgYGB7cn0KeCA8LSBjKDEsOCw1LDQpCnNvcnQoeCkKb3JkZXIoeCkKYGBgCgoqICoqYXBwbHkqKiBhcHBseSBhIGZ1bmN0aW9uICoqZioqIHRvIHRoZSByb3dzIG9yIGNvbHVtbnMgb2YgYSBtYXRyaXggb3IgYSBkYXRhZnJhbWUKCmBgYHtyfQpWMSA8LSAxOjEwClYyIDwtIHNlcSgtMjAsMjUsbGVuZ3RoPTEwKQpkZiA8LSBkYXRhLmZyYW1lKFYxLFYyKQphcHBseShkZiwxLG1lYW4pCmFwcGx5KGRmLDIsc3VtKQpgYGAKCiMjIyBFeGVyY2lzZSAyCgoxLiBDcmVhdGUgdGhlIGZvbGxvd2luZyBtYXRyaXggKm1hdCogKHdpdGggdGhlIGNvbHVtbiBhbmQgcm93IG5hbWVzLCB5b3UgY2FuIHVzZSAqKnJvd25hbWVzKiogYW5kICoqY29sbmFtZXMqKiBmdW5jdGlvbnMpOgoKfCAgICAgIHxjb2x1bW4gMSB8IGNvbHVtbiAyIHxjb2x1bW4gMyB8IGNvbHVtbiA0IHwKfDotLS0tOnw6LS0tLS0tLTp8Oi0tLS0tLS0tOnw6LS0tLS0tLTp8Oi0tLS0tLS0tOnwKfHJvdy0xIHwgICAgMSAgICB8ICAgICA1ICAgIHwgICAgNSAgICB8ICAgIDAgICAgIHwKfHJvdy0yIHwgICAgMCAgICB8ICAgICA1ICAgIHwgICAgNiAgICB8ICAgIDEgICAgIHwKfHJvdy0zIHwgICAgMyAgICB8ICAgICAwICAgIHwgICAgMyAgICB8ICAgIDMgICAgIHwKfHJvdy00IHwgICAgNCAgICB8ICAgICA0ICAgIHwgICAgNCAgICB8ICAgIDIgICAgIHwKCgoyLiBDcmVhdGUgYSB2ZWN0b3IgY29udGFpbmluZyB0aGUgZGlhZ29uYWwgZWxlbWVudHMgb2YgdGhlIG1hdHJpeCAqKm1hdCoqLgoKMy4gQ3JlYXRlIGEgbWF0cml4IGNvbnRhaW5pbmcgdGhlIGZpcnN0IDIgcm93cyBvZiAqKm1hdCoqLgoKNC4gQ3JlYXRlIGEgbWF0cml4IGNvbnRhaW5pbmcgdGhlIGxhc3QgMiBjb2x1bW5zIG9mICoqbWF0KiouCgo1LiBDYWxjdWxhdGUgdGhlIGRldGVybWluYW50IGFuZCB0aGVuIGludmVydCB0aGUgbWF0cml4IHVzaW5nIHRoZSBhcHByb3ByaWF0ZSBmdW5jdGlvbnMuCgojIyMgRXhlcmNpc2UgMwoKV2UgY29uc2lkZXIgdGhlICoqaXJpcyoqIGRhdGFzZXQgYXZhaWxhYmxlIGluICoqUioqICh1c2UgKipkYXRhKGlyaXMpKiogdG8gbG9hZCBpdCBhbmQgdGhlbiAqKmhlYWQoaXJpcykqKiB0byB2aXN1YWxpc2UgdGhlIGZpcnN0IHJvd3MpLgoKYGBge3J9CmRhdGEoaXJpcykKaGVhZChpcmlzKQpgYGAKCgoxLiBDb21wdXRlIHRoZSBtZWFuIGFuZCB0aGUgdmFyaWFuY2UgZm9yIHRoZSB2YXJpYWJsZXMgKipTZXBhbC5XaWR0aCoqIGFuZCAqKlBldGFsLkxlbmd0aCoqIDoKCgoyLiBDcmVhdGUgYSBzdWItZGF0YXNldCBjb21wcmlzaW5nIG9ubHkgdGhlIGRhdGEgZm9yIHRoZSBjYXRlZ29yeSAqdmVyc2ljb2xvciogb2YgdGhlIHZhcmlhYmxlICpzcGVjaWVzKiAoY2FsbCB0aGlzIG5ldyBkYXRhc2V0ICoqaXJpczIqKikuCgoKMy4gU29ydCB0aGUgZGF0YSBpbiAqKmlyaXMyKiogaW4gZGVzY2VuZGluZyBvcmRlciBhY2NvcmRpbmcgdG8gdGhlIHZhcmlhYmxlICoqU2VwYWwuTGVuZ3RoKiogKHlvdSBjYW4gdXNlIHRoZSAqKm9yZGVyKiogZnVuY3Rpb24pLgoKCjQuIENvbXB1dGUgdGhlIG1lYW4gb2YgKipTZXBhbC5MZW5ndGgqKiBmb3IgZWFjaCBzcGVjaWVzLgoKCjUuIEFkZCBhIHZhcmlhYmxlIChjYWxsZWQgKipzdW0uUGV0YWwqKikgaW4gdGhlIGRhdGFmcmFtZSBpcmlzIHdoaWNoIGNvcnJlc3BvbmRzIHRvIHRoZSBzdW0gb2YgKipQZXRhbC5MZW5ndGgqKiBhbmQgKipQZXRhbC5XaWR0aCoqLgoKCgojIyMgRXhlcmNpc2UgNAoKMS4gQ2FsY3VsYXRlIHRoZSBiZW5jaG1hcmsgc3RhdGlzdGljcyAobWVhbiwgbWluLCBtYXgsIGV0Yy4pIGZvciB0aGUgdGhyZWUgdmFyaWFibGVzIG9mIHRoZSAqKmV0aGFub2wqKiBkYXRhc2V0IChhdmFpbGFibGUgaW4gdGhlICpsYXR0aWNlKiBwYWNrYWdlKS4gCgoKMi4gQ2FsY3VsYXRlIHRoZSBxdWFydGlsZXMgZm9yIGVhY2ggb2YgdGhlIHRocmVlIHZhcmlhYmxlcy4gVG8gZG8gdGhpcywgdXNlIHRoZSAqKmFwcGx5KiogZnVuY3Rpb24gd2l0aCB0aGUgKipxdWFudGlsZSoqIGZ1bmN0aW9uLgoKCjMuIEFnYWluIHdpdGggdGhlICoqYXBwbHkqKiBmdW5jdGlvbiwgY2FsY3VsYXRlIGFsbCB0aGUgZGVjaWxlcyBmb3IgZWFjaCBvZiB0aGUgdGhyZWUgdmFyaWFibGVzIHVzaW5nIHRoZSBhcmd1bWVudCAqKnByb2JzKiogb2YgdGhlICoqcXVhbnRpbGUqKiBmdW5jdGlvbi4KCgoKIyMjIEV4ZXJjaXNlIDUKCldlIGNvbnNpZGVyIHRoZSAqKnByZWRpZGVudHMqKiBkYXRhc2V0LgoKYGBge3J9CmRhdGEoInByZXNpZGVudHMiKQpkZiA8LSBtYXRyaXgocHJlc2lkZW50cyxuY29sPTQsYnlyb3c9VCkKYGBgCgoxLiBJcyB0aGVyZSBhdCBsZWFzdCBvbmUgbWlzc2luZyB2YWx1ZSBpbiB0aGUgMjB0aCBsaW5lIG9mIHRoZSBkYXRhc2V0ICh5b3UgY2FuIHVzZSB0aGUgKiphbnkqKiBmdW5jdGlvbikuCgoKMi4gV2hpY2ggbGluZXMgaW4gdGhlIHRhYmxlIGNvbnRhaW4gYXQgbGVhc3Qgb25lIG1pc3NpbmcgZGF0YT8gWW91IGNhbiB1c2UgKip3aGljaCoqLgoKMy4gRGVsZXRlIHRoZSByb3dzIG9mIHRoZSB0YWJsZSB0aGF0IGNvbnRhaW4gYXQgbGVhc3Qgb25lIG1pc3NpbmcgZGF0YS4KCgo=