Solutions to this workshop can be found here

Review: vectors, functions, and types

Vectors and functions

# Create a variable, vect_1 that holds a vector containing any 4 numbers

# Calculate the sum of vect_1 and print it out on the screen

# Create a new variable, vect_2, that contains each value of vect_1 squared
# (Don't manually enter the numbers, use vect_1 to calculate this)

Notice that lots of functions work on vectors!

Sequences of numbers

# Create a vector of numbers from -5 to 5 containing 21 elements called review_vec

When we get missing values

A HUGE part of analyzing real scientific data is dealing with missing values. There are lots of ways we can get missing values; these are probably the most common:

Every programming language has its own special way of representing ‘missing’ data; R, ever so special, uses two: NA or NaN, depending on the situation; don’t worry about the difference, I (Eugene) literally learned it while preparing this class, after 5 years of programming in R.

Let’s take a look at how these missing values work.

Performing nonsensical operations

Let’s try to see what R does when we ask it to do something that clearly doesn’t make sense. Remember that we can ask R to convert a list of characters to numbers. Let’s try that again.

weird_number_vector <- c('1', '4', 'koala', '18')

# Convert weird_number_vector to numeric type, and print out the result

Taboo math operations

Another way to get missing values is to perform a math operation that R doesn’t like. Let’s try doing this. Remember that we can perform operations on vectors, e.g. adding two vectors to each other. Let’s try dividing vectors this way.

vector_1 <- c(1, 2, 0, 3, 0, -5)
vector_2 <- c(0, -3, 1, 6, 0, 0)

# What do you think you'll get if you divide vector_1 by vector_2?

# Try it

Real missing data

Finally, you can enter NA into your vector, just like you would any other value

# Create a vector, data_vector, which has some numbers and at least one NA value

# What happens if you take the sum of data_vector?

Lots of functions in R, including sum(), have a way of dealing with missing data automatically. There are lots of times when we may want to just ignore the missing values and work with the rest of the data we have. Take a look at the documentation for sum(); do you see anything in there that might suggest how you could get the function to ignore missing values and take the sum of data_vector anyways?

# Try using sum() to get the sum of the non-missing values in data_vector

Logicals

Introduction to logicals

In R, in addition to character and numeric values, we can have logical values. Logical values are TRUE and FALSE. These words, when you type them, are something like NA in that they’re special words.

Logical values are often generated by comparisons between two values. These comparisons are made with logical operators. Many of them you will be familiar with.

3 > 4
8 < 5
4 <= 4

Note that the logical operator “is equal to” is == in R. If you only use =, you will reassign your variable (that is = in R is the same as <-).
“Not” is specified by !. So “is not equal to” is !=.

Try to figure out what the output of each of the following lines will be before running them.

TRUE == TRUE

TRUE == FALSE

TRUE != FALSE

3 != 4

char = 'a'
char == 'a'

char = 'b'
char == 'a'

Looking for missing values in a vector

One useful function that results in a logical value is is.na()

# try using is.na() on position 11 in review_vec

# try using is.na() on review_vec

# try using is.na() on data_vector

Just like you can make a vector of characters or a vector of numeric values, you can also make a vector of logicals.

# Make a vector with 3 TRUEs and 2 FALSEs, save it as logical_vec1

# Make a vector called num_vec that starts at 2 and ends at 10 (increasing by 1)

logical_vec2 <- num_vec %% 3 == 2 #what is this line of code doing?

Treating numbers as logicals

In R, FALSE is also encoded as 0, and TRUE is encoded as 1.

0==FALSE
1==TRUE

# How do you think we could easily figure out how many TRUEs there are in logical_vec2?

# How can you get R to tell you the number of missing values in data_vector?

Numbers can be treated like logical values, especially with as.logical(). 0 is false, everything else is true.

as.logical(-2:2)

sum(as.logical(-2:2)) # what is going on here?

Exercise

Imagine that you’re doing an experiment measuring plant height, but some of the plants didn’t grow. You decide those should be considered missing values, so they entered NA for those plants. Let’s count the number of plants that DID grow in your experiment.

plant_heights <- c(1.9, 0.1, NA, 0.8, 0.4, 0.2, 7.9, NA, 16.8, 3.5)

# create a logical vector, plant_NA_vector, that contains information on whether
# each value in plant_heights is missing (NA)

# use plant_NA_vector to figure out how many plants total didn't grow
# assign this number to a variable and print it out

# use plant_NA_vector to figure out how many plants DID grow
# assign this number to a variable and print it out

# bonus:figure out what PROPORTION of plants grew
# assign this number to a variable and print it out

Selecting and replacing values from vectors based on logicals

In addition to using indices to get R to tell us a specific position in a vector, we can also use them to replace specific values. Take a look at this example.

vector_to_sub <- c(12, 13, 14, 15, NA, 17, 18, 19)

# replace the 2nd value in vector_to_sub with 54
vector_to_sub[2] <- 54
print(vector_to_sub)

# now, try replacing the 1st, 3rd, and 8th values in vector_to_sub with 28,
# using only one line of code (i.e. do it all at once)

One really powerful way to use this vector substitution is to combine it with logical vectors. Take a look at the example below:

vector_to_sub2 <- 1:3
vector_to_sub2[c(TRUE, FALSE, TRUE)] <- 42

# What do you think vector_to_sub2 looks like now? Print it out to check

Try this for yourself. Lots of times, we want to replace missing values in vectors. Let’s say that, when you do your analysis on the plant example above, you want to treat the plants that didn’t grow as having a height of 0 rather than being missing.

# use plant_NA_vector to replace every missing value in plant_heights with a 0

# print the modified plant_heights vector

Operations on logicals (AND, OR)

We can also do “and” (&) and “or” (|, all the way on the right side of your keyboard). “And” only returns true if both things are true. “Or” returns true if at least one thing is true.

Try predicting what all the operations below will return

TRUE & TRUE
TRUE & FALSE
FALSE & FALSE

FALSE | TRUE
TRUE | TRUE
FALSE | FALSE

# bonus: perform some operations on the following variables (unicorns and
# rainbows) that will result in a TRUE value being returned
unicorns <- FALSE
rainbows <- FALSE

Things we hope you’ve learned today (and will hopefully remember next time)

LS0tCnRpdGxlOiAiSW50cm8gUiBDb3Vyc2UsIFdvcmtzaG9wIDQ6IE1pc3NpbmcgdmFsdWVzIGFuZCBMb2dpY2FsIG9wZXJhdGlvbnMiCnN1YnRpdGxlOiB8CiAgICB8ICAgLSBjcmVhdGluZywgc3RvcmluZywgYW5kIHdvcmtpbmcgd2l0aCBtaXNzaW5nIHZhbHVlcwogICAgfCAgIC0gbG9naWNhbCAoYm9vbGVhbikgdHlwZXMKICAgIHwgICAtIHVzaW5nIGxvZ2ljYWwgdHlwZXMgdG8gc2VsZWN0IGRhdGEgb2YgaW50ZXJlc3QKICAgIHwgICAtIG9wZXJhdGlvbnMgd2l0aCBsb2dpY2FsIGRhdGEgdHlwZXMKYXV0aG9yOgogIC0gRXVnZW5lIFBsYXZza2luCiAgLSBHcmFjZSBBdmVjaWxsYQogIC0gVG9iaSBTaHJhaW5rCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBzaG93CiAgICBkZXB0aDogMwogICAgdGlkeTogeWVzCiAgICB0b2M6IHllcwotLS0KKipTb2x1dGlvbnMgdG8gdGhpcyB3b3Jrc2hvcCBjYW4gYmUgZm91bmQgW2hlcmVdKFNvbHV0aW9uc19Xb3Jrc2hvcF80Lm5iLmh0bWwpKioKCiMgUmV2aWV3OiB2ZWN0b3JzLCBmdW5jdGlvbnMsIGFuZCB0eXBlcwoKIyMgVmVjdG9ycyBhbmQgZnVuY3Rpb25zCmBgYHtyfQojIENyZWF0ZSBhIHZhcmlhYmxlLCB2ZWN0XzEgdGhhdCBob2xkcyBhIHZlY3RvciBjb250YWluaW5nIGFueSA0IG51bWJlcnMKCiMgQ2FsY3VsYXRlIHRoZSBzdW0gb2YgdmVjdF8xIGFuZCBwcmludCBpdCBvdXQgb24gdGhlIHNjcmVlbgoKIyBDcmVhdGUgYSBuZXcgdmFyaWFibGUsIHZlY3RfMiwgdGhhdCBjb250YWlucyBlYWNoIHZhbHVlIG9mIHZlY3RfMSBzcXVhcmVkCiMgKERvbid0IG1hbnVhbGx5IGVudGVyIHRoZSBudW1iZXJzLCB1c2UgdmVjdF8xIHRvIGNhbGN1bGF0ZSB0aGlzKQoKYGBgCgpOb3RpY2UgdGhhdCBsb3RzIG9mIGZ1bmN0aW9ucyB3b3JrIG9uIHZlY3RvcnMhCgojIyBTZXF1ZW5jZXMgb2YgbnVtYmVycwpgYGB7cn0KIyBDcmVhdGUgYSB2ZWN0b3Igb2YgbnVtYmVycyBmcm9tIC01IHRvIDUgY29udGFpbmluZyAyMSBlbGVtZW50cyBjYWxsZWQgcmV2aWV3X3ZlYwoKYGBgCgojIFdoZW4gd2UgZ2V0IG1pc3NpbmcgdmFsdWVzCgpBICoqSFVHRSoqIHBhcnQgb2YgYW5hbHl6aW5nIHJlYWwgc2NpZW50aWZpYyBkYXRhIGlzIGRlYWxpbmcgd2l0aCBtaXNzaW5nIHZhbHVlcy4gVGhlcmUgYXJlIGxvdHMgb2Ygd2F5cyB3ZSBjYW4gZ2V0IG1pc3NpbmcgdmFsdWVzOyB0aGVzZSBhcmUgcHJvYmFibHkgdGhlIG1vc3QgY29tbW9uOgoKKiBXaGVuIHdlIHRyeSB0byBnZXQgUiB0byBkbyBhIG5vbnNlbnNpY2FsIHRoaW5nCiogV2hlbiB3ZSBwZXJmb3JtIHNvbWUgc3VwZXIgdGFib28gbWF0aCBvcGVyYXRpb24KKiBXaGVuIHdlIGFyZSB1c2luZyByZWFsIGRhdGEgYW5kIHdlIGRpZG4ndCBjb2xsZWN0IGV2ZXJ5IG9ic2VydmF0aW9uICgqZWcqIHlvdSBtZWFzdXJlZCB0aGUgaGVpZ2h0IG9mIGEgYnVuY2ggb2YgcGxhbnRzIGV2ZXJ5IHdlZWsgYnV0IGJ5IHRoZSB0aGlyZCB3ZWVrLCBzb21lIG9mIHRoZW0gZGllZCkKCkV2ZXJ5IHByb2dyYW1taW5nIGxhbmd1YWdlIGhhcyBpdHMgb3duIHNwZWNpYWwgd2F5IG9mIHJlcHJlc2VudGluZyAnbWlzc2luZycgZGF0YTsgUiwgZXZlciBzbyBzcGVjaWFsLCB1c2VzIHR3bzogKk5BKiBvciAqTmFOKiwgZGVwZW5kaW5nIG9uIHRoZSBzaXR1YXRpb247IGRvbid0IHdvcnJ5IGFib3V0IHRoZSBkaWZmZXJlbmNlLCBJIChFdWdlbmUpIGxpdGVyYWxseSBsZWFybmVkIGl0IHdoaWxlIHByZXBhcmluZyB0aGlzIGNsYXNzLCBhZnRlciA1IHllYXJzIG9mIHByb2dyYW1taW5nIGluIFIuCgpMZXQncyB0YWtlIGEgbG9vayBhdCBob3cgdGhlc2UgbWlzc2luZyB2YWx1ZXMgd29yay4KCiMjIFBlcmZvcm1pbmcgbm9uc2Vuc2ljYWwgb3BlcmF0aW9ucwoKTGV0J3MgdHJ5IHRvIHNlZSB3aGF0IFIgZG9lcyB3aGVuIHdlIGFzayBpdCB0byBkbyBzb21ldGhpbmcgdGhhdCBjbGVhcmx5IGRvZXNuJ3QgbWFrZSBzZW5zZS4gUmVtZW1iZXIgdGhhdCB3ZSBjYW4gYXNrIFIgdG8gY29udmVydCBhIGxpc3Qgb2YgY2hhcmFjdGVycyB0byBudW1iZXJzLiBMZXQncyB0cnkgdGhhdCBhZ2Fpbi4KYGBge3J9CndlaXJkX251bWJlcl92ZWN0b3IgPC0gYygnMScsICc0JywgJ2tvYWxhJywgJzE4JykKCiMgQ29udmVydCB3ZWlyZF9udW1iZXJfdmVjdG9yIHRvIG51bWVyaWMgdHlwZSwgYW5kIHByaW50IG91dCB0aGUgcmVzdWx0CgpgYGAKCiMjIFRhYm9vIG1hdGggb3BlcmF0aW9ucwoKQW5vdGhlciB3YXkgdG8gZ2V0IG1pc3NpbmcgdmFsdWVzIGlzIHRvIHBlcmZvcm0gYSBtYXRoIG9wZXJhdGlvbiB0aGF0IFIgZG9lc24ndCBsaWtlLiBMZXQncyB0cnkgZG9pbmcgdGhpcy4gUmVtZW1iZXIgdGhhdCB3ZSBjYW4gcGVyZm9ybSBvcGVyYXRpb25zIG9uIHZlY3RvcnMsIGUuZy4gYWRkaW5nIHR3byB2ZWN0b3JzIHRvIGVhY2ggb3RoZXIuIExldCdzIHRyeSBkaXZpZGluZyB2ZWN0b3JzIHRoaXMgd2F5LgpgYGB7cn0KdmVjdG9yXzEgPC0gYygxLCAyLCAwLCAzLCAwLCAtNSkKdmVjdG9yXzIgPC0gYygwLCAtMywgMSwgNiwgMCwgMCkKCiMgV2hhdCBkbyB5b3UgdGhpbmsgeW91J2xsIGdldCBpZiB5b3UgZGl2aWRlIHZlY3Rvcl8xIGJ5IHZlY3Rvcl8yPwoKIyBUcnkgaXQKCmBgYAoKIyMgUmVhbCBtaXNzaW5nIGRhdGEKRmluYWxseSwgeW91IGNhbiBlbnRlciBOQSBpbnRvIHlvdXIgdmVjdG9yLCBqdXN0IGxpa2UgeW91IHdvdWxkIGFueSBvdGhlciB2YWx1ZQpgYGB7cn0KIyBDcmVhdGUgYSB2ZWN0b3IsIGRhdGFfdmVjdG9yLCB3aGljaCBoYXMgc29tZSBudW1iZXJzIGFuZCBhdCBsZWFzdCBvbmUgTkEgdmFsdWUKCiMgV2hhdCBoYXBwZW5zIGlmIHlvdSB0YWtlIHRoZSBzdW0gb2YgZGF0YV92ZWN0b3I/CgpgYGAKCkxvdHMgb2YgZnVuY3Rpb25zIGluIFIsIGluY2x1ZGluZyBgc3VtKClgLCBoYXZlIGEgd2F5IG9mIGRlYWxpbmcgd2l0aCBtaXNzaW5nIGRhdGEgYXV0b21hdGljYWxseS4gVGhlcmUgYXJlIGxvdHMgb2YgdGltZXMgd2hlbiB3ZSBtYXkgd2FudCB0byBqdXN0IGlnbm9yZSB0aGUgbWlzc2luZyB2YWx1ZXMgYW5kIHdvcmsgd2l0aCB0aGUgcmVzdCBvZiB0aGUgZGF0YSB3ZSBoYXZlLiBUYWtlIGEgbG9vayBhdCB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgYHN1bSgpYDsgZG8geW91IHNlZSBhbnl0aGluZyBpbiB0aGVyZSB0aGF0IG1pZ2h0IHN1Z2dlc3QgaG93IHlvdSBjb3VsZCBnZXQgdGhlIGZ1bmN0aW9uIHRvIGlnbm9yZSBtaXNzaW5nIHZhbHVlcyBhbmQgdGFrZSB0aGUgc3VtIG9mICpkYXRhX3ZlY3RvciogYW55d2F5cz8KYGBge3J9CiMgVHJ5IHVzaW5nIHN1bSgpIHRvIGdldCB0aGUgc3VtIG9mIHRoZSBub24tbWlzc2luZyB2YWx1ZXMgaW4gZGF0YV92ZWN0b3IKCmBgYAoKIyBMb2dpY2FscwoKIyMgSW50cm9kdWN0aW9uIHRvIGxvZ2ljYWxzCgpJbiBSLCBpbiBhZGRpdGlvbiB0byBjaGFyYWN0ZXIgYW5kIG51bWVyaWMgdmFsdWVzLCB3ZSBjYW4gaGF2ZSBsb2dpY2FsIHZhbHVlcy4gTG9naWNhbCB2YWx1ZXMgYXJlIGBUUlVFYCBhbmQgYEZBTFNFYC4gVGhlc2Ugd29yZHMsIHdoZW4geW91IHR5cGUgdGhlbSwgYXJlIHNvbWV0aGluZyBsaWtlIGBOQWAgaW4gdGhhdCB0aGV5J3JlIHNwZWNpYWwgd29yZHMuIAoKTG9naWNhbCB2YWx1ZXMgYXJlIG9mdGVuIGdlbmVyYXRlZCBieSBjb21wYXJpc29ucyBiZXR3ZWVuIHR3byB2YWx1ZXMuIFRoZXNlIGNvbXBhcmlzb25zIGFyZSBtYWRlIHdpdGggbG9naWNhbCBvcGVyYXRvcnMuIE1hbnkgb2YgdGhlbSB5b3Ugd2lsbCBiZSBmYW1pbGlhciB3aXRoLgpgYGB7ciBMb2dpY30KMyA+IDQKOCA8IDUKNCA8PSA0CmBgYAoKTm90ZSB0aGF0IHRoZSBsb2dpY2FsIG9wZXJhdG9yICJpcyBlcXVhbCB0byIgaXMgYD09YCBpbiBSLiBJZiB5b3Ugb25seSB1c2UgYD1gLCB5b3Ugd2lsbCByZWFzc2lnbiB5b3VyIHZhcmlhYmxlICh0aGF0IGlzIGA9YCBpbiBSIGlzIHRoZSBzYW1lIGFzIGA8LWApLiAgCiJOb3QiIGlzIHNwZWNpZmllZCBieSBgIWAuIFNvICJpcyBub3QgZXF1YWwgdG8iIGlzIGAhPWAuCgpUcnkgdG8gZmlndXJlIG91dCB3aGF0IHRoZSBvdXRwdXQgb2YgZWFjaCBvZiB0aGUgZm9sbG93aW5nIGxpbmVzIHdpbGwgYmUgYmVmb3JlIHJ1bm5pbmcgdGhlbS4KYGBge3J9ClRSVUUgPT0gVFJVRQoKVFJVRSA9PSBGQUxTRQoKVFJVRSAhPSBGQUxTRQoKMyAhPSA0CgpjaGFyID0gJ2EnCmNoYXIgPT0gJ2EnCgpjaGFyID0gJ2InCmNoYXIgPT0gJ2EnCmBgYAoKIyMgTG9va2luZyBmb3IgbWlzc2luZyB2YWx1ZXMgaW4gYSB2ZWN0b3IKCk9uZSB1c2VmdWwgZnVuY3Rpb24gdGhhdCByZXN1bHRzIGluIGEgbG9naWNhbCB2YWx1ZSBpcyBgaXMubmEoKWAKYGBge3J9CiMgdHJ5IHVzaW5nIGlzLm5hKCkgb24gcG9zaXRpb24gMTEgaW4gcmV2aWV3X3ZlYwoKIyB0cnkgdXNpbmcgaXMubmEoKSBvbiByZXZpZXdfdmVjCgojIHRyeSB1c2luZyBpcy5uYSgpIG9uIGRhdGFfdmVjdG9yCgpgYGAKCkp1c3QgbGlrZSB5b3UgY2FuIG1ha2UgYSB2ZWN0b3Igb2YgY2hhcmFjdGVycyBvciBhIHZlY3RvciBvZiBudW1lcmljIHZhbHVlcywgeW91IGNhbiBhbHNvIG1ha2UgYSB2ZWN0b3Igb2YgbG9naWNhbHMuCmBgYHtyfQojIE1ha2UgYSB2ZWN0b3Igd2l0aCAzIFRSVUVzIGFuZCAyIEZBTFNFcywgc2F2ZSBpdCBhcyBsb2dpY2FsX3ZlYzEKCiMgTWFrZSBhIHZlY3RvciBjYWxsZWQgbnVtX3ZlYyB0aGF0IHN0YXJ0cyBhdCAyIGFuZCBlbmRzIGF0IDEwIChpbmNyZWFzaW5nIGJ5IDEpCgpsb2dpY2FsX3ZlYzIgPC0gbnVtX3ZlYyAlJSAzID09IDIgI3doYXQgaXMgdGhpcyBsaW5lIG9mIGNvZGUgZG9pbmc/CmBgYAoKIyMgVHJlYXRpbmcgbnVtYmVycyBhcyBsb2dpY2FscwoKSW4gUiwgRkFMU0UgaXMgYWxzbyBlbmNvZGVkIGFzIDAsIGFuZCBUUlVFIGlzIGVuY29kZWQgYXMgMS4gCmBgYHtyfQowPT1GQUxTRQoxPT1UUlVFCgojIEhvdyBkbyB5b3UgdGhpbmsgd2UgY291bGQgZWFzaWx5IGZpZ3VyZSBvdXQgaG93IG1hbnkgVFJVRXMgdGhlcmUgYXJlIGluIGxvZ2ljYWxfdmVjMj8KCiMgSG93IGNhbiB5b3UgZ2V0IFIgdG8gdGVsbCB5b3UgdGhlIG51bWJlciBvZiBtaXNzaW5nIHZhbHVlcyBpbiBkYXRhX3ZlY3Rvcj8KCmBgYAoKTnVtYmVycyBjYW4gYmUgdHJlYXRlZCBsaWtlIGxvZ2ljYWwgdmFsdWVzLCBlc3BlY2lhbGx5IHdpdGggYGFzLmxvZ2ljYWwoKWAuIDAgaXMgZmFsc2UsIGV2ZXJ5dGhpbmcgZWxzZSBpcyB0cnVlLgpgYGB7cn0KYXMubG9naWNhbCgtMjoyKQoKc3VtKGFzLmxvZ2ljYWwoLTI6MikpICMgd2hhdCBpcyBnb2luZyBvbiBoZXJlPwpgYGAKCiMjIEV4ZXJjaXNlCgpJbWFnaW5lIHRoYXQgeW91J3JlIGRvaW5nIGFuIGV4cGVyaW1lbnQgbWVhc3VyaW5nIHBsYW50IGhlaWdodCwgYnV0IHNvbWUgb2YgdGhlIHBsYW50cyBkaWRuJ3QgZ3Jvdy4gWW91IGRlY2lkZSB0aG9zZSBzaG91bGQgYmUgY29uc2lkZXJlZCBtaXNzaW5nIHZhbHVlcywgc28gdGhleSBlbnRlcmVkIGBOQWAgZm9yIHRob3NlIHBsYW50cy4gTGV0J3MgY291bnQgdGhlIG51bWJlciBvZiBwbGFudHMgdGhhdCBESUQgZ3JvdyBpbiB5b3VyIGV4cGVyaW1lbnQuCgpgYGB7cn0KcGxhbnRfaGVpZ2h0cyA8LSBjKDEuOSwgMC4xLCBOQSwgMC44LCAwLjQsIDAuMiwgNy45LCBOQSwgMTYuOCwgMy41KQoKIyBjcmVhdGUgYSBsb2dpY2FsIHZlY3RvciwgcGxhbnRfTkFfdmVjdG9yLCB0aGF0IGNvbnRhaW5zIGluZm9ybWF0aW9uIG9uIHdoZXRoZXIKIyBlYWNoIHZhbHVlIGluIHBsYW50X2hlaWdodHMgaXMgbWlzc2luZyAoTkEpCgojIHVzZSBwbGFudF9OQV92ZWN0b3IgdG8gZmlndXJlIG91dCBob3cgbWFueSBwbGFudHMgdG90YWwgZGlkbid0IGdyb3cKIyBhc3NpZ24gdGhpcyBudW1iZXIgdG8gYSB2YXJpYWJsZSBhbmQgcHJpbnQgaXQgb3V0CgojIHVzZSBwbGFudF9OQV92ZWN0b3IgdG8gZmlndXJlIG91dCBob3cgbWFueSBwbGFudHMgRElEIGdyb3cKIyBhc3NpZ24gdGhpcyBudW1iZXIgdG8gYSB2YXJpYWJsZSBhbmQgcHJpbnQgaXQgb3V0CgojIGJvbnVzOmZpZ3VyZSBvdXQgd2hhdCBQUk9QT1JUSU9OIG9mIHBsYW50cyBncmV3CiMgYXNzaWduIHRoaXMgbnVtYmVyIHRvIGEgdmFyaWFibGUgYW5kIHByaW50IGl0IG91dAoKYGBgCgojIFNlbGVjdGluZyBhbmQgcmVwbGFjaW5nIHZhbHVlcyBmcm9tIHZlY3RvcnMgYmFzZWQgb24gbG9naWNhbHMKCkluIGFkZGl0aW9uIHRvIHVzaW5nIGluZGljZXMgdG8gZ2V0IFIgdG8gdGVsbCB1cyBhIHNwZWNpZmljIHBvc2l0aW9uIGluIGEgdmVjdG9yLCB3ZSBjYW4gYWxzbyB1c2UgdGhlbSB0byByZXBsYWNlIHNwZWNpZmljIHZhbHVlcy4gVGFrZSBhIGxvb2sgYXQgdGhpcyBleGFtcGxlLgpgYGB7cn0KdmVjdG9yX3RvX3N1YiA8LSBjKDEyLCAxMywgMTQsIDE1LCBOQSwgMTcsIDE4LCAxOSkKCiMgcmVwbGFjZSB0aGUgMm5kIHZhbHVlIGluIHZlY3Rvcl90b19zdWIgd2l0aCA1NAp2ZWN0b3JfdG9fc3ViWzJdIDwtIDU0CnByaW50KHZlY3Rvcl90b19zdWIpCgojIG5vdywgdHJ5IHJlcGxhY2luZyB0aGUgMXN0LCAzcmQsIGFuZCA4dGggdmFsdWVzIGluIHZlY3Rvcl90b19zdWIgd2l0aCAyOCwKIyB1c2luZyBvbmx5IG9uZSBsaW5lIG9mIGNvZGUgKGkuZS4gZG8gaXQgYWxsIGF0IG9uY2UpCgpgYGAKCk9uZSByZWFsbHkgcG93ZXJmdWwgd2F5IHRvIHVzZSB0aGlzIHZlY3RvciBzdWJzdGl0dXRpb24gaXMgdG8gY29tYmluZSBpdCB3aXRoIGxvZ2ljYWwgdmVjdG9ycy4gVGFrZSBhIGxvb2sgYXQgdGhlIGV4YW1wbGUgYmVsb3c6CmBgYHtyfQp2ZWN0b3JfdG9fc3ViMiA8LSAxOjMKdmVjdG9yX3RvX3N1YjJbYyhUUlVFLCBGQUxTRSwgVFJVRSldIDwtIDQyCgojIFdoYXQgZG8geW91IHRoaW5rIHZlY3Rvcl90b19zdWIyIGxvb2tzIGxpa2Ugbm93PyBQcmludCBpdCBvdXQgdG8gY2hlY2sKCmBgYAoKVHJ5IHRoaXMgZm9yIHlvdXJzZWxmLiBMb3RzIG9mIHRpbWVzLCB3ZSB3YW50IHRvIHJlcGxhY2UgbWlzc2luZyB2YWx1ZXMgaW4gdmVjdG9ycy4gTGV0J3Mgc2F5IHRoYXQsIHdoZW4geW91IGRvIHlvdXIgYW5hbHlzaXMgb24gdGhlIHBsYW50IGV4YW1wbGUgYWJvdmUsIHlvdSB3YW50IHRvIHRyZWF0IHRoZSBwbGFudHMgdGhhdCBkaWRuJ3QgZ3JvdyBhcyBoYXZpbmcgYSBoZWlnaHQgb2YgMCByYXRoZXIgdGhhbiBiZWluZyBtaXNzaW5nLgpgYGB7cn0KIyB1c2UgcGxhbnRfTkFfdmVjdG9yIHRvIHJlcGxhY2UgZXZlcnkgbWlzc2luZyB2YWx1ZSBpbiBwbGFudF9oZWlnaHRzIHdpdGggYSAwCgojIHByaW50IHRoZSBtb2RpZmllZCBwbGFudF9oZWlnaHRzIHZlY3RvcgoKYGBgCgojIE9wZXJhdGlvbnMgb24gbG9naWNhbHMgKEFORCwgT1IpCgpXZSBjYW4gYWxzbyBkbyAiYW5kIiAoYCZgKSBhbmQgIm9yIiAoYHxgLCBhbGwgdGhlIHdheSBvbiB0aGUgcmlnaHQgc2lkZSBvZiB5b3VyIGtleWJvYXJkKS4gIkFuZCIgb25seSByZXR1cm5zIHRydWUgaWYgYm90aCB0aGluZ3MgYXJlIHRydWUuICJPciIgcmV0dXJucyB0cnVlIGlmIGF0IGxlYXN0IG9uZSB0aGluZyBpcyB0cnVlLgoKVHJ5IHByZWRpY3Rpbmcgd2hhdCBhbGwgdGhlIG9wZXJhdGlvbnMgYmVsb3cgd2lsbCByZXR1cm4KYGBge3J9ClRSVUUgJiBUUlVFClRSVUUgJiBGQUxTRQpGQUxTRSAmIEZBTFNFCgpGQUxTRSB8IFRSVUUKVFJVRSB8IFRSVUUKRkFMU0UgfCBGQUxTRQoKIyBib251czogcGVyZm9ybSBzb21lIG9wZXJhdGlvbnMgb24gdGhlIGZvbGxvd2luZyB2YXJpYWJsZXMgKHVuaWNvcm5zIGFuZAojIHJhaW5ib3dzKSB0aGF0IHdpbGwgcmVzdWx0IGluIGEgVFJVRSB2YWx1ZSBiZWluZyByZXR1cm5lZAp1bmljb3JucyA8LSBGQUxTRQpyYWluYm93cyA8LSBGQUxTRQoKYGBgCgojIFRoaW5ncyB3ZSBob3BlIHlvdSd2ZSBsZWFybmVkIHRvZGF5IChhbmQgd2lsbCBob3BlZnVsbHkgcmVtZW1iZXIgbmV4dCB0aW1lKQoKKiBXaGVuIG1pc3NpbmcgdmFsdWVzIGFyaXNlCiogVXNpbmcgYGlzLm5hKClgIHRvIGlkZW50aWZ5IHRoZSBwb3NpdGlvbnMgd2l0aCBtaXNzaW5nIHZhbHVlcyBpbiBhIHZlY3RvcgoqIExvZ2ljYWxzCiogVXNpbmcgbG9naWNhbHMgYXMgaW5kaWNlcyB0byBwdWxsIG91dCBvciBzdWJzdGl0dXRlIGVsZW1lbnRzIG9mIGEgdmVjdG9yIHRoYXQgbWF0Y2ggc29tZSBjcml0ZXJpYQoqIE9wZXJhdGlvbnMgdGhhdCBjYW4gYmUgcGVyZm9ybWVkIG9uIGxvZ2ljYWxzIChgJmAgYW5kIGB8YCk=