Introduction
Feature selection is a critical and widely used technique in data
processing, aimed at selecting the most relevant features from noisy
data. This approach not only enhances the execution speed of data
processing algorithms but also improves prediction accuracy and reduces
variability in results.
Feature Selection
Methods
Feature selection, a dimensionality reduction technique, focuses on
identifying a small subset of relevant features from the original
dataset by eliminating irrelevant, redundant, or noisy features. This
process typically enhances learning performance, improves model
accuracy, reduces computational costs, and increases model
interpretability.
Several statistical methods relevant to feature selection have been
discussed in various statistics courses. This section provides an
overview of feature selection types, methodologies, and techniques
commonly employed in both statistics and machine learning. Based on
their nature, these methods are categorized into four distinct types,
which will be outlined in the following subsections.
Filter Methods
Filter methods are statistical-based feature selection methods that
involve evaluating the relationship between each input variable and the
target (response) variable using statistics and selecting those input
variables that have the strongest relationship with the target variable.
These methods can be fast and effective, although the choice of
statistical measures depends on the data type of both the input and
output variables. Here are some of these methods with brief
descriptions.
Chi-square
Test
Let’s consider a scenario where we need to determine the relationship
between the independent category feature (predictor) and dependent
category feature(response). In feature selection, we aim to select the
features which are highly dependent on the response. We calculate
Chi-square between each feature and the response variable. and select
the desired number of features with the best Chi-square scores.
In order to correctly apply the chi-squared test for the relationship
between various features in the data set and the target variable, the
following conditions have to be met: the variables have to be
categorical, sampled independently and values should have an expected
frequency greater than 5.
Fisher’s Score
Fisher score is one of the most widely used supervised feature
selection methods. It seeks features with the best discriminant ability.
It is based on maximizing the distances between data points of different
classes and minimizing the distances among points of the same class. To
rank the features in the order of their relevancy, they are sorted in
the decreasing order of their obtained fisher score. Thus, as the value
of an assigned score to a feature increases, its importance also
increases.
Let \(Y\) be the categorical
variable with \(C\) categories and
\(X\) be a numerical variable. The
Fisher’s score of \(X\) is defined
by
\[
F_X = \frac{\sum_{i=1}^C N_i(\mu_{X}^i-\mu_{X})^2}{\sum_{i=1}^CN_i\times
(\sigma_X^i)^2}
\] where \(N_i\) is the number
of data points in class \(i\), \(\mu_X\) is the mean of feature variable
\(X\), and \(\mu_X^i\) and \((\sigma_X^i)^2\) are the mean and the
variance of class \(i\) upon the
feature \(X\) respectively.
The algorithm returns the ranks of the variables based on the
fisher’s score in descending order. We can then select the variables
based on the scores.
Correlation
Coefficient
Correlation is a measure of the linear relationship of 2 or more
variables. Through correlation, we can predict one variable from the
other. The logic behind using correlation for feature selection is that
the good variables are highly correlated with the response. Furthermore,
variables should be correlated with the response but should be
uncorrelated among themselves. This method is valid when both response
and feature variables are numeric.
Variance
Threshold
The variance threshold is a simple baseline approach to feature
selection. It removes all features which variance does not meet some
threshold. The logic for this method is that features with a higher
variance may contain more useful information.
Wrapper Methods
Wrappers require some method to search the space of all possible
subsets of features, assessing their quality by learning and evaluating
a classifier with that feature subset. The feature selection process is
based on a specific machine learning algorithm that we are trying to fit
on a given data set. It follows a greedy search approach by evaluating
all the possible combinations of features against the evaluation
criterion. The wrapper methods usually result in better predictive
accuracy than filter methods.
The following are a few such methods.
Forward Feature
Selection
This is an iterative method we start with the best performing
variable against the target. Next, we select another variable that gives
the best performance in combination with the first selected variable.
This process continues until the preset criterion is achieved.
Backward Feature
Elimination
This method works exactly opposite to the Forward Feature Selection
method. Here, we start with all the features available and build a
model. Next, we the variable from the model which gives the best
evaluation measure value. This process is continued until the preset
criterion is achieved.
Subset Feature
Selection
This is the most robust feature selection method covered so far. This
is a brute-force evaluation of each feature subset. This means that it
tries every possible combination of the variables and returns the
best-performing subset.
Embedded Methods
These methods encompass the benefits of both the wrapper and filter
methods, by including interactions of features but also maintaining
reasonable computational cost. Embedded methods are iterative in the
sense that takes care of each iteration of the model training process
and carefully extract those features which contribute the most to the
training for a particular iteration.
LASSO
Regularization
Regularization consists of adding a penalty to the different
parameters of the machine learning model to reduce the freedom of the
model, i.e. to avoid over-fitting. In linear model regularization, the
penalty is applied over the coefficients that multiply each of the
predictors. From the different types of regularization, Lasso or L1 has
the property that can shrink some of the coefficients to zero.
Therefore, that feature can be removed from the model.
Random Forest
Importance
Random Forests is a kind of a Bagging Algorithm that aggregates a
specified number of decision trees. The tree-based strategies used by
random forests naturally rank by how well they improve the purity of the
node, or in other words a decrease in the impurity (Gini impurity) over
all trees. Nodes with the greatest decrease in impurity happen at the
start of the trees, while notes with the least decrease in impurity
occur at the end of trees. Thus, by pruning trees below a particular
node, we can create a subset of the most important features.
Hybrid Methods
Hybrid methods try to exploit the qualities of both approaches,
filter, and wrapper, trying to have a good compromise between efficiency
(computational effort) and effectiveness (quality in the associated
objective task when using the selected features).
To take advantage of the filter and wrapper approaches, hybrid
methods, in a filter stage, the features are ranked or selected applying
a measure based on intrinsic properties of the data. While, in a wrapper
stage, certain feature subsets are evaluated for finding the best one,
through a specific clustering algorithm. We can distinguish two types of
hybrid methods: methods based on ranking and methods non-based on the
ranking of features.
LS0tDQp0aXRsZTogIkZlYXR1cmUgU2VsZWN0aW9uIGFuZCBFeHRyYWN0aW9uIg0KYXV0aG9yOiAiQ2hlbmcgUGVuZyINCmRhdGU6ICJTVEEgNTUxIEZvdW5kYXRpb25zIG9mIERhdGEgU2NpZW5jZSINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDogDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZmxvYXQ6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ193aWR0aDogNg0KICAgIGZpZ19oZWlnaHQ6IDQNCiAgICBmaWdfY2FwdGlvbjogeWVzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMNCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMNCiAgICB0aGVtZTogbHVtZW4NCiAgICBkZl9wcmludDoga2FibGUNCiAgcGRmX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgZmlnX3dpZHRoOiA1DQogICAgZmlnX2hlaWdodDogNA0KICB3b3JkX2RvY3VtZW50OiANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIGZpZ19jYXB0aW9uOiB5ZXMNCiAgICBrZWVwX21kOiB5ZXMNCi0tLQ0KDQpgYGB7PWh0bWx9DQo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPg0KDQpkaXYjVE9DIGxpIHsNCiAgICBsaXN0LXN0eWxlOm5vbmU7DQogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOw0KICAgIGJhY2tncm91bmQtcmVwZWF0Om5vbmU7DQogICAgYmFja2dyb3VuZC1wb3NpdGlvbjowOw0KfQ0KDQpoMS50aXRsZSB7DQogIGZvbnQtc2l6ZTogMjRweDsNCiAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5hdXRob3IgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrUmVkOw0KICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgZm9udC1zaXplOiAxOHB4Ow0KICBmb250LXdlaWdodDogYm9sZDsNCiAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogIGNvbG9yOiBEYXJrQmx1ZTsNCiAgdGV4dC1hbGlnbjogY2VudGVyOw0KfQ0KaDEgeyAvKiBIZWFkZXIgMyAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMjJweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBjZW50ZXI7DQp9DQpoMiB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovDQogICAgZm9udC1zaXplOiAxOHB4Ow0KICAgIGZvbnQtd2VpZ2h0OiBib2xkOw0KICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOw0KICAgIGNvbG9yOiBuYXZ5Ow0KICAgIHRleHQtYWxpZ246IGxlZnQ7DQp9DQoNCmgzIHsgLyogSGVhZGVyIDMgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8NCiAgICBmb250LXNpemU6IDE1cHg7DQogICAgZm9udC13ZWlnaHQ6IGJvbGQ7DQogICAgZm9udC1mYW1pbHk6ICJUaW1lcyBOZXcgUm9tYW4iLCBUaW1lcywgc2VyaWY7DQogICAgY29sb3I6IG5hdnk7DQogICAgdGV4dC1hbGlnbjogbGVmdDsNCn0NCg0KaDQgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLw0KICAgIGZvbnQtc2l6ZTogMThweDsNCiAgICBmb250LXdlaWdodDogYm9sZDsNCiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsNCiAgICBjb2xvcjogZGFya3JlZDsNCiAgICB0ZXh0LWFsaWduOiBsZWZ0Ow0KfQ0KPC9zdHlsZT4NCmBgYA0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCiMgY29kZSBjaHVuayBzcGVjaWZpZXMgd2hldGhlciB0aGUgUiBjb2RlLCB3YXJuaW5ncywgYW5kIG91dHB1dCANCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLg0KaWYgKCFyZXF1aXJlKCJ3ZWJzaG90IikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoIndlYnNob3QiKQ0KICAgbGlicmFyeSh3ZWJzaG90KQ0KfQ0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImdncGxvdDIiKQ0KICAgbGlicmFyeShnZ3Bsb3QyKQ0KfQ0KIyMjIGxvYWQgJ01BU1MnIHBhY2thZ2UNCmlmKCFyZXF1aXJlKE1BU1MpKXsNCiAgaW5zdGFsbC5wYWNrYWdlcygiTUFTUyIpDQogIGxpYnJhcnkoTUFTUykNCn0NCiMjIyBsb2FkICdrbGFSJyBwYWNrYWdlDQppZighcmVxdWlyZShrbGFSKSl7DQogIGluc3RhbGwucGFja2FnZXMoImtsYVIiKQ0KICBsaWJyYXJ5KGtsYVIpDQp9DQppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsNCiAgIGluc3RhbGwucGFja2FnZXMoImtuaXRyIikNCiAgIGxpYnJhcnkoa25pdHIpDQp9DQoNCiMga25pdHI6Om9wdHNfa25pdCRzZXQocm9vdC5kaXIgPSAiQzovVXNlcnMvNzVDUEVORy9PbmVEcml2ZSAtIFdlc3QgQ2hlc3RlciBVbml2ZXJzaXR5IG9mIFBBL0RvY3VtZW50cyIpDQojIGtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gIkM6XFxTVEE0OTBcXHcwNSIpDQoNCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSwgICAgICAgDQogICAgICAgICAgICAgICAgICAgICAgd2FybmluZyA9IEZBTFNFLCAgIA0KICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IFRSVUUsICAgDQogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFKQ0KYGBgDQoNCiMgSW50cm9kdWN0aW9uDQoNCkZlYXR1cmUgc2VsZWN0aW9uIGlzIGEgY3JpdGljYWwgYW5kIHdpZGVseSB1c2VkIHRlY2huaXF1ZSBpbiBkYXRhIHByb2Nlc3NpbmcsIGFpbWVkIGF0IHNlbGVjdGluZyB0aGUgbW9zdCByZWxldmFudCBmZWF0dXJlcyBmcm9tIG5vaXN5IGRhdGEuIFRoaXMgYXBwcm9hY2ggbm90IG9ubHkgZW5oYW5jZXMgdGhlIGV4ZWN1dGlvbiBzcGVlZCBvZiBkYXRhIHByb2Nlc3NpbmcgYWxnb3JpdGhtcyBidXQgYWxzbyBpbXByb3ZlcyBwcmVkaWN0aW9uIGFjY3VyYWN5IGFuZCByZWR1Y2VzIHZhcmlhYmlsaXR5IGluIHJlc3VsdHMuIA0KDQoNCiMgRmVhdHVyZSBTZWxlY3Rpb24gTWV0aG9kcw0KDQpGZWF0dXJlIHNlbGVjdGlvbiwgYSBkaW1lbnNpb25hbGl0eSByZWR1Y3Rpb24gdGVjaG5pcXVlLCBmb2N1c2VzIG9uIGlkZW50aWZ5aW5nIGEgc21hbGwgc3Vic2V0IG9mIHJlbGV2YW50IGZlYXR1cmVzIGZyb20gdGhlIG9yaWdpbmFsIGRhdGFzZXQgYnkgZWxpbWluYXRpbmcgaXJyZWxldmFudCwgcmVkdW5kYW50LCBvciBub2lzeSBmZWF0dXJlcy4gVGhpcyBwcm9jZXNzIHR5cGljYWxseSBlbmhhbmNlcyBsZWFybmluZyBwZXJmb3JtYW5jZSwgaW1wcm92ZXMgbW9kZWwgYWNjdXJhY3ksIHJlZHVjZXMgY29tcHV0YXRpb25hbCBjb3N0cywgYW5kIGluY3JlYXNlcyBtb2RlbCBpbnRlcnByZXRhYmlsaXR5Lg0KDQpTZXZlcmFsIHN0YXRpc3RpY2FsIG1ldGhvZHMgcmVsZXZhbnQgdG8gZmVhdHVyZSBzZWxlY3Rpb24gaGF2ZSBiZWVuIGRpc2N1c3NlZCBpbiB2YXJpb3VzIHN0YXRpc3RpY3MgY291cnNlcy4gVGhpcyBzZWN0aW9uIHByb3ZpZGVzIGFuIG92ZXJ2aWV3IG9mIGZlYXR1cmUgc2VsZWN0aW9uIHR5cGVzLCBtZXRob2RvbG9naWVzLCBhbmQgdGVjaG5pcXVlcyBjb21tb25seSBlbXBsb3llZCBpbiBib3RoIHN0YXRpc3RpY3MgYW5kIG1hY2hpbmUgbGVhcm5pbmcuIEJhc2VkIG9uIHRoZWlyIG5hdHVyZSwgdGhlc2UgbWV0aG9kcyBhcmUgY2F0ZWdvcml6ZWQgaW50byBmb3VyIGRpc3RpbmN0IHR5cGVzLCB3aGljaCB3aWxsIGJlIG91dGxpbmVkIGluIHRoZSBmb2xsb3dpbmcgc3Vic2VjdGlvbnMuDQoNCg0KIyMgRmlsdGVyIE1ldGhvZHMNCg0KRmlsdGVyIG1ldGhvZHMgYXJlIHN0YXRpc3RpY2FsLWJhc2VkIGZlYXR1cmUgc2VsZWN0aW9uIG1ldGhvZHMgdGhhdCBpbnZvbHZlIGV2YWx1YXRpbmcgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIGVhY2ggaW5wdXQgdmFyaWFibGUgYW5kIHRoZSB0YXJnZXQgKHJlc3BvbnNlKSB2YXJpYWJsZSB1c2luZyBzdGF0aXN0aWNzIGFuZCBzZWxlY3RpbmcgdGhvc2UgaW5wdXQgdmFyaWFibGVzIHRoYXQgaGF2ZSB0aGUgc3Ryb25nZXN0IHJlbGF0aW9uc2hpcCB3aXRoIHRoZSB0YXJnZXQgdmFyaWFibGUuIFRoZXNlIG1ldGhvZHMgY2FuIGJlIGZhc3QgYW5kIGVmZmVjdGl2ZSwgYWx0aG91Z2ggdGhlIGNob2ljZSBvZiBzdGF0aXN0aWNhbCBtZWFzdXJlcyBkZXBlbmRzIG9uIHRoZSBkYXRhIHR5cGUgb2YgYm90aCB0aGUgaW5wdXQgYW5kIG91dHB1dCB2YXJpYWJsZXMuIEhlcmUgYXJlIHNvbWUgb2YgdGhlc2UgbWV0aG9kcyB3aXRoIGJyaWVmIGRlc2NyaXB0aW9ucy4NCg0KIyMjIEluZm9ybWF0aW9uIEdhaW4NCg0KSW5mb3JtYXRpb24gZ2FpbiBjYWxjdWxhdGVzIHRoZSByZWR1Y3Rpb24gaW4gZW50cm9weSBmcm9tIHRoZSB0cmFuc2Zvcm1hdGlvbiBvZiBhIGRhdGEgc2V0LiBJdCBjYW4gYmUgdXNlZCBmb3IgZmVhdHVyZSBzZWxlY3Rpb24gYnkgZXZhbHVhdGluZyB0aGUgSW5mb3JtYXRpb24gZ2FpbiBvZiBlYWNoIHZhcmlhYmxlIGluIHRoZSBjb250ZXh0IG9mIHRoZSB0YXJnZXQgdmFyaWFibGUuIFdlIGhhdmUgYnJpZWZseSBkZXNjcmliZWQgdGhpcyBtZXRob2QgaW4gZGVjaXNpb24gaW5kdWN0aW9uLg0KDQojIyMgQ2hpLXNxdWFyZSBUZXN0DQoNCkxldOKAmXMgY29uc2lkZXIgYSBzY2VuYXJpbyB3aGVyZSB3ZSBuZWVkIHRvIGRldGVybWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdGhlIGluZGVwZW5kZW50IGNhdGVnb3J5IGZlYXR1cmUgKHByZWRpY3RvcikgYW5kIGRlcGVuZGVudCBjYXRlZ29yeSBmZWF0dXJlKHJlc3BvbnNlKS4gSW4gZmVhdHVyZSBzZWxlY3Rpb24sIHdlIGFpbSB0byBzZWxlY3QgdGhlIGZlYXR1cmVzIHdoaWNoIGFyZSBoaWdobHkgZGVwZW5kZW50IG9uIHRoZSByZXNwb25zZS4gV2UgY2FsY3VsYXRlIENoaS1zcXVhcmUgYmV0d2VlbiBlYWNoIGZlYXR1cmUgYW5kIHRoZSByZXNwb25zZSB2YXJpYWJsZS4gYW5kIHNlbGVjdCB0aGUgZGVzaXJlZCBudW1iZXIgb2YgZmVhdHVyZXMgd2l0aCB0aGUgYmVzdCBDaGktc3F1YXJlIHNjb3Jlcy4gDQoNCkluIG9yZGVyIHRvIGNvcnJlY3RseSBhcHBseSB0aGUgY2hpLXNxdWFyZWQgdGVzdCBmb3IgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHZhcmlvdXMgZmVhdHVyZXMgaW4gdGhlIGRhdGEgc2V0IGFuZCB0aGUgdGFyZ2V0IHZhcmlhYmxlLCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgaGF2ZSB0byBiZSBtZXQ6IHRoZSB2YXJpYWJsZXMgaGF2ZSB0byBiZSBjYXRlZ29yaWNhbCwgc2FtcGxlZCBpbmRlcGVuZGVudGx5IGFuZCB2YWx1ZXMgc2hvdWxkIGhhdmUgYW4gZXhwZWN0ZWQgZnJlcXVlbmN5IGdyZWF0ZXIgdGhhbiA1LiANCg0KIyMjIEZpc2hlcidzIFNjb3JlIA0KDQpGaXNoZXIgc2NvcmUgaXMgb25lIG9mIHRoZSBtb3N0IHdpZGVseSB1c2VkIHN1cGVydmlzZWQgZmVhdHVyZSBzZWxlY3Rpb24gbWV0aG9kcy4gSXQgc2Vla3MgZmVhdHVyZXMgd2l0aCB0aGUgYmVzdCBkaXNjcmltaW5hbnQgYWJpbGl0eS4gSXQgaXMgYmFzZWQgb24gbWF4aW1pemluZyB0aGUgZGlzdGFuY2VzIGJldHdlZW4gZGF0YSBwb2ludHMgb2YgZGlmZmVyZW50IGNsYXNzZXMgYW5kIG1pbmltaXppbmcgdGhlIGRpc3RhbmNlcyBhbW9uZyBwb2ludHMgb2YgdGhlIHNhbWUgY2xhc3MuIFRvIHJhbmsgdGhlIGZlYXR1cmVzIGluIHRoZSBvcmRlciBvZiB0aGVpciByZWxldmFuY3ksIHRoZXkgYXJlIHNvcnRlZCBpbiB0aGUgZGVjcmVhc2luZyBvcmRlciBvZiB0aGVpciBvYnRhaW5lZCBmaXNoZXIgc2NvcmUuIFRodXMsIGFzIHRoZSB2YWx1ZSBvZiBhbiBhc3NpZ25lZCBzY29yZSB0byBhIGZlYXR1cmUgaW5jcmVhc2VzLCBpdHMgaW1wb3J0YW5jZSBhbHNvIGluY3JlYXNlcy4NCg0KTGV0ICRZJCBiZSB0aGUgY2F0ZWdvcmljYWwgdmFyaWFibGUgd2l0aCAkQyQgY2F0ZWdvcmllcyBhbmQgJFgkIGJlIGEgbnVtZXJpY2FsIHZhcmlhYmxlLiBUaGUgRmlzaGVyJ3Mgc2NvcmUgb2YgJFgkIGlzIGRlZmluZWQgYnkNCg0KJCQNCkZfWCA9IFxmcmFje1xzdW1fe2k9MX1eQyBOX2koXG11X3tYfV5pLVxtdV97WH0pXjJ9e1xzdW1fe2k9MX1eQ05faVx0aW1lcyAoXHNpZ21hX1heaSleMn0NCiQkDQp3aGVyZSAkTl9pJCBpcyB0aGUgbnVtYmVyIG9mIGRhdGEgcG9pbnRzIGluIGNsYXNzICRpJCwgJFxtdV9YJCBpcyB0aGUgbWVhbiBvZiBmZWF0dXJlIHZhcmlhYmxlICRYJCwgYW5kICRcbXVfWF5pJCBhbmQgJChcc2lnbWFfWF5pKV4yJCBhcmUgdGhlIG1lYW4gYW5kIHRoZSB2YXJpYW5jZSBvZg0KY2xhc3MgJGkkIHVwb24gdGhlIGZlYXR1cmUgJFgkIHJlc3BlY3RpdmVseS4NCg0KVGhlIGFsZ29yaXRobSByZXR1cm5zIHRoZSByYW5rcyBvZiB0aGUgdmFyaWFibGVzIGJhc2VkIG9uIHRoZSBmaXNoZXLigJlzIHNjb3JlIGluIGRlc2NlbmRpbmcgb3JkZXIuIFdlIGNhbiB0aGVuIHNlbGVjdCB0aGUgdmFyaWFibGVzIGJhc2VkIG9uIHRoZSBzY29yZXMuDQoNCg0KIyMjIENvcnJlbGF0aW9uIENvZWZmaWNpZW50DQoNCkNvcnJlbGF0aW9uIGlzIGEgbWVhc3VyZSBvZiB0aGUgbGluZWFyIHJlbGF0aW9uc2hpcCBvZiAyIG9yIG1vcmUgdmFyaWFibGVzLiBUaHJvdWdoIGNvcnJlbGF0aW9uLCB3ZSBjYW4gcHJlZGljdCBvbmUgdmFyaWFibGUgZnJvbSB0aGUgb3RoZXIuIFRoZSBsb2dpYyBiZWhpbmQgdXNpbmcgY29ycmVsYXRpb24gZm9yIGZlYXR1cmUgc2VsZWN0aW9uIGlzIHRoYXQgdGhlIGdvb2QgdmFyaWFibGVzIGFyZSBoaWdobHkgY29ycmVsYXRlZCB3aXRoIHRoZSByZXNwb25zZS4gRnVydGhlcm1vcmUsIHZhcmlhYmxlcyBzaG91bGQgYmUgY29ycmVsYXRlZCB3aXRoIHRoZSByZXNwb25zZSBidXQgc2hvdWxkIGJlIHVuY29ycmVsYXRlZCBhbW9uZyB0aGVtc2VsdmVzLiBUaGlzIG1ldGhvZCBpcyB2YWxpZCB3aGVuIGJvdGggcmVzcG9uc2UgYW5kIGZlYXR1cmUgdmFyaWFibGVzIGFyZSBudW1lcmljLg0KDQojIyMgVmFyaWFuY2UgVGhyZXNob2xkDQoNClRoZSB2YXJpYW5jZSB0aHJlc2hvbGQgaXMgYSBzaW1wbGUgYmFzZWxpbmUgYXBwcm9hY2ggdG8gZmVhdHVyZSBzZWxlY3Rpb24uIEl0IHJlbW92ZXMgYWxsIGZlYXR1cmVzIHdoaWNoIHZhcmlhbmNlIGRvZXMgbm90IG1lZXQgc29tZSB0aHJlc2hvbGQuIFRoZSBsb2dpYyBmb3IgdGhpcyBtZXRob2QgaXMgdGhhdCBmZWF0dXJlcyB3aXRoIGEgaGlnaGVyIHZhcmlhbmNlIG1heSBjb250YWluIG1vcmUgdXNlZnVsIGluZm9ybWF0aW9uLiANCg0KDQojIyBXcmFwcGVyIE1ldGhvZHMNCg0KV3JhcHBlcnMgcmVxdWlyZSBzb21lIG1ldGhvZCB0byBzZWFyY2ggdGhlIHNwYWNlIG9mIGFsbCBwb3NzaWJsZSBzdWJzZXRzIG9mIGZlYXR1cmVzLCBhc3Nlc3NpbmcgdGhlaXIgcXVhbGl0eSBieSBsZWFybmluZyBhbmQgZXZhbHVhdGluZyBhIGNsYXNzaWZpZXIgd2l0aCB0aGF0IGZlYXR1cmUgc3Vic2V0LiBUaGUgZmVhdHVyZSBzZWxlY3Rpb24gcHJvY2VzcyBpcyBiYXNlZCBvbiBhIHNwZWNpZmljIG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtIHRoYXQgd2UgYXJlIHRyeWluZyB0byBmaXQgb24gYSBnaXZlbiBkYXRhIHNldC4gSXQgZm9sbG93cyBhIGdyZWVkeSBzZWFyY2ggYXBwcm9hY2ggYnkgZXZhbHVhdGluZyBhbGwgdGhlIHBvc3NpYmxlIGNvbWJpbmF0aW9ucyBvZiBmZWF0dXJlcyBhZ2FpbnN0IHRoZSBldmFsdWF0aW9uIGNyaXRlcmlvbi4gVGhlIHdyYXBwZXIgbWV0aG9kcyB1c3VhbGx5IHJlc3VsdCBpbiBiZXR0ZXIgcHJlZGljdGl2ZSBhY2N1cmFjeSB0aGFuIGZpbHRlciBtZXRob2RzLg0KDQpUaGUgZm9sbG93aW5nIGFyZSBhIGZldyBzdWNoIG1ldGhvZHMuDQoNCiMjIyBGb3J3YXJkIEZlYXR1cmUgU2VsZWN0aW9uDQoNClRoaXMgaXMgYW4gaXRlcmF0aXZlIG1ldGhvZCB3ZSBzdGFydCB3aXRoIHRoZSBiZXN0IHBlcmZvcm1pbmcgdmFyaWFibGUgYWdhaW5zdCB0aGUgdGFyZ2V0LiBOZXh0LCB3ZSBzZWxlY3QgYW5vdGhlciB2YXJpYWJsZSB0aGF0IGdpdmVzIHRoZSBiZXN0IHBlcmZvcm1hbmNlIGluIGNvbWJpbmF0aW9uIHdpdGggdGhlIGZpcnN0IHNlbGVjdGVkIHZhcmlhYmxlLiBUaGlzIHByb2Nlc3MgY29udGludWVzIHVudGlsIHRoZSBwcmVzZXQgY3JpdGVyaW9uIGlzIGFjaGlldmVkLg0KDQojIyMgQmFja3dhcmQgRmVhdHVyZSBFbGltaW5hdGlvbg0KDQpUaGlzIG1ldGhvZCB3b3JrcyBleGFjdGx5IG9wcG9zaXRlIHRvIHRoZSBGb3J3YXJkIEZlYXR1cmUgU2VsZWN0aW9uIG1ldGhvZC4gSGVyZSwgd2Ugc3RhcnQgd2l0aCBhbGwgdGhlIGZlYXR1cmVzIGF2YWlsYWJsZSBhbmQgYnVpbGQgYSBtb2RlbC4gTmV4dCwgd2UgdGhlIHZhcmlhYmxlIGZyb20gdGhlIG1vZGVsIHdoaWNoIGdpdmVzIHRoZSBiZXN0IGV2YWx1YXRpb24gbWVhc3VyZSB2YWx1ZS4gVGhpcyBwcm9jZXNzIGlzIGNvbnRpbnVlZCB1bnRpbCB0aGUgcHJlc2V0IGNyaXRlcmlvbiBpcyBhY2hpZXZlZC4NCg0KIyMjIFN1YnNldCBGZWF0dXJlIFNlbGVjdGlvbg0KDQpUaGlzIGlzIHRoZSBtb3N0IHJvYnVzdCBmZWF0dXJlIHNlbGVjdGlvbiBtZXRob2QgY292ZXJlZCBzbyBmYXIuIFRoaXMgaXMgYSBicnV0ZS1mb3JjZSBldmFsdWF0aW9uIG9mIGVhY2ggZmVhdHVyZSBzdWJzZXQuIFRoaXMgbWVhbnMgdGhhdCBpdCB0cmllcyBldmVyeSBwb3NzaWJsZSBjb21iaW5hdGlvbiBvZiB0aGUgdmFyaWFibGVzIGFuZCByZXR1cm5zIHRoZSBiZXN0LXBlcmZvcm1pbmcgc3Vic2V0Lg0KDQoNCiMjIEVtYmVkZGVkIE1ldGhvZHMNCg0KVGhlc2UgbWV0aG9kcyBlbmNvbXBhc3MgdGhlIGJlbmVmaXRzIG9mIGJvdGggdGhlIHdyYXBwZXIgYW5kIGZpbHRlciBtZXRob2RzLCBieSBpbmNsdWRpbmcgaW50ZXJhY3Rpb25zIG9mIGZlYXR1cmVzIGJ1dCBhbHNvIG1haW50YWluaW5nIHJlYXNvbmFibGUgY29tcHV0YXRpb25hbCBjb3N0LiBFbWJlZGRlZCBtZXRob2RzIGFyZSBpdGVyYXRpdmUgaW4gdGhlIHNlbnNlIHRoYXQgdGFrZXMgY2FyZSBvZiBlYWNoIGl0ZXJhdGlvbiBvZiB0aGUgbW9kZWwgdHJhaW5pbmcgcHJvY2VzcyBhbmQgY2FyZWZ1bGx5IGV4dHJhY3QgdGhvc2UgZmVhdHVyZXMgd2hpY2ggY29udHJpYnV0ZSB0aGUgbW9zdCB0byB0aGUgdHJhaW5pbmcgZm9yIGEgcGFydGljdWxhciBpdGVyYXRpb24uDQoNCiMjIyBMQVNTTyBSZWd1bGFyaXphdGlvbiANCg0KUmVndWxhcml6YXRpb24gY29uc2lzdHMgb2YgYWRkaW5nIGEgcGVuYWx0eSB0byB0aGUgZGlmZmVyZW50IHBhcmFtZXRlcnMgb2YgdGhlIG1hY2hpbmUgbGVhcm5pbmcgbW9kZWwgdG8gcmVkdWNlIHRoZSBmcmVlZG9tIG9mIHRoZSBtb2RlbCwgaS5lLiB0byBhdm9pZCBvdmVyLWZpdHRpbmcuIEluIGxpbmVhciBtb2RlbCByZWd1bGFyaXphdGlvbiwgdGhlIHBlbmFsdHkgaXMgYXBwbGllZCBvdmVyIHRoZSBjb2VmZmljaWVudHMgdGhhdCBtdWx0aXBseSBlYWNoIG9mIHRoZSBwcmVkaWN0b3JzLiBGcm9tIHRoZSBkaWZmZXJlbnQgdHlwZXMgb2YgcmVndWxhcml6YXRpb24sIExhc3NvIG9yIEwxIGhhcyB0aGUgcHJvcGVydHkgdGhhdCBjYW4gc2hyaW5rIHNvbWUgb2YgdGhlIGNvZWZmaWNpZW50cyB0byB6ZXJvLiBUaGVyZWZvcmUsIHRoYXQgZmVhdHVyZSBjYW4gYmUgcmVtb3ZlZCBmcm9tIHRoZSBtb2RlbC4NCg0KIyMjIFJhbmRvbSBGb3Jlc3QgSW1wb3J0YW5jZQ0KDQpSYW5kb20gRm9yZXN0cyBpcyBhIGtpbmQgb2YgYSBCYWdnaW5nIEFsZ29yaXRobSB0aGF0IGFnZ3JlZ2F0ZXMgYSBzcGVjaWZpZWQgbnVtYmVyIG9mIGRlY2lzaW9uIHRyZWVzLiBUaGUgdHJlZS1iYXNlZCBzdHJhdGVnaWVzIHVzZWQgYnkgcmFuZG9tIGZvcmVzdHMgbmF0dXJhbGx5IHJhbmsgYnkgaG93IHdlbGwgdGhleSBpbXByb3ZlIHRoZSBwdXJpdHkgb2YgdGhlIG5vZGUsIG9yIGluIG90aGVyIHdvcmRzIGEgZGVjcmVhc2UgaW4gdGhlIGltcHVyaXR5IChHaW5pIGltcHVyaXR5KSBvdmVyIGFsbCB0cmVlcy4gTm9kZXMgd2l0aCB0aGUgZ3JlYXRlc3QgZGVjcmVhc2UgaW4gaW1wdXJpdHkgaGFwcGVuIGF0IHRoZSBzdGFydCBvZiB0aGUgdHJlZXMsIHdoaWxlIG5vdGVzIHdpdGggdGhlIGxlYXN0IGRlY3JlYXNlIGluIGltcHVyaXR5IG9jY3VyIGF0IHRoZSBlbmQgb2YgdHJlZXMuIFRodXMsIGJ5IHBydW5pbmcgdHJlZXMgYmVsb3cgYSBwYXJ0aWN1bGFyIG5vZGUsIHdlIGNhbiBjcmVhdGUgYSBzdWJzZXQgb2YgdGhlIG1vc3QgaW1wb3J0YW50IGZlYXR1cmVzLg0KDQoNCiMjIEh5YnJpZCBNZXRob2RzDQoNCkh5YnJpZCBtZXRob2RzIHRyeSB0byBleHBsb2l0IHRoZSBxdWFsaXRpZXMgb2YgYm90aCBhcHByb2FjaGVzLCBmaWx0ZXIsIGFuZCB3cmFwcGVyLCB0cnlpbmcgdG8gaGF2ZSBhIGdvb2QgY29tcHJvbWlzZSBiZXR3ZWVuIGVmZmljaWVuY3kgKGNvbXB1dGF0aW9uYWwgZWZmb3J0KSBhbmQgZWZmZWN0aXZlbmVzcyAocXVhbGl0eSBpbiB0aGUgYXNzb2NpYXRlZCBvYmplY3RpdmUgdGFzayB3aGVuIHVzaW5nIHRoZSBzZWxlY3RlZCBmZWF0dXJlcykuDQoNClRvIHRha2UgYWR2YW50YWdlIG9mIHRoZSBmaWx0ZXIgYW5kIHdyYXBwZXIgYXBwcm9hY2hlcywgaHlicmlkIG1ldGhvZHMsIGluIGEgZmlsdGVyIHN0YWdlLCB0aGUgZmVhdHVyZXMgYXJlIHJhbmtlZCBvciBzZWxlY3RlZCBhcHBseWluZyBhIG1lYXN1cmUgYmFzZWQgb24gaW50cmluc2ljIHByb3BlcnRpZXMgb2YgdGhlIGRhdGEuIFdoaWxlLCBpbiBhIHdyYXBwZXIgc3RhZ2UsIGNlcnRhaW4gZmVhdHVyZSBzdWJzZXRzIGFyZSBldmFsdWF0ZWQgZm9yIGZpbmRpbmcgdGhlIGJlc3Qgb25lLCB0aHJvdWdoIGEgc3BlY2lmaWMgY2x1c3RlcmluZyBhbGdvcml0aG0uIFdlIGNhbiBkaXN0aW5ndWlzaCB0d28gdHlwZXMgb2YgaHlicmlkIG1ldGhvZHM6IG1ldGhvZHMgYmFzZWQgb24gcmFua2luZyBhbmQgbWV0aG9kcyBub24tYmFzZWQgb24gdGhlIHJhbmtpbmcgb2YgZmVhdHVyZXMuDQoNCiMgRmVhdHVyZSBFeHRyYWN0aW9uIE1ldGhvZHMNCg0KQnkgZmluZGluZyBhIHNtYWxsZXIgc2V0IG9mIG5ldyB2YXJpYWJsZXMsIGVhY2ggYmVpbmcgYSBjb21iaW5hdGlvbiBvZiB0aGUgaW5wdXQgdmFyaWFibGVzLCBjb250YWluaW5nIGJhc2ljYWxseSB0aGUgc2FtZSBpbmZvcm1hdGlvbiBhcyB0aGUgaW5wdXQgdmFyaWFibGVzLiBJbiBvdGhlciB3b3JkcywgZmVhdHVyZSBleHRyYWN0aW9uIGlzIGEgcHJvY2VkdXJlIHRoYXQgZGVmaW5lcyBuZXcgdmFyaWFibGVzIGJ5IGFnZ3JlZ2F0aW5nIHRoZSBpbmZvcm1hdGlvbiBmcm9tIGV4aXN0aW5nIGZlYXR1cmVzLiBGb3IgZXhhbXBsZSwgdGhlIG5ldyBmZWF0dXJlIHZhcmlhYmxlIGNvdWxkIGJlIGEgZnVuY3Rpb24gb2YgdGhlIGV4aXN0aW5nIGZlYXR1cmVzLiBUaGUgbmV3IHNldCBvZiBmZWF0dXJlcyB3aWxsIGhhdmUgZGlmZmVyZW50IHZhbHVlcyBhcyBjb21wYXJlZCB0byB0aGUgb3JpZ2luYWwgZmVhdHVyZSB2YWx1ZXMuIA0KDQpUaGUgbWFpbiBhaW0gaXMgdGhhdCBmZXdlciBmZWF0dXJlcyB3aWxsIGJlIHJlcXVpcmVkIHRvIGNhcHR1cmUgdGhlIHNhbWUgaW5mb3JtYXRpb24uIA0KDQojIyBDbHVzdGVyIEFuYWx5c2lzDQoNCmNsdXN0ZXIgYW5hbHlzaXMsIGluIHN0YXRpc3RpY3MsIHNldCBvZiB0b29scyBhbmQgYWxnb3JpdGhtcyB0aGF0IGFyZSB1c2VkIHRvIGNsYXNzaWZ5IGRpZmZlcmVudCBvYmplY3RzIGludG8gZ3JvdXBzIGluIHN1Y2ggYSB3YXkgdGhhdCB0aGUgc2ltaWxhcml0eSBiZXR3ZWVuIHR3byBvYmplY3RzIGlzIG1heGltYWwgaWYgdGhleSBiZWxvbmcgdG8gdGhlIHNhbWUgZ3JvdXAgYW5kIG1pbmltYWwgb3RoZXJ3aXNlLiBUaGUgY2x1c3RlciBJRCBpcyBhIG5ldyBmZWF0dXJlIHRoYXQgY2FuIGJlIHVzZWQgdG8gY2FwdHVyZSBoZXRlcm9nZW5lb3VzIGluZm9ybWF0aW9uIGFjcm9zcyBjbHVzdGVycy4NCg0KDQojIyBQcmluY2lwYWwgQ29tcG9uZW50IEFuYWx5c2lzIChQQ0EpDQoNCldlIGhhdmUgaW50cm9kdWNlZCBsaW5lYXIgcHJpbmNpcGFsIGNvbXBvbmVudCBhbmFseXNpcyAoUENBKS4gVGhlIGlkZWEgaXMgdG8gbWFwIHRoZSBleGlzdGluZyBmZWF0dXJlIHNwYWNlIHRvIGEgbmV3IHNwYWNlIChwcmluY2lwYWwgY29tcG9uZW50cyBzcGFjZSkuDQoNClRlY2huaWNhbGx5LCBhIHByaW5jaXBhbCBjb21wb25lbnQgY2FuIGJlIGRlZmluZWQgYXMgYSBsaW5lYXIgY29tYmluYXRpb24gb2Ygb3B0aW1hbGx5LXdlaWdodGVkIG9ic2VydmVkIHZhcmlhYmxlcy4gVGhlIG91dHB1dCBvZiBQQ0EgaXMgdGhlc2UgcHJpbmNpcGFsIGNvbXBvbmVudHMuIFRoZSBudW1iZXIgb2YgUENzIHRvIHJldGFpbiBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIG51bWJlciBvZiBvcmlnaW5hbCB2YXJpYWJsZXMuIFRoZSBQQ3MgcG9zc2VzcyBzb21lIHVzZWZ1bCBwcm9wZXJ0aWVzDQoNCiogVGhlIFBDcyBhcmUgZXNzZW50aWFsbHkgdGhlIGxpbmVhciBjb21iaW5hdGlvbnMgb2YgdGhlIG9yaWdpbmFsIHZhcmlhYmxlcywgdGhlIHdlaWdodHMgdmVjdG9yIGluIHRoaXMgY29tYmluYXRpb24gaXMgYWN0dWFsbHkgdGhlIGVpZ2VudmVjdG9yIGZvdW5kIHdoaWNoIGluIHR1cm4gc2F0aXNmaWVzIHRoZSBwcmluY2lwbGUgb2YgbGVhc3Qgc3F1YXJlcy4NCg0KKiBUaGUgUENzIGFyZSBvcnRob2dvbmFsLCBhcyBhbHJlYWR5IGRpc2N1c3NlZC4NCg0KKiBUaGUgdmFyaWF0aW9uIHByZXNlbnQgaW4gdGhlIFBDcyBkZWNyZWFzZSBhcyB3ZSBtb3ZlIGZyb20gdGhlIDFzdCBQQyB0byB0aGUgbGFzdCBvbmUsIGhlbmNlIHRoZSBpbXBvcnRhbmNlLg0KDQoqIFRoZSBsZWFzdCBpbXBvcnRhbnQgUENzIGFyZSBhbHNvIHNvbWV0aW1lcyB1c2VmdWwgaW4gcmVncmVzc2lvbiwgb3V0bGllciBkZXRlY3Rpb24sIGV0Yy4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgMS4gSWxsdXN0cmF0aW9uIG9mIFBDQS4gVGhlIGxlYXN0ICgybmQpIGltcG9ydGFudCBjb21wb25lbnQgY2FuIGJlIHVzZWQgZm9yIGFub21hbHkgZGV0ZWN0aW9uLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLVBDQS5qcGciKQ0KYGBgDQoNCiMjIExpbmVhciBEaXNjcmltaW5hbnQgQW5hbHlzaXMgKExEQSkNCg0KTGluZWFyIGRpc2NyaW1pbmFudCBhbmFseXNpcyAoTERBKSBhbHNvIGNyZWF0ZXMgbGluZWFyIGNvbWJpbmF0aW9ucyBvZiB5b3VyIG9yaWdpbmFsIGZlYXR1cmVzLiBIb3dldmVyLCB1bmxpa2UgUENBLCBMREEgZG9lc24ndCBtYXhpbWl6ZSBleHBsYWluZWQgdmFyaWFuY2UuIEluc3RlYWQsIGl0IG1heGltaXplcyB0aGUgc2VwYXJhYmlsaXR5IGJldHdlZW4gY2xhc3Nlcy4NCg0KSW4gb3RoZXIgd29yZHMsIHRoZSBnb2FsIG9mIGFuIExEQSBpcyB0byBwcm9qZWN0IGEgZmVhdHVyZSBzcGFjZSAoYSBkYXRhIHNldCBuLWRpbWVuc2lvbmFsIHNhbXBsZXMpIG9udG8gYSBzbWFsbGVyIHN1YnNwYWNlIGsgKHdoZXJlICQgayBcbGUgbuKIkjEkKSB3aGlsZSBtYWludGFpbmluZyB0aGUgY2xhc3MtZGlzY3JpbWluYXRvcnkgaW5mb3JtYXRpb24uDQoNCkluIGdlbmVyYWwsIGRpbWVuc2lvbmFsaXR5IHJlZHVjdGlvbiBkb2VzIG5vdCBvbmx5IGhlbHAgcmVkdWNlIGNvbXB1dGF0aW9uYWwgY29zdHMgZm9yIGEgZ2l2ZW4gY2xhc3NpZmljYXRpb24gdGFzaywgYnV0IGl0IGNhbiBhbHNvIGJlIGhlbHBmdWwgdG8gYXZvaWQgb3ZlcmZpdHRpbmcgYnkgbWluaW1pemluZyB0aGUgZXJyb3IgaW4gcGFyYW1ldGVyIGVzdGltYXRpb24gKOKAnGN1cnNlIG9mIGRpbWVuc2lvbmFsaXR54oCdKS4NCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTMsIGZpZy5jYXA9IkZpZ3VyZSAyLiBJbGx1c3RyYXRpb24gb2YgTERBLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLUxEQS5qcGciKQ0KYGBgDQoNClRoZXJlZm9yZSwgTERBIGlzIGEgc3VwZXJ2aXNlZCBtZXRob2QgdGhhdCBjYW4gb25seSBiZSB1c2VkIHdpdGggbGFiZWxlZCBkYXRhLiBUaGUgTERBIHRyYW5zZm9ybWF0aW9uIGlzIGFsc28gZGVwZW5kZW50IG9uIHNjYWxlLCBzbyB3ZSBzaG91bGQgbm9ybWFsaXplIG9yaWdpbmFsIGZlYXR1cmVzIGluIHRoZSBkYXRhIHNldCBmaXJzdC4NCg0KKipTdHJlbmd0aHMqKjogTERBIGlzIHN1cGVydmlzZWQsIHdoaWNoIGNhbiAoYnV0IGRvZXNuJ3QgYWx3YXlzKSBpbXByb3ZlIHRoZSBwcmVkaWN0aXZlIHBlcmZvcm1hbmNlIG9mIHRoZSBleHRyYWN0ZWQgZmVhdHVyZXMuIEZ1cnRoZXJtb3JlLCBMREEgb2ZmZXJzIHZhcmlhdGlvbnMgKGkuZS4gcXVhZHJhdGljIExEQSkgdG8gdGFja2xlIHNwZWNpZmljIHJvYWRibG9ja3MuDQoNCioqV2Vha25lc3NlcyoqOiBBcyB3aXRoIFBDQSwgdGhlIG5ldyBmZWF0dXJlcyBhcmUgbm90IGVhc2lseSBpbnRlcnByZXRhYmxlLCBhbmQgd2UgbXVzdCBzdGlsbCBtYW51YWxseSBzZXQgb3IgdHVuZSB0aGUgbnVtYmVyIG9mIGNvbXBvbmVudHMgdG8ga2VlcC4gTERBIGFsc28gcmVxdWlyZXMgbGFiZWxlZCBkYXRhLg0KDQoNCioqUENBIHZzIExEQSoqOiBXaGljaCBpcyBiZXR0ZXI/IFRoZSByZXN1bHRzIHdpbGwgdmFyeSBmcm9tIHByb2JsZW0gdG8gcHJvYmxlbS4gSW4gb3RoZXIgd29yZHMsIHRoZSAqKk5vIEZyZWUgTHVuY2gqKiBUaGVvcmVtIGFwcGxpZXMgdG8gdGhpcyBzaXR1YXRpb24uIFRoZSBmb2xsb3dpbmcgZmlndXJlIGRlcGljdHMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBQQ0EgYW5kIExEQS4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgMy4gSWxsdXN0cmF0aW9uIG9mIHRoZSBkaWZmZXJlbmNlIG9mIFBDQSBhbmQgTERBLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLUxEQS12cy1MREEuanBnIikNCmBgYA0KDQojIyBDYXNlLXN0dWR5OiBMREEgd2l0aCBJcmlzIERhdGEgDQoNCmxpa2UgUENBIHdob3NlIG1hdGhlbWF0aWNhbCBmb3JtdWxhdGlvbiBpbnZvbHZlcyBtYXRyaXggYWxnZWJyYSAoZWlnZW52ZWN0b3IgYW5kIGVpZ2VudmFsdWVzKSBhbmQgbGluZWFyIHByb2dyYW1taW5nIChvcHRpbWl6YXRpb24gd2l0aCBsaW5lYXIgY29uc3RyYWludHMpLCBpbiBMREEgd2Ugc3RpbGwgbmVlZCB0byB1c2UgdGhlIHNhbWUgdG9vbHMgYnV0IHdpdGggZGlmZmVyZW50IG9iamVjdGl2ZSBmdW5jdGlvbnMgZm9yIG9wdGltaXphdGlvbi4gV2Ugd2lsbCBub3QgaW50cm9kdWNlIHRoZXNlIG1hdGhlbWF0aWNhbCBzdGVwcyB0byBmaW5kIHRoZSBsaW5lYXIgZGlzY3JpbWluYW50IGNvbXBvbmVudHMuIA0KDQpOZXh0LCB3ZSB1c2UgUiBmdW5jdGlvbiAqKmxkYSgpKiogaW4gbGlicmFyeSAqKntNQVNTfSoqIHRvIGZpbmQgTERBIGNvbXBvbmVudHMgYmFzZWQgb24gdGhlIGZvdXIgbnVtZXJpY2FsIGZlYXR1cmVzIGluIElyaXMgZGF0YS4NCg0KKipsZGEoKSoqIHJldHVybnMgc2V2ZXJhbCByZXN1bHRzOg0KDQoqIFRoZSBtb3N0IGltcG9ydGFudCByZXN1bHQgaGVyZSBpcyB0aGUgY29lZmZpY2llbnRzLCB0aGV5IGFyZSB2YWx1ZXMgdGhhdCBkZXNjcmliZSB0aGUgbmV3IGZlYXR1cmUgc3BhY2Ugd2hlcmUgdGhlIGRhdGEgd2lsbCBiZSBwcm9qZWN0ZWQgaW4uIA0KDQoqIExEQSByZWR1Y2VzIGRpbWVuc2lvbmFsaXR5IGZyb20gdGhlIG9yaWdpbmFsIG51bWJlciBvZiBmZWF0dXJlcyB0byBDIOKAlCAxIGZlYXR1cmVzLCB3aGVyZSBDIGlzIHRoZSBudW1iZXIgb2YgY2xhc3Nlcy4gSW4gdGhpcyBjYXNlLCB3ZSBoYXZlIDMgY2xhc3NlcywgdGhlcmVmb3JlIHRoZSBuZXcgZmVhdHVyZSBzcGFjZSB3aWxsIGhhdmUgb25seSAyIGZlYXR1cmVzLiANCg0KDQpgYGB7cn0NCmRhdGEoaXJpcykNCiMgRGF0YSBwYXJ0aXRpb24NCnRyYWluaW5nX3NhbXBsZSA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIG5yb3coaXJpcyksIHJlcGxhY2UgPSBULCBwcm9iID0gYygwLjYsMC40KSkNCnRyYWluIDwtIGlyaXNbdHJhaW5pbmdfc2FtcGxlLCBdDQp0ZXN0IDwtIGlyaXNbIXRyYWluaW5nX3NhbXBsZSwgXQ0KIw0KbGRhLmlyaXMgPC0gbGRhKFNwZWNpZXMgfiAuLCBkYXRhID0gdHJhaW4pIywgcHJpb3IgPSByZXAoMS8zLCAzKSkNCmthYmxlKGxkYS5pcmlzJHNjYWxpbmcsIGNhcHRpb249IlRoZSBzY2FsaW5nIGNvZWZmaWNpZW50cyBvZiBMREEiKSAgIyBzaG93IHJlc3VsdHMNCmBgYA0KDQpUaGUgdHdvIG5ldyBmZWF0dXJlIHZhcmlhYmxlcyBiYXNlZCBvbiB0aGUgdHdvIExEQSBhcmUgZXhwbGljaXRseSBnaXZlbiBieQ0KDQokJA0KTERBXzEgPSAoMC41MVx0aW1lcyBTZXBhbC5MZW5ndGgpICsgKDEuOTZcdGltZXMgU2VwYWwuV2lkdGgpICsgKC0yLjEyXHRpbWVzIFBldGFsLkxlbmd0aCkgKyAoLTIuOThcdGltZXMgUGV0YWwuV2lkdGgpIA0KJCQNCiQkDQpMREFfMiA9ICgtMC43Nlx0aW1lcyBTZXBhbC5MZW5ndGgpICsgKDIuODVcdGltZXMgU2VwYWwuV2lkdGgpICsgKC0xLjA1XHRpbWVzIFBldGFsLkxlbmd0aCkgKyAoMS45Mlx0aW1lcyBQZXRhbC5XaWR0aCkNCiQkDQpOZXh0LCB3ZSB1c2UgTERBIHRvIG1ha2UgYSBwcmVkaWN0aW9uIHVzaW5nIHRoZSBob2xkLW91dCB0ZXN0IGRhdGEuIE5vdGUgdGhhdCBwcmVkaWN0KCkgcmV0dXJucyB0aHJlZSBvYmplY3RzIHdpdGggdGhyZWUgZGlmZmVyZW50IHBpZWNlcyBvZiBpbmZvcm1hdGlvbjoNCg0KKiAqKmxkYS50ZXN0JGNsYXNzKiogY29udGFpbnMgdGhlIHByZWRpY3RlZCBsYWJlbHMuDQoqICoqbGRhLnRlc3QkcG9zdGVyaW9yKiogY29udGFpbnMgdGhlIHByZWRpY3RpdmUgY2xhc3MgcHJvYmFiaWxpdGllcyBvZiBuZXcgZGF0YSBwb2ludHMuDQoqICoqbGRhLnRlc3QkeCoqIGNvbnRhaW5zIHRoZSB0d28gTERBIHNjb3Jlcy4NCg0KSW4gdGhlIGZvbGxvd2luZyBjb2RlLCB3ZSBleHRyYWN0IHRoZSBwcmVkaWN0ZWQgbGFiZWxzIGFuZCB0aGVuIGNvbXBhcmUgdGhlbSB3aXRoIHRoZSBhY3R1YWwgbGFiZWxzIHRvIGZpbmQgdGhlIGNvbmZ1c2lvbiBtYXRyaXggYW5kIGNhbGN1bGF0ZSB0aGUgYWNjdXJhY3kgb2YgY2xhc3NpZmljYXRpb24gTERBLg0KDQoNCmBgYHtyfQ0KbGRhLnRlc3QgPC0gcHJlZGljdChsZGEuaXJpcywgbmV3ZGF0YSA9IHRlc3QpDQp0ZXN0JGxkYSA8LSBsZGEudGVzdCRjbGFzcyAgDQpjb25mdXNpb24ubWF0cml4ID0gdGFibGUodGVzdCRsZGEsdGVzdCRTcGVjaWVzKQ0Ka2FibGUoY29uZnVzaW9uLm1hdHJpeCwgY2FwdGlvbiA9ICJDb25mdXNpb24gbWF0cml4IGJhc2VkIG9uZSBMREEuIikNCmBgYA0KDQpUaGUgYWNjdXJhY3kgb2YgTERBIHByZWRpY3Rpb24gb24gdGhlIHRlc3QgZGF0YSBzZXQgaXMgJDQ5LzUwID0gOThcJSQuDQoNCiMjIFJlbWFya3MNCg0KV2UgaGF2ZSBpbnRyb2R1Y2VkIHR3byB3ZWxsLWtub3duIGZlYXR1cmUgZXh0cmFjdGlvbiBtZXRob2RzOiBQQ0EgYW5kIExEQS4gQm90aCBhcmUgbGluZWFyIGV4dHJhY3Rpb24gbWV0aG9kcy4gUENBIGlzIGFuIHVuc3VwZXJ2aXNlZCBleHRyYWN0aW9uIG1ldGhvZCBhbmQgTERBIGlzIGEgc3VwZXJ2aXNlZCBtZXRob2QuIEJvdGggbWV0aG9kcyBhcmUgZGV2ZWxvcGVkIGZvciBkaWZmZXJlbnQgcHVycG9zZXMgYnV0IGJvdGggY2FuIGJlIHVzZWQgZm9yIGRpbWVuc2lvbmFsIHJlZHVjdGlvbi4NCg0KQm90aCBQQ0EgYW5kIExEQSBjYW4gYmUgYWRhcHRlZCBmb3Igbm9ubGluZWFyIGZlYXR1cmUgZXh0cmFjdGlvbiBieSBpbnRyb2R1Y2luZyBrZXJuZWwgZnVuY3Rpb25zIChpLmUuLCBrZXJuZWwgUENBIGFuZCBrZXJuZWwgTERBKSBvciBjaGFuZ2luZyB0aGUgbGluZWFyIGNvbWJpbmF0aW9uIG9mIHRoZSBvcmlnaW5hbCBmZWF0dXJlcyBpbnRvIHRoZSBwb2x5bm9taWFsIGV4cHJlc3Npb24gdG8gY2FwdHVyZSB0aGUgbm9ubGluZWFyIHBhdHRlcm5zIChpLmUuLCBwb2x5bm9taWFsIFBDQSBhbmQgcG9seW5vbWlhbCBMREEpLg0KDQpUaGUgdmFyaW91cyB2YXJpYWJsZSB0cmFuc2Zvcm1hdGlvbnMgaW5jbHVkaW5nIHRoZSB3ZWxsLWtub3duIEJveC1Db3ggdHJhbnNmb3JtYXRpb24sIGRpc2NyZXRpemF0aW9uLCBhbmQgcmVkZWZpbmluZyBjYXRlZ29yaWNhbCB2YXJpYWJsZXMgYnkgY29tYmluZyBjYXRlZ29yaWVzIGluIG1lYW5pbmdmdWwgd2F5cyBhcmUgYWxsIGNhbGxlZCBmZWF0dXJlIGV4dHJhY3Rpb24gbWV0aG9kcy4gDQoNCg0KIyBGZWF0dXJlIEV4dHJhY3Rpb24gd2l0aCBTZXJpYWwgRGF0YQ0KDQpUaGUgZmVhdHVyZSBleHRyYWN0aW9uIG1ldGhvZHMgaW50cm9kdWNlZCBpbiB0aGUgcHJldmlvdXMgc2VjdGlvbiBhcmUgYmFzZWQgb24gY3Jvc3Mtc2VjdGlvbmFsIGRhdGEuIFRoZXJlIGFyZSBvbmx5IHZlcnkgbGltaXRlZCBkaXNjdXNzaW9ucyBvbiBmZWF0dXJlIGV4dHJhY3Rpb24gYmFzZWQgb24gc2VyaWFsIGRhdGEgaW5jbHVkaW5nIHRpbWUgc2VyaWVzIGFuZCBwYW5lbCBkYXRhLiBJbiBwYXJ0aWN1bGFyLCBubyBmZWF0dXJlIGV4dHJhY3Rpb24gbWV0aG9kIGJhc2VkIG9uIHBhbmVsIGRhdGEgaGFzIGJlZW4gZGlzY3Vzc2VkIHNvIGZhciBpbiB0aGUgbGl0ZXJhdHVyZS4NCg0KSW4gdGhpcyBzZWN0aW9uLCB3ZSBmaXJzdCBpbnRyb2R1Y2UgdGhlIHdheSBhbmQgdHlwZSBvZiBmZWF0dXJlcyBvbmUgY2FuIGV4dHJhY3QgZnJvbSBhIHRpbWUgc2VyaWVzLiBUaGVuIHdlIGludHJvZHVjZSBhIG5ldyBtZXRob2QgZm9yIGV4dHJhY3RpbmcgZmVhdHVyZXMgZnJvbSBwYW5lbCBkYXRhLiBUaGlzIG1ldGhvZCBjYW4gYWxzbyBiZSB1c2VkIHRvIGRlZmluZSBhIGZlYXR1cmUgYmFzZWQgb24gdGhlIHJlZ3VsYXIgdGltZSBzZXJpZXMuIFRoZSBuZXcgbWV0aG9kIGJvcnJvd3MgdGhlIGlkZWEgb2YgdGhlIGZvcm11bGF0aW9uIG9mIHRoZSBwcm9jZXNzIGNhcGFiaWxpdHkgaW5kZXggaW4gc3RhdGlzdGljYWwgcHJvY2VzcyBhbmQgcXVhbGl0eSBjb250cm9sLg0KDQojIyBGZWF0dXJlIEV4dHJhY3Rpb24gd2l0aCBUaW1lIFNlcmllcw0KDQpUaW1lIHNlcmllcyBkYXRhIGlzIGRhdGEgdGhhdCBpcyBjb2xsZWN0ZWQgYXQgZGlmZmVyZW50IHBvaW50cyBpbiB0aW1lLiBUaGlzIGlzIG9wcG9zZWQgdG8gY3Jvc3Mtc2VjdGlvbmFsIGRhdGEgd2hpY2ggb2JzZXJ2ZXMgaW5kaXZpZHVhbHMsIGNvbXBhbmllcywgZXRjLiBhdCBhIHNpbmdsZSBwb2ludCBpbiB0aW1lLg0KDQpCZWNhdXNlIGRhdGEgcG9pbnRzIGluIHRpbWUgc2VyaWVzIGFyZSBjb2xsZWN0ZWQgYXQgYWRqYWNlbnQgdGltZSBwZXJpb2RzIHRoZXJlIGlzIHBvdGVudGlhbCBmb3IgY29ycmVsYXRpb24gYmV0d2VlbiBvYnNlcnZhdGlvbnMuIFRoaXMgaXMgb25lIG9mIHRoZSBmZWF0dXJlcyB0aGF0IGRpc3Rpbmd1aXNoZXMgdGltZS1zZXJpZXMgZGF0YSBmcm9tIGNyb3NzLXNlY3Rpb25hbCBkYXRhLg0KDQpUaW1lIHNlcmllcyBkYXRhIGNhbiBiZSBmb3VuZCBpbiBlY29ub21pY3MsIHNvY2lhbCBzY2llbmNlcywgZmluYW5jZSwgZXBpZGVtaW9sb2d5LCBhbmQgdGhlIHBoeXNpY2FsIHNjaWVuY2VzLiANCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgNC4gSWxsdXN0cmF0aW9uIG9mIHRpbWVzIHBhdHRlcm5zLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLVdoYXQtaXMtVFMuanBnIikNCmBgYA0KDQpUaGVyZSBhcmUgdHdvIG1haW4gZ29hbHMgb2YgdGltZSBzZXJpZXMgYW5hbHlzaXM6IGlkZW50aWZ5aW5nIHRoZSBuYXR1cmUgb2YgdGhlIHBoZW5vbWVub24gcmVwcmVzZW50ZWQgYnkgdGhlIHNlcXVlbmNlIG9mIG9ic2VydmF0aW9ucywgYW5kIGZvcmVjYXN0aW5nIChwcmVkaWN0aW5nIGZ1dHVyZSB2YWx1ZXMgb2YgdGhlIHRpbWUgc2VyaWVzIHZhcmlhYmxlKS4gIA0KDQojIyMgU3RhdGlzdGljYWwgTW9kZWxzDQoNClRoZSBtb3N0IGNvbW1vbiBhbmQgZWZmZWN0aXZlIHN0YXRpc3RpY2FsIG1ldGhvZHMgb2YgRm9yZWNhc3RpbmcgYXJlIFNpbXBsZSBNb3ZpbmcgQXZlcmFnZSAoU01BKSwgRXhwb25lbnRpYWwgU21vb3RoaW5nIChTRVMpLCBBdXRvLXJlZ3Jlc3NpdmUgSW50ZWdyYXRpb24gTW92aW5nIEF2ZXJhZ2UgKEFSSU1BKS4NCg0KV2Ugd2lsbCBub3QgZGlzY3VzcyB0aGVzZSBtZXRob2RzIGluIHRoaXMgbm90ZSBidXQgd2lsbCBpbnRyb2R1Y2UgdGhlIGV4cG9uZW50aWFsIHNtb290aGluZyBtZXRob2QgZm9yIHRoZSB0aW1lIHNlcmllcyBuZXh0IHdlZWsuDQoNCiMjIyBNYWNoaW5lIExlYXJuaW5nIEFsZ29yaXRobXMNCg0KT25lIG9mIHRoZSBtb3N0IGltcG9ydGFudCBwcm9wZXJ0aWVzIGFuIGFsZ29yaXRobSBuZWVkcyBpbiBvcmRlciB0byBiZSBjb25zaWRlcmVkIGEgdGltZS1zZXJpZXMgYWxnb3JpdGhtIGlzIHRoZSBhYmlsaXR5IHRvIGV4dHJhcG9sYXRlIHBhdHRlcm5zIG91dHNpZGUgb2YgdGhlIGRvbWFpbiBvZiB0cmFpbmluZyBkYXRhLiBNYW55IG1hY2hpbmUgbGVhcm5pbmcgYWxnb3JpdGhtcyBkbyBub3QgaGF2ZSB0aGlzIGNhcGFiaWxpdHksIGFzIHRoZXkgdGVuZCB0byBiZSByZXN0cmljdGVkIHRvIGEgZG9tYWluIHRoYXQgaXMgZGVmaW5lZCBieSB0cmFpbmluZyBkYXRhLiBUaGVyZWZvcmUsIHRoZXkgYXJlIG5vdCBzdWl0ZWQgZm9yIHRpbWUgc2VyaWVzLCBhcyB0aGUgb2JqZWN0aXZlIG9mIHRpbWUgc2VyaWVzIGlzIHRvIHByb2plY3QgaW50byB0aGUgZnV0dXJlLg0KDQpBbm90aGVyIGltcG9ydGFudCBwcm9wZXJ0eSBvZiBhIHRpbWUgc2VyaWVzIGFsZ29yaXRobSBpcyB0aGUgYWJpbGl0eSB0byBkZXJpdmUgY29uZmlkZW5jZSBpbnRlcnZhbHMuIFdoaWxlIHRoaXMgaXMgYSBkZWZhdWx0IHByb3BlcnR5IG9mIHRpbWUgc2VyaWVzIG1vZGVscywgbW9zdCBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBkbyBub3QgaGF2ZSB0aGlzIGFiaWxpdHkgYmVjYXVzZSB0aGV5IGFyZSBub3QgYWxsIGJhc2VkIG9uIHN0YXRpc3RpY2FsIGRpc3RyaWJ1dGlvbnMuIA0KDQpUaGVyZSBhcmUgYWxzbyBtYWNoaW5lIGxlYXJuaW5nIG1vZGVscyBzdWNoIGFzIG5ldXJhbCBuZXR3b3JrIG1vZGVscyB0aGF0IGNhbiBiZSBhcHBsaWVkIHRvIHRpbWUgc2VyaWVzIHdoaWNoIHVzZSBgbGFnZ2VkIHByZWRpY3RvcnNgIGFuZCBjYW4gaGFuZGxlIGBleHRyYWN0ZWQgZmVhdHVyZXNgLCBzdWNoIGFzIE5ldXJhbCBOZXR3b3JrcyBBdXRvcmVncmVzc2lvbiAoTk5BUikuIFRoZXJlIGFyZSBldmVuIHRpbWUtc2VyaWVzIG1vZGVscyBib3Jyb3dlZCBmcm9tIGRlZXAgbGVhcm5pbmcsIHNwZWNpZmljYWxseSBpbiB0aGUgUk5OIChSZWN1cnJlbnQgTmV1cmFsIE5ldHdvcmspIGZhbWlseS4gIFRoZSBmb2xsb3dpbmcgZmlndXJlIHNob3dzIGhvdyB0byB1c2UgZXh0cmFjdGVkIGZlYXR1cmVzIGluIGEgbmV1cmFsIG5ldHdvcmsgbW9kZWwgZm9yIGZvcmVjYXN0aW5nLiANCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTMsIGZpZy5jYXA9IkZpZ3VyZSA1LiBIb3cgdG8gQU5OIHRvIG1vZGVsIHRpbWUgc2VyaWVzLiJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLUFOTi1UUy5qcGciKQ0KYGBgDQoNCg0KIyMjIEZlYXR1cmUgRXh0cmFjdGlvbiBmb3IgVGltZSBTZXJpZXMNCg0KU2luY2UgdGhlIG1hY2hpbmUgbGVhcm5pbmcgbWV0aG9kIGNhbiBpbmNvcnBvcmF0ZSBib3RoIGxhZ2dlZCBwcmVkaWN0b3JzIGFuZCBhZGRpdGlvbmFsIGZlYXR1cmVzIHRvIGltcHJvdmUgdGhlIGZvcmVjYXN0IGFjY3VyYWN5LCB3ZSBjYW4gZXh0cmFjdCBzb21lIGZlYXR1cmVzIGZyb20gdGhlIHVuZGVybHlpbmcgZmVhdHVyZXMuIFRoZSBmb2xsb3dpbmcgZmlndXJlIGlsbHVzdHJhdGVzIHRoZSBwcm9jZXNzIG9mIGhvdyB0byBleHRyYWN0IGZlYXR1cmVzIGZyb20gdGltZS1zZXJpZXMgZGF0YS4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgNi4gSG93IHRvIGV4dHJhY3QgZmVhdHVyZXMgZnJvbSB0aW1lIHNlcmllcy4ifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1nL3cxMC1TZXJpYWwtRmVhdHVyZS1FeHRyYWN0aW9uLmpwZyIpDQpgYGANCg0KQXMgc2hvd24gaW4gdGhlIGFib3ZlIGZpZ3VyZSwgdGhyZWUgdHlwZXMgb2YgZmVhdHVyZXMgY2FuIGJlIGV4dHJhY3RlZCBmcm9tIHRpbWUtc2VyaWVzIGRhdGEuDQoNCiogKipUZW1wb3JhbCBmZWF0dXJlcyAodGltZS1kb21haW4gZmVhdHVyZXMpKiogYXJlIHNpbXBsZSB0byBleHRyYWN0IGFuZCBoYXZlIGFuIGVhc3kgcGh5c2ljYWwgaW50ZXJwcmV0YXRpb24uIA0KDQoqICoqU3RhdGlzdGljYWwgZmVhdHVyZXMqKiBhcmUgbWFpbmx5IGRlc2NyaXB0aXZlIHN0YXRpc3RpY3Mgc3VjaCBhcyB3aW5kb3dlZCBtZWFuLCBtZWRpYW4sIHNrZXduZXNzLCBldGMuIA0KDQoqICoqU3BlY3RyYWwgZmVhdHVyZXMgKGZyZXF1ZW5jeS1iYXNlZCBmZWF0dXJlcykqKiBhcmUgb2J0YWluZWQgYnkgY29udmVydGluZyB0aGUgdGltZS1iYXNlZCBzaWduYWwgaW50byB0aGUgZnJlcXVlbmN5IGRvbWFpbi4gDQoNClRoZXNlIGZlYXR1cmVzIGFyZSBkZXNjcmlwdGl2ZSBhbmQgY2FuIGJlIGVhc2lseSBhdXRvbWF0ZWQuIFNvbWUgc29mdHdhcmUgcHJvZ3JhbXMgaGF2ZSBiZWVuIG1hZGUgdG8gZXh0cmFjdCB0aGVzZSB0eXBlcyBvZiBmZWF0dXJlcyBhdXRvbWF0aWNhbGx5IGluIHByYWN0aWNlLg0KDQoNCiMjIE1vZGVsLWJhc2VkIEZlYXR1cmUgRXh0cmFjdGlvbiB3aXRoIFBhbmVsIERhdGENCg0KVGhpcyBzdWJzZWN0aW9uIGZvY3VzZXMgb24gYSBuZXcgZmVhdHVyZSBleHRyYWN0aW9uIG1ldGhvZCB0aGF0IGV4dHJhY3RzIGluZm9ybWF0aW9uIGJhc2VkIG9uIG1vZGVscyBhbmQgYWxnb3JpdGhtcyBmcm9tIHNlcXVlbnRpYWwgZGF0YS4gVGhlIGFsZ29yaXRobSBib3Jyb3dzIHRoZSBpZGVhIG9mIG1lYXN1cmluZyB0aGUgcHJvY2VzcyBpbmZvcm1hdGlvbiAoc3VjaCBhcyBjYXBhYmlsaXR5IGFuZCBxdWFsaXR5KSB0aHJvdWdoIHRoZSBzZXF1ZW5jZSBkYXRhIGdlbmVyYXRlZCBieSB0aGUgcHJvY2Vzcy4gDQoNClNpbmNlIHRoaXMgaXMgYSBtb2RlbC1iYXNlZCBhbGdvcml0aG0sIGl0IGlzIG1vcmUgcG93ZXJmdWwgdGhhbiB0aG9zZSBmZWF0dXJlcyBleHRyYWN0ZWQgZnJvbSB0aGUgdGltZSBzZXJpZXMgZGlzY3Vzc2VkIGluIHRoZSBwcmV2aW91cyBzdWJzZWN0aW9uLg0KDQojIyMgQ29uY2VwdHMgUHJvY2VzcyBDYXBhYmlsaXR5IGFuZCBDb250cm9sIENoYXJ0DQoNClByb2Nlc3MgY29udHJvbCBpcyB0aGUgYWJpbGl0eSB0byBtb25pdG9yIGFuZCBhZGp1c3QgYSBwcm9jZXNzIHRvIGdpdmUgdGhlIGRlc2lyZWQgb3V0cHV0LiBJdCBpcyB1c2VkIGluIHRoZSBpbmR1c3RyeSB0byBtYWludGFpbiBxdWFsaXR5IGFuZCBpbXByb3ZlIHBlcmZvcm1hbmNlLiBLZXkgdG9vbHMgaW4gcHJvY2VzcyBjb250cm9sIGluY2x1ZGUgY29udHJvbCBjaGFydCwgcHJvY2VzcyBjYXBhYmlsaXR5IGluZGV4LCBldGMuDQoNCkJvdGggY29udHJvbCBjaGFydCBhbmQgcHJvY2VzcyBjYXBhYmlsaXR5IGluZGV4IHVzZSB0aGUgc2FtZSBrZXkgY2hhcmFjdGVyaXN0aWNzIG9mIHRoZSB1bmRlcmx5aW5nIHByb2Nlc3MgaW4gdGhlaXIgY29uc3RydWN0aW9uOg0KDQoqICoqU3BlY2lmaWNhdGlvbiBsaW1pdHMqKiBjYW4gYmUgZGVmaW5lZCBhcyB0YXJnZXRzIHRoYXQgYXJlIHNldCBmb3IgYSBwYXJ0aWN1bGFyIHByb2Nlc3Mgb3IgYSBwcm9kdWN0IGVpdGhlciBieSB0aGUgY3VzdG9tZXIgb3IgYmFzZWQgb24gdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBtYXJrZXQuIEluIG90aGVyIHdvcmRzLCBpdCBjYW4gYWxzbyBiZSBkZWZpbmVkIGFzIGEgcmVzdWx0IHRoYXQgaXMgZXhwZWN0ZWQgZnJvbSBhIHBhcnRpY3VsYXIgbWV0cmljLiBTcGVjaWZpY2F0aW9uIGxpbWl0cyBhcmUgc2V0IGJ5IGN1c3RvbWVycyBvciB0aGUgbWFuYWdlbWVudC4NCg0KKiAqKkNvbnRyb2wgbGltaXRzKiogb24gdGhlIG90aGVyIGhhbmQgaGVscCBpbiBpbmRpY2F0aW5nIHRoZSBjaGFuZ2VzIHdoaWNoIG9jY3VyIGluIHRoZSBwZXJmb3JtYW5jZSBvZiBhIHBhcnRpY3VsYXIgcHJvY2Vzcy4gQ29udHJvbCBsaW1pdHMgYWxzbyBwcm92aWRlIHJlYWwtdGltZSB2YWx1ZS4gQ29udHJvbCBsaW1pdHMgYXJlIGRlcGVuZGVudCBvbiB0aGUgdW5kZXJseWluZyBwcm9jZXNzLg0KDQpDb250cm9sIGxpbWl0cyBjYW4gYmUgZWl0aGVyIHVwcGVyIGNvbnRyb2wgbGltaXQgKFVDTCkgb3IgbG93ZXIgY29udHJvbCBsaW1pdCAoTENMKS4gU2ltaWxhcmx5LCBzcGVjaWZpY2F0aW9uIGxpbWl0cyBjYW4gYmUgZWl0aGVyIHVwcGVyIHNwZWNpZmljYXRpb24gbGltaXQgKFVTTCkgb3IgbG93ZXIgc3BlY2lmaWNhdGlvbiBsaW1pdCAoTFNMKS4NCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgNy4gU3RydWN0dXJlIG9mIGEgY29udHJvbCBjaGFydC4ifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1nL3cxMC1jb250cm9sLXNwZWMtbGltaXRzLmpwZyIpDQpgYGANCg0KKipVbmRlcnN0YW5kaW5nIHRoZSBjb250cm9sIGNoYXJ0KiogDQoNClNldmVyYWwgY29uY2VwdHMgd2lsbCBiZSB1c2VkIGluIHRoZSBkZWZpbml0aW9uIG9mIHRoZSBwcm9jZXNzIGNhcGFiaWxpdHkgaW5kZXguDQoNCkNvbnRyb2wgY2hhcnRzIGFyZSBvbmUgb2YgdGhlIG1vc3QgcG9wdWxhciBTUEMgdG9vbHMgdXNlZCBieSBtYW51ZmFjdHVyZXJzLiBUaGV5IGFyZSB1c2VkIHRvIGRldGVybWluZSAqKndoZXRoZXIgYSBwcm9jZXNzIGlzIGluLSBvciBvdXQtb2YtY29udHJvbCoqLg0KDQpXaGVuIHBvaW50cyBvbiBhIGNvbnRyb2wgY2hhcnQgbW92ZSBvdXRzaWRlIHRoZSB1cHBlciBvciBsb3dlciBjb250cm9sIGxpbWl0LCB0aGUgcHJvY2VzcyBhcmUgc2FpZCB0byBiZSAqKuKAnG91dC1vZi1jb250cm9sLuKAnSoqIEFzIGxvbmcgYXMgdGhlIHBvaW50cyBhcmUgd2l0aGluIGNvbnRyb2wgbGltaXRzLCB0aGUgcHJvY2VzcyBpcyAqKuKAnGluLWNvbnRyb2zigJ0qKi4gQW4gKipvdXQtb2YtY29udHJvbCBwcm9jZXNzKiogY291bGQgcHJvZHVjZSBkZWZlY3RpdmUgcGFydHMuIEhvd2V2ZXIsIGlmIGEgcG9pbnQgaXMgb3V0c2lkZSB0aGUgKipzcGVjaWZpY2F0aW9uIGxpbWl0cyoqLCB0aGUgcHJvY2VzcyBwcm9kdWNlcyBkZWZlY3RpdmUgcHJvZHVjdHMuIA0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9MywgZmlnLmNhcD0iRmlndXJlIDguIEluLWNvbnRyb2wgYW5kIG91dC1vZi1jb250cm9sIHByb2Nlc3Nlcy4ifQ0KaW5jbHVkZV9ncmFwaGljcygiaW1nL3cxMC1jb250cm9sLWNoYXJ0LmpwZyIpDQpgYGANCg0KQ29udHJvbCBjaGFydHMgYXJlIHZpc3VhbCB0b29scyBmb3IgbW9uaXRvcmluZyB0aGUgcHJvY2VzcyBjYXBhYmlsaXR5LiBXaXRoIGEgY29udHJvbCBjaGFydCwgd2UgY2FuIHNlZSB0aGUgcG90ZW50aWFsIHNoaWZ0IG9mIHByb2Nlc3MgbWVhbiBhbmQgdmFyaWF0aW9uIGF0IHRoZSBzYW1lIHRpbWUuIEEgbnVtZXJpY2FsIG1lYXN1cmUgdGhhdCBjYW4gYmUgZGVmaW5lZCB0byBjYXB0dXJlIGJvdGggYWZvcmVtZW50aW9uZWQgc2hpZnRzIG9mIGEgcHJvY2VzcyBpbiBhIHNpbmdsZSBudW1iZXIgaXMgdGhlIHByb2Nlc3MgY2FwYWJpbGl0eSBpbmRleCAoUENJKS4NCg0KIyMjIENvbmNlcHQgb2YgUHJvY2VzcyBDYXBhYmlsaXR5IEluZGV4IChQQ0kpDQoNClByb2Nlc3MgY2FwYWJpbGl0eSBpbmRleCBtZWFzdXJlcyB0aGUgZGVncmVlIG9mIHZhcmlhdGlvbiBhbiBpbi1jb250cm9sIHByb2Nlc3MgZXhwZXJpZW5jZXMgcmVsYXRpdmUgdG8gaXRzIHNwZWNpZmljYXRpb24gbGltaXRzLiBJdCBjYW4gYWxzbyBiZSB1c2VkIHRvIGNvbXBhcmUgZGlmZmVyZW50IHByb2Nlc3NlcyB3aXRoIHJlc3BlY3QgdG8gdGhlIG9wdGltYWwgc2l0dWF0aW9uIG9yIGlmIHRoZXkgY29tZSB1cCB0byBvdXIgZXhwZWN0YXRpb25zLiANCg0KVGhlIGZpcnN0IHByb2Nlc3MgY2FwYWJpbGl0eSBpbmRleCBpcyBkZWZpbmVkIGJ5ICRDX3AkLCANCg0KJCQNCkNfcCA9IFxmcmFje1VTTC1MU0x9ezZcc2lnbWF9DQokJA0KDQp3aGljaCBpcyBhbiBlc3RpbWF0ZSBvZiB3aGF0IHRoZSBwcm9jZXNzIGlzIGNhcGFibGUgb2YgcHJvZHVjaW5nIGlmIHRoZSBwcm9jZXNzIG1lYW4gd2VyZSB0byBiZSBjZW50ZXJlZCBiZXR3ZWVuIHRoZSBzcGVjaWZpY2F0aW9uIGxpbWl0cywgYXNzdW1pbmcgdGhhdCB0aGUgcHJvY2VzcyBvdXRwdXQgaXMgYXBwcm94aW1hdGVseSBub3JtYWxseSBkaXN0cmlidXRlZC4gVGhpcyBmaXJzdCAkQ19wJCB3YXMgaW52ZW50ZWQgYW5kIHVzZWQgaW4gdGhlIEphcGFuZXNlIHNlbWljb25kdWN0b3IgaW5kdXN0cnkgaW4gdGhlIDE5NzBzLiANCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmFsaWduPSdjZW50ZXInLCBmaWcud2lkdGg9MywgZmlnLmhlaWdodD0zLCBmaWcuY2FwPSJGaWd1cmUgOS4gRmlyc3QgYW5kIHNlY29uZCBnZW5lcmF0aW9uIFBDSXMuIn0NCmluY2x1ZGVfZ3JhcGhpY3MoImltZy93MTAtMXN0LTJuZC1nZW5lcmF0aW9uLVBDSXMuanBnIikNCmBgYA0KDQoNClNpbmNlICRDX3AkIGRvZXMgbm90IGNvbnNpZGVyIHByb2Nlc3MgbWVhbnMgYW5kIHByb2Nlc3MgdGFyZ2V0LCBzZXZlcmFsIG1ham9yIGZhbWlsaWVzIG9mIFBDSXMgd2VyZSBkZWZpbmVkIGFmdGVyICRDX3AkLiBUaGUgZm9sbG93aW5nIHRhYmxlIGxpc3RzIG1ham9yIFBDSXMgdXNlZCBpbiB0aGUgaW5kdXN0cnkgZm9yIHZhcmlvdXMgcHVycG9zZXMuDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5hbGlnbj0nY2VudGVyJywgZmlnLndpZHRoPTMsIGZpZy5oZWlnaHQ9M30NCmluY2x1ZGVfZ3JhcGhpY3MoImltZy93MTAtbGlzdC1vZi1QQ0lzLmpwZyIpDQpgYGANCg0KSW4gdGhlIG1hbnVmYWN0dXJpbmcgaW5kdXN0cnksIFBDSXMgYXJlIHVzZWQgdG8gbWVhc3VyZSB0aGUgcXVhbGl0eSBvZiBhIHByb2Nlc3MgKHByb2R1Y3QpLCBVU0wsIGFuZCBMU0wgYW5kIFQgKHRhcmdldCkgYXJlIGdpdmVuIGJ5IGN1c3RvbWVycyBvciB0aGUgbWFuYWdlbWVudC4gV2hlbiBhcHBseWluZyBQQ0kgaW4gb3RoZXIgZmllbGRzIHN1Y2ggYXMgZnJhdWQgZGV0ZWN0aW9uLCBVU0wsIExTTCBhbmQgVCBhcmUgbm90IGdpdmVuLCB3ZSBuZWVkIHRvIGZpZ3VyZSBvdXQgYSB3YXkgdG8gb2J0YWluIHJlYXNvbmFibGUgVVNMLCBMU0wsIGFuZCBUIGluIG9yZGVyIHRvIGRlZmluZSB0aGUgUENJLiBUaGUgbmV4dCBzdWJzZWN0aW9uIGV4cGxhaW5zIHRoZSBpZGVhIG9mIHVzaW5nIFBDSSB0byBkZWZpbmUgZnJhdWQgaW5kZXguDQoNCiMjIyBGcmFtZXdvcmsgb2YgRnJhdWQgSW5kZXggQmFzZWQgb24gUENJDQoNCldlIGNhbiBjb25zaWRlciBhIGNyZWRpdCBjYXJkIGFzICoqYSBwcm9jZXNzKiogdGhhdCBwcm9kdWNlcyB0cmFuc2FjdGlvbnMuIFRoaXMgcHJvY2VzcyBjaGFyYWN0ZXJpemVzIHRoZSBjYXJkIGhvbGRlcidzIHNwZW5kaW5nIGJlaGF2aW9yLiBGb3IgYW4gZXN0YWJsaXNoZWQgY3JlZGl0IGNhcmQgYWNjb3VudCwgd2UgY2FuIHNlZ21lbnQgdGhlIHNwZW5kaW5nIGluIGRpZmZlcmVudCBzdWJjYXRlZ29yaWVzIGFuZCBkZWZpbmUgZGlmZmVyZW50IHN1Yi1wcm9jZXNzZXMuIEEgUENJIGNhbiBiZSBkZWZpbmVkIGZvciBlYWNoIHN1Yi1wcm9jZXNzLiBUaGUgcXVlc3Rpb24gaXMgdGhhdCB0aGVyZSBhcmUgbm8gc3BlY2lmaWNhdGlvbiBsaW1pdHMgc2V0IHRvIHRoZXNlIHR5cGVzIG9mICJwcm9jZXNzZXMiLiBXZSBuZWVkIHRvIHVzZSBoaXN0b3JpY2FsIGRhdGEgdG8gb2J0YWluIG9wdGltYWwgc3BlY2lmaWNhdGlvbiBsaW1pdHMgaW4gb3JkZXIgdG8gZGVmaW5lIHF1YWxpdHkgUENJcy4NCg0KVGhlIGZvbGxvd2luZyBjaGFydCBleHBsYWlucyB0aGUgaWRlYSBvZiBob3cgdG8gZGVmaW5lIFBDSSBmb3IgYSBwcm9jZXNzIHdpdGhvdXQgYmVpbmcgZ2l2ZW4gcHJlLXNldCBwcm9jZXNzIGxpbWl0cy4NCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuYWxpZ249J2NlbnRlcicsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTMsIGZpZy5jYXA9IkZpZ3VyZSAxMC4gSWxsdXN0cmF0aW9uIG9mIGRlZmluaW5nIFBDSSBvZiBhIHByb2Nlc3Mgd2l0aG91dCBnaXZlbiBwcm9jZXNzIGxpbWl0cyJ9DQppbmNsdWRlX2dyYXBoaWNzKCJpbWcvdzEwLVJvbGxpbmctUENJcy5qcGciKQ0KYGBgDQoNClNpbmNlIGZyYXVkIGRldGVjdGlvbiBpcyBhIHJlYWwtdGltZSBwcm9jZXNzLCB0aGUgZnJhdWQgaW5kZXggbXVzdCBhbHNvIGJlIGRlZmluZWQgaW4gcmVhbC10aW1lLiBUaGUgYWJvdmUgZXhwbGFpbnMgaG93IHJlYWwtdGltZSBQQ0kgY2FuIGJlIGRlZmluZWQuIFRoZSBQQ0kgZGVmaW5lZCBpbiB0aGUgYWJvdmUgaWxsdXN0cmF0aW9uIGlzIGEgcm9sbGluZyBQQ0kgc2luY2UgaXRzIHNwZWNpZmljYXRpb24gbGltaXRzIGFyZSBjaGFuZ2luZyBvdmVyIHRpbWUuIFRoZSBzcGVjaWZpY2F0aW9uIGxpbWl0cyBjYW4gYWxzbyBiZSBzZXQgYXMgaHlwZXJwYXJhbWV0ZXJzLiBXZSBjYW4gdGhlbiBzZWFyY2ggZm9yIG9wdGltYWwgaHlwZXJwYXJhbWV0ZXJzIHRvIGRlZmluZSBvcHRpbWFsIFBDSSBmb3IgZnJhdWQgZGV0ZWN0aW9uLiANCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQoNCg0KDQo=