Instructions

This assignment is due on Friday October 19, 2018 at 11:59pm. You must submit your homework as report including a write up and all relevant code, and associated outputs it generated. You should learn how to use R Markdown to generate such a report and render it either as an HTML, PDF or Word Document. You can refer to chapter 3 of R Markdown: The Definitive Guide to review details on generating reports using R Markdown. If you generate your report with R Markdown, submit both the “.Rmd” file AND a rendered document.

Remarks:

  • This homework covers the material of lectures 1-6, so you are encouraged to start working on it early and continue gradually as we advance into the class.

  • If you generate random numbers, set a seed and report it, so that all your work can be perfectly reproduced.

  • Do not print an entire data.frame or a whole vector with more than 20 entries in your homework, since it would produce an unnecessarily large file, when you render your document.

  • Clearly label your final answer to the questions asked instead of only producing output of your code. Your answers should be as concise as possible and your code should be easily understandable.

  • You are welcome to work with other students, but you must write your own code, and prepare your own write up separately. If you choose to collaborate, indicate who you worked with on your submission.

  • You are free to use the web or any books to look up the documentation of relevant R functions and debug errors, but you cannot look for the solution to the specific homework problems.

  • If you have any questions regarding the homework, please ask on canvas or at office hours.

Exercise 1: R Basics [20 pt]

Material: Lecture 1.

a. Arithmetic operations [5pt]

Compute the following using R:

  • \(4.84 \log_{10}(51!)\), where \(x!\) is factorial of \(x\)
  • \(4.02 \sqrt[3]{7^2 + e^7}\)
  • \(20\cos( 2\pi + 0.25) + 32 \sin \left({3 \pi \over 4} \right)\)
  • \(\left \lfloor {4.011 \pi \over 3} {5 \choose 2} \right \rfloor\), where \(\lfloor x \rfloor\) means rounding to the largest integer not greater than x. where \({x \choose y}\) is the notation for combination
  • \(8.1 \sum_{i = 1}^{100} {1 \over i}\)

b. Matrix operations [5pt]

Generate a matrix \(A\) with 15 rows and 5 columns with entries being random uniform numbers on an interval \([0, 1]\). Then generate a matrix \(B\) with 5 rows and 7 columns where entries drawn from a Gaussian distribution with mean 0 and variance 10. Use set.seed() function with a chosen seed (record the seed) for reproducibility. Type in ?set.seed in the R console to learn more about the function. With the two matrices compute:

  • \(AB\) (a matrix product)
  • multiply the 3rd row of \(A\) by the 4th column of \(B\) and compute the sum of entries in the resulting vector, then check that agrees with a corresponding term in the matrix product you computed in the previous part.
  • obtain a vector which is a product of matrix multiplication between in matrix \(A\) and the 4th column of \(B\).

c. Factors [5pt]

In this part of the exercise we use a built-in data set, sleep, on student’s sleep. This data stores information on the increase in hours of sleep, type of drug administered, and the patient ID, in respective columns. You can learn more about this dataset from the page, accessed by calling ?sleep.

The column ID for patient identity is a factor with labels from 1 to 10. Rename the ID labels to letters of the alphabet in the reverse order, with label “A” assigned to patient 10, “B” to patient 9, “C” to patient 8, …, and “J” to patient 1.

d. Tibbles [5pt]

Create a tibble, ‘birthdays’, which stores information on the birthdays of 5 people either real of fictional. The data table should have columns:

  1. ‘first’: first name
  2. ‘last’: last name
  3. ‘birthday’: the person’s birthday in format YYYY-MM-DD (“%Y-%m-%d”)
  4. ‘city’: city where the person lives

Convert the birthdays to date objects using as.Date() function. Compute the difference (in days) between your birthday and the birthday of each of the people and append that information as a new column ‘bday_diff’ of the data-frame.

Exercise 2: Programming [20pt]

Material: Lecture 2.

a. Parametric function [5pt].

  • Write a function in are that evaluates the following:
\[\begin{align*} f(\theta) &= 7 - 0.5\sin(\theta) + 2.5\sin(3\theta) + 2\sin(5\theta) - 1.7\sin(7\theta) + \\ & \quad + 3\cos(2\theta) - 2\cos(4\theta) - 0.4\cos(16\theta) \end{align*}\]
  • Generate a vector, , equal to a sequence from \(0\) to \(2\pi\) with increments of \(0.01\)
  • Compute a vector \(x = f(\theta) \cdot \cos(\theta)\) and \(y = f(\theta) \cdot \sin(\theta)\) for \(\theta\) you just created.
  • Plot a scatter plot of (x, y) with two vectors computed.

b. Multiple arguments [10pt]

Write a function time_diff() that takes two dates as inputs and returns the difference between them in units of “hours”, “days”, “weeks”, “months”, or “years”, defined by an optional argument ‘units’, set by default to “days”. Use the function to compute time left to your next birthday separately in units of: months, days, and hours.

c. Control flow: Fibonacci numbers [5pt].

Fibonacci sequence starts with numbers 1 and 2, and each subsequent term is generated by adding the previous two terms. The first 10 terms of the Fibonacci sequence are thus: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, … . Find the total sum of even numbers in the Fibonacci sequence, each not exceeding one million.

Exercise 3: Data Import/Export and transformation [20pt]

Material: Lecture 3 and 5.

a. Import data [5pt]

Visit the following URL: https://raw.githubusercontent.com/cme195/cme195.github.io/master/assets/data/share-of-people-who-say-they-are-happy.txt

Observe the structure and format of the data. Then, use a function from readr package to read the data in the URL into R. Then, find the country with the highest share of happy people in 2014.

b. Export data [5pt]

Filter observations from the data set on happiness that correspond to years after 2000. Export the subset of the data as a tab-delimited text file to a chosen location on your computer.

c. dplyr functions [5pt]

In this exercise we use the package, nycflights13, storing datasets on flights and airports in the city of New York in 2013. Install the package with install.packages("nycflights13") if you have not done so already, then load it with library(nycflights13).

The dataset ‘fights’ is a tibble with 336,776 observations! To learn about the details about this dataset, type ?flights in your R console.

Use dplyr functions (and the %>% operator) to compute, for each combination of departure airport,‘origin’, destination airport, ‘dest’, and ‘carrier’: the average ‘dep_delay’, the average ‘air_time’ and the average ratio ‘dep_delay’/‘air_time’

For each ‘carrier’ report the route (‘origin’-‘dest’) with the highest mean ratio of departure delay over air time. Now, you know which flights not to take with a given carrier.

Note: Since, the dataset contains missing values, when computing the averages, remember to exclude the missing values (use ‘na.rm = TRUE’ in mean() function).

d. Joining/merging datasets [5pt]

The nycflights13 package also includes datasets other than flights. In this exercise you will combine data tables together.

  • First, drop columns that contain delay (ending with ‘delay’), and scheduling (starting with ’sched’) information, and save as a new tibble flights2.

  • Add a column with the full name of carriers operating the flights to flights2 by merging it with the airline tibble. Which column is(are) used for joining?

  • Another dataset available in the package is weather, storing data on weather at different airports at specific days and times. Use this dataset to merge the weather information to the data in the previous step. Which column is(are) used for joining?

  • There, is also a data-frame planes included in the package. planes share columns ‘year’ and ‘tailnum’ in planes with flights2 data-frame, but column ‘year’ in planes means a different thing (year produced) than in flights2(year of flight). Use only the column ‘tailnum’ to merge flights2 and planes. Note that the ‘suffix’ argument can be used to set different names to distinguish between year of production and year of of the flight.

  • Now, use the data-frame airports to merge flights2 with the information on the origin airport. Note that the column ‘faa’ is the airport identifier in the dataset airports. You must use the by = argument in the join function and specify which columns from flights2 you are matching to which column in airports.

Exercise 4: Data Visualization [20pt]

Material: Lecture 3-4.

The following url contains data on fossil fuel emissions for different countries between 1751 and 2014: “http://cdiac.ess-dive.lbl.gov/ftp/ndp030/CSV-FILES/nation.1751_2014.csv

a. Import data with readr [5pt]

This dataset is messy, and you will need to fix the warning messages read_csv() returns.

  • Rows 1-3 in contain information on the dataset itself, and not the variables; so after reading the data in, we need to delete these rows.
  • The datasets contains characters “.” which needs to be replaced with NA for missing data.
  • Rename column Total CO2 emissions from fossil-fuels and cement production (thousand metric tons of C) to something shorter, e.g. ‘Total_CO2’

b. Summarize data [5pt]

Use dplyr functions to compute the total yearly \(CO_2\) emissions (column Total.CO2.emissions.from.fossil.fuels.and.cement.production..thousand.metric. tons.of.C.) summed over all countries (the world total \(CO_2\) emission). Use the dataset to plot the World’s yearly \(CO_2\) emission in Gt.

c. Line plots [5pt]

Find the top 10 countries with highest emission after year 2000 (including 2000).

Plot the yearly total CO2 emissions of these top 10 countries with a different color for each country. Use billion tonnes (Gt) units, i.e. divide the total emissions by 10^6.

d. Stacked plots [5pt]

Use geom_area() to generate a plot similar to the one you generated above but, with emission levels stacked on top of each other (summing to the total for the ten countries) with areas colored by countries.

Exercise 5: Linear Models [20pt]

Material: Lecture 4 and 6.

In this exercise we will use a dataset containing information on sales of a product and the amount spent on advertising using different media channels. The data are available from: http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv.

a. Import and plot the data [5pt]

Read the data from “http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv”.

Then, generate a scatterplot of sales against the amount of TV advertising. Color the points by the mount of ‘radio’ advertising. Then, add a linear fit line.

b. Simple Linear Regression [5pt]

The dataset has 200 rows. Divide it into a train set with 150 observations and a test set with 50 observations, i.e. use sample() without replacement to randomly choose row indices of the advertising dataset to include in the train set. The remaining indices should be used for the test set.

Fit a linear model to the training set, where the sales values are predicted by the amount of TV advertising. Print the summary of the fitted model. Then, predict the sales values for the test set and evaluate the test model accuracy in terms of root mean squared error (RMSE), which measures the average level of error between the prediction and the true response. \[RMSE = \sqrt{\frac{1}{n} \sum\limits_{i = 1}^n(\hat y_i - y_i)^2}\]

c. Multiple linear regression [5pt]

Fit a multiple linear regression model including all the variables ‘TV’, ‘radio’, ‘newspaper’ to model the ‘sales’ in the training set. Then, compute the predicted sales for the test set with the new model and evaluate the RMSE.
Did the error decrease from the one corresponding to the previous model?

d. Evaluate the model [5pt]

Look at the summary output for the multiple regression model and note which of the coefficient in the model is significant. Are all of them significant? If not refit the model including only the features found significant. Which of the models should you choose?

LS0tCnRpdGxlOiAiSG9tZXdvcmsiCmF1dGhvcjogJ0Fzc2lnbmVkOiBPY3RvYmVyIDYsIDIwMTgnCmRhdGU6ICdEdWU6IE9jdG9iZXIgMTksIDIwMTggYXQgMTE6NTlwbScKb3V0cHV0OgogIHBkZl9kb2N1bWVudDoKICAgIG51bWJlcl9zZWN0aW9uczogbm8KICBodG1sX25vdGVib29rOgogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKc3VidGl0bGU6IENNRS9TVEFUIDE5NSwgRmFsbCAyMDE4Ci0tLQoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CnJtKGxpc3QgPSBscygpKQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmxpYnJhcnkodGlkeXZlcnNlKQpgYGAKCiMgSW5zdHJ1Y3Rpb25zCgpUaGlzIGFzc2lnbm1lbnQgaXMgZHVlIG9uIEZyaWRheSBPY3RvYmVyIDE5LCAyMDE4IGF0IDExOjU5cG0uIFlvdSBtdXN0IHN1Ym1pdCAKeW91ciBob21ld29yayBhcyByZXBvcnQgaW5jbHVkaW5nIGEgd3JpdGUgdXAgYW5kIGFsbCByZWxldmFudCBjb2RlLCBhbmQgCmFzc29jaWF0ZWQgb3V0cHV0cyBpdCBnZW5lcmF0ZWQuIFlvdSBzaG91bGQgbGVhcm4gaG93IHRvIHVzZSBSIE1hcmtkb3duIHRvCmdlbmVyYXRlIHN1Y2ggYSByZXBvcnQgYW5kIHJlbmRlciBpdCBlaXRoZXIgYXMgYW4gSFRNTCwgUERGIG9yIFdvcmQgRG9jdW1lbnQuCllvdSBjYW4gcmVmZXIgdG8gY2hhcHRlciAzIG9mIApbUiBNYXJrZG93bjogVGhlIERlZmluaXRpdmUgR3VpZGVdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi8pCnRvIHJldmlldyBkZXRhaWxzIG9uIGdlbmVyYXRpbmcgcmVwb3J0cyB1c2luZyBSIE1hcmtkb3duLiBJZiB5b3UgZ2VuZXJhdGUKeW91ciByZXBvcnQgd2l0aCBSIE1hcmtkb3duLCBzdWJtaXQgYm90aCB0aGUgIi5SbWQiIGZpbGUgCkFORCBhIHJlbmRlcmVkIGRvY3VtZW50LgoKUmVtYXJrczoKCiogVGhpcyBob21ld29yayBjb3ZlcnMgdGhlIG1hdGVyaWFsIG9mIGxlY3R1cmVzIDEtNiwgc28geW91IGFyZSBlbmNvdXJhZ2VkIAp0byBzdGFydCB3b3JraW5nIG9uIGl0IGVhcmx5IGFuZCBjb250aW51ZSBncmFkdWFsbHkgYXMgd2UgYWR2YW5jZSBpbnRvIHRoZSAKY2xhc3MuIAoKKiBJZiB5b3UgZ2VuZXJhdGUgcmFuZG9tIG51bWJlcnMsIHNldCBhIHNlZWQgYW5kIHJlcG9ydCBpdCwgCnNvIHRoYXQgYWxsIHlvdXIgd29yayBjYW4gYmUgcGVyZmVjdGx5IHJlcHJvZHVjZWQuIAoKKiBEbyBub3QgcHJpbnQgYW4gZW50aXJlIGBkYXRhLmZyYW1lYCBvciBhIHdob2xlIHZlY3RvciB3aXRoIG1vcmUgdGhhbiAyMAplbnRyaWVzIGluIHlvdXIgaG9tZXdvcmssIHNpbmNlIGl0IHdvdWxkIHByb2R1Y2UgYW4gdW5uZWNlc3NhcmlseSBsYXJnZSAKZmlsZSwgd2hlbiB5b3UgcmVuZGVyIHlvdXIgZG9jdW1lbnQuCgoqIENsZWFybHkgbGFiZWwgeW91ciBmaW5hbCBhbnN3ZXIgdG8gdGhlIHF1ZXN0aW9ucyBhc2tlZCBpbnN0ZWFkIG9mIG9ubHkKcHJvZHVjaW5nIG91dHB1dCBvZiB5b3VyIGNvZGUuIFlvdXIgYW5zd2VycyBzaG91bGQgYmUgYXMgY29uY2lzZSBhcyBwb3NzaWJsZSAKYW5kIHlvdXIgY29kZSBzaG91bGQgYmUgZWFzaWx5IHVuZGVyc3RhbmRhYmxlLiAKCiogWW91IGFyZSB3ZWxjb21lIHRvIHdvcmsgd2l0aCBvdGhlciBzdHVkZW50cywgYnV0IHlvdSBtdXN0IHdyaXRlIHlvdXIgb3duIGNvZGUsCmFuZCBwcmVwYXJlIHlvdXIgb3duIHdyaXRlIHVwIHNlcGFyYXRlbHkuIElmIHlvdSBjaG9vc2UgdG8gY29sbGFib3JhdGUsCmluZGljYXRlIHdobyB5b3Ugd29ya2VkIHdpdGggb24geW91ciBzdWJtaXNzaW9uLiAKCiogWW91IGFyZSBmcmVlIHRvIHVzZSB0aGUgd2ViIG9yIGFueSBib29rcyB0byBsb29rIHVwIHRoZSBkb2N1bWVudGF0aW9uIG9mIApyZWxldmFudCBSIGZ1bmN0aW9ucyBhbmQgZGVidWcgZXJyb3JzLCBidXQgeW91IGNhbm5vdCBsb29rIGZvciB0aGUgc29sdXRpb24KdG8gdGhlIHNwZWNpZmljIGhvbWV3b3JrIHByb2JsZW1zLiAKCiogSWYgeW91IGhhdmUgYW55IHF1ZXN0aW9ucyByZWdhcmRpbmcgdGhlIGhvbWV3b3JrLCBwbGVhc2UgYXNrIG9uIFtjYW52YXNdKGh0dHBzOi8vY2FudmFzLnN0YW5mb3JkLmVkdS8pIG9yIGF0IG9mZmljZSBob3Vycy4KCgojIEV4ZXJjaXNlIDE6IFIgQmFzaWNzIFsyMCBwdF0KCioqTWF0ZXJpYWw6IExlY3R1cmUgMS4qKgoKIyMgYS4gQXJpdGhtZXRpYyBvcGVyYXRpb25zIFs1cHRdIAoKQ29tcHV0ZSB0aGUgZm9sbG93aW5nIHVzaW5nIFI6CgoqICQ0Ljg0IFxsb2dfezEwfSg1MSEpJCwgd2hlcmUgJHghJCBpcyBmYWN0b3JpYWwgb2YgJHgkCiogJDQuMDIgXHNxcnRbM117N14yICsgZV43fSQKKiAkMjBcY29zKCAyXHBpICsgMC4yNSkgKyAzMiBcc2luIFxsZWZ0KHszIFxwaSBcb3ZlciA0fSBccmlnaHQpJAoqICRcbGVmdCBcbGZsb29yIHs0LjAxMSBccGkgXG92ZXIgM30gIHs1IFxjaG9vc2UgMn0gXHJpZ2h0IFxyZmxvb3IkLCB3aGVyZQokXGxmbG9vciB4IFxyZmxvb3IkIG1lYW5zIHJvdW5kaW5nIHRvIHRoZSBsYXJnZXN0IGludGVnZXIgbm90IGdyZWF0ZXIgdGhhbiB4Lgp3aGVyZSAke3ggXGNob29zZSB5fSQgaXMgdGhlIG5vdGF0aW9uIGZvciBbY29tYmluYXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NvbWJpbmF0aW9uKQoqICQ4LjEgXHN1bV97aSA9IDF9XnsxMDB9IHsxIFxvdmVyIGl9JAoKCiMjIGIuIE1hdHJpeCBvcGVyYXRpb25zIFs1cHRdIAoKR2VuZXJhdGUgYSBtYXRyaXggJEEkIHdpdGggMTUgcm93cyBhbmQgNSBjb2x1bW5zIHdpdGggZW50cmllcyAKYmVpbmcgcmFuZG9tIHVuaWZvcm0gbnVtYmVycyBvbiBhbiBpbnRlcnZhbCAkWzAsIDFdJC4KVGhlbiBnZW5lcmF0ZSBhIG1hdHJpeCAkQiQgd2l0aCA1IHJvd3MgYW5kIDcgY29sdW1ucyB3aGVyZSBlbnRyaWVzCmRyYXduIGZyb20gYSBHYXVzc2lhbiBkaXN0cmlidXRpb24gd2l0aCBtZWFuIDAgYW5kIHZhcmlhbmNlIDEwLgpVc2UgYHNldC5zZWVkKClgIGZ1bmN0aW9uIHdpdGggYSBjaG9zZW4gc2VlZCAocmVjb3JkIHRoZSBzZWVkKQpmb3IgcmVwcm9kdWNpYmlsaXR5LiBUeXBlIGluIGA/c2V0LnNlZWRgIGluIHRoZSBSIGNvbnNvbGUgdG8gbGVhcm4KbW9yZSBhYm91dCB0aGUgZnVuY3Rpb24uIFdpdGggdGhlIHR3byBtYXRyaWNlcyBjb21wdXRlOgoKKiAkQUIkIChhIG1hdHJpeCBwcm9kdWN0KQoqIG11bHRpcGx5IHRoZSAzcmQgcm93IG9mICRBJCBieSB0aGUgNHRoIGNvbHVtbiBvZiAkQiQgYW5kIGNvbXB1dGUKdGhlIHN1bSBvZiBlbnRyaWVzIGluIHRoZSByZXN1bHRpbmcgdmVjdG9yLCB0aGVuIGNoZWNrIHRoYXQgYWdyZWVzIHdpdGgKYSBjb3JyZXNwb25kaW5nIHRlcm0gaW4gdGhlIG1hdHJpeCBwcm9kdWN0IHlvdSBjb21wdXRlZCBpbiB0aGUgcHJldmlvdXMKcGFydC4KKiBvYnRhaW4gYSB2ZWN0b3Igd2hpY2ggaXMgYSBwcm9kdWN0IG9mIG1hdHJpeCBtdWx0aXBsaWNhdGlvbgpiZXR3ZWVuIGluIG1hdHJpeCAkQSQgYW5kIHRoZSA0dGggY29sdW1uIG9mICRCJC4gCgoKIyMgYy4gRmFjdG9ycyBbNXB0XSAKCkluIHRoaXMgcGFydCBvZiB0aGUgZXhlcmNpc2Ugd2UgdXNlIGEgYnVpbHQtaW4gZGF0YSBzZXQsIGBzbGVlcGAsIApvbiBzdHVkZW50J3Mgc2xlZXAuIFRoaXMgZGF0YSBzdG9yZXMgaW5mb3JtYXRpb24gb24gdGhlIAppbmNyZWFzZSBpbiBob3VycyBvZiBzbGVlcCwgdHlwZSBvZiBkcnVnIGFkbWluaXN0ZXJlZCwgYW5kIHRoZSBwYXRpZW50IElELAppbiByZXNwZWN0aXZlIGNvbHVtbnMuIFlvdSBjYW4gbGVhcm4gbW9yZSBhYm91dCB0aGlzIGRhdGFzZXQgZnJvbSB0aGUgcGFnZSwKYWNjZXNzZWQgYnkgY2FsbGluZyBgP3NsZWVwYC4gCgpUaGUgY29sdW1uIGBJRGAgZm9yIHBhdGllbnQgaWRlbnRpdHkgaXMgYSBmYWN0b3Igd2l0aCBsYWJlbHMgZnJvbSAxIHRvIDEwLgpSZW5hbWUgdGhlIElEIGxhYmVscyB0byBsZXR0ZXJzIG9mIHRoZSBhbHBoYWJldCBpbiB0aGUgcmV2ZXJzZSBvcmRlciwKd2l0aCBsYWJlbCAiQSIgYXNzaWduZWQgdG8gcGF0aWVudCAxMCwgIkIiIHRvIHBhdGllbnQgOSwgIkMiIHRvIHBhdGllbnQgOCwgCi4uLiwgYW5kICJKIiB0byBwYXRpZW50IDEuCgoKIyMgZC4gVGliYmxlcyBbNXB0XSAKCkNyZWF0ZSBhIHRpYmJsZSwgJ2JpcnRoZGF5cycsIHdoaWNoIHN0b3JlcyBpbmZvcm1hdGlvbiBvbiAKdGhlIGJpcnRoZGF5cyBvZiA1IHBlb3BsZSBlaXRoZXIgcmVhbCBvZiBmaWN0aW9uYWwuIApUaGUgZGF0YSB0YWJsZSBzaG91bGQgaGF2ZSBjb2x1bW5zOgoKMS4gJ2ZpcnN0JzogZmlyc3QgbmFtZQoyLiAnbGFzdCc6IGxhc3QgbmFtZQozLiAnYmlydGhkYXknOiB0aGUgcGVyc29uJ3MgYmlydGhkYXkgaW4gZm9ybWF0IFlZWVktTU0tREQgKCIlWS0lbS0lZCIpCjQuICdjaXR5JzogY2l0eSB3aGVyZSB0aGUgcGVyc29uIGxpdmVzCgpDb252ZXJ0IHRoZSBiaXJ0aGRheXMgdG8gZGF0ZSBvYmplY3RzIHVzaW5nIGBhcy5EYXRlKClgIGZ1bmN0aW9uLgpDb21wdXRlIHRoZSBkaWZmZXJlbmNlIChpbiBkYXlzKSBiZXR3ZWVuIHlvdXIgYmlydGhkYXkgYW5kIHRoZSBiaXJ0aGRheSAKb2YgZWFjaCBvZiB0aGUgcGVvcGxlIGFuZCBhcHBlbmQgdGhhdCBpbmZvcm1hdGlvbiBhcyBhIG5ldyBjb2x1bW4gCidiZGF5X2RpZmYnIG9mIHRoZSBkYXRhLWZyYW1lLgoKCiMgRXhlcmNpc2UgMjogUHJvZ3JhbW1pbmcgWzIwcHRdCgoqKk1hdGVyaWFsOiBMZWN0dXJlIDIuKioKCiMjIGEuIFBhcmFtZXRyaWMgZnVuY3Rpb24gWzVwdF0uCgoqIFdyaXRlIGEgZnVuY3Rpb24gaW4gYXJlIHRoYXQgZXZhbHVhdGVzIHRoZSBmb2xsb3dpbmc6CgpcYmVnaW57YWxpZ24qfQpmKFx0aGV0YSkgJj0gNyAtIDAuNVxzaW4oXHRoZXRhKSArIDIuNVxzaW4oM1x0aGV0YSkgKyAyXHNpbig1XHRoZXRhKSAtIDEuN1xzaW4oN1x0aGV0YSkgKyBcXAomIFxxdWFkICArICAzXGNvcygyXHRoZXRhKSAtIDJcY29zKDRcdGhldGEpIC0gMC40XGNvcygxNlx0aGV0YSkKXGVuZHthbGlnbip9CgoqIEdlbmVyYXRlIGEgdmVjdG9yLCBcdGV4dHR0e3RoZXRhfSwgZXF1YWwgdG8gYSBzZXF1ZW5jZSBmcm9tICQwJCB0byAkMlxwaSQgCndpdGggaW5jcmVtZW50cyBvZiAkMC4wMSQKKiBDb21wdXRlIGEgdmVjdG9yICR4ID0gZihcdGhldGEpIFxjZG90IFxjb3MoXHRoZXRhKSQgYW5kIAokeSA9IGYoXHRoZXRhKSBcY2RvdCBcc2luKFx0aGV0YSkkIGZvciAkXHRoZXRhJCB5b3UganVzdCBjcmVhdGVkLgoqIFBsb3QgYSBzY2F0dGVyIHBsb3Qgb2YgKHgsIHkpIHdpdGggdHdvIHZlY3RvcnMgY29tcHV0ZWQuCgoKIyMgYi4gTXVsdGlwbGUgYXJndW1lbnRzIFsxMHB0XQoKV3JpdGUgYSBmdW5jdGlvbiBgdGltZV9kaWZmKClgIHRoYXQgdGFrZXMgdHdvIGRhdGVzIGFzIGlucHV0cyBhbmQgcmV0dXJucwp0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZW0gaW4gdW5pdHMgb2YgImhvdXJzIiwgImRheXMiLCAid2Vla3MiLCAibW9udGhzIiwKb3IgInllYXJzIiwgZGVmaW5lZCBieSBhbiBvcHRpb25hbCBhcmd1bWVudCAndW5pdHMnLCBzZXQgYnkgZGVmYXVsdAp0byAiZGF5cyIuIFVzZSB0aGUgZnVuY3Rpb24gdG8gY29tcHV0ZSB0aW1lIGxlZnQgdG8geW91ciBuZXh0IGJpcnRoZGF5CnNlcGFyYXRlbHkgaW4gdW5pdHMgb2Y6IG1vbnRocywgZGF5cywgYW5kIGhvdXJzLgogCgojIyBjLiBDb250cm9sIGZsb3c6IEZpYm9uYWNjaSBudW1iZXJzIFs1cHRdLiAKCkZpYm9uYWNjaSBzZXF1ZW5jZSBzdGFydHMgd2l0aCBudW1iZXJzIDEgYW5kIDIsIGFuZCBlYWNoIHN1YnNlcXVlbnQgdGVybSAKaXMgZ2VuZXJhdGVkIGJ5IGFkZGluZyB0aGUgcHJldmlvdXMgdHdvIHRlcm1zLiBUaGUgZmlyc3QgMTAgdGVybXMgb2YgCnRoZSBGaWJvbmFjY2kgc2VxdWVuY2UgYXJlIHRodXM6IDEsIDIsIDMsIDUsIDgsIDEzLCAyMSwgMzQsIDU1LCA4OSwgLi4uIC4KRmluZCB0aGUgdG90YWwgc3VtIG9mICoqZXZlbiBudW1iZXJzKiogaW4gdGhlIEZpYm9uYWNjaSBzZXF1ZW5jZSwgCmVhY2ggbm90IGV4Y2VlZGluZyBvbmUgbWlsbGlvbi4KCiMgRXhlcmNpc2UgMzogRGF0YSBJbXBvcnQvRXhwb3J0IGFuZCB0cmFuc2Zvcm1hdGlvbiBbMjBwdF0KCioqTWF0ZXJpYWw6IExlY3R1cmUgMyBhbmQgNS4qKgoKIyMgYS4gSW1wb3J0IGRhdGEgWzVwdF0KClZpc2l0IHRoZSBmb2xsb3dpbmcgVVJMOgpodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vY21lMTk1L2NtZTE5NS5naXRodWIuaW8vbWFzdGVyL2Fzc2V0cy9kYXRhL3NoYXJlLW9mLXBlb3BsZS13aG8tc2F5LXRoZXktYXJlLWhhcHB5LnR4dAoKT2JzZXJ2ZSB0aGUgc3RydWN0dXJlIGFuZCBmb3JtYXQgb2YgdGhlIGRhdGEuIFRoZW4sIHVzZSBhIGZ1bmN0aW9uIGZyb20KYHJlYWRyYCBwYWNrYWdlIHRvIHJlYWQgdGhlIGRhdGEgaW4gdGhlIFVSTCBpbnRvIFIuClRoZW4sIGZpbmQgdGhlIGNvdW50cnkgd2l0aCB0aGUgaGlnaGVzdCBzaGFyZSBvZiBoYXBweSBwZW9wbGUgaW4gMjAxNC4KCiMjIGIuIEV4cG9ydCBkYXRhIFs1cHRdCgpGaWx0ZXIgb2JzZXJ2YXRpb25zIGZyb20gdGhlIGRhdGEgc2V0IG9uIGhhcHBpbmVzcyB0aGF0IGNvcnJlc3BvbmQgdG8geWVhcnMgCmFmdGVyIDIwMDAuIEV4cG9ydCB0aGUgc3Vic2V0IG9mIHRoZSBkYXRhIGFzIGEgdGFiLWRlbGltaXRlZCB0ZXh0IGZpbGUgCnRvIGEgY2hvc2VuIGxvY2F0aW9uIG9uIHlvdXIgY29tcHV0ZXIuCgoKIyMgYy4gYGRwbHlyYCBmdW5jdGlvbnMgWzVwdF0KCkluIHRoaXMgZXhlcmNpc2Ugd2UgdXNlIHRoZSBwYWNrYWdlLCBgbnljZmxpZ2h0czEzYCwgCnN0b3JpbmcgZGF0YXNldHMgb24gZmxpZ2h0cyBhbmQgYWlycG9ydHMgaW4gdGhlIGNpdHkgb2YgTmV3IFlvcmsgaW4gMjAxMy4KSW5zdGFsbCB0aGUgcGFja2FnZSB3aXRoIGBpbnN0YWxsLnBhY2thZ2VzKCJueWNmbGlnaHRzMTMiKWAgaWYgeW91CmhhdmUgbm90IGRvbmUgc28gYWxyZWFkeSwgdGhlbiBsb2FkIGl0IHdpdGggYGxpYnJhcnkobnljZmxpZ2h0czEzKWAuIAoKVGhlIGRhdGFzZXQgJ2ZpZ2h0cycgaXMgYSB0aWJibGUgd2l0aCAzMzYsNzc2IG9ic2VydmF0aW9ucyEgVG8gbGVhcm4gYWJvdXQgCnRoZSBkZXRhaWxzIGFib3V0IHRoaXMgZGF0YXNldCwgdHlwZSBgP2ZsaWdodHNgIGluIHlvdXIgUiBjb25zb2xlLiAKClVzZSBgZHBseXJgIGZ1bmN0aW9ucyAoYW5kIHRoZSBgJT4lYCBvcGVyYXRvcikgdG8gY29tcHV0ZSwgZm9yIGVhY2ggCmNvbWJpbmF0aW9uIG9mIGRlcGFydHVyZSBhaXJwb3J0LCdvcmlnaW4nLCBkZXN0aW5hdGlvbiBhaXJwb3J0LCAnZGVzdCcsCmFuZCAnY2Fycmllcic6IHRoZSBhdmVyYWdlICdkZXBfZGVsYXknLCB0aGUgYXZlcmFnZSAnYWlyX3RpbWUnCmFuZCB0aGUgYXZlcmFnZSByYXRpbyAnZGVwX2RlbGF5Jy8nYWlyX3RpbWUnCgpGb3IgZWFjaCAnY2FycmllcicgcmVwb3J0IHRoZSByb3V0ZSAoJ29yaWdpbictJ2Rlc3QnKSB3aXRoCnRoZSBoaWdoZXN0IG1lYW4gcmF0aW8gb2YgZGVwYXJ0dXJlIGRlbGF5IG92ZXIgYWlyIHRpbWUuIE5vdywgeW91IGtub3cKd2hpY2ggZmxpZ2h0cyBub3QgdG8gdGFrZSB3aXRoIGEgZ2l2ZW4gY2Fycmllci4KCgoqKk5vdGUqKjogU2luY2UsIHRoZSBkYXRhc2V0IGNvbnRhaW5zIG1pc3NpbmcgdmFsdWVzLCB3aGVuIGNvbXB1dGluZyB0aGUgCmF2ZXJhZ2VzLCByZW1lbWJlciB0byBleGNsdWRlIHRoZSBtaXNzaW5nIHZhbHVlcyAodXNlICduYS5ybSA9IFRSVUUnIGluIApgbWVhbigpYCBmdW5jdGlvbikuCgoKIyNkLiBKb2luaW5nL21lcmdpbmcgZGF0YXNldHMgWzVwdF0KClRoZSBgbnljZmxpZ2h0czEzYCBwYWNrYWdlIGFsc28gaW5jbHVkZXMgZGF0YXNldHMgb3RoZXIgdGhhbiBgZmxpZ2h0c2AuCkluIHRoaXMgZXhlcmNpc2UgeW91IHdpbGwgY29tYmluZSBkYXRhIHRhYmxlcyB0b2dldGhlci4KCiogRmlyc3QsIGRyb3AgY29sdW1ucyB0aGF0IGNvbnRhaW4gZGVsYXkgKGVuZGluZyB3aXRoICdfZGVsYXknKSwgYW5kCnNjaGVkdWxpbmcgKHN0YXJ0aW5nIHdpdGggJ3NjaGVkXycpIGluZm9ybWF0aW9uLCBhbmQKc2F2ZSBhcyBhIG5ldyB0aWJibGUgYGZsaWdodHMyYC4KCiogQWRkIGEgY29sdW1uIHdpdGggdGhlIGZ1bGwgbmFtZSBvZiBjYXJyaWVycyBvcGVyYXRpbmcgdGhlIGZsaWdodHMgdG8gCmBmbGlnaHRzMmAgYnkgbWVyZ2luZyBpdCB3aXRoIHRoZSBgYWlybGluZWAgdGliYmxlLiBXaGljaCBjb2x1bW4gaXMoYXJlKSAKdXNlZCBmb3Igam9pbmluZz8KCiogQW5vdGhlciBkYXRhc2V0IGF2YWlsYWJsZSBpbiB0aGUgcGFja2FnZSBpcyBgd2VhdGhlcmAsIHN0b3JpbmcgZGF0YSBvbiAKd2VhdGhlciBhdCBkaWZmZXJlbnQgYWlycG9ydHMgYXQgc3BlY2lmaWMgZGF5cyBhbmQgdGltZXMuIFVzZSB0aGlzIGRhdGFzZXQgdG8gCm1lcmdlIHRoZSB3ZWF0aGVyIGluZm9ybWF0aW9uIHRvIHRoZSBkYXRhIGluIHRoZSBwcmV2aW91cyBzdGVwLiAKV2hpY2ggY29sdW1uIGlzKGFyZSkgdXNlZCBmb3Igam9pbmluZz8KCiogVGhlcmUsIGlzIGFsc28gYSBkYXRhLWZyYW1lIGBwbGFuZXNgIGluY2x1ZGVkIGluIHRoZSBwYWNrYWdlLgpgcGxhbmVzYCBzaGFyZSBjb2x1bW5zICd5ZWFyJyBhbmQgJ3RhaWxudW0nIGluIGBwbGFuZXNgIHdpdGggYGZsaWdodHMyYApkYXRhLWZyYW1lLCBidXQgY29sdW1uICd5ZWFyJyBpbiBgcGxhbmVzYCBtZWFucyBhIGRpZmZlcmVudCB0aGluZyAKKHllYXIgcHJvZHVjZWQpIHRoYW4gaW4gYGZsaWdodHMyYCh5ZWFyIG9mIGZsaWdodCkuIFVzZSBvbmx5IHRoZSBjb2x1bW4gJ3RhaWxudW0nCnRvIG1lcmdlIGBmbGlnaHRzMmAgYW5kIGBwbGFuZXNgLiBOb3RlIHRoYXQgdGhlICdzdWZmaXgnIGFyZ3VtZW50IGNhbiBiZQp1c2VkIHRvIHNldCBkaWZmZXJlbnQgbmFtZXMgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiB5ZWFyIG9mIHByb2R1Y3Rpb24gYW5kIHllYXIKb2Ygb2YgdGhlIGZsaWdodC4KCiogTm93LCB1c2UgdGhlIGRhdGEtZnJhbWUgYGFpcnBvcnRzYCB0byBtZXJnZSBgZmxpZ2h0czJgCndpdGggdGhlIGluZm9ybWF0aW9uICoqb24gdGhlIG9yaWdpbiBhaXJwb3J0KiouIE5vdGUgdGhhdCB0aGUgY29sdW1uIAonZmFhJyBpcyB0aGUgYWlycG9ydCBpZGVudGlmaWVyIGluIHRoZSBkYXRhc2V0IGBhaXJwb3J0c2AuCllvdSBtdXN0IHVzZSB0aGUgYGJ5ID0gYCBhcmd1bWVudCBpbiB0aGUgam9pbiBmdW5jdGlvbgphbmQgc3BlY2lmeSB3aGljaCBjb2x1bW5zIGZyb20gYGZsaWdodHMyYCB5b3UgYXJlIG1hdGNoaW5nCnRvIHdoaWNoIGNvbHVtbiBpbiAgYGFpcnBvcnRzYC4KCgoKIyBFeGVyY2lzZSA0OiBEYXRhIFZpc3VhbGl6YXRpb24gWzIwcHRdCgoqKk1hdGVyaWFsOiBMZWN0dXJlIDMtNC4qKgoKVGhlIGZvbGxvd2luZyB1cmwgY29udGFpbnMgZGF0YSBvbiBmb3NzaWwgZnVlbCBlbWlzc2lvbnMgZm9yIGRpZmZlcmVudCAKY291bnRyaWVzIGJldHdlZW4gMTc1MSBhbmQgMjAxNDogImh0dHA6Ly9jZGlhYy5lc3MtZGl2ZS5sYmwuZ292L2Z0cC9uZHAwMzAvQ1NWLUZJTEVTL25hdGlvbi4xNzUxXzIwMTQuY3N2IgoKIyMgYS4gSW1wb3J0IGRhdGEgd2l0aCBgcmVhZHJgIFs1cHRdCgpUaGlzIGRhdGFzZXQgaXMgbWVzc3ksIGFuZCB5b3Ugd2lsbCBuZWVkIHRvIGZpeCB0aGUgd2FybmluZyBtZXNzYWdlcwpgcmVhZF9jc3YoKWAgcmV0dXJucy4KCiogUm93cyAxLTMgaW4gY29udGFpbiBpbmZvcm1hdGlvbiBvbiB0aGUgZGF0YXNldCBpdHNlbGYsIGFuZCBub3QgdGhlIHZhcmlhYmxlczsKc28gYWZ0ZXIgcmVhZGluZyB0aGUgZGF0YSBpbiwgd2UgbmVlZCB0byBkZWxldGUgdGhlc2Ugcm93cy4gCiogVGhlIGRhdGFzZXRzIGNvbnRhaW5zIGNoYXJhY3RlcnMgIi4iIHdoaWNoIG5lZWRzIHRvIGJlIHJlcGxhY2VkCndpdGggYE5BYCBmb3IgbWlzc2luZyBkYXRhLgoqIFJlbmFtZSBjb2x1bW4gYFRvdGFsIENPMiBlbWlzc2lvbnMgZnJvbSBmb3NzaWwtZnVlbHMgYW5kIGNlbWVudCBwcm9kdWN0aW9uICh0aG91c2FuZCBtZXRyaWMgdG9ucyBvZiBDKWAgdG8gc29tZXRoaW5nIHNob3J0ZXIsIGUuZy4gJ1RvdGFsX0NPMicKCiMjIGIuIFN1bW1hcml6ZSBkYXRhIFs1cHRdCgpVc2UgIGBkcGx5cmAgZnVuY3Rpb25zIHRvIGNvbXB1dGUgdGhlIHRvdGFsIHllYXJseSAkQ09fMiQgZW1pc3Npb25zIChjb2x1bW4gYFRvdGFsLkNPMi5lbWlzc2lvbnMuZnJvbS5mb3NzaWwuZnVlbHMuYW5kLmNlbWVudC5wcm9kdWN0aW9uLi50aG91c2FuZC5tZXRyaWMuCnRvbnMub2YuQy5gKSBzdW1tZWQgb3ZlciBhbGwgY291bnRyaWVzICh0aGUgd29ybGQgdG90YWwgJENPXzIkIGVtaXNzaW9uKS4gClVzZSB0aGUgZGF0YXNldCB0byBwbG90IHRoZSBXb3JsZCdzIHllYXJseSAkQ09fMiQgZW1pc3Npb24gaW4gR3QuCgoKIyMgYy4gTGluZSBwbG90cyBbNXB0XQoKRmluZCB0aGUgdG9wIDEwIGNvdW50cmllcyB3aXRoIGhpZ2hlc3QgZW1pc3Npb24gYWZ0ZXIgeWVhciAyMDAwIChpbmNsdWRpbmcgCjIwMDApLgoKUGxvdCB0aGUgeWVhcmx5IHRvdGFsIENPMiBlbWlzc2lvbnMgb2YgdGhlc2UgdG9wIDEwIGNvdW50cmllcwp3aXRoIGEgZGlmZmVyZW50IGNvbG9yIGZvciBlYWNoIGNvdW50cnkuIFVzZSBiaWxsaW9uIHRvbm5lcyAoR3QpIHVuaXRzLCAKaS5lLiBkaXZpZGUgdGhlIHRvdGFsIGVtaXNzaW9ucyBieSAxMF42LgoKCiMjIGQuIFN0YWNrZWQgcGxvdHMgWzVwdF0KClVzZSBgZ2VvbV9hcmVhKClgIHRvIGdlbmVyYXRlIGEgcGxvdCBzaW1pbGFyIHRvIHRoZSBvbmUgeW91IGdlbmVyYXRlZAphYm92ZSBidXQsIHdpdGggZW1pc3Npb24gbGV2ZWxzIHN0YWNrZWQgb24gdG9wCm9mIGVhY2ggb3RoZXIgKHN1bW1pbmcgdG8gdGhlIHRvdGFsIGZvciB0aGUgdGVuIGNvdW50cmllcykKd2l0aCBhcmVhcyBjb2xvcmVkIGJ5IGNvdW50cmllcy4KCgojIEV4ZXJjaXNlIDU6IExpbmVhciBNb2RlbHMgWzIwcHRdCgoqKk1hdGVyaWFsOiBMZWN0dXJlIDQgYW5kIDYuKioKCkluIHRoaXMgZXhlcmNpc2Ugd2Ugd2lsbCB1c2UgYSBkYXRhc2V0IGNvbnRhaW5pbmcgaW5mb3JtYXRpb24gb24gc2FsZXMgb2YKYSBwcm9kdWN0IGFuZCB0aGUgYW1vdW50IHNwZW50IG9uIGFkdmVydGlzaW5nIHVzaW5nIGRpZmZlcmVudCBtZWRpYSBjaGFubmVscy4KVGhlIGRhdGEgYXJlIGF2YWlsYWJsZSBmcm9tOiBodHRwOi8vd3d3LWJjZi51c2MuZWR1L35nYXJldGgvSVNML0FkdmVydGlzaW5nLmNzdi4KCiMjIGEuIEltcG9ydCBhbmQgcGxvdCB0aGUgZGF0YSBbNXB0XQoKUmVhZCB0aGUgZGF0YSBmcm9tICJodHRwOi8vd3d3LWJjZi51c2MuZWR1L35nYXJldGgvSVNML0FkdmVydGlzaW5nLmNzdiIuCgpUaGVuLCBnZW5lcmF0ZSBhIHNjYXR0ZXJwbG90IG9mIHNhbGVzIGFnYWluc3QgdGhlIGFtb3VudCBvZiBUViBhZHZlcnRpc2luZy4gCkNvbG9yIHRoZSBwb2ludHMgYnkgdGhlIG1vdW50IG9mICdyYWRpbycgYWR2ZXJ0aXNpbmcuIFRoZW4sIGFkZCBhIGxpbmVhciAKZml0IGxpbmUuCgoKIyMgYi4gU2ltcGxlIExpbmVhciBSZWdyZXNzaW9uIFs1cHRdCgpUaGUgZGF0YXNldCBoYXMgMjAwIHJvd3MuIERpdmlkZSBpdCBpbnRvIGEgdHJhaW4gc2V0IHdpdGggMTUwIG9ic2VydmF0aW9ucwphbmQgYSB0ZXN0IHNldCB3aXRoIDUwIG9ic2VydmF0aW9ucywgaS5lLiB1c2UgYHNhbXBsZSgpYCB3aXRob3V0CnJlcGxhY2VtZW50IHRvIHJhbmRvbWx5IGNob29zZSByb3cgaW5kaWNlcyBvZiB0aGUgYWR2ZXJ0aXNpbmcgZGF0YXNldCAKdG8gaW5jbHVkZSBpbiB0aGUgdHJhaW4gc2V0LiBUaGUgcmVtYWluaW5nIGluZGljZXMgc2hvdWxkIGJlIHVzZWQgZm9yIAp0aGUgdGVzdCBzZXQuIAoKRml0IGEgbGluZWFyIG1vZGVsIHRvIHRoZSB0cmFpbmluZyBzZXQsIHdoZXJlIHRoZSBzYWxlcyB2YWx1ZXMgYXJlCnByZWRpY3RlZCBieSB0aGUgYW1vdW50IG9mIFRWIGFkdmVydGlzaW5nLiBQcmludCB0aGUgc3VtbWFyeSBvZiB0aGUgZml0dGVkIG1vZGVsLgpUaGVuLCBwcmVkaWN0IHRoZSBzYWxlcyB2YWx1ZXMgZm9yIHRoZSB0ZXN0IHNldCBhbmQgZXZhbHVhdGUgdGhlIHRlc3QgbW9kZWwgCmFjY3VyYWN5IGluIHRlcm1zIG9mIHJvb3QgbWVhbiBzcXVhcmVkIGVycm9yIChSTVNFKSwgd2hpY2ggbWVhc3VyZXMgCnRoZSBhdmVyYWdlIGxldmVsIG9mIGVycm9yIGJldHdlZW4gdGhlIHByZWRpY3Rpb24gYW5kIHRoZSB0cnVlIHJlc3BvbnNlLgokJFJNU0UgPSBcc3FydHtcZnJhY3sxfXtufSBcc3VtXGxpbWl0c197aSA9IDF9Xm4oXGhhdCB5X2kgLSB5X2kpXjJ9JCQKCgojIyBjLiBNdWx0aXBsZSBsaW5lYXIgcmVncmVzc2lvbiBbNXB0XQoKRml0IGEgbXVsdGlwbGUgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgaW5jbHVkaW5nIGFsbCB0aGUgdmFyaWFibGVzICdUVicsCidyYWRpbycsICduZXdzcGFwZXInIHRvIG1vZGVsIHRoZSAnc2FsZXMnIGluIHRoZSB0cmFpbmluZyBzZXQuIFRoZW4sIGNvbXB1dGUgCnRoZSBwcmVkaWN0ZWQgc2FsZXMgZm9yIHRoZSB0ZXN0IHNldCB3aXRoIHRoZSBuZXcgbW9kZWwgYW5kIGV2YWx1YXRlIHRoZSBSTVNFLiAgCkRpZCB0aGUgZXJyb3IgZGVjcmVhc2UgZnJvbSB0aGUgb25lIGNvcnJlc3BvbmRpbmcgdG8gdGhlIHByZXZpb3VzIG1vZGVsPwoKCiMjIGQuIEV2YWx1YXRlIHRoZSBtb2RlbCBbNXB0XQoKTG9vayBhdCB0aGUgc3VtbWFyeSBvdXRwdXQgZm9yIHRoZSBtdWx0aXBsZSByZWdyZXNzaW9uIG1vZGVsIGFuZCBub3RlIHdoaWNoIApvZiB0aGUgY29lZmZpY2llbnQgaW4gdGhlIG1vZGVsIGlzIHNpZ25pZmljYW50LiBBcmUgYWxsIG9mIHRoZW0gc2lnbmlmaWNhbnQ/CklmIG5vdCByZWZpdCB0aGUgbW9kZWwgaW5jbHVkaW5nIG9ubHkgdGhlIGZlYXR1cmVzIGZvdW5kIHNpZ25pZmljYW50LgpXaGljaCBvZiB0aGUgbW9kZWxzIHNob3VsZCB5b3UgY2hvb3NlPyAKCg==