Introduction
This document presents a step-by-step demonstration of how the GSDtools
package created by Brett Eaton and Dan Moore can be applied to your bed surface grain size data. The package implements the use of binomial sampling theory to estimate percentile confidence ranges, as described by Eaton et. al (in review). The package contains a number of functions to easily visualize the data, but this example focuses on how to generate estimates of the upper and lower confidence bounds, and how to export them for use in a spreadsheet.
Setting up your working environment
We assume that you have already installed the R language on your computer, and that you have a graphical interface in which to run the code we present in this document. To install R, start at the R Project website. We recommend using the R Studio graphical interface to run R code (which can be downloaded here), but you may use whatever interface you are most comfortable with.
Entering the data
Users familiar with R will know that there are various ways of importing data and creating the necessary variables for analysis. To keep things simple, we will enter the grain size data as a string of numbers, the cumulative percent finer data as another string of data, and then combine them into a single table of data called a data.frame
in R. The following line of code creates a list of grain size data in the standard Wentworth size classes.
Now lets enter the cumulative proportion finer data that corresponds to each size.
Finally, we combine these two strings of number into a single data frame for analysis.
You can verify that the data match up properly by looking at the table.
print(my.data)
We can also plot the data to ensure that it all looks right.
plot(my.data, type = "b", log = "x", xlim = c(1, 1000))
Estimating the confidence bounds
Once we have a data.frame
with the necessary data that has variables called size
and probs
, we can calculate any percentile of interest (e.g. \(D_{50}\)), and its associated confidence range, but only if we know the number of stones that were measured to define the grain size distribution. Let’s assume that our distribution was based on a Wolman sample of 103 stones.
This can be done for a single percentile as follows:
This produces a data.frame
that records the percentile being estimated, the estimate of the percentile, and the upper and lower bounds for that estimate.
print(my.D50)
A more useful example would be to estimate the percentiles between \(D_{10}\) and \(D_{90}\) in increments of 5.
This produces a data.frame
with several lines of data, each representing an estimated percentile, along with its confidence interval.
head(my.Dvalues) #this command only shows the first few lines of data
Exporting the data
To export the data as a .csv
file, we simply specify a file name, and run the following command.
The file created by this command will be saved to whatever your working director is. If you don’t know what your working directory is, you can find out by running the command.
getwd()
You can use setwd
or the user interface menus to navigate to the directory where you want to save your file. In R Studio
, you go first to the Session
menu, then to Set Working Directory
, and finally you choose Choose Directory
.
The file you just generated can be imported into a spreadsheet, and you can generate whatever kind of plots you would like using the data. If you
Visualizing the data
The GSDtools
package also includes functions to make it easier to plot the confidence bounds. The key one is PolyCI
. Below, we plot the grain size data as before, then add a polygon the represents the confidence interval using the same inputs as were used above to generate my.Dvalues
.
{plot(my.data, type = "b", log = "x", xlim = c(1, 1000))
my.polygon = PolyCI(cfd = my.data, n = my.n, P = my.percentile, alpha = my.alpha)
polygon(my.polygon, lty = 0, col = rgb(0,0,1,0.25)) #makes a blue polygon
abline(h = c(0.1, 0.9), lty = 2)} #add lines indicating range of confidence interval
Comparing two distributions
There are two tools for comparing samples to determine if they are statistically similar or not. One tool uses raw data comprising measurements of b axis diameters for individual stones. The other tool uses data binned into size classes. We will use a random number generator to produce two samples of raw data to demonstrate the use of the first tool (CompareRAWs
), then we will bin that data to produce a cumulative frequency distribution to demonstrate the use of the second tool (CompareCFDs
).
We can create two samples as follows:
The CompareRAWs
tool uses a re-sampling (with replacement) approach to produce bootstrap confidence intervals for the differences in user-specified percentiles.
first.comparison = CompareRAWs(Raw1,Raw2, P = 50) #compare the 50th percentile
print(first.comparison)
Hint: You can play around with the sample size (n1
and n2
) to figure out when the differences in the 50th percentile are statistically significant, and when they are not.
We can also compare a number of percentiles at the same time.
scnd.comparison = CompareRAWs(Raw1,Raw2, P = seq(10,90,10)) #compare the 50th percentile
print(scnd.comparison)
hint: try running the sample generation code (i.e., Raw1 = 2^rnorm(n1, mean = 4.1, sd = 1)
) a few times with the same values and see how the results change.
Usually, we do not have measurements of individual grain sizes, we have binned data. We can transform our samples into cumulative frequency distributions as follows.
GSD1 = MakeCFD(Raw1)
GSD2 = MakeCFD(Raw2)
head(GSD1) #lets look at first few lines of the results for our first sample
We can use the inverse transform sampling approach to get a bootstrap estimate of the confidence interval for the differences between percentiles using the CompareCFDs
tool.
thrd.comparison = CompareCFDs(GSD1, GSD2, n1, n2, P = seq(10,90,10))
print(thrd.comparison)
Because we are using binned data, the CompareCFDs
tool will sometimes produce slightly different results than the CompareRAWs
tool, but our tests of the tools shows that they are generally produce relatively similar results. The differences are presumably introduced by the act of binning the raw data into 0.5\(\phi\) classes.
LS0tCnRpdGxlOiAiY2FsY3VsYXRpbmcgY29uZmlkZW5jZSBpbnRlcnZhbHMgZm9yIHN1cmZhY2UgZ3JhaW4gc2l6ZSBzYW1wbGVzIgphdXRob3I6ICJCcmV0dCBFYXRvbiIKZGF0ZTogIk1heSAyNCwgMjAxOSIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICBkZl9wcmludDogcGFnZWQKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMgSW50cm9kdWN0aW9uCgpUaGlzIGRvY3VtZW50IHByZXNlbnRzIGEgc3RlcC1ieS1zdGVwIGRlbW9uc3RyYXRpb24gb2YgaG93IHRoZSBgR1NEdG9vbHNgIHBhY2thZ2UgY3JlYXRlZCBieSBbQnJldHQgRWF0b25dKGh0dHBzOi8vYmxvZ3MudWJjLmNhL2JlYXRvbi8pIGFuZCBbRGFuIE1vb3JlXShodHRwOi8vaWJpcy5nZW9nLnViYy5jYS9+cmRtb29yZS8pIGNhbiBiZSBhcHBsaWVkIHRvIHlvdXIgYmVkIHN1cmZhY2UgZ3JhaW4gc2l6ZSBkYXRhLiBUaGUgcGFja2FnZSBpbXBsZW1lbnRzIHRoZSB1c2Ugb2YgYmlub21pYWwgc2FtcGxpbmcgdGhlb3J5IHRvIGVzdGltYXRlIHBlcmNlbnRpbGUgY29uZmlkZW5jZSByYW5nZXMsIGFzIGRlc2NyaWJlZCBieSBFYXRvbiBldC4gYWwgKGluIHJldmlldykuIFRoZSBwYWNrYWdlIGNvbnRhaW5zIGEgbnVtYmVyIG9mIGZ1bmN0aW9ucyB0byBlYXNpbHkgdmlzdWFsaXplIHRoZSBkYXRhLCBidXQgdGhpcyBleGFtcGxlIGZvY3VzZXMgb24gaG93IHRvIGdlbmVyYXRlIGVzdGltYXRlcyBvZiB0aGUgdXBwZXIgYW5kIGxvd2VyIGNvbmZpZGVuY2UgYm91bmRzLCBhbmQgaG93IHRvIGV4cG9ydCB0aGVtIGZvciB1c2UgaW4gYSBzcHJlYWRzaGVldC4KCiMgU2V0dGluZyB1cCB5b3VyIHdvcmtpbmcgZW52aXJvbm1lbnQKCldlIGFzc3VtZSB0aGF0IHlvdSBoYXZlIGFscmVhZHkgaW5zdGFsbGVkIHRoZSBSIGxhbmd1YWdlIG9uIHlvdXIgY29tcHV0ZXIsIGFuZCB0aGF0IHlvdSBoYXZlIGEgZ3JhcGhpY2FsIGludGVyZmFjZSBpbiB3aGljaCB0byBydW4gdGhlIGNvZGUgd2UgcHJlc2VudCBpbiB0aGlzIGRvY3VtZW50LiBUbyBpbnN0YWxsIFIsIHN0YXJ0IGF0IHRoZSBbUiBQcm9qZWN0XShodHRwczovL3d3dy5yLXByb2plY3Qub3JnLykgd2Vic2l0ZS4gV2UgcmVjb21tZW5kIHVzaW5nIHRoZSBSIFN0dWRpbyBncmFwaGljYWwgaW50ZXJmYWNlIHRvIHJ1biBSIGNvZGUgKHdoaWNoIGNhbiBiZSBkb3dubG9hZGVkIFtoZXJlXShodHRwczovL3d3dy5yc3R1ZGlvLmNvbS8pKSwgYnV0IHlvdSBtYXkgdXNlIHdoYXRldmVyIGludGVyZmFjZSAgeW91IGFyZSBtb3N0IGNvbWZvcnRhYmxlIHdpdGguCgojIyBJbnN0YWxsaW5nIHRoZSBHU0R0b29scyBwYWNrYWdlClRoZSBgR1NEdG9vbHNgIHBhY2thZ2UgaXMgaG9zdGVkIG9uIEJyZXR0IEVhdG9uJ3MgR2l0SHViIHBhZ2UsIGFuZCBpcyBmcmVlbHkgYWNjZXNzaWJsZSB0byBkb3dubG9hZC4gVG8gZG8gdGhpcywgd2Ugd2lsbCB1c2UgY29tbWFuZHMgaW4gdGhlIGBkZXZ0b29sc2AgcGFja2FnZS4gSWYgeW91IGhhdmUgbm90IGluc3RhbGxlZCBgZGV2dG9vbHNgIHlldCwgeW91IGNhbiBzaW1wbHkgcnVuIHRoZSBmb2xsb3dpbmcgY29tbWFuZC4KCmBgYHtyfQppZigiZGV2dG9vbHMiICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpID09IEZBTFNFKXsKICBpbnN0YWxsLnBhY2thZ2VzKCJkZXZ0b29scyIpfQpgYGAKCk5vdyB3ZSBjYW4gaW5zdGFsbCB0aGUgYEdTRHRvb2xzYCBwYWNrYWdlIGZyb20gR2l0SHViLgoKYGBge3J9CmlmKCJHU0R0b29scyIgJWluJSByb3duYW1lcyhpbnN0YWxsZWQucGFja2FnZXMoKSkgPT0gRkFMU0UpewogIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiYmNlYXRvbi9HU0R0b29scyIpfQpgYGAKCkZpbmFsbHksIHdlIG5lZWQgdG8gdGVsbCBSIHRoYXQgd2Ugd2lzaCB0byB1c2UgdGhlIGZ1bmN0aW9ucyBpbiB0aGUgYEdTRHRvb2xzYCBwYWNrYWdlIGJ5IHJ1bm5pbmcgdGhlIGZvbGxvd2luZyBjb21tYW5kLgoKYGBge3J9CmxpYnJhcnkoR1NEdG9vbHMpCmBgYAoKQXQgdGhpcyBwb2ludCwgd2Ugc2hvdWxkIGJlIHJlYWR5IHRvIGdvIHdpdGggb3VyIGFuYWx5c2lzLgoKIyBFbnRlcmluZyB0aGUgZGF0YQpVc2VycyBmYW1pbGlhciB3aXRoIFIgd2lsbCBrbm93IHRoYXQgdGhlcmUgYXJlIHZhcmlvdXMgd2F5cyBvZiBpbXBvcnRpbmcgZGF0YSBhbmQgY3JlYXRpbmcgdGhlIG5lY2Vzc2FyeSB2YXJpYWJsZXMgZm9yIGFuYWx5c2lzLiBUbyBrZWVwIHRoaW5ncyBzaW1wbGUsIHdlIHdpbGwgZW50ZXIgdGhlIGdyYWluIHNpemUgZGF0YSBhcyBhIHN0cmluZyBvZiBudW1iZXJzLCB0aGUgY3VtdWxhdGl2ZSBwZXJjZW50IGZpbmVyIGRhdGEgYXMgYW5vdGhlciBzdHJpbmcgb2YgZGF0YSwgYW5kIHRoZW4gY29tYmluZSB0aGVtIGludG8gYSBzaW5nbGUgdGFibGUgb2YgZGF0YSBjYWxsZWQgYSBgZGF0YS5mcmFtZWAgaW4gUi4gVGhlIGZvbGxvd2luZyBsaW5lIG9mIGNvZGUgY3JlYXRlcyBhIGxpc3Qgb2YgZ3JhaW4gc2l6ZSBkYXRhIGluIHRoZSBzdGFuZGFyZCBXZW50d29ydGggc2l6ZSBjbGFzc2VzLgoKYGBge3J9CnNpemUgPSBjKDI1NiwgMTgyLCAxMjgsIDkwLCA2NCwgNDUsIDMyLCAyMi42LCAxNiwgMTEuMywgOCwgNS42LCA0KQpgYGAKCk5vdyBsZXRzIGVudGVyIHRoZSBjdW11bGF0aXZlIHByb3BvcnRpb24gZmluZXIgZGF0YSB0aGF0IGNvcnJlc3BvbmRzIHRvIGVhY2ggc2l6ZS4KCmBgYHtyfQpwcm9icyA9IGMoMS4wMCwgMC45NywgMC44MywgMC43NiwgMC42MywgMC41MywgMC40MywgMC4zMiwgMC4yMSwgMC4xNSwgMC4xLCAwLjA1LCAwKQpgYGAKCkZpbmFsbHksIHdlIGNvbWJpbmUgdGhlc2UgdHdvIHN0cmluZ3Mgb2YgbnVtYmVyIGludG8gYSBzaW5nbGUgZGF0YSBmcmFtZSBmb3IgYW5hbHlzaXMuCgpgYGB7cn0KbXkuZGF0YSA9IGRhdGEuZnJhbWUoc2l6ZSwgcHJvYnMpCmBgYAoKWW91IGNhbiB2ZXJpZnkgdGhhdCB0aGUgZGF0YSBtYXRjaCB1cCBwcm9wZXJseSBieSBsb29raW5nIGF0IHRoZSB0YWJsZS4KCmBgYHtyfQpwcmludChteS5kYXRhKQpgYGAKCldlIGNhbiBhbHNvIHBsb3QgdGhlIGRhdGEgdG8gZW5zdXJlIHRoYXQgaXQgYWxsIGxvb2tzIHJpZ2h0LgoKYGBge3J9CnBsb3QobXkuZGF0YSwgdHlwZSA9ICJiIiwgbG9nID0gIngiLCB4bGltID0gYygxLCAxMDAwKSkKYGBgCgoKIyBFc3RpbWF0aW5nIHRoZSBjb25maWRlbmNlIGJvdW5kcwpPbmNlIHdlIGhhdmUgYSBgZGF0YS5mcmFtZWAgd2l0aCB0aGUgbmVjZXNzYXJ5IGRhdGEgdGhhdCBoYXMgdmFyaWFibGVzIGNhbGxlZCBgc2l6ZWAgYW5kIGBwcm9ic2AsIHdlIGNhbiBjYWxjdWxhdGUgYW55IHBlcmNlbnRpbGUgb2YgaW50ZXJlc3QgKGUuZy4gJERfezUwfSQpLCBhbmQgaXRzIGFzc29jaWF0ZWQgY29uZmlkZW5jZSByYW5nZSwgYnV0IG9ubHkgaWYgd2Uga25vdyB0aGUgbnVtYmVyIG9mIHN0b25lcyB0aGF0IHdlcmUgbWVhc3VyZWQgdG8gZGVmaW5lIHRoZSBncmFpbiBzaXplIGRpc3RyaWJ1dGlvbi4gTGV0J3MgYXNzdW1lIHRoYXQgb3VyIGRpc3RyaWJ1dGlvbiB3YXMgYmFzZWQgb24gYSBXb2xtYW4gc2FtcGxlIG9mIDEwMyBzdG9uZXMuCgpgYGB7cn0KbXkubiA9IDEwMwpgYGAKClRoaXMgY2FuIGJlIGRvbmUgZm9yIGEgc2luZ2xlIHBlcmNlbnRpbGUgYXMgZm9sbG93czoKCmBgYHtyfQpteS5wZXJjZW50aWxlID0gNTAgICNlc3RpbWF0ZSB0aGUgNTB0aCBwZXJjZW50aWxlCm15LmFscGhhID0gMC4wNSAgI3NldCB0aGUgY29uZmlkZW5jZSBpbnRlcnZhbCB0byBjb3ZlciA5NSUgb2YgdGhlIGRhdGEKbXkuRDUwID0gV29sbWFuQ0koY2ZkID0gbXkuZGF0YSwgbiA9IG15Lm4sIFAgPSBteS5wZXJjZW50aWxlLCBhbHBoYSA9IG15LmFscGhhKQpgYGAKClRoaXMgcHJvZHVjZXMgYSBgZGF0YS5mcmFtZWAgdGhhdCByZWNvcmRzIHRoZSBwZXJjZW50aWxlIGJlaW5nIGVzdGltYXRlZCwgdGhlIGVzdGltYXRlIG9mIHRoZSBwZXJjZW50aWxlLCBhbmQgdGhlIHVwcGVyIGFuZCBsb3dlciBib3VuZHMgZm9yIHRoYXQgZXN0aW1hdGUuCgpgYGB7cn0KcHJpbnQobXkuRDUwKQpgYGAKCkEgbW9yZSB1c2VmdWwgZXhhbXBsZSB3b3VsZCBiZSB0byBlc3RpbWF0ZSB0aGUgcGVyY2VudGlsZXMgYmV0d2VlbiAkRF97MTB9JCBhbmQgJERfezkwfSQgaW4gaW5jcmVtZW50cyBvZiA1LgoKYGBge3J9Cm15LnBlcmNlbnRpbGUgPSBjKDEwLCAxNSwgMjAsIDI1LCAzMCwgMzUsIDQwLCA0NSwgNTAsIAogICAgICAgICAgICAgNTUsIDYwLCA2NSwgNzAsIDc1LCA4MCwgODUsIDkwKQoKIyAgQWx0ZXJuYXRpdmUgY29kZSB0byBnZW5lcmF0ZSB5b3UgbGlzdCBvZiBwZXJjZW50aWxlcyB0byBlc3RpbWF0ZQojbXkucGVyY2VudGlsZXMgPSBzZXEoZnJvbSA9IDEwLCB0byA9IDkwLCBieSA9IDUpICAjZG9lcyB0aGUgc2FtZSB0aGluZyBhcyBhYm92ZQojbXkucGVyY2VudGlsZSA9IHNlcShmcm9tID0gMSwgdG8gPSA5MCwgYnkgPSAxKSAgI2dlbmVyYXRlcyBhbGwgcGVyY2VudGlsZXMsIDEwIHRvIDkwCgpteS5EdmFsdWVzID0gV29sbWFuQ0koY2ZkID0gbXkuZGF0YSwgbiA9IG15Lm4sIFAgPSBteS5wZXJjZW50aWxlLCBhbHBoYSA9IG15LmFscGhhKQpgYGAKClRoaXMgcHJvZHVjZXMgYSBgZGF0YS5mcmFtZWAgd2l0aCBzZXZlcmFsIGxpbmVzIG9mIGRhdGEsIGVhY2ggcmVwcmVzZW50aW5nIGFuIGVzdGltYXRlZCBwZXJjZW50aWxlLCBhbG9uZyB3aXRoIGl0cyBjb25maWRlbmNlIGludGVydmFsLgoKYGBge3J9CmhlYWQobXkuRHZhbHVlcykgICN0aGlzIGNvbW1hbmQgb25seSBzaG93cyB0aGUgZmlyc3QgZmV3IGxpbmVzIG9mIGRhdGEKYGBgCgojIEV4cG9ydGluZyB0aGUgZGF0YQpUbyBleHBvcnQgdGhlIGRhdGEgYXMgYSBgLmNzdmAgZmlsZSwgd2Ugc2ltcGx5IHNwZWNpZnkgYSBmaWxlIG5hbWUsIGFuZCBydW4gdGhlIGZvbGxvd2luZyBjb21tYW5kLgpgYGB7cn0KbXkuZmlsZSA9ICJzYW1wbGVfZGF0YS5jc3YiCndyaXRlLnRhYmxlKG15LkR2YWx1ZXMsIG15LmZpbGUsIHJvdy5uYW1lcyA9IEYsIHNlcCA9ICIsIikKYGBgCgpUaGUgZmlsZSBjcmVhdGVkIGJ5IHRoaXMgY29tbWFuZCB3aWxsIGJlIHNhdmVkIHRvIHdoYXRldmVyIHlvdXIgd29ya2luZyBkaXJlY3RvciBpcy4gSWYgeW91IGRvbid0IGtub3cgd2hhdCB5b3VyIHdvcmtpbmcgZGlyZWN0b3J5IGlzLCB5b3UgY2FuIGZpbmQgb3V0IGJ5IHJ1bm5pbmcgdGhlIGNvbW1hbmQuCgpgYGB7cn0KZ2V0d2QoKQpgYGAKCgpZb3UgY2FuIHVzZSBgc2V0d2RgIG9yIHRoZSB1c2VyIGludGVyZmFjZSBtZW51cyB0byBuYXZpZ2F0ZSB0byB0aGUgZGlyZWN0b3J5IHdoZXJlIHlvdSB3YW50IHRvIHNhdmUgeW91ciBmaWxlLiBJbiBgUiBTdHVkaW9gLCB5b3UgZ28gZmlyc3QgdG8gdGhlIGBTZXNzaW9uYCBtZW51LCB0aGVuIHRvIGBTZXQgV29ya2luZyBEaXJlY3RvcnlgLCBhbmQgZmluYWxseSB5b3UgY2hvb3NlIGBDaG9vc2UgRGlyZWN0b3J5YC4KClRoZSBmaWxlIHlvdSBqdXN0IGdlbmVyYXRlZCBjYW4gYmUgaW1wb3J0ZWQgaW50byBhIHNwcmVhZHNoZWV0LCBhbmQgeW91IGNhbiBnZW5lcmF0ZSB3aGF0ZXZlciBraW5kIG9mIHBsb3RzIHlvdSB3b3VsZCBsaWtlIHVzaW5nIHRoZSBkYXRhLiAgSWYgeW91CgojIFZpc3VhbGl6aW5nIHRoZSBkYXRhClRoZSBgR1NEdG9vbHNgIHBhY2thZ2UgYWxzbyBpbmNsdWRlcyBmdW5jdGlvbnMgdG8gbWFrZSBpdCBlYXNpZXIgdG8gcGxvdCB0aGUgY29uZmlkZW5jZSBib3VuZHMuIFRoZSBrZXkgb25lIGlzIGBQb2x5Q0lgLiBCZWxvdywgd2UgcGxvdCB0aGUgZ3JhaW4gc2l6ZSBkYXRhIGFzIGJlZm9yZSwgdGhlbiBhZGQgYSBwb2x5Z29uIHRoZSByZXByZXNlbnRzIHRoZSBjb25maWRlbmNlIGludGVydmFsIHVzaW5nIHRoZSBzYW1lIGlucHV0cyBhcyB3ZXJlIHVzZWQgYWJvdmUgdG8gZ2VuZXJhdGUgYG15LkR2YWx1ZXNgLiAKYGBge3J9CntwbG90KG15LmRhdGEsIHR5cGUgPSAiYiIsIGxvZyA9ICJ4IiwgeGxpbSA9IGMoMSwgMTAwMCkpCm15LnBvbHlnb24gPSBQb2x5Q0koY2ZkID0gbXkuZGF0YSwgbiA9IG15Lm4sIFAgPSBteS5wZXJjZW50aWxlLCBhbHBoYSA9IG15LmFscGhhKQpwb2x5Z29uKG15LnBvbHlnb24sIGx0eSA9IDAsIGNvbCA9IHJnYigwLDAsMSwwLjI1KSkgICNtYWtlcyBhIGJsdWUgcG9seWdvbiAKYWJsaW5lKGggPSBjKDAuMSwgMC45KSwgbHR5ID0gMil9ICAjYWRkIGxpbmVzIGluZGljYXRpbmcgcmFuZ2Ugb2YgY29uZmlkZW5jZSBpbnRlcnZhbApgYGAKCiMgQ29tcGFyaW5nIHR3byBkaXN0cmlidXRpb25zCgpUaGVyZSBhcmUgdHdvIHRvb2xzIGZvciBjb21wYXJpbmcgc2FtcGxlcyB0byBkZXRlcm1pbmUgaWYgdGhleSBhcmUgc3RhdGlzdGljYWxseSBzaW1pbGFyIG9yIG5vdC4gT25lIHRvb2wgdXNlcyByYXcgZGF0YSBjb21wcmlzaW5nIG1lYXN1cmVtZW50cyBvZiBiIGF4aXMgZGlhbWV0ZXJzIGZvciBpbmRpdmlkdWFsIHN0b25lcy4gVGhlIG90aGVyIHRvb2wgdXNlcyBkYXRhIGJpbm5lZCBpbnRvIHNpemUgY2xhc3Nlcy4gV2Ugd2lsbCB1c2UgYSByYW5kb20gbnVtYmVyIGdlbmVyYXRvciB0byBwcm9kdWNlIHR3byBzYW1wbGVzIG9mIHJhdyBkYXRhIHRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdGhlIGZpcnN0IHRvb2wgKGBDb21wYXJlUkFXc2ApLCB0aGVuIHdlIHdpbGwgYmluIHRoYXQgZGF0YSB0byBwcm9kdWNlIGEgY3VtdWxhdGl2ZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9uIHRvIGRlbW9uc3RyYXRlIHRoZSB1c2Ugb2YgdGhlIHNlY29uZCB0b29sIChgQ29tcGFyZUNGRHNgKS4KCldlIGNhbiBjcmVhdGUgdHdvIHNhbXBsZXMgYXMgZm9sbG93czoKCmBgYHtyfQpuMSA9IDE5NSAgI2RldGVybWluZSB0aGUgbnVtYmVyIG9mICJtZWFzdXJlbWVudHMiIHRvIG1ha2UgZm9yIHNhbXBsZSAxClJhdzEgPSAyXnJub3JtKG4xLCBtZWFuID0gNC4xLCBzZCA9IDEpICAjZ2VuZXJhdGUgYSBsb2ctbm9ybWFsIGRpc3RyaWJ1dGlvbiB3aXRoIHNwZWMuIG1lYW4gYW5kIHN0YW5kYXJkIGRldmlhdGlvbgpuMiA9IDIwMyAgI251bWJlciBvZiBtZWFzdXJlbWVudHMsIHNhbXBsZSAyClJhdzIgPSAyXnJub3JtKG4yLCBtZWFuID0gNC4zLCBzZCA9IDEpICAjbG9nLW5vcm1hbCBkaXN0cmlidXRpb24sIGRpZmZlcmVudCBtZWFuCmBgYAoKVGhlIGBDb21wYXJlUkFXc2AgdG9vbCB1c2VzIGEgcmUtc2FtcGxpbmcgKHdpdGggcmVwbGFjZW1lbnQpIGFwcHJvYWNoIHRvIHByb2R1Y2UgYm9vdHN0cmFwIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGZvciB0aGUgZGlmZmVyZW5jZXMgaW4gdXNlci1zcGVjaWZpZWQgcGVyY2VudGlsZXMuCgpgYGB7cn0KZmlyc3QuY29tcGFyaXNvbiA9IENvbXBhcmVSQVdzKFJhdzEsUmF3MiwgUCA9IDUwKSAgI2NvbXBhcmUgdGhlIDUwdGggcGVyY2VudGlsZQpwcmludChmaXJzdC5jb21wYXJpc29uKQpgYGAKSGludDogWW91IGNhbiBwbGF5IGFyb3VuZCB3aXRoIHRoZSBzYW1wbGUgc2l6ZSAoYG4xYCBhbmQgYG4yYCkgdG8gZmlndXJlIG91dCB3aGVuIHRoZSBkaWZmZXJlbmNlcyBpbiB0aGUgNTB0aCBwZXJjZW50aWxlIGFyZSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50LCBhbmQgd2hlbiB0aGV5IGFyZSBub3QuCgpXZSBjYW4gYWxzbyBjb21wYXJlIGEgbnVtYmVyIG9mIHBlcmNlbnRpbGVzIGF0IHRoZSBzYW1lIHRpbWUuCgpgYGB7cn0Kc2NuZC5jb21wYXJpc29uID0gQ29tcGFyZVJBV3MoUmF3MSxSYXcyLCBQID0gc2VxKDEwLDkwLDEwKSkgICNjb21wYXJlIHRoZSA1MHRoIHBlcmNlbnRpbGUKcHJpbnQoc2NuZC5jb21wYXJpc29uKQpgYGAKaGludDogdHJ5IHJ1bm5pbmcgdGhlIHNhbXBsZSBnZW5lcmF0aW9uIGNvZGUgKGkuZS4sIGBSYXcxID0gMl5ybm9ybShuMSwgbWVhbiA9IDQuMSwgc2QgPSAxKWApIGEgZmV3IHRpbWVzIHdpdGggdGhlIHNhbWUgdmFsdWVzIGFuZCBzZWUgaG93IHRoZSByZXN1bHRzIGNoYW5nZS4KClVzdWFsbHksIHdlIGRvIG5vdCBoYXZlIG1lYXN1cmVtZW50cyBvZiBpbmRpdmlkdWFsIGdyYWluIHNpemVzLCB3ZSBoYXZlIGJpbm5lZCBkYXRhLiBXZSBjYW4gdHJhbnNmb3JtIG91ciBzYW1wbGVzIGludG8gY3VtdWxhdGl2ZSBmcmVxdWVuY3kgZGlzdHJpYnV0aW9ucyBhcyBmb2xsb3dzLgoKYGBge3J9CkdTRDEgPSBNYWtlQ0ZEKFJhdzEpCkdTRDIgPSBNYWtlQ0ZEKFJhdzIpCmhlYWQoR1NEMSkgICNsZXRzIGxvb2sgYXQgZmlyc3QgZmV3IGxpbmVzIG9mIHRoZSByZXN1bHRzIGZvciBvdXIgZmlyc3Qgc2FtcGxlCmBgYAoKV2UgY2FuIHVzZSB0aGUgaW52ZXJzZSB0cmFuc2Zvcm0gc2FtcGxpbmcgYXBwcm9hY2ggdG8gZ2V0IGEgYm9vdHN0cmFwIGVzdGltYXRlIG9mIHRoZSBjb25maWRlbmNlIGludGVydmFsIGZvciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBwZXJjZW50aWxlcyB1c2luZyB0aGUgYENvbXBhcmVDRkRzYCB0b29sLgoKYGBge3J9CnRocmQuY29tcGFyaXNvbiA9IENvbXBhcmVDRkRzKEdTRDEsIEdTRDIsIG4xLCBuMiwgUCA9IHNlcSgxMCw5MCwxMCkpCnByaW50KHRocmQuY29tcGFyaXNvbikKYGBgCkJlY2F1c2Ugd2UgYXJlIHVzaW5nIGJpbm5lZCBkYXRhLCB0aGUgYENvbXBhcmVDRkRzYCB0b29sIHdpbGwgc29tZXRpbWVzIHByb2R1Y2Ugc2xpZ2h0bHkgZGlmZmVyZW50IHJlc3VsdHMgdGhhbiB0aGUgYENvbXBhcmVSQVdzYCB0b29sLCBidXQgb3VyIHRlc3RzIG9mIHRoZSB0b29scyBzaG93cyB0aGF0IHRoZXkgYXJlIGdlbmVyYWxseSBwcm9kdWNlIHJlbGF0aXZlbHkgc2ltaWxhciByZXN1bHRzLiBUaGUgZGlmZmVyZW5jZXMgYXJlIHByZXN1bWFibHkgaW50cm9kdWNlZCBieSB0aGUgYWN0IG9mIGJpbm5pbmcgdGhlIHJhdyBkYXRhIGludG8gMC41JFxwaGkkIGNsYXNzZXMuCg==