Vectors are a collection of a single kind of data

Creating Vectors

It is rather rare that we work with a single entity for any data type. The main syntax in R used to make a collection of objects is to enclose them into the c() function (c for combine and since we use it so often, making it as short as possible—anything we can do to type less is good for reducing the number of errors in our code).

Here is how we can get a vector of numeric values.

x <- c(1,2,3,4,5,6,7)
x
[1] 1 2 3 4 5 6 7

The variable x contains a number of numeric types and is a single object.

length( x )
[1] 7

Vectors from Sequences

It would really suck if we had to type in all the elements into every array we want. Say we want a vector of 100 numbers, it would be really likely if we had to type all the numbers 1, 2, 3, ... , 99, 100 (and quite boring 💤). The main way we will get data into R is by loading it from files or databases, which we will get to later, but for now let’s look at how we can specifically create sequences of values with a little bit of code.

The first is the colon operator. The syntax is X:Y which will produce the values from X to Y (inclusive on both ends). In R we use it like this:

y <- 3:8 
y
[1] 3 4 5 6 7 8

This is just a shortcut for the more general seq() function (seq is short for sequence). This function takes a value to start at and one to end with (inclusive just like above).

y <- seq(3,8)
y
[1] 3 4 5 6 7 8

These are the required arguments. By default, the seq() function counts by \(1.0\) (either up or down, depending upon the magnitude of the first and second argument).

seq(8,3)
[1] 8 7 6 5 4 3

If we want it to count by some other interval, we can tell it by passing the optional argument by=.

y <- seq(3,8,by=0.25)
y
 [1] 3.00 3.25 3.50 3.75 4.00 4.25 4.50 4.75 5.00 5.25 5.50 5.75 6.00 6.25 6.50
[16] 6.75 7.00 7.25 7.50 7.75 8.00

Another way we can use the seq() function is to create a vector of values that are equally spaced. For example, consider the sampling locations below where I collected Sonoran desert bark beetles (Araptus attenuatus).

If I wanted an elevation profile along the Baja Califorinia Peninsula (the red line), I could ask for a sequence in latitude (the north-south dimension) with exactly 50 equally spaced entities starting at the southern site near Cabo San Lucas and finishing up just north of Nva. Chapala (n.b., the data are in longitude and latitude).

coords <- cbind(  seq(-109.6487 , -114.2935 , length.out = 50), 
                  seq( 23.07, 29.32, length.out = 50) )

coords[1:5,]
          [,1]     [,2]
[1,] -109.6487 23.07000
[2,] -109.7435 23.19755
[3,] -109.8383 23.32510
[4,] -109.9331 23.45265
[5,] -110.0279 23.58020

From these locals we, we can then quickly query an elevation raster to extract the values at those sites

Indexing

Since vector objects contains collections of variables, we often need to get or set the value at a particular location or within a slice of the vector. For example, the object y above has 21 entities in it. To get to these individual entities within the y we use a square bracket notation to indicate that we want to get an item within the variable and must indicate which element (or elements) we are interested in getting. The numeric indices within the brackets are 1-based (e.g., the first element is 1, the second is 2, etc.). So the code

y[4]
[1] 3.75

returns the 4\(^{th}\) element in the vector. This notation can be used to get as well as set values within the vector.

y[2] <- 42
y
 [1]  3.00 42.00  3.50  3.75  4.00  4.25  4.50  4.75  5.00  5.25  5.50  5.75
[13]  6.00  6.25  6.50  6.75  7.00  7.25  7.50  7.75  8.00

In addition to numbers, you can also do logical values.

x <- 1:5
x[ c(TRUE, FALSE, TRUE, FALSE, FALSE) ]
[1] 1 3

Slices

In addition to getting a single entity from a vector, we can also grab a sequence of values by using a sequence of indices within the square brackets. For example, if I wanted the first five entries of y I could ask for it as:

y[1:5]
[1]  3.00 42.00  3.50  3.75  4.00

You can also grab the end parts of a vector using the head() and tail() functions. By default, they return 6 entries each, though you can customize it.

y
 [1]  3.00 42.00  3.50  3.75  4.00  4.25  4.50  4.75  5.00  5.25  5.50  5.75
[13]  6.00  6.25  6.50  6.75  7.00  7.25  7.50  7.75  8.00
head(y, n=2)
[1]  3 42
tail(y, n=3)
[1] 7.50 7.75 8.00

The tail() function is really convienent because you do not have to know how many elements are in the vector to grab the last few. If you were going to use indices, you’d have to figure out how many elements are in the vector.

to <- length(y)
from <- to - 6
y[from:to]
[1] 6.50 6.75 7.00 7.25 7.50 7.75 8.00

Dropping Values

While less often used, it is sometimes convienent to remove some values from a vector. We can do this by passing a negative index.

x <- 1:5
x[-3]
[1] 1 2 4 5

It works with slices as well:

x[-(2:4)]
[1] 1 5

However, unless you assign this back to x, the values in x are not changed in any way.

x
[1] 1 2 3 4 5

If you want to change the values in x then you would have to reassign the values back to x

x <- x[-(2:4)]
x
[1] 1 5

Concatenating Vectors

WE can concatenate vectors together (as well as vectors and individual elements)

x <- 1:5
y <- 6:10
z <- c(x,y, 12)
z
 [1]  1  2  3  4  5  6  7  8  9 10 12

If you attempt to concatenate things with different data types, it will coerce them all (if possible) into the least common denominator. For example, if we look at the first five counting integers and the first five letters of the English alphabet, when they are concatenated, R will coerce the letters into character data types to enforce the requirement that all entities in a vector are the same data type.

a <- 1:5
b <- LETTERS[1:5]
c(a,b)
 [1] "1" "2" "3" "4" "5" "A" "B" "C" "D" "E"
1

2

3

4

5

A

B

C

D

E

Vector Arithmatic

Just like we can use opertors to work on single entites (numeric, character, logical, etc.), you can apply the same operations on vectors of data types.

x <- 1:5
x * 12   
[1] 12 24 36 48 60
b <- 6:10
x + b 
[1]  7  9 11 13 15

Named Vectors

Thus far, we’ve seen individual elements in a vector represented by only the numerical index.

x 
[1] 1 2 3 4 5

There are several occasions where being more verbose in our data may increase interpretation and readability. One way to to this is to assign an actual name to one or more (or all) of the elements in a vector rather than just having them sitting in a row right next to each other (like above). By default, the names() of elements in a vector are blank (which the total absence of anything in R is NULL.

names(x)
NULL

However, we can assign values to those name like this:

names(x) <- c("James", "Patuxent", "Potomac", "Rappahannock", "York")
x
       James     Patuxent      Potomac Rappahannock         York 
           1            2            3            4            5 

Once you name these elements, you can similarily use the names as indice.

x[ c("James","Potomac")]
  James Potomac 
      1       3 

The Recycling Rule

Operations on vectors that expect a particular length are handled (somewhat gracefully) using the

Recycling Rule: The shorter of the two vectors will be stretched by reusing values from the start to equal the length of the larger vector.
x <- c(10,20,30)
y <- c(1,2,3,4,5,6,7,8,9) 
x + y
[1] 11 22 33 14 25 36 17 28 39

If the shorter vector length is not a clean multiple of the larger one, it will issue a warning to let you know in case these dangling parts could cause problems.

y <- 1:10
x + y
Warning in x + y: longer object length is not a multiple of shorter object
length
 [1] 11 22 33 14 25 36 17 28 39 20

LS0tCnRpdGxlOiAiVmVjdG9ycyIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgICBjc3M6ICJlbnZzNTQzLXN0eWxlcy5jc3MiCi0tLQoKYGBge3Igc3RhcnR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkocmFzdGVyKQpsaWJyYXJ5KGxlYWZsZXQpCmxpYnJhcnkoZW1vKQp0aGVtZV9zZXQoIHRoZW1lX21pbmltYWwoKSkKYGBgCgo+IFZlY3RvcnMgYXJlIGEgY29sbGVjdGlvbiBvZiBhIHNpbmdsZSBraW5kIG9mIGRhdGEKCiMjIENyZWF0aW5nIFZlY3RvcnMKCkl0IGlzIHJhdGhlciByYXJlIHRoYXQgd2Ugd29yayB3aXRoIGEgc2luZ2xlIGVudGl0eSBmb3IgYW55IGRhdGEgdHlwZS4gICBUaGUgbWFpbiBzeW50YXggaW4gYFJgIHVzZWQgdG8gbWFrZSBhIGNvbGxlY3Rpb24gb2Ygb2JqZWN0cyBpcyB0byBlbmNsb3NlIHRoZW0gaW50byB0aGUgYGMoKWAgZnVuY3Rpb24gKCpjKiBmb3IgKmMqb21iaW5lIGFuZCBzaW5jZSB3ZSB1c2UgaXQgc28gb2Z0ZW4sIG1ha2luZyBpdCBhcyBzaG9ydCBhcyBwb3NzaWJsZeKAlGFueXRoaW5nIHdlIGNhbiBkbyB0byB0eXBlIGxlc3MgaXMgZ29vZCBmb3IgcmVkdWNpbmcgdGhlIG51bWJlciBvZiBlcnJvcnMgaW4gb3VyIGNvZGUpLiAgCgpIZXJlIGlzIGhvdyB3ZSBjYW4gZ2V0IGEgdmVjdG9yIG9mIGBudW1lcmljYCB2YWx1ZXMuCgpgYGB7cn0KeCA8LSBjKDEsMiwzLDQsNSw2LDcpCngKYGBgCgpUaGUgdmFyaWFibGUgYHhgIGNvbnRhaW5zIGEgbnVtYmVyIG9mIG51bWVyaWMgdHlwZXMgYW5kIGlzIGEgc2luZ2xlIG9iamVjdC4KCmBgYHtyfQpsZW5ndGgoIHggKQpgYGAKCgojIyBWZWN0b3JzIGZyb20gU2VxdWVuY2VzCgpJdCB3b3VsZCByZWFsbHkgc3VjayBpZiB3ZSBoYWQgdG8gdHlwZSBpbiBhbGwgdGhlIGVsZW1lbnRzIGludG8gZXZlcnkgYXJyYXkgd2Ugd2FudC4gIFNheSB3ZSB3YW50IGEgdmVjdG9yIG9mIDEwMCBudW1iZXJzLCBpdCB3b3VsZCBiZSByZWFsbHkgbGlrZWx5IGlmIHdlIGhhZCB0byB0eXBlIGFsbCB0aGUgbnVtYmVycyBgMSwgMiwgMywgLi4uICwgOTksIDEwMGAgKGFuZCBxdWl0ZSBib3JpbmcgYHIgZW1vOjpqaSgienp6IilgKS4gIFRoZSBtYWluIHdheSB3ZSB3aWxsIGdldCBkYXRhIGludG8gYFJgIGlzIGJ5IGxvYWRpbmcgaXQgZnJvbSBmaWxlcyBvciBkYXRhYmFzZXMsIHdoaWNoIHdlIHdpbGwgZ2V0IHRvIGxhdGVyLCBidXQgZm9yIG5vdyBsZXQncyBsb29rIGF0IGhvdyB3ZSBjYW4gc3BlY2lmaWNhbGx5IGNyZWF0ZSBzZXF1ZW5jZXMgb2YgdmFsdWVzIHdpdGggYSBsaXR0bGUgYml0IG9mIGNvZGUuCgpUaGUgZmlyc3QgaXMgdGhlIGNvbG9uIG9wZXJhdG9yLiAgVGhlIHN5bnRheCBpcyBgWDpZYCB3aGljaCB3aWxsIHByb2R1Y2UgdGhlIHZhbHVlcyBmcm9tIGBYYCB0byBgWWAgKGluY2x1c2l2ZSBvbiBib3RoIGVuZHMpLiAgSW4gYFJgIHdlIHVzZSBpdCBsaWtlIHRoaXM6CgpgYGB7cn0KeSA8LSAzOjggCnkKYGBgCgpUaGlzIGlzIGp1c3QgYSBzaG9ydGN1dCBmb3IgdGhlIG1vcmUgZ2VuZXJhbCBgc2VxKClgIGZ1bmN0aW9uICgqc2VxKiBpcyBzaG9ydCBmb3IgKnNlcXVlbmNlKikuICBUaGlzIGZ1bmN0aW9uIHRha2VzIGEgdmFsdWUgdG8gc3RhcnQgYXQgYW5kIG9uZSB0byBlbmQgd2l0aCAoaW5jbHVzaXZlIGp1c3QgbGlrZSBhYm92ZSkuCgpgYGB7cn0KeSA8LSBzZXEoMyw4KQp5CmBgYAoKVGhlc2UgYXJlIHRoZSAqcmVxdWlyZWQqIGFyZ3VtZW50cy4gIEJ5IGRlZmF1bHQsIHRoZSBgc2VxKClgIGZ1bmN0aW9uIGNvdW50cyBieSAkMS4wJCAoZWl0aGVyIHVwIG9yIGRvd24sIGRlcGVuZGluZyB1cG9uIHRoZSBtYWduaXR1ZGUgb2YgdGhlIGZpcnN0IGFuZCBzZWNvbmQgYXJndW1lbnQpLgoKYGBge3J9CnNlcSg4LDMpCmBgYAoKSWYgd2Ugd2FudCBpdCB0byBjb3VudCBieSBzb21lIG90aGVyIGludGVydmFsLCB3ZSBjYW4gdGVsbCBpdCBieSBwYXNzaW5nIHRoZSAqb3B0aW9uYWwgYXJndW1lbnQqIGBieT1gLgoKYGBge3J9CnkgPC0gc2VxKDMsOCxieT0wLjI1KQp5CmBgYAoKCkFub3RoZXIgd2F5IHdlIGNhbiB1c2UgdGhlIGBzZXEoKWAgZnVuY3Rpb24gaXMgdG8gY3JlYXRlIGEgdmVjdG9yIG9mIHZhbHVlcyB0aGF0IGFyZSBlcXVhbGx5IHNwYWNlZC4gIEZvciBleGFtcGxlLCBjb25zaWRlciB0aGUgc2FtcGxpbmcgbG9jYXRpb25zIGJlbG93IHdoZXJlIEkgY29sbGVjdGVkIFNvbm9yYW4gZGVzZXJ0IGJhcmsgYmVldGxlcyAoKkFyYXB0dXMgYXR0ZW51YXR1cyopLiAgCgpgYGB7ciBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQp1cmwgPC0gImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9keWVybGFiL0VOVlMtTGVjdHVyZXMvbWFzdGVyL2RhdGEvYXJhcGF0LmNzdiIKcmVhZF9jc3YodXJsKSAlPiUKICBmaWx0ZXIoIFN0cmF0dW0gJWluJSBjKCI5OCIsIjg4IikpICU+JQogIGxlYWZsZXQoKSAlPiUKICBhZGRQcm92aWRlclRpbGVzKCJTdGFtZW4uVGVycmFpbkJhY2tncm91bmQiKSAlPiUKICBhZGRQb2x5bGluZXMofkxvbmdpdHVkZSwgfkxhdGl0dWRlLCBjb2xvcj0iI2ZmMDAwMDg4Iiwgd2VpZ2h0ID0gMyApICU+JQogIGFkZE1hcmtlcnMoIH5Mb25naXR1ZGUsIH5MYXRpdHVkZSwgbGFiZWwgPSB+U3RyYXR1bSkKYGBgCklmIEkgd2FudGVkIGFuIGVsZXZhdGlvbiBwcm9maWxlIGFsb25nIHRoZSBCYWphIENhbGlmb3JpbmlhIFBlbmluc3VsYSAodGhlIHJlZCBsaW5lKSwgSSBjb3VsZCBhc2sgZm9yIGEgc2VxdWVuY2UgaW4gbGF0aXR1ZGUgKHRoZSBub3J0aC1zb3V0aCBkaW1lbnNpb24pIHdpdGggZXhhY3RseSA1MCBlcXVhbGx5IHNwYWNlZCBlbnRpdGllcyBzdGFydGluZyBhdCB0aGUgc291dGhlcm4gc2l0ZSBuZWFyIENhYm8gU2FuIEx1Y2FzIGFuZCBmaW5pc2hpbmcgdXAganVzdCBub3J0aCBvZiBOdmEuIENoYXBhbGEgKG4uYi4sIHRoZSBkYXRhIGFyZSBpbiBsb25naXR1ZGUgYW5kIGxhdGl0dWRlKS4KCmBgYHtyfQpjb29yZHMgPC0gY2JpbmQoICBzZXEoLTEwOS42NDg3CSwgLTExNC4yOTM1CSwgbGVuZ3RoLm91dCA9IDUwKSwgCiAgICAgICAgICAgICAgICAgIHNlcSggMjMuMDcsIDI5LjMyLCBsZW5ndGgub3V0ID0gNTApICkKCmNvb3Jkc1sxOjUsXQpgYGAKCkZyb20gdGhlc2UgbG9jYWxzIHdlLCB3ZSBjYW4gdGhlbiBxdWlja2x5IHF1ZXJ5IGFuIGVsZXZhdGlvbiByYXN0ZXIgdG8gZXh0cmFjdCB0aGUgdmFsdWVzIGF0IHRob3NlIHNpdGVzCgpgYGB7ciBlY2hvPUZBTFNFfQpsb2FkKCIuLi8uLi8uLi9kYXRhL2FsdC5yZGEiKQpwdHMgPC0gU3BhdGlhbFBvaW50cyggY29vcmRzICkKdmFscyA8LSBleHRyYWN0KCBhbHQsIHB0cyApCmRhdGEuZnJhbWUoIExhdGl0dWRlPWNvb3Jkc1ssMl0sIEVsZXZhdGlvbj12YWxzKSAlPiUKICBnZ3Bsb3QoIGFlcyhMYXRpdHVkZSxFbGV2YXRpb24pKSArIAogIGdlb21fbGluZSggY29sb3I9InJlZCIpICsgeWxhYigiRWxldmF0aW9uIChtKSIpCmBgYAoKCiMjIEluZGV4aW5nCgpTaW5jZSBgdmVjdG9yYCBvYmplY3RzIGNvbnRhaW5zIGNvbGxlY3Rpb25zIG9mIHZhcmlhYmxlcywgd2Ugb2Z0ZW4gbmVlZCB0byAqZ2V0KiBvciAqc2V0KiB0aGUgdmFsdWUgYXQgYSBwYXJ0aWN1bGFyIGxvY2F0aW9uIG9yIHdpdGhpbiBhIHNsaWNlIG9mIHRoZSB2ZWN0b3IuICBGb3IgZXhhbXBsZSwgdGhlIG9iamVjdCBgeWAgYWJvdmUgaGFzIGByIGxlbmd0aCh5KWAgZW50aXRpZXMgaW4gaXQuICBUbyBnZXQgdG8gdGhlc2UgaW5kaXZpZHVhbCBlbnRpdGllcyB3aXRoaW4gdGhlIGB5YCB3ZSB1c2UgYSBzcXVhcmUgYnJhY2tldCBub3RhdGlvbiB0byBpbmRpY2F0ZSB0aGF0IHdlIHdhbnQgdG8gZ2V0IGFuIGl0ZW0gKndpdGhpbiogdGhlIHZhcmlhYmxlIGFuZCBtdXN0IGluZGljYXRlIHdoaWNoIGVsZW1lbnQgKG9yIGVsZW1lbnRzKSB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBnZXR0aW5nLiAgVGhlIG51bWVyaWMgaW5kaWNlcyB3aXRoaW4gdGhlIGJyYWNrZXRzIGFyZSAxLWJhc2VkIChlLmcuLCB0aGUgZmlyc3QgZWxlbWVudCBpcyAxLCB0aGUgc2Vjb25kIGlzIDIsIGV0Yy4pLiAgU28gdGhlIGNvZGUKCmBgYHtyfQp5WzRdCmBgYAoKcmV0dXJucyB0aGUgNCRee3RofSQgZWxlbWVudCBpbiB0aGUgdmVjdG9yLiAgVGhpcyBub3RhdGlvbiBjYW4gYmUgdXNlZCB0byAqZ2V0KiBhcyB3ZWxsIGFzICpzZXQqIHZhbHVlcyB3aXRoaW4gdGhlIHZlY3Rvci4KCmBgYHtyfQp5WzJdIDwtIDQyCnkKYGBgCgpJbiBhZGRpdGlvbiB0byBudW1iZXJzLCB5b3UgY2FuIGFsc28gZG8gbG9naWNhbCB2YWx1ZXMuCgpgYGB7cn0KeCA8LSAxOjUKeFsgYyhUUlVFLCBGQUxTRSwgVFJVRSwgRkFMU0UsIEZBTFNFKSBdCmBgYAoKCiMjIFNsaWNlcwoKSW4gYWRkaXRpb24gdG8gZ2V0dGluZyBhIHNpbmdsZSBlbnRpdHkgZnJvbSBhIHZlY3Rvciwgd2UgY2FuIGFsc28gZ3JhYiBhIHNlcXVlbmNlIG9mIHZhbHVlcyBieSB1c2luZyBhIHNlcXVlbmNlIG9mIGluZGljZXMgd2l0aGluIHRoZSBzcXVhcmUgYnJhY2tldHMuICBGb3IgZXhhbXBsZSwgaWYgSSB3YW50ZWQgdGhlIGZpcnN0IGZpdmUgZW50cmllcyBvZiBgeWAgSSBjb3VsZCBhc2sgZm9yIGl0IGFzOgoKYGBge3J9CnlbMTo1XQpgYGAKCgpZb3UgY2FuIGFsc28gZ3JhYiB0aGUgZW5kIHBhcnRzIG9mIGEgdmVjdG9yIHVzaW5nIHRoZSBgaGVhZCgpYCBhbmQgYHRhaWwoKWAgZnVuY3Rpb25zLiAgQnkgZGVmYXVsdCwgdGhleSByZXR1cm4gNiBlbnRyaWVzIGVhY2gsIHRob3VnaCB5b3UgY2FuIGN1c3RvbWl6ZSBpdC4KCmBgYHtyfQp5CmhlYWQoeSwgbj0yKQp0YWlsKHksIG49MykKYGBgCgpUaGUgYHRhaWwoKWAgZnVuY3Rpb24gaXMgcmVhbGx5IGNvbnZpZW5lbnQgYmVjYXVzZSB5b3UgZG8gbm90IGhhdmUgdG8ga25vdyBob3cgbWFueSBlbGVtZW50cyBhcmUgaW4gdGhlIHZlY3RvciB0byBncmFiIHRoZSBsYXN0IGZldy4gIElmIHlvdSB3ZXJlIGdvaW5nIHRvIHVzZSBpbmRpY2VzLCB5b3UnZCBoYXZlIHRvIGZpZ3VyZSBvdXQgaG93IG1hbnkgZWxlbWVudHMgYXJlIGluIHRoZSB2ZWN0b3IuCgpgYGB7cn0KdG8gPC0gbGVuZ3RoKHkpCmZyb20gPC0gdG8gLSA2CnlbZnJvbTp0b10KYGBgCgoKCgojIyBEcm9wcGluZyBWYWx1ZXMgCgpXaGlsZSBsZXNzIG9mdGVuIHVzZWQsIGl0IGlzIHNvbWV0aW1lcyBjb252aWVuZW50IHRvIHJlbW92ZSBzb21lIHZhbHVlcyBmcm9tIGEgdmVjdG9yLiAgV2UgY2FuIGRvIHRoaXMgYnkgcGFzc2luZyBhIG5lZ2F0aXZlIGluZGV4LgoKYGBge3J9CnggPC0gMTo1CnhbLTNdCmBgYAoKSXQgd29ya3Mgd2l0aCBzbGljZXMgYXMgd2VsbDoKCmBgYHtyfQp4Wy0oMjo0KV0KYGBgCgo8ZGl2IGNsYXNzPSJib3gtcmVkIj4KSG93ZXZlciwgdW5sZXNzIHlvdSBhc3NpZ24gdGhpcyBiYWNrIHRvIGB4YCwgdGhlIHZhbHVlcyBpbiB4IGFyZSBub3QgY2hhbmdlZCBpbiBhbnkgd2F5LiAgCmBgYHtyfQp4CmBgYAoKSWYgeW91IHdhbnQgdG8gY2hhbmdlIHRoZSB2YWx1ZXMgaW4gYHhgIHRoZW4geW91IHdvdWxkIGhhdmUgdG8gcmVhc3NpZ24gdGhlIHZhbHVlcyBiYWNrIHRvIHgKCmBgYHtyfQp4IDwtIHhbLSgyOjQpXQp4CmBgYAo8L2Rpdj4KCgoKCgoKIyMgQ29uY2F0ZW5hdGluZyBWZWN0b3JzCgpXRSBjYW4gY29uY2F0ZW5hdGUgdmVjdG9ycyB0b2dldGhlciAoYXMgd2VsbCBhcyB2ZWN0b3JzIGFuZCBpbmRpdmlkdWFsIGVsZW1lbnRzKQoKYGBge3J9CnggPC0gMTo1CnkgPC0gNjoxMAp6IDwtIGMoeCx5LCAxMikKegpgYGAKCklmIHlvdSBhdHRlbXB0IHRvIGNvbmNhdGVuYXRlIHRoaW5ncyB3aXRoIGRpZmZlcmVudCBkYXRhIHR5cGVzLCBpdCB3aWxsIGNvZXJjZSB0aGVtIGFsbCAoaWYgcG9zc2libGUpIGludG8gdGhlIGxlYXN0IGNvbW1vbiBkZW5vbWluYXRvci4gIEZvciBleGFtcGxlLCBpZiB3ZSBsb29rIGF0IHRoZSBmaXJzdCBmaXZlIGNvdW50aW5nIGludGVnZXJzIGFuZCB0aGUgZmlyc3QgZml2ZSBsZXR0ZXJzIG9mIHRoZSBFbmdsaXNoIGFscGhhYmV0LCB3aGVuIHRoZXkgYXJlIGNvbmNhdGVuYXRlZCwgYFJgIHdpbGwgY29lcmNlIHRoZSBsZXR0ZXJzIGludG8gYGNoYXJhY3RlcmAgZGF0YSB0eXBlcyB0byBlbmZvcmNlIHRoZSByZXF1aXJlbWVudCB0aGF0IGFsbCBlbnRpdGllcyBpbiBhIHZlY3RvciBhcmUgdGhlIHNhbWUgZGF0YSB0eXBlLgoKCmBgYHtyfQphIDwtIDE6NQpiIDwtIExFVFRFUlNbMTo1XQpjKGEsYikKYGBgCgoKCiMjIFZlY3RvciBBcml0aG1hdGljCgpKdXN0IGxpa2Ugd2UgY2FuIHVzZSBvcGVydG9ycyB0byB3b3JrIG9uIHNpbmdsZSBlbnRpdGVzIChudW1lcmljLCBjaGFyYWN0ZXIsIGxvZ2ljYWwsIGV0Yy4pLCB5b3UgY2FuIGFwcGx5IHRoZSBzYW1lIG9wZXJhdGlvbnMgb24gdmVjdG9ycyBvZiBkYXRhIHR5cGVzLgoKYGBge3J9CnggPC0gMTo1CnggKiAxMiAgIApgYGAKCmBgYHtyfQpiIDwtIDY6MTAKeCArIGIgCmBgYAoKCgoKCiMjIE5hbWVkIFZlY3RvcnMKClRodXMgZmFyLCB3ZSd2ZSBzZWVuIGluZGl2aWR1YWwgZWxlbWVudHMgaW4gYSBgdmVjdG9yYCByZXByZXNlbnRlZCBieSBvbmx5IHRoZSBudW1lcmljYWwgaW5kZXguCgpgYGB7cn0KeCAKYGBgCgpUaGVyZSBhcmUgc2V2ZXJhbCBvY2Nhc2lvbnMgd2hlcmUgYmVpbmcgbW9yZSAqdmVyYm9zZSogaW4gb3VyIGRhdGEgbWF5IGluY3JlYXNlIGludGVycHJldGF0aW9uIGFuZCByZWFkYWJpbGl0eS4gIE9uZSB3YXkgdG8gdG8gdGhpcyBpcyB0byBhc3NpZ24gYW4gYWN0dWFsIG5hbWUgdG8gb25lIG9yIG1vcmUgKG9yIGFsbCkgb2YgdGhlIGVsZW1lbnRzIGluIGEgdmVjdG9yIHJhdGhlciB0aGFuIGp1c3QgaGF2aW5nIHRoZW0gc2l0dGluZyBpbiBhIHJvdyByaWdodCBuZXh0IHRvIGVhY2ggb3RoZXIgKGxpa2UgYWJvdmUpLiAgQnkgZGVmYXVsdCwgdGhlIGBuYW1lcygpYCBvZiBlbGVtZW50cyBpbiBhIHZlY3RvciBhcmUgYmxhbmsgKHdoaWNoIHRoZSB0b3RhbCBhYnNlbmNlIG9mIGFueXRoaW5nIGluIGBSYCBpcyBgTlVMTGAuCgpgYGB7cn0KbmFtZXMoeCkKYGBgCgpIb3dldmVyLCB3ZSBjYW4gYXNzaWduIHZhbHVlcyB0byB0aG9zZSBuYW1lIGxpa2UgdGhpczoKCmBgYHtyfQpuYW1lcyh4KSA8LSBjKCJKYW1lcyIsICJQYXR1eGVudCIsICJQb3RvbWFjIiwgIlJhcHBhaGFubm9jayIsICJZb3JrIikKeApgYGAKCgoKCk9uY2UgeW91IG5hbWUgdGhlc2UgZWxlbWVudHMsIHlvdSBjYW4gc2ltaWxhcmlseSB1c2UgdGhlIG5hbWVzIGFzIGluZGljZS4KCmBgYHtyfQp4WyBjKCJKYW1lcyIsIlBvdG9tYWMiKV0KYGBgCgojIyBUaGUgUmVjeWNsaW5nIFJ1bGUKCk9wZXJhdGlvbnMgb24gdmVjdG9ycyB0aGF0IGV4cGVjdCBhIHBhcnRpY3VsYXIgbGVuZ3RoIGFyZSBoYW5kbGVkIChzb21ld2hhdCBncmFjZWZ1bGx5KSB1c2luZyB0aGUgCgo8ZGl2IGNsYXNzPSJib3gtZ3JlZW4iPipSZWN5Y2xpbmcgUnVsZSo6IFRoZSBzaG9ydGVyIG9mIHRoZSB0d28gdmVjdG9ycyB3aWxsIGJlIHN0cmV0Y2hlZCBieSByZXVzaW5nIHZhbHVlcyBmcm9tIHRoZSBzdGFydCB0byBlcXVhbCB0aGUgbGVuZ3RoIG9mIHRoZSBsYXJnZXIgdmVjdG9yLjwvZGl2PgoKCmBgYHtyfQp4IDwtIGMoMTAsMjAsMzApCnkgPC0gYygxLDIsMyw0LDUsNiw3LDgsOSkgCnggKyB5CmBgYAoKSWYgdGhlIHNob3J0ZXIgdmVjdG9yIGxlbmd0aCBpcyBub3QgYSBjbGVhbiBtdWx0aXBsZSBvZiB0aGUgbGFyZ2VyIG9uZSwgaXQgd2lsbCBpc3N1ZSBhIHdhcm5pbmcgdG8gbGV0IHlvdSBrbm93IGluIGNhc2UgdGhlc2UgZGFuZ2xpbmcgcGFydHMgY291bGQgY2F1c2UgcHJvYmxlbXMuCgpgYGB7cn0KeSA8LSAxOjEwCnggKyB5CmBgYAoKCgotLS0KCgo=