Boxplots for Exploratory Analysis.
This chapter will provide an overview of box and whiskers plots, describing what they are, why we use them and how to create them.
When we work with data, whether to explore it, use it to test hypotheses, or to present it to other people, we need to summarize all of our observations in a smaller number of summary statistics or visualizations. How we do this depends on the type of data that we have, the size of the data set, and the audience.
When it comes to types of variables, remember that we typically divide variables up into nominal/categorical, ordinal and interval/ratio. Some people add more types, for example calculated variables such as the murder rate or the poverty rate, but for this chapter we are going to group those with the interval/ratio variables. What makes these variables distinct is that they have an underlying unit that represents a fixed interval. Examples might be the number of children, the hours worked in a single day, or the percent of a state’s households that have income below the poverty level.
Describing numeric data
When we work with numerical variables and want to summarize them there are three basic characteristics that we usually focus on:
- Center also called central tendency or what is an “average” ot “typical” value for an observation.
- Variation or how different observations are from each other.
- Shape which can include anything from whether the distribution has one or more modes, whether it is symmetrical (if you folded it in half both sides would match), and whether it is more peaked or less peaked than a normal distribution (sometimes called kurtosis).
Each of these are at least somewhat related to the other two.
In trying to understand our data or to present the data to others we have a lot of choices.
Let’s use the iris data set as an example. We can use a set of basic statistics to describe Sepal.Length.
First a quick review about the median and quartiles. The median or 50th percentile is the value which half the observations are below and half the observations are above. To find it, we sort our data and then find the middle value.
Sepal.Length.Sorted <- sort(iris$Sepal.Length)
Sepal.Length.Sorted
[1] 4.3 4.4 4.4 4.4 4.5 4.6 4.6 4.6 4.6 4.7 4.7 4.8 4.8 4.8 4.8 4.8 4.9 4.9 4.9 4.9 4.9 4.9 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0 5.0
[32] 5.0 5.1 5.1 5.1 5.1 5.1 5.1 5.1 5.1 5.1 5.2 5.2 5.2 5.2 5.3 5.4 5.4 5.4 5.4 5.4 5.4 5.5 5.5 5.5 5.5 5.5 5.5 5.5 5.6 5.6 5.6
[63] 5.6 5.6 5.6 5.7 5.7 5.7 5.7 5.7 5.7 5.7 5.7 5.8 5.8 5.8 5.8 5.8 5.8 5.8 5.9 5.9 5.9 6.0 6.0 6.0 6.0 6.0 6.0 6.1 6.1 6.1 6.1
[94] 6.1 6.1 6.2 6.2 6.2 6.2 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.3 6.4 6.4 6.4 6.4 6.4 6.4 6.4 6.5 6.5 6.5 6.5 6.5 6.6 6.6 6.7 6.7
[125] 6.7 6.7 6.7 6.7 6.7 6.7 6.8 6.8 6.8 6.9 6.9 6.9 6.9 7.0 7.1 7.2 7.2 7.2 7.3 7.4 7.6 7.7 7.7 7.7 7.7 7.9
Since there are 150 irises, the middle value is between the 75th and 76th observations in the sorted data (150/2 =75). In this case
Sepal.Length.Sorted[75]
[1] 5.8
Sepal.Length.Sorted[76]
[1] 5.8
So our median is 5.8.
To get the first quartile or 25th percentile, we know that 150/4 = 37.5. Rounding up that is 38. Thirty-seven observations are below observation 38 and 37 observations are above observation 38 and below the space between observations 75 and 76.
Sepal.Length.Sorted[38]
[1] 5.1
On the other side, 75.5+37.5 = 113. There are 37 observations between starting at observation 76 and stopping at 112. There are 37 observations starting at just above 113 and going to 150.
Sepal.Length.Sorted[113]
[1] 6.4
You can get the same values by counting through the list of observations.
Or we can do a short cut.
summary(iris$Sepal.Length)
Min. 1st Qu. Median Mean 3rd Qu. Max.
4.300 5.100 5.800 5.843 6.400 7.900
This set of values, the so-called five number summary plus the mean, give us a fair amount of information about the Sepal.Length values. For example we see the highest and lowest values, which we could use to also calculate a measure of variation, the range (in this case, 7.9 - 4.3 = 3.6). We see the First and Third quaritles which we could use to calculate the interquartile range in this case (6.4 - 5.1 = 1.3).
We also see the mean and the median. For exploratory analysis we usually use the median as our basic measure of central tendency, but having both the mean and the median is useful because it often gives us a clue about skewness. If a mean is greater than the median the skew is often to the right. If it is less, the skew is usually to the left. If they are about the same there is generally no meaningful skew.
In the case of our Sepal.Length data we can see that the mean and median are almost the same. But we can also see that the maximum is a bit further from the median than the minimum is (7.9 - 5.8 = 2.1 versus 5.8 - 4.3 = 1.5). Once we start trying to make those kinds of comparisons, things quickly become complex. Using a data visualization can help with that, and a box and whiskers plot is one of the basic ways to do that. Let’s try yet another way to get our five number summary.
dplyr::summarize(iris, Minimum=min(Sepal.Length),
"1st Quartile" = quantile(Sepal.Length, .25),
Median = median(Sepal.Length),
"3rd Quartile" = quantile(Sepal.Length, .75),
Maximum = max(Sepal.Length))
This is great. However, now supposed we want to compare the five number summary for the three different species of irises to see if they are different. By the way, the sepal is the green part the encloses the petals of the flower.
iris.grouped<-dplyr::group_by(iris, Species)
dplyr::summarize(iris.grouped, Minimum=min(Sepal.Length),
"1st Quartile" = quantile(Sepal.Length, .25),
Median = median(Sepal.Length),
"3rd Quartile" = quantile(Sepal.Length, .75),
Maximum = max(Sepal.Length))
Table: Five Number Summary by Species
This is still a nice, compact summary but it is a bit difficult to see what is going on. For example we can see that the minimum for two species is the same, but their maximums and medians are different. Is this meaningful? Using a visual representation can help with making the comparisons.
Creating a Box Plot using ggplot2
The statistician and mathematician John Tukey developed box plots as a way to summarize this information visually. He was particularly interested in how to accurately summarize and interpret data without making any assumptions about the data and in the detection of unusual or influential data points, often called outliers. He wrote a ground breaking book called Exploratoray Data Analysis that presented many of his ideas about this.
library(ggplot2)
ggplot(iris, aes(y=Sepal.Length, x=Species)) +
geom_boxplot() +
ggtitle("Sepal Length by Species in Anderson's Iris Data")

This plot shows the same information as the table …. but even more. Let’s break it down. Each of the three species is represented by a box and whiskers – the lines sticking out of the boxes. One species–virginica– also has a point by itself. Each of the boxes has a dark line in the middle. For sertosa this is at 5.0, for versicolor this is at 5.9, and for virginica this is at 6.5. Compare those numbers to the table, and you will see that these represent the medians for each of the species. If you look at the bottom of the boxes, you will see they are at 4.8, 5.6, and 6.2. That is, they represent the first quartile. The top of the boxes are at 5.2, 6.3, and 6.9. They represent the third quartile.
That means that the boxes represent the middle 50% of the observations for each species, those between the first and the third quartile (25th and 75th percentiles).
If we look more closely at these boxes the visualization tells us some interesting things. For example there is no overlap between the setosa species middle half and those of the other two species. There is a tiny amount of overlap between the middle 50% of the versicolor and virginica species. The overlap is small enough that the median of versicolor is below the 25th percentile of virginica and the median of virginica is above the 75th percentile of versicolor.
If we took the distance from the top of each box to the bottom that would be the interquartile range. We can see that the IQR for setosa is much smaller than that for the other two species. We can also see that the median of setosa is in the middle of of its box, while for the other two species the median is closer to the bottom of the box than to the top.
Make sure you read over the previous two paragraphs really carefully and understand all of the sentences. If percentiles are new to you, it is totally normal that you will have to read it and look at the graphs several times.
Now let’s take a look at the whiskers. For setosa the bottom whisker extends to 4.3 and the top one to 5.8. Those correspond to the maximum and minimum values. Similathrly the lower whisker for versicolor extends to the minimum value, 4.9, and the top whisker extends to the maximum, 7.0. So for these two species, the whiskers represent the first and fourth quartiles. All five numbers from the five number summary are shown.
We can see that all of the setosa values fall below the medians of both the versicolor and virginica values.
Virginica is different. Notice that in addition to the lower whisker there is a single dot. Remember that in our table the minimum value for virginica was the same as that for setosa, 4.9. This is very strange considering that the median and first quartile of virginica are so much higher than for setosa. The box and whiskers plot highlights the strangeness of this and highlights just how far away that point is from the rest of the virginica observations. This kind of point is called an outlier because it is so far away from the other values. It’s such an odd plant for that species that we might even wonder if an example from another species was mislabelled or an error was made when the measurements were taken or copied by hand. On the other hand, maybe it is just a small flower because it was growing in the shade, was crowded by other plants or a random mutation. Many articles and books have been written using the iris data, and some errors have been found, but not for this flower.
This highlights an important point. Part of the purpose of a box and whiskers plot is to help identify outliers. That is why whiskers do not always go to the minimum or maximum value. There is a lot of debate in statistics about how to know if an observation is an outlier. Basically, this is an art and not a science but there are some rules of thumb that people use. In the case of box and whiskers plots this is how our graph would done if we were going to do it by hand rather than using convenient functions in our software.
- Calculate the Interquartile range.
third_quartile<-6.9
first_quartile<-6.225
iqr <- third_quartile - first_quartile
iqr
[1] 0.675
- Multiply the IQR by 1.5.
iqr1.5 <- 1.5* iqr
iqr1.5
[1] 1.0125
- Take this value and subtract it from the first quartile and add it to the third quartile
first_quartile - iqr1.5
[1] 5.2125
third_quartile + iqr1.5
[1] 7.9125
Any values 5.2 or lower or 7.9 or higher would be considered outliers. Therefore the observation that is 4.9 is an outlier, and it is the only virginica observation below 5.2. The lower whisker extends only to the lowest value that is greater than 5.2. Keep in mind that the original data was rounded to the nearest tenth when the plants were measured and we do not want to round an already rounded number.
Some crucial points
Here’s a crucial point. As a researcher and data analyst you have the ability to make many choices. In our box plots we used 1.5 times the IQR to define the whiskers. Not every box plot you see does this; in fact there are many variations on box plots. For example, sometimes a researcher may use 2 times the IQR or sometimes they may choose to extend the whiskers to the maximum.
If you learned to make a boxplot in elementary school you probably learned to extend the whiskers to the maximum. You could read the Help page for geom_boxplot() and learn how to change 1.5 to some other value.
If you are using a box plot for your own information, you can do what makes sense, but if you are presentng it to others you should always explain what approach you took to this.
Here’s a second crucial point. Just because you identified a point as an outlier does not mean you know what to do about it. As an analyst you have to consider what the outlier means and how its presence should impact your analysis. Whatever you do you should record the decision and reasons for it completely and make sure to share that information with consumers of your work. This is an essential element of doing reproducible research.
Now that you have seen how a box plot is created, you can understand why sometimes people are very confused by them. They are jam-packed with information and you could write many paragraphs just summarizing what our box plot shows us about these species of irises.
Here are ten statements based on our box plot. Make sure you understand why each one of them is true.
- More than 75% of virginica have longer sepal lengths than the median versicolor.
- All setosa have sepal lengths shorter than 75% of virginica.
- The longest setosa is about equal to the median versicolor.
- The shortest versicolor and shortest virginica are the same length.
- All of the irises with sepal length greater than 7 are virginica.
- All of the irises with sepal length less than 4.9 are setosa.
- The interquartile ranges for virginica and versicolor overlap but neither group’s median is in the overlapping area.
- The virginica species sepal length has one possible outlier.
- The variation of setosa is less than that of the other two species.
- THe virginica and versicolor distributions (centers, variation and shape) are more similar to each other than either is to the setosa.
LS0tCnRpdGxlOiAiQm94cGxvdCBOb3RlYm9vayIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQojIEJveHBsb3RzIGZvciBFeHBsb3JhdG9yeSBBbmFseXNpcy4KCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkobGVobWFuc29jaW9sb2d5KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmBgYAoKClRoaXMgY2hhcHRlciB3aWxsIHByb3ZpZGUgYW4gb3ZlcnZpZXcgb2YgYm94IGFuZCB3aGlza2VycyBwbG90cywgZGVzY3JpYmluZyB3aGF0IHRoZXkgYXJlLCB3aHkgd2UgdXNlIHRoZW0gYW5kIGhvdyB0byBjcmVhdGUgdGhlbS4KCldoZW4gd2Ugd29yayB3aXRoIGRhdGEsIHdoZXRoZXIgdG8gZXhwbG9yZSBpdCwgdXNlIGl0IHRvIHRlc3QgaHlwb3RoZXNlcywgb3IgdG8gcHJlc2VudCBpdCB0byBvdGhlciBwZW9wbGUsIHdlIG5lZWQgdG8gc3VtbWFyaXplIAphbGwgb2Ygb3VyIG9ic2VydmF0aW9ucyBpbiBhIHNtYWxsZXIgbnVtYmVyIG9mIHN1bW1hcnkgc3RhdGlzdGljcyBvciB2aXN1YWxpemF0aW9ucy4gIEhvdyB3ZSBkbyB0aGlzIGRlcGVuZHMgb24gdGhlIHR5cGUgb2YgZGF0YSB0aGF0IHdlIGhhdmUsIHRoZSBzaXplIG9mIHRoZSBkYXRhIHNldCwgYW5kIHRoZSBhdWRpZW5jZS4KCldoZW4gaXQgY29tZXMgdG8gdHlwZXMgb2YgdmFyaWFibGVzLCByZW1lbWJlciB0aGF0IHdlIHR5cGljYWxseSBkaXZpZGUgdmFyaWFibGVzIHVwIGludG8gbm9taW5hbC9jYXRlZ29yaWNhbCwgb3JkaW5hbCBhbmQgaW50ZXJ2YWwvcmF0aW8uICBTb21lIHBlb3BsZSBhZGQgbW9yZSB0eXBlcywgZm9yIGV4YW1wbGUgY2FsY3VsYXRlZCB2YXJpYWJsZXMgc3VjaCBhcyB0aGUgbXVyZGVyIHJhdGUgb3IgdGhlIHBvdmVydHkgcmF0ZSwgYnV0IGZvciB0aGlzIGNoYXB0ZXIgd2UgYXJlIGdvaW5nIHRvIGdyb3VwIHRob3NlIHdpdGggdGhlIGludGVydmFsL3JhdGlvIHZhcmlhYmxlcy4gV2hhdCBtYWtlcyB0aGVzZSB2YXJpYWJsZXMgZGlzdGluY3QgaXMgdGhhdCB0aGV5IGhhdmUgYW4gdW5kZXJseWluZyB1bml0IHRoYXQgcmVwcmVzZW50cyBhIGZpeGVkIGludGVydmFsLiBFeGFtcGxlcyBtaWdodCBiZSB0aGUgbnVtYmVyIG9mIGNoaWxkcmVuLCB0aGUgaG91cnMgd29ya2VkIGluIGEgc2luZ2xlIGRheSwgb3IgdGhlIHBlcmNlbnQgb2YgYSBzdGF0ZSdzIGhvdXNlaG9sZHMgdGhhdCBoYXZlIGluY29tZSBiZWxvdyB0aGUgcG92ZXJ0eSBsZXZlbC4gCgojIyBEZXNjcmliaW5nIG51bWVyaWMgZGF0YQoKV2hlbiB3ZSB3b3JrIHdpdGggbnVtZXJpY2FsIHZhcmlhYmxlcyBhbmQgd2FudCB0byBzdW1tYXJpemUgdGhlbSB0aGVyZSBhcmUgdGhyZWUgYmFzaWMgY2hhcmFjdGVyaXN0aWNzIHRoYXQgd2UgdXN1YWxseSBmb2N1cyBvbjogCgogKiBfQ2VudGVyXyBhbHNvIGNhbGxlZCBjZW50cmFsIHRlbmRlbmN5IG9yIHdoYXQgaXMgYW4gImF2ZXJhZ2UiIG90ICJ0eXBpY2FsIiB2YWx1ZSBmb3IgYW4gb2JzZXJ2YXRpb24uIAogKiBfVmFyaWF0aW9uXyBvciBob3cgZGlmZmVyZW50IG9ic2VydmF0aW9ucyBhcmUgZnJvbSBlYWNoIG90aGVyLiAKICogX1NoYXBlXyB3aGljaCBjYW4gaW5jbHVkZSBhbnl0aGluZyBmcm9tIHdoZXRoZXIgdGhlIGRpc3RyaWJ1dGlvbiBoYXMgb25lIG9yIG1vcmUgbW9kZXMsIHdoZXRoZXIgaXQgaXMgc3ltbWV0cmljYWwgKGlmIHlvdSBmb2xkZWQgaXQgaW4gaGFsZiBib3RoIHNpZGVzIHdvdWxkIG1hdGNoKSwgYW5kIHdoZXRoZXIgaXQgaXMgbW9yZSBwZWFrZWQgb3IgbGVzcyBwZWFrZWQgdGhhbiBhIG5vcm1hbCBkaXN0cmlidXRpb24gKHNvbWV0aW1lcyBjYWxsZWQga3VydG9zaXMpLiAKIApFYWNoIG9mIHRoZXNlIGFyZSBhdCBsZWFzdCBzb21ld2hhdCByZWxhdGVkIHRvIHRoZSBvdGhlciB0d28uIAoKSW4gdHJ5aW5nIHRvIHVuZGVyc3RhbmQgb3VyIGRhdGEgb3IgdG8gcHJlc2VudCB0aGUgZGF0YSB0byBvdGhlcnMgd2UgaGF2ZSBhIGxvdCBvZiBjaG9pY2VzLiAKCkxldCdzIHVzZSB0aGUgaXJpcyBkYXRhIHNldCBhcyBhbiBleGFtcGxlLiBXZSBjYW4gdXNlIGEgc2V0IG9mIGJhc2ljIHN0YXRpc3RpY3MgdG8gZGVzY3JpYmUgU2VwYWwuTGVuZ3RoLgoKRmlyc3QgYSBxdWljayByZXZpZXcgYWJvdXQgdGhlIG1lZGlhbiBhbmQgcXVhcnRpbGVzLiAgVGhlIG1lZGlhbiBvciA1MHRoIHBlcmNlbnRpbGUgaXMgdGhlIHZhbHVlIHdoaWNoIGhhbGYgdGhlIG9ic2VydmF0aW9ucyBhcmUgYmVsb3cgYW5kIGhhbGYgdGhlIG9ic2VydmF0aW9ucyBhcmUgYWJvdmUuICBUbyBmaW5kIGl0LCB3ZSBzb3J0IG91ciBkYXRhIGFuZCB0aGVuIGZpbmQgdGhlIG1pZGRsZSB2YWx1ZS4KCmBgYHtyfQpTZXBhbC5MZW5ndGguU29ydGVkIDwtIHNvcnQoaXJpcyRTZXBhbC5MZW5ndGgpClNlcGFsLkxlbmd0aC5Tb3J0ZWQKYGBgCgpTaW5jZSB0aGVyZSBhcmUgMTUwIGlyaXNlcywgdGhlIG1pZGRsZSB2YWx1ZSBpcyBiZXR3ZWVuIHRoZSA3NXRoIGFuZCA3NnRoIG9ic2VydmF0aW9ucyBpbiB0aGUgc29ydGVkIGRhdGEgKDE1MC8yID03NSkuIEluIHRoaXMgY2FzZQpgYGB7cn0KU2VwYWwuTGVuZ3RoLlNvcnRlZFs3NV0KU2VwYWwuTGVuZ3RoLlNvcnRlZFs3Nl0KYGBgClNvIG91ciBtZWRpYW4gaXMgNS44LiAgCgpUbyBnZXQgdGhlIGZpcnN0IHF1YXJ0aWxlIG9yIDI1dGggcGVyY2VudGlsZSwgIHdlIGtub3cgdGhhdCAxNTAvNCA9IDM3LjUuIFJvdW5kaW5nIHVwIHRoYXQgaXMgMzguIFRoaXJ0eS1zZXZlbiBvYnNlcnZhdGlvbnMgYXJlIGJlbG93IG9ic2VydmF0aW9uIDM4IGFuZCAzNyBvYnNlcnZhdGlvbnMgYXJlIGFib3ZlIG9ic2VydmF0aW9uIDM4IGFuZCBiZWxvdyB0aGUgc3BhY2UgYmV0d2VlbiBvYnNlcnZhdGlvbnMgNzUgYW5kIDc2LiAKCmBgYHtyfQpTZXBhbC5MZW5ndGguU29ydGVkWzM4XQpgYGAKCk9uIHRoZSBvdGhlciBzaWRlLCA3NS41KzM3LjUgPSAxMTMuICBUaGVyZSBhcmUgMzcgb2JzZXJ2YXRpb25zIGJldHdlZW4gc3RhcnRpbmcgYXQgb2JzZXJ2YXRpb24gNzYgYW5kIHN0b3BwaW5nIGF0IDExMi4gVGhlcmUgYXJlICAzNyBvYnNlcnZhdGlvbnMgc3RhcnRpbmcgYXQganVzdCBhYm92ZSAxMTMgYW5kIGdvaW5nIHRvIDE1MC4KYGBge3J9ClNlcGFsLkxlbmd0aC5Tb3J0ZWRbMTEzXQpgYGAKCllvdSBjYW4gZ2V0IHRoZSBzYW1lIHZhbHVlcyBieSBjb3VudGluZyB0aHJvdWdoIHRoZSBsaXN0IG9mIG9ic2VydmF0aW9ucy4KCk9yIHdlIGNhbiBkbyBhIHNob3J0IGN1dC4KCmBgYHtyfQoKc3VtbWFyeShpcmlzJFNlcGFsLkxlbmd0aCkKCmBgYAoKVGhpcyBzZXQgb2YgdmFsdWVzLCB0aGUgc28tY2FsbGVkIGZpdmUgbnVtYmVyIHN1bW1hcnkgcGx1cyB0aGUgbWVhbiwgZ2l2ZSB1cyBhIGZhaXIgYW1vdW50IG9mIGluZm9ybWF0aW9uIGFib3V0IHRoZSBTZXBhbC5MZW5ndGggdmFsdWVzLgpGb3IgZXhhbXBsZSB3ZSBzZWUgdGhlIGhpZ2hlc3QgYW5kIGxvd2VzdCB2YWx1ZXMsIHdoaWNoIHdlIGNvdWxkIHVzZSB0byBhbHNvIGNhbGN1bGF0ZSBhIG1lYXN1cmUgb2YgdmFyaWF0aW9uLCB0aGUgcmFuZ2UgKGluIHRoaXMgY2FzZSwgNy45IC0gNC4zID0gMy42KS4gIFdlIHNlZSB0aGUgRmlyc3QgYW5kIFRoaXJkIHF1YXJpdGxlcyB3aGljaCB3ZSBjb3VsZCB1c2UgdG8gY2FsY3VsYXRlIHRoZSBpbnRlcnF1YXJ0aWxlIHJhbmdlIGluIHRoaXMgY2FzZSAoNi40IC0gNS4xID0gMS4zKS4KCldlIGFsc28gc2VlIHRoZSBtZWFuIGFuZCB0aGUgbWVkaWFuLiAgRm9yIGV4cGxvcmF0b3J5IGFuYWx5c2lzIHdlIHVzdWFsbHkgdXNlIHRoZSBtZWRpYW4gYXMgb3VyIGJhc2ljIG1lYXN1cmUgb2YgY2VudHJhbCB0ZW5kZW5jeSwgYnV0IGhhdmluZyBib3RoIHRoZSBtZWFuIGFuZCB0aGUgbWVkaWFuIGlzIHVzZWZ1bCBiZWNhdXNlIGl0IG9mdGVuIGdpdmVzIHVzIGEgY2x1ZSBhYm91dCBza2V3bmVzcy4gSWYgYSBtZWFuIGlzIGdyZWF0ZXIgdGhhbiB0aGUgbWVkaWFuIHRoZSBza2V3IGlzIG9mdGVuIHRvIHRoZSByaWdodC4gSWYgaXQgaXMgbGVzcywgdGhlIHNrZXcgaXMgdXN1YWxseSB0byB0aGUgbGVmdC4gIElmIHRoZXkgYXJlIGFib3V0IHRoZSBzYW1lIHRoZXJlIGlzIGdlbmVyYWxseSBubyBtZWFuaW5nZnVsIHNrZXcuCgpJbiB0aGUgY2FzZSBvZiBvdXIgU2VwYWwuTGVuZ3RoIGRhdGEgd2UgY2FuIHNlZSB0aGF0IHRoZSBtZWFuIGFuZCBtZWRpYW4gYXJlIGFsbW9zdCB0aGUgc2FtZS4gQnV0IHdlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZSBtYXhpbXVtIGlzIGEgYml0IGZ1cnRoZXIgZnJvbSB0aGUgbWVkaWFuIHRoYW4gdGhlIG1pbmltdW0gaXMgKDcuOSAtIDUuOCA9IDIuMSB2ZXJzdXMgIDUuOCAtIDQuMyA9IDEuNSkuIE9uY2Ugd2Ugc3RhcnQgdHJ5aW5nIHRvIG1ha2UgdGhvc2Uga2luZHMgb2YgY29tcGFyaXNvbnMsIHRoaW5ncyBxdWlja2x5IGJlY29tZSBjb21wbGV4LiBVc2luZyBhIGRhdGEgdmlzdWFsaXphdGlvbiBjYW4gaGVscCB3aXRoIHRoYXQsIGFuZCBhIGJveCBhbmQgd2hpc2tlcnMgcGxvdCBpcyBvbmUgb2YgdGhlIGJhc2ljIHdheXMgdG8gZG8gdGhhdC4gTGV0J3MgdHJ5IHlldCBhbm90aGVyIHdheSB0byBnZXQgb3VyIGZpdmUgbnVtYmVyIHN1bW1hcnkuCgpgYGB7cn0KZHBseXI6OnN1bW1hcml6ZShpcmlzLCBNaW5pbXVtPW1pbihTZXBhbC5MZW5ndGgpLCAKICAgICAgICAgICAgICAgICAiMXN0IFF1YXJ0aWxlIiA9IHF1YW50aWxlKFNlcGFsLkxlbmd0aCwgLjI1KSwKICAgICAgICAgICAgICAgICBNZWRpYW4gPSBtZWRpYW4oU2VwYWwuTGVuZ3RoKSwgCiAgICAgICAgICAgICAgICAgIjNyZCBRdWFydGlsZSIgPSBxdWFudGlsZShTZXBhbC5MZW5ndGgsIC43NSksIAogICAgICAgICAgICAgICAgIE1heGltdW0gPSBtYXgoU2VwYWwuTGVuZ3RoKSkKYGBgCgpUaGlzIGlzIGdyZWF0LiAgSG93ZXZlciwgbm93IHN1cHBvc2VkIHdlIHdhbnQgdG8gY29tcGFyZSB0aGUgZml2ZSBudW1iZXIgc3VtbWFyeSBmb3IgdGhlIHRocmVlIGRpZmZlcmVudCBzcGVjaWVzIG9mIGlyaXNlcyB0byBzZWUgaWYgCnRoZXkgYXJlIGRpZmZlcmVudC4gIEJ5IHRoZSB3YXksIHRoZSBzZXBhbCAgaXMgdGhlIGdyZWVuIHBhcnQgdGhlIGVuY2xvc2VzIHRoZSBwZXRhbHMgb2YgdGhlIGZsb3dlci4KCgpgYGB7ciB0YWJsZS5jYXA9IlNlcGFsIExlbmd0aCA1IE51bWJlciBTdW1tYXJ5IGJ5IFNwZWNpZXMifQppcmlzLmdyb3VwZWQ8LWRwbHlyOjpncm91cF9ieShpcmlzLCBTcGVjaWVzKQpkcGx5cjo6c3VtbWFyaXplKGlyaXMuZ3JvdXBlZCwgTWluaW11bT1taW4oU2VwYWwuTGVuZ3RoKSwgCiAgICAgICAgICAgICAgICAgIjFzdCBRdWFydGlsZSIgPSBxdWFudGlsZShTZXBhbC5MZW5ndGgsIC4yNSksCiAgICAgICAgICAgICAgICAgTWVkaWFuID0gbWVkaWFuKFNlcGFsLkxlbmd0aCksIAogICAgICAgICAgICAgICAgICIzcmQgUXVhcnRpbGUiID0gcXVhbnRpbGUoU2VwYWwuTGVuZ3RoLCAuNzUpLCAKICAgICAgICAgICAgICAgICBNYXhpbXVtID0gbWF4KFNlcGFsLkxlbmd0aCkpCmBgYAoKVGFibGU6IEZpdmUgTnVtYmVyIFN1bW1hcnkgYnkgU3BlY2llcwoKVGhpcyBpcyBzdGlsbCBhIG5pY2UsIGNvbXBhY3Qgc3VtbWFyeSBidXQgaXQgaXMgYSBiaXQgZGlmZmljdWx0IHRvIHNlZSB3aGF0IGlzIGdvaW5nIG9uLiBGb3IgZXhhbXBsZSB3ZSBjYW4gc2VlIHRoYXQgdGhlIG1pbmltdW0gZm9yIHR3byBzcGVjaWVzIGlzIHRoZSBzYW1lLCBidXQgdGhlaXIgbWF4aW11bXMgYW5kIG1lZGlhbnMgYXJlIGRpZmZlcmVudC4gSXMgdGhpcyBtZWFuaW5nZnVsPyBVc2luZyBhIHZpc3VhbCByZXByZXNlbnRhdGlvbiBjYW4gaGVscCB3aXRoIG1ha2luZyB0aGUgY29tcGFyaXNvbnMuCgojIyBDcmVhdGluZyBhIEJveCBQbG90IHVzaW5nIGdncGxvdDIKClRoZSBzdGF0aXN0aWNpYW4gYW5kIG1hdGhlbWF0aWNpYW4gSm9obiBUdWtleSBkZXZlbG9wZWQgYm94IHBsb3RzIGFzIGEgd2F5IHRvIHN1bW1hcml6ZSB0aGlzIGluZm9ybWF0aW9uIHZpc3VhbGx5LiBIZSB3YXMgcGFydGljdWxhcmx5IGludGVyZXN0ZWQgaW4gaG93IHRvIGFjY3VyYXRlbHkgc3VtbWFyaXplIGFuZCBpbnRlcnByZXQgZGF0YSB3aXRob3V0IG1ha2luZyBhbnkgYXNzdW1wdGlvbnMgYWJvdXQgdGhlIGRhdGEgYW5kIGluIHRoZSBkZXRlY3Rpb24gb2YgdW51c3VhbCBvciBpbmZsdWVudGlhbCBkYXRhIHBvaW50cywgb2Z0ZW4gY2FsbGVkIG91dGxpZXJzLiBIZSB3cm90ZSBhIGdyb3VuZCBicmVha2luZyBib29rIGNhbGxlZCBfRXhwbG9yYXRvcmF5IERhdGEgQW5hbHlzaXNfIHRoYXQgcHJlc2VudGVkIG1hbnkgb2YgaGlzIGlkZWFzIGFib3V0IHRoaXMuCgogCmBgYHtyIGZpZy5jYXA9IlNlcGFsIExlbmd0aCBieSBTcGVjaWVzIn0KbGlicmFyeShnZ3Bsb3QyKQpnZ3Bsb3QoaXJpcywgYWVzKHk9U2VwYWwuTGVuZ3RoLCB4PVNwZWNpZXMpKSArCiAgICBnZW9tX2JveHBsb3QoKSArCiAgICBnZ3RpdGxlKCJTZXBhbCBMZW5ndGggYnkgU3BlY2llcyBpbiBBbmRlcnNvbidzIElyaXMgRGF0YSIpCmBgYAoKVGhpcyBwbG90IHNob3dzIHRoZSBzYW1lIGluZm9ybWF0aW9uIGFzIHRoZSB0YWJsZSAuLi4uIGJ1dCBldmVuIG1vcmUuIExldCdzIGJyZWFrIGl0IGRvd24uCkVhY2ggb2YgdGhlIHRocmVlIHNwZWNpZXMgaXMgcmVwcmVzZW50ZWQgYnkgYSBib3ggYW5kIHdoaXNrZXJzIC0tIHRoZSBsaW5lcyBzdGlja2luZyBvdXQgb2YgdGhlIGJveGVzLiBPbmUgc3BlY2llcy0tX3ZpcmdpbmljYV8tLSBhbHNvIApoYXMgYSBwb2ludCBieSBpdHNlbGYuCkVhY2ggb2YgdGhlIGJveGVzIGhhcyBhIGRhcmsgbGluZSBpbiB0aGUgbWlkZGxlLiBGb3IgX3NlcnRvc2FfIHRoaXMgaXMgYXQgNS4wLCBmb3IgX3ZlcnNpY29sb3JfIHRoaXMgaXMgYXQgNS45LCBhbmQgZm9yIF92aXJnaW5pY2FfIHRoaXMgaXMgYXQgNi41LgpDb21wYXJlIHRob3NlIG51bWJlcnMgdG8gdGhlIHRhYmxlLCBhbmQgeW91IHdpbGwgc2VlIHRoYXQgdGhlc2UgcmVwcmVzZW50IHRoZSBtZWRpYW5zIGZvciBlYWNoIG9mIHRoZSBzcGVjaWVzLgpJZiB5b3UgbG9vayBhdCB0aGUgYm90dG9tIG9mIHRoZSBib3hlcywgeW91IHdpbGwgc2VlIHRoZXkgYXJlIGF0IDQuOCwgNS42LCBhbmQgNi4yLiBUaGF0IGlzLCB0aGV5IHJlcHJlc2VudCB0aGUgZmlyc3QgcXVhcnRpbGUuICBUaGUgCnRvcCBvZiB0aGUgYm94ZXMgYXJlIGF0IDUuMiwgNi4zLCBhbmQgNi45LiBUaGV5IHJlcHJlc2VudCB0aGUgdGhpcmQgcXVhcnRpbGUuCgpUaGF0IG1lYW5zIHRoYXQgdGhlIGJveGVzIHJlcHJlc2VudCB0aGUgbWlkZGxlIDUwJSBvZiB0aGUgb2JzZXJ2YXRpb25zIGZvciBlYWNoIHNwZWNpZXMsIHRob3NlIGJldHdlZW4gdGhlIGZpcnN0IGFuZCB0aGUgdGhpcmQgcXVhcnRpbGUgKDI1dGggYW5kIDc1dGggcGVyY2VudGlsZXMpLiAKCklmIHdlIGxvb2sgbW9yZSBjbG9zZWx5IGF0IHRoZXNlIGJveGVzIHRoZSB2aXN1YWxpemF0aW9uIHRlbGxzIHVzIHNvbWUgaW50ZXJlc3RpbmcgdGhpbmdzLiBGb3IgZXhhbXBsZSB0aGVyZSBpcyBubyBvdmVybGFwIGJldHdlZW4gdGhlIF9zZXRvc2FfIHNwZWNpZXMgbWlkZGxlIGhhbGYgYW5kIHRob3NlIG9mIHRoZSBvdGhlciB0d28gc3BlY2llcy4gVGhlcmUgaXMgYSB0aW55IGFtb3VudCBvZiBvdmVybGFwIGJldHdlZW4gdGhlIG1pZGRsZSA1MCUgb2YgdGhlIF92ZXJzaWNvbG9yXyBhbmQgX3ZpcmdpbmljYV8gc3BlY2llcy4gVGhlIG92ZXJsYXAgaXMgc21hbGwgZW5vdWdoIHRoYXQgdGhlIG1lZGlhbiBvZiB2ZXJzaWNvbG9yIGlzIGJlbG93IHRoZSAyNXRoIHBlcmNlbnRpbGUgb2YgX3ZpcmdpbmljYV8gYW5kIHRoZSBtZWRpYW4gb2YgX3ZpcmdpbmljYV8gaXMgYWJvdmUgdGhlIDc1dGggcGVyY2VudGlsZSBvZiB2ZXJzaWNvbG9yLgoKSWYgd2UgdG9vayB0aGUgZGlzdGFuY2UgZnJvbSB0aGUgdG9wIG9mIGVhY2ggYm94IHRvIHRoZSBib3R0b20gdGhhdCB3b3VsZCBiZSB0aGUgaW50ZXJxdWFydGlsZSByYW5nZS4gV2UgY2FuIHNlZSB0aGF0IHRoZSBJUVIgZm9yIHNldG9zYSBpcyBtdWNoIHNtYWxsZXIgdGhhbiB0aGF0IGZvciB0aGUgb3RoZXIgdHdvIHNwZWNpZXMuICBXZSBjYW4gYWxzbyBzZWUgdGhhdCB0aGUgbWVkaWFuIG9mIHNldG9zYSBpcyBpbiB0aGUgbWlkZGxlIG9mIG9mIGl0cyBib3gsIHdoaWxlIGZvciB0aGUgb3RoZXIgdHdvIHNwZWNpZXMgdGhlIG1lZGlhbiBpcyBjbG9zZXIgdG8gdGhlIGJvdHRvbSBvZiB0aGUgYm94IHRoYW4gdG8gdGhlIHRvcC4gCgoKPk1ha2Ugc3VyZSB5b3UgcmVhZCBvdmVyIHRoZSBwcmV2aW91cyB0d28gcGFyYWdyYXBocyByZWFsbHkgY2FyZWZ1bGx5IGFuZCB1bmRlcnN0YW5kIGFsbCBvZiB0aGUgc2VudGVuY2VzLiBJZiBwZXJjZW50aWxlcyBhcmUgbmV3IHRvIHlvdSwgaXQgaXMgdG90YWxseSBub3JtYWwgdGhhdCB5b3Ugd2lsbCBoYXZlIHRvIHJlYWQgaXQgYW5kIGxvb2sgYXQgdGhlIGdyYXBocyBzZXZlcmFsIHRpbWVzLgoKCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgd2hpc2tlcnMuICBGb3IgX3NldG9zYV8gdGhlIGJvdHRvbSB3aGlza2VyIGV4dGVuZHMgdG8gNC4zIGFuZCB0aGUgdG9wIG9uZSB0byA1LjguIFRob3NlIGNvcnJlc3BvbmQgdG8gdGhlIG1heGltdW0gYW5kIG1pbmltdW0gdmFsdWVzLiAgU2ltaWxhdGhybHkgdGhlIGxvd2VyIHdoaXNrZXIgZm9yIF92ZXJzaWNvbG9yXyBleHRlbmRzIHRvIHRoZSBtaW5pbXVtIHZhbHVlLCA0LjksIGFuZCB0aGUgdG9wIHdoaXNrZXIKZXh0ZW5kcyB0byB0aGUgbWF4aW11bSwgNy4wLiBTbyBmb3IgdGhlc2UgdHdvIHNwZWNpZXMsIHRoZSB3aGlza2VycyByZXByZXNlbnQgdGhlIGZpcnN0IGFuZCBmb3VydGggcXVhcnRpbGVzLiAgQWxsIGZpdmUgbnVtYmVycyBmcm9tIHRoZSBmaXZlIG51bWJlciBzdW1tYXJ5IGFyZSBzaG93bi4gCgpXZSBjYW4gc2VlIHRoYXQgYWxsIG9mIHRoZSBfc2V0b3NhXyB2YWx1ZXMgZmFsbCBiZWxvdyB0aGUgbWVkaWFucyBvZiBib3RoIHRoZSBfdmVyc2ljb2xvcl8gYW5kIF92aXJnaW5pY2FfIHZhbHVlcy4gIAoKX1ZpcmdpbmljYV8gaXMgZGlmZmVyZW50LiBOb3RpY2UgdGhhdCBpbiBhZGRpdGlvbiB0byB0aGUgbG93ZXIgd2hpc2tlciB0aGVyZSBpcyBhIHNpbmdsZSBkb3QuICBSZW1lbWJlciB0aGF0IGluIG91ciB0YWJsZSB0aGUgbWluaW11bQp2YWx1ZSBmb3IgX3ZpcmdpbmljYV8gd2FzIHRoZSBzYW1lIGFzIHRoYXQgZm9yIF9zZXRvc2FfLCA0LjkuICBUaGlzIGlzIHZlcnkgc3RyYW5nZSBjb25zaWRlcmluZyB0aGF0IHRoZSBtZWRpYW4gYW5kIGZpcnN0IHF1YXJ0aWxlIG9mIF92aXJnaW5pY2FfIGFyZSBzbyBtdWNoIGhpZ2hlciB0aGFuIGZvciBfc2V0b3NhXy4gIFRoZSBib3ggYW5kIHdoaXNrZXJzIHBsb3QgaGlnaGxpZ2h0cyB0aGUgc3RyYW5nZW5lc3Mgb2YgdGhpcyBhbmQgaGlnaGxpZ2h0cyBqdXN0IGhvdyBmYXIgYXdheSB0aGF0IHBvaW50IGlzIGZyb20gdGhlIHJlc3Qgb2YgdGhlIF92aXJnaW5pY2FfIG9ic2VydmF0aW9ucy4gVGhpcyBraW5kIG9mIHBvaW50IGlzIGNhbGxlZCBhbiBfb3V0bGllcl8gYmVjYXVzZSBpdCBpcyBzbyBmYXIgYXdheSBmcm9tIHRoZSBvdGhlciB2YWx1ZXMuIEl0J3Mgc3VjaCBhbiBvZGQgcGxhbnQgZm9yIHRoYXQgc3BlY2llcyB0aGF0IHdlIG1pZ2h0IGV2ZW4gd29uZGVyIGlmIGFuIGV4YW1wbGUgZnJvbSBhbm90aGVyIHNwZWNpZXMgd2FzIG1pc2xhYmVsbGVkIG9yIGFuIGVycm9yIHdhcyBtYWRlIHdoZW4gdGhlIG1lYXN1cmVtZW50cyB3ZXJlIHRha2VuIG9yIGNvcGllZCBieSBoYW5kLiBPbiB0aGUgb3RoZXIgaGFuZCwgbWF5YmUgaXQgaXMganVzdCBhIHNtYWxsIGZsb3dlciBiZWNhdXNlIGl0IHdhcyBncm93aW5nIGluIHRoZSBzaGFkZSwgd2FzIGNyb3dkZWQgYnkgb3RoZXIgcGxhbnRzIG9yIGEgcmFuZG9tIG11dGF0aW9uLiBNYW55IGFydGljbGVzIGFuZCBib29rcyBoYXZlIGJlZW4gd3JpdHRlbiB1c2luZyB0aGUgaXJpcyBkYXRhLCBhbmQgc29tZSBlcnJvcnMgaGF2ZSBiZWVuIGZvdW5kLCBidXQgbm90IGZvciB0aGlzIGZsb3dlci4KClRoaXMgaGlnaGxpZ2h0cyBhbiBpbXBvcnRhbnQgcG9pbnQuICBQYXJ0IG9mIHRoZSBwdXJwb3NlIG9mIGEgYm94IGFuZCB3aGlza2VycyBwbG90IGlzIHRvIGhlbHAgaWRlbnRpZnkgb3V0bGllcnMuIFRoYXQgaXMgd2h5IF93aGlza2VycyBkbyBub3QgYWx3YXlzIGdvIHRvIHRoZSBtaW5pbXVtIG9yIG1heGltdW0gdmFsdWVfLiAKVGhlcmUgaXMgYSBsb3Qgb2YgZGViYXRlIGluIHN0YXRpc3RpY3MgYWJvdXQgaG93IHRvIGtub3cgaWYgYW4gb2JzZXJ2YXRpb24gaXMgYW4gb3V0bGllci4gIEJhc2ljYWxseSwgdGhpcyBpcyBhbiBhcnQgYW5kIG5vdCBhIHNjaWVuY2UgYnV0IHRoZXJlIGFyZSBzb21lIHJ1bGVzIG9mIHRodW1iIHRoYXQgcGVvcGxlIHVzZS4KSW4gdGhlIGNhc2Ugb2YgYm94IGFuZCB3aGlza2VycyBwbG90cyB0aGlzIGlzIGhvdyBvdXIgZ3JhcGggd291bGQgZG9uZSBpZiB3ZSB3ZXJlIGdvaW5nIHRvIGRvIGl0IGJ5IGhhbmQgcmF0aGVyIHRoYW4gdXNpbmcgY29udmVuaWVudCBmdW5jdGlvbnMgaW4gb3VyIHNvZnR3YXJlLgoKIDEuIENhbGN1bGF0ZSB0aGUgSW50ZXJxdWFydGlsZSByYW5nZS4KIAogCmBgYHtyfQp0aGlyZF9xdWFydGlsZTwtNi45CmZpcnN0X3F1YXJ0aWxlPC02LjIyNQppcXIgPC0gdGhpcmRfcXVhcnRpbGUgLSBmaXJzdF9xdWFydGlsZQppcXIKYGBgCgogMi4gTXVsdGlwbHkgdGhlIElRUiBieSAxLjUuCiAKCmBgYHtyfQppcXIxLjUgPC0gMS41KiBpcXIKaXFyMS41CmBgYAoKMy4gVGFrZSB0aGlzIHZhbHVlIGFuZCBzdWJ0cmFjdCBpdCBmcm9tIHRoZSBmaXJzdCBxdWFydGlsZSBhbmQgYWRkIGl0IHRvIHRoZSB0aGlyZCBxdWFydGlsZQoKCmBgYHtyfQpmaXJzdF9xdWFydGlsZSAtIGlxcjEuNQp0aGlyZF9xdWFydGlsZSArIGlxcjEuNQoKYGBgCgpBbnkgdmFsdWVzIDUuMiBvciBsb3dlciBvciA3Ljkgb3IgaGlnaGVyIHdvdWxkIGJlIGNvbnNpZGVyZWQgb3V0bGllcnMuICBUaGVyZWZvcmUgdGhlIG9ic2VydmF0aW9uIHRoYXQgaXMgNC45IGlzIGFuIG91dGxpZXIsIGFuZCBpdCBpcyB0aGUgb25seSB2aXJnaW5pY2Egb2JzZXJ2YXRpb24gYmVsb3cgNS4yLiAgVGhlIGxvd2VyIHdoaXNrZXIgZXh0ZW5kcyBvbmx5IHRvIHRoZSBsb3dlc3QgdmFsdWUgdGhhdCBpcyBncmVhdGVyIHRoYW4gNS4yLiBLZWVwIGluIG1pbmQgdGhhdCB0aGUgb3JpZ2luYWwgZGF0YSB3YXMgcm91bmRlZCB0byB0aGUgbmVhcmVzdCB0ZW50aCB3aGVuIHRoZSBwbGFudHMgd2VyZSBtZWFzdXJlZCBhbmQgd2UgZG8gbm90IHdhbnQgdG8gcm91bmQgYW4gYWxyZWFkeSByb3VuZGVkIG51bWJlci4KCiMjIFNvbWUgY3J1Y2lhbCBwb2ludHMKCkhlcmUncyBhIGNydWNpYWwgcG9pbnQuICBBcyBhIHJlc2VhcmNoZXIgYW5kIGRhdGEgYW5hbHlzdCB5b3UgaGF2ZSB0aGUgYWJpbGl0eSB0byBtYWtlIG1hbnkgY2hvaWNlcy4gIEluIG91ciBib3ggcGxvdHMgd2UgdXNlZCAxLjUgdGltZXMgdGhlIElRUiB0byBkZWZpbmUgdGhlIHdoaXNrZXJzLiBOb3QgZXZlcnkgYm94IHBsb3QgeW91IHNlZSBkb2VzIHRoaXM7IGluIGZhY3QgdGhlcmUgYXJlIG1hbnkgdmFyaWF0aW9ucyBvbiBib3ggcGxvdHMuICBGb3IgZXhhbXBsZSwgc29tZXRpbWVzIGEgcmVzZWFyY2hlciBtYXkgdXNlIDIgdGltZXMgdGhlIElRUiBvciBzb21ldGltZXMgdGhleSBtYXkgY2hvb3NlIHRvIGV4dGVuZCB0aGUgd2hpc2tlcnMgdG8gdGhlIG1heGltdW0uICAKSWYgeW91IGxlYXJuZWQgdG8gbWFrZSBhIGJveHBsb3QgaW4gZWxlbWVudGFyeSBzY2hvb2wgeW91IHByb2JhYmx5IGxlYXJuZWQgdG8gZXh0ZW5kIHRoZSB3aGlza2VycyB0byB0aGUgbWF4aW11bS4gWW91IGNvdWxkIHJlYWQgdGhlIEhlbHAgcGFnZSBmb3IgZ2VvbV9ib3hwbG90KCkgYW5kIGxlYXJuIGhvdyB0byBjaGFuZ2UgMS41IHRvIHNvbWUgb3RoZXIgdmFsdWUuIAoKSWYgeW91IGFyZSB1c2luZyBhIGJveCBwbG90IGZvciB5b3VyIG93biBpbmZvcm1hdGlvbiwgeW91IGNhbiBkbyB3aGF0IG1ha2VzIHNlbnNlLCBidXQgaWYgeW91IGFyZSBwcmVzZW50bmcgaXQgdG8gb3RoZXJzIHlvdSBzaG91bGQgYWx3YXlzIGV4cGxhaW4gd2hhdCBhcHByb2FjaCB5b3UgdG9vayB0byB0aGlzLgoKSGVyZSdzIGEgc2Vjb25kIGNydWNpYWwgcG9pbnQuIEp1c3QgYmVjYXVzZSB5b3UgaWRlbnRpZmllZCBhIHBvaW50IGFzIGFuIG91dGxpZXIgZG9lcyBub3QgbWVhbiB5b3Uga25vdyB3aGF0IHRvIGRvIGFib3V0IGl0LiBBcyBhbiBhbmFseXN0IHlvdSBoYXZlIHRvIGNvbnNpZGVyIHdoYXQgdGhlIG91dGxpZXIgbWVhbnMgYW5kIGhvdyBpdHMgcHJlc2VuY2Ugc2hvdWxkIGltcGFjdCB5b3VyIGFuYWx5c2lzLiAgV2hhdGV2ZXIgeW91IGRvIHlvdSBzaG91bGQgcmVjb3JkIHRoZSBkZWNpc2lvbiBhbmQgcmVhc29ucyBmb3IgaXQgY29tcGxldGVseSBhbmQgbWFrZSBzdXJlIHRvIHNoYXJlIHRoYXQgaW5mb3JtYXRpb24gd2l0aCBjb25zdW1lcnMgb2YgeW91ciB3b3JrLiBUaGlzIGlzIGFuIGVzc2VudGlhbCBlbGVtZW50IG9mIGRvaW5nIHJlcHJvZHVjaWJsZSByZXNlYXJjaC4KCk5vdyB0aGF0IHlvdSBoYXZlIHNlZW4gaG93IGEgYm94IHBsb3QgaXMgY3JlYXRlZCwgeW91IGNhbiB1bmRlcnN0YW5kIHdoeSBzb21ldGltZXMgcGVvcGxlIGFyZSB2ZXJ5IGNvbmZ1c2VkIGJ5IHRoZW0uIFRoZXkgYXJlIGphbS1wYWNrZWQgd2l0aCBpbmZvcm1hdGlvbiBhbmQgeW91IGNvdWxkIHdyaXRlIG1hbnkgcGFyYWdyYXBocyBqdXN0IHN1bW1hcml6aW5nIHdoYXQgb3VyIGJveCBwbG90IHNob3dzIHVzIGFib3V0IHRoZXNlIHNwZWNpZXMgb2YgaXJpc2VzLgoKSGVyZSBhcmUgdGVuIHN0YXRlbWVudHMgYmFzZWQgb24gb3VyIGJveCBwbG90LiAgTWFrZSBzdXJlIHlvdSB1bmRlcnN0YW5kIHdoeSBlYWNoIG9uZSBvZiB0aGVtIGlzIHRydWUuICAKCj4xLiBNb3JlIHRoYW4gNzUlIG9mIF92aXJnaW5pY2FfIGhhdmUgbG9uZ2VyIHNlcGFsIGxlbmd0aHMgdGhhbiB0aGUgbWVkaWFuIF92ZXJzaWNvbG9yXy4gIAo+Mi4gQWxsIF9zZXRvc2FfIGhhdmUgc2VwYWwgbGVuZ3RocyBzaG9ydGVyIHRoYW4gNzUlIG9mIF92aXJnaW5pY2FfLiAgCj4zLiBUaGUgbG9uZ2VzdCBfc2V0b3NhXyBpcyBhYm91dCBlcXVhbCB0byB0aGUgbWVkaWFuIF92ZXJzaWNvbG9yXy4gIAo+NC4gVGhlIHNob3J0ZXN0IF92ZXJzaWNvbG9yXyBhbmQgc2hvcnRlc3QgX3ZpcmdpbmljYV8gYXJlIHRoZSBzYW1lIGxlbmd0aC4gIAo+NS4gQWxsIG9mICB0aGUgaXJpc2VzIHdpdGggc2VwYWwgbGVuZ3RoIGdyZWF0ZXIgdGhhbiA3IGFyZSBfdmlyZ2luaWNhXy4gIAo+Ni4gQWxsIG9mIHRoZSBpcmlzZXMgd2l0aCBzZXBhbCBsZW5ndGggbGVzcyB0aGFuIDQuOSBhcmUgX3NldG9zYV8uICAKPjcuIFRoZSBpbnRlcnF1YXJ0aWxlIHJhbmdlcyBmb3IgX3ZpcmdpbmljYV8gYW5kIF92ZXJzaWNvbG9yXyBvdmVybGFwIGJ1dCBuZWl0aGVyIGdyb3VwJ3MgbWVkaWFuIGlzIGluIHRoZSBvdmVybGFwcGluZyBhcmVhLiAgCj44LiBUaGUgX3ZpcmdpbmljYV8gc3BlY2llcyBzZXBhbCBsZW5ndGggaGFzIG9uZSBwb3NzaWJsZSBvdXRsaWVyLiAgIAo+OS4gVGhlIHZhcmlhdGlvbiBvZiBfc2V0b3NhXyBpcyBsZXNzIHRoYW4gdGhhdCBvZiB0aGUgb3RoZXIgdHdvIHNwZWNpZXMuICAKPjEwLiBUSGUgX3ZpcmdpbmljYV8gYW5kIF92ZXJzaWNvbG9yXyBkaXN0cmlidXRpb25zIChjZW50ZXJzLCB2YXJpYXRpb24gYW5kIHNoYXBlKSBhcmUgbW9yZSBzaW1pbGFyIHRvIGVhY2ggb3RoZXIgdGhhbiBlaXRoZXIgaXMgdG8gdGhlIF9zZXRvc2FfLiAgCgoKCg==