About
This notebook isn’t really about code as much as it’s about math. As my knowledge grows (and/or refreshes) with respect to statistics, calculus and other maths, this notebook will gradually expand, and the organizational structure will shift to accommodate. All math formulas were made using my custom tool at: https://christopherball.github.io/math/asciiMath/.
Calculus
Derivatives
Product Rule
Formula Source:
d/dx[color(red)f(x)color(blue)g(x)]=color(red)f(x)d/dx[color(blue)g(x)]+d/dx[color(red)f(x)]color(blue)g(x)
Interpretation: When finding derivatives, often times it can be useful to chunk the expression so that it’s easier to tackle determining the derivatives of its smaller constituent parts. Key takeaway is look for expressions that contain multiplication, as they are prime candidates.
Quotient Rule
Formula Source:
d/dx[color(red)f(x)/color(blue)g(x)]=(d/dx[color(red)f(x)]color(blue)g(x)-color(red)f(x)d/dx[color(blue)g(x)])/[color(blue)g(x)]^2
Interpretation: When finding derivatives, often times it can be useful to chunk the expression so that it’s easier to tackle determining the derivatives of its smaller constituent parts. Key takeaway is look for expressions that contain division, as they are prime candidates.
Chain Rule
Formula Source:
d/dx[(f(g(x))]=f'(g(x))*g'(x)
Interpretation: When finding derivatives, often times it can be useful to chunk the expression so that it’s easier to tackle determining the derivatives of its smaller constituent parts. Key takeaway is look for expressions that can be broken down in two steps, such as a square root of x-squared, where we’d consider the outer step of square root to be f(x) and the inner step of x-squared to be g(x).
Statistics
Population Standard Deviation
Formula Source:
σ=sqrt(1/Nsum_(i=1)^N (color(red)(x_i)-color(blue)(mu))^2)
color(red)(x_i)=i^(th)"observation value"
color(blue)(mu)="population mean"
N="population size"
Summary: Population Standard Deviation (SD) is typically represented in math equations using the Greek letter sigma σ. Standard deviations apply to normal distributions and speak about deviations from the mean. The value of a standard deviation is in the same units as the response variable.
Interpretation: There is a n empirical rule (68%/95%/99.7%) corresponding to 1, 2, and 3 SD +/-. It states that approximately 68% of the given population values will fall within 1 SD +/- (that is, 1 SD above, 1 SD below), 95% within 2 SD +/-, and 99.7% within 3 SD +/-. This means that all but .03% of your normal population should fall within 3 SD.
Sample Standard Deviation
Formula Source:
s=sqrt(1/(n-1)sum_(i=1)^n (color(red)(x_i)-color(blue)(bar x))^2)
color(red)(x_i)=i^(th)"observation value"
color(blue)(bar x)="sample mean"
n="sample size"
Summary: Sample Standard Deviation is typically represented in math equations using a lowercase s, to differentiate it from the full population flavor. The only other difference worth calling out is that the final mean taken uses 1 less than the sample size, known as Bessel’s Correction.
Interpretation: Same as for Population Standard Deviation, keeping in mind that this calculation here is an estimate based on the sample.
Root Mean Square
Formula Source:
RMS=sqrt(1/nsum_(i=1)^n color(red)(x_i)^2)
color(red)(x_i)=i^(th)"observation value"
n="sample size"
Summary: Also known as the quadratic mean.
Interpretation:
Root Mean Square Error
Formula Source:
RMSE=sqrt(1/Nsum_(i=1)^N (color(red)(x_i)-color(blue)(hat x_i))^2)
color(red)(x_i)=i^(th)"observation value"
color(blue)(hat x_i)=i^(th)"prediction value"
N="population size"
Summary: RMSE is also known as the Root Mean Square Deviation (RMSD). Given a set of numeric model predictions, and their corresponding observational response values, for every prediction, we’re basically diffing how far off our prediction is, squaring that diff to eliminate negative sign issues, summing up all of these across our set, taking the mean of these values, and finally taking the square root to bring the final value back into the same scale as the predictions and observations.
Interpretation: Numbers are absolute values in the same unit as the predicted / observation values. As a model improves and matures, your RMSE should get smaller and smaller because your predictions should become closer and closer to the actual observational values (as modeled by a linear regression, etc…).
Residual Sum of Squares
Formula Source:
RSS=sum_(i=1)^n(color(red)(y_i)-color(blue)(hat y_i))^2
color(red)(y_i)=i^(th)"observation value"
color(blue)(hat y_i)=i^(th)"prediction value"
n="sample size"
Summary:
Interpretation:
Total Sum of Squares
Formula Source:
TSS=sum_(i=1)^n(color(red)(y_i)-color(blue)(bar y))^2
color(red)(y_i)=i^(th)"observation value"
color(blue)(bar y)="sample mean"
n="sample size"
Summary:
Interpretation:
R-Squared
Formula Source:
R^2=1-(RSS)/(TSS)
Summary: Otherwise known as the “Coefficient of Determination”, to be used for assessing model accuracy where only one independent variable is used in the model. If you add more independent variables, R-squared will go up which is why you should use Adjusted R-Squared instead for such situations (see below). For normal R-squared, you can think of the numerator as “explained variation” and the denominator as “total variation”.
Interpretation: Results are always between 0 and 100%, with higher generally being better. That is, high R-squared percentages signal a prediction model that likely fits (explains) the data well. There are exceptions to this rule however. It’s fairly common for R-squared results to be high, but when you look closely at the prediction curve of the model compared to the response data, there can be a pattern (bias) where certain areas of the model consistently under or over-predict response values. This is confirmed by looking at a “residuals versus fits” plot and looking for patterns (you want to see randomness).
Adjusted R-Squared
Formula Source:
R_(adj)^2=1-(1-R^2)((color(red)n-1)/(color(red)n-color(blue)k-1))
color(blue)k="number of independent variables, excluding constant"
color(red)n="sample size"
Summary: Like R-Squared, Adjusted R-Squared also indicates how well a model curve explains response values. Unlike regular R-Squared, the Adjusted version handles models that are built on top of multiple independent variables, and will penalize the score if additional independent variables don’t add to the model accuracy. Adjusted R-Squared values can’t be higher than regular R-Squared.
Interpretation: Precisely the same as normal R-Squared.
LS0tCnRpdGxlOiAiTWF0aCBGb3JtdWxhcyBFeHBsYWluZWQiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazogCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICB0b2NfZmxvYXQ6IHllcwotLS0KCmBgYHtjc3MsIGVjaG8gPSBGQUxTRX0KQG1lZGlhIG9ubHkgc2NyZWVuIGFuZCAobWF4LXdpZHRoOiA3NjhweCkgewogICNUT0MgewogICAgZGlzcGxheTogbm9uZTsKICB9Cn0KYGBgCgojIyBBYm91dAoKVGhpcyBub3RlYm9vayBpc24ndCByZWFsbHkgYWJvdXQgY29kZSBhcyBtdWNoIGFzIGl0J3MgYWJvdXQgbWF0aC4gQXMgbXkga25vd2xlZGdlIGdyb3dzIChhbmQvb3IgcmVmcmVzaGVzKSB3aXRoIHJlc3BlY3QgdG8gc3RhdGlzdGljcywgY2FsY3VsdXMgYW5kIG90aGVyIG1hdGhzLCB0aGlzIG5vdGVib29rIHdpbGwgZ3JhZHVhbGx5IGV4cGFuZCwgYW5kIHRoZSBvcmdhbml6YXRpb25hbCBzdHJ1Y3R1cmUgd2lsbCBzaGlmdCB0byBhY2NvbW1vZGF0ZS4gQWxsIG1hdGggZm9ybXVsYXMgd2VyZSBtYWRlIHVzaW5nIG15IGN1c3RvbSB0b29sIGF0OiA8aHR0cHM6Ly9jaHJpc3RvcGhlcmJhbGwuZ2l0aHViLmlvL21hdGgvYXNjaWlNYXRoLz4uCgojIyBBbGdlYnJhCgojIyMjIExvZ2FyaXRobXMKCiFbXShpbWFnZXMvcGFzdGUtRTZFMDJCQjUucG5nKXt3aWR0aD0iNTUwIn0KCiMjIFRyaWdvbm9tZXRyeQoKIyMjIyBVbml0IENpcmNsZSBSZWxhdGlvbnNoaXBzCgohW10oaW1hZ2VzL3Bhc3RlLTk2NUYyM0M0LnBuZyl7d2lkdGg9IjU1MCJ9CgojIyMjIFRyaWdvbm9tZXRyaWMgRnVuY3Rpb24gR3JhcGhzCgohW10oaW1hZ2VzL3Bhc3RlLTg3NkIzNEU4LnBuZyl7d2lkdGg9IjU1MCJ9CgojIyMjIENvbW1vbiBUcmlnIFZhbHVlcyBUYWJsZSAoRXhhY3QpCgohW10oaW1hZ2VzL3Bhc3RlLTIxRDVDMDk1LnBuZyl7d2lkdGg9IjU1MCJ9CgojIyMjIENvbXBsZXRlIFRyaWcgVmFsdWVzIFRhYmxlIChBcHByb3guKQoKIVtdKGltYWdlcy9wYXN0ZS04OUU1RDAwRS5wbmcpe3dpZHRoPSI1NTAifQoKIyMgQ2FsY3VsdXMKCiMjIyMgRGVyaXZhdGl2ZXMKClsqKlByb2R1Y3QgUnVsZSoqXXsudWx9CgohW10oaW1hZ2VzL3Bhc3RlLTZFRjY2RkNCLnBuZyl7d2lkdGg9IjU1MCJ9CgoqKkZvcm11bGEgU291cmNlKio6CgogICAgZC9keFtjb2xvcihyZWQpZih4KWNvbG9yKGJsdWUpZyh4KV09Y29sb3IocmVkKWYoeClkL2R4W2NvbG9yKGJsdWUpZyh4KV0rZC9keFtjb2xvcihyZWQpZih4KV1jb2xvcihibHVlKWcoeCkKCioqSW50ZXJwcmV0YXRpb24qKjogV2hlbiBmaW5kaW5nIGRlcml2YXRpdmVzLCBvZnRlbiB0aW1lcyBpdCBjYW4gYmUgdXNlZnVsIHRvIGNodW5rIHRoZSBleHByZXNzaW9uIHNvIHRoYXQgaXQncyBlYXNpZXIgdG8gdGFja2xlIGRldGVybWluaW5nIHRoZSBkZXJpdmF0aXZlcyBvZiBpdHMgc21hbGxlciBjb25zdGl0dWVudCBwYXJ0cy4gS2V5IHRha2Vhd2F5IGlzIGxvb2sgZm9yIGV4cHJlc3Npb25zIHRoYXQgY29udGFpbiBtdWx0aXBsaWNhdGlvbiwgYXMgdGhleSBhcmUgcHJpbWUgY2FuZGlkYXRlcy4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKWyoqUXVvdGllbnQgUnVsZSoqXXsudWx9CgohW10oaW1hZ2VzL3Bhc3RlLUJGNkVFQzVGLnBuZyl7d2lkdGg9IjU1MCJ9CgoqKkZvcm11bGEgU291cmNlKio6CgogICAgZC9keFtjb2xvcihyZWQpZih4KS9jb2xvcihibHVlKWcoeCldPShkL2R4W2NvbG9yKHJlZClmKHgpXWNvbG9yKGJsdWUpZyh4KS1jb2xvcihyZWQpZih4KWQvZHhbY29sb3IoYmx1ZSlnKHgpXSkvW2NvbG9yKGJsdWUpZyh4KV1eMgoKKipJbnRlcnByZXRhdGlvbioqOiBXaGVuIGZpbmRpbmcgZGVyaXZhdGl2ZXMsIG9mdGVuIHRpbWVzIGl0IGNhbiBiZSB1c2VmdWwgdG8gY2h1bmsgdGhlIGV4cHJlc3Npb24gc28gdGhhdCBpdCdzIGVhc2llciB0byB0YWNrbGUgZGV0ZXJtaW5pbmcgdGhlIGRlcml2YXRpdmVzIG9mIGl0cyBzbWFsbGVyIGNvbnN0aXR1ZW50IHBhcnRzLiBLZXkgdGFrZWF3YXkgaXMgbG9vayBmb3IgZXhwcmVzc2lvbnMgdGhhdCBjb250YWluIGRpdmlzaW9uLCBhcyB0aGV5IGFyZSBwcmltZSBjYW5kaWRhdGVzLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpbKipDaGFpbiBSdWxlKipdey51bH0KCiFbXShpbWFnZXMvcGFzdGUtNTU0NzcyNUQucG5nKXt3aWR0aD0iNTUwIiBoZWlnaHQ9IjUxIn0KCioqRm9ybXVsYSBTb3VyY2UqKjoKCiAgICBkL2R4WyhmKGcoeCkpXT1mJyhnKHgpKSpnJyh4KQoKKipJbnRlcnByZXRhdGlvbioqOiBXaGVuIGZpbmRpbmcgZGVyaXZhdGl2ZXMsIG9mdGVuIHRpbWVzIGl0IGNhbiBiZSB1c2VmdWwgdG8gY2h1bmsgdGhlIGV4cHJlc3Npb24gc28gdGhhdCBpdCdzIGVhc2llciB0byB0YWNrbGUgZGV0ZXJtaW5pbmcgdGhlIGRlcml2YXRpdmVzIG9mIGl0cyBzbWFsbGVyIGNvbnN0aXR1ZW50IHBhcnRzLiBLZXkgdGFrZWF3YXkgaXMgbG9vayBmb3IgZXhwcmVzc2lvbnMgdGhhdCBjYW4gYmUgYnJva2VuIGRvd24gaW4gdHdvIHN0ZXBzLCBzdWNoIGFzIGEgc3F1YXJlIHJvb3Qgb2YgeC1zcXVhcmVkLCB3aGVyZSB3ZSdkIGNvbnNpZGVyIHRoZSBvdXRlciBzdGVwIG9mIHNxdWFyZSByb290IHRvIGJlIGYoeCkgYW5kIHRoZSBpbm5lciBzdGVwIG9mIHgtc3F1YXJlZCB0byBiZSBnKHgpLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyBTdGF0aXN0aWNzCgojIyMjIFBvcHVsYXRpb24gU3RhbmRhcmQgRGV2aWF0aW9uCgohW10oaW1hZ2VzL3Bhc3RlLTBGMkJDRkMyLnBuZyl7d2lkdGg9IjU1MCJ9CgoqKkZvcm11bGEgU291cmNlKio6CgogICAgz4M9c3FydCgxL05zdW1fKGk9MSleTiAoY29sb3IocmVkKSh4X2kpLWNvbG9yKGJsdWUpKG11KSleMikKCiAgICBjb2xvcihyZWQpKHhfaSk9aV4odGgpIm9ic2VydmF0aW9uIHZhbHVlIgogICAgY29sb3IoYmx1ZSkobXUpPSJwb3B1bGF0aW9uIG1lYW4iCiAgICBOPSJwb3B1bGF0aW9uIHNpemUiCgoqKlN1bW1hcnkqKjogUG9wdWxhdGlvbiBTdGFuZGFyZCBEZXZpYXRpb24gKFNEKSBpcyB0eXBpY2FsbHkgcmVwcmVzZW50ZWQgaW4gbWF0aCBlcXVhdGlvbnMgdXNpbmcgdGhlIEdyZWVrIGxldHRlciBzaWdtYSDPgy4gU3RhbmRhcmQgZGV2aWF0aW9ucyBhcHBseSB0byBub3JtYWwgZGlzdHJpYnV0aW9ucyBhbmQgc3BlYWsgYWJvdXQgZGV2aWF0aW9ucyBmcm9tIHRoZSBtZWFuLiBUaGUgdmFsdWUgb2YgYSBzdGFuZGFyZCBkZXZpYXRpb24gaXMgaW4gdGhlIHNhbWUgdW5pdHMgYXMgdGhlIHJlc3BvbnNlIHZhcmlhYmxlLgoKKipJbnRlcnByZXRhdGlvbioqOiBUaGVyZSBpcyBhIG4gZW1waXJpY2FsIHJ1bGUgKDY4JS85NSUvOTkuNyUpIGNvcnJlc3BvbmRpbmcgdG8gMSwgMiwgYW5kIDMgU0QgKy8tLiBJdCBzdGF0ZXMgdGhhdCBhcHByb3hpbWF0ZWx5IDY4JSBvZiB0aGUgZ2l2ZW4gcG9wdWxhdGlvbiB2YWx1ZXMgd2lsbCBmYWxsIHdpdGhpbiAxIFNEICsvLSAodGhhdCBpcywgMSBTRCBhYm92ZSwgMSBTRCBiZWxvdyksIDk1JSB3aXRoaW4gMiBTRCArLy0sIGFuZCA5OS43JSB3aXRoaW4gMyBTRCArLy0uIFRoaXMgbWVhbnMgdGhhdCBhbGwgYnV0IC4wMyUgb2YgeW91ciBub3JtYWwgcG9wdWxhdGlvbiBzaG91bGQgZmFsbCB3aXRoaW4gMyBTRC4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIyBTYW1wbGUgU3RhbmRhcmQgRGV2aWF0aW9uCgohW10oaW1hZ2VzL3Bhc3RlLTI5Q0NERUJGLnBuZyl7d2lkdGg9IjU1MCJ9CgoqKkZvcm11bGEgU291cmNlKio6CgogICAgcz1zcXJ0KDEvKG4tMSlzdW1fKGk9MSlebiAoY29sb3IocmVkKSh4X2kpLWNvbG9yKGJsdWUpKGJhciB4KSleMikKCiAgICBjb2xvcihyZWQpKHhfaSk9aV4odGgpIm9ic2VydmF0aW9uIHZhbHVlIgogICAgY29sb3IoYmx1ZSkoYmFyIHgpPSJzYW1wbGUgbWVhbiIKICAgIG49InNhbXBsZSBzaXplIgoKKipTdW1tYXJ5Kio6IFNhbXBsZSBTdGFuZGFyZCBEZXZpYXRpb24gaXMgdHlwaWNhbGx5IHJlcHJlc2VudGVkIGluIG1hdGggZXF1YXRpb25zIHVzaW5nIGEgbG93ZXJjYXNlIHMsIHRvIGRpZmZlcmVudGlhdGUgaXQgZnJvbSB0aGUgZnVsbCBwb3B1bGF0aW9uIGZsYXZvci4gVGhlIG9ubHkgb3RoZXIgZGlmZmVyZW5jZSB3b3J0aCBjYWxsaW5nIG91dCBpcyB0aGF0IHRoZSBmaW5hbCBtZWFuIHRha2VuIHVzZXMgMSBsZXNzIHRoYW4gdGhlIHNhbXBsZSBzaXplLCBrbm93biBhcyBCZXNzZWwncyBDb3JyZWN0aW9uLgoKKipJbnRlcnByZXRhdGlvbioqOiBTYW1lIGFzIGZvciBQb3B1bGF0aW9uIFN0YW5kYXJkIERldmlhdGlvbiwga2VlcGluZyBpbiBtaW5kIHRoYXQgdGhpcyBjYWxjdWxhdGlvbiBoZXJlIGlzIGFuIGVzdGltYXRlIGJhc2VkIG9uIHRoZSBzYW1wbGUuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyMgUm9vdCBNZWFuIFNxdWFyZQoKIVtdKGltYWdlcy9wYXN0ZS02RDZBRjJFOS5wbmcpe3dpZHRoPSI1NTAifQoKKipGb3JtdWxhIFNvdXJjZSoqOgoKICAgIFJNUz1zcXJ0KDEvbnN1bV8oaT0xKV5uIGNvbG9yKHJlZCkoeF9pKV4yKQoKICAgIGNvbG9yKHJlZCkoeF9pKT1pXih0aCkib2JzZXJ2YXRpb24gdmFsdWUiCiAgICBuPSJzYW1wbGUgc2l6ZSIKCioqU3VtbWFyeSoqOiBBbHNvIGtub3duIGFzIHRoZSBxdWFkcmF0aWMgbWVhbi4KCioqSW50ZXJwcmV0YXRpb24qKjoKCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIyBSb290IE1lYW4gU3F1YXJlIEVycm9yCgohW10oaW1hZ2VzL3Bhc3RlLTQ5QjJBRTA5LnBuZyl7d2lkdGg9IjU1MCJ9CgoqKkZvcm11bGEgU291cmNlKio6CgogICAgUk1TRT1zcXJ0KDEvTnN1bV8oaT0xKV5OIChjb2xvcihyZWQpKHhfaSktY29sb3IoYmx1ZSkoaGF0IHhfaSkpXjIpCgogICAgY29sb3IocmVkKSh4X2kpPWleKHRoKSJvYnNlcnZhdGlvbiB2YWx1ZSIKICAgIGNvbG9yKGJsdWUpKGhhdCB4X2kpPWleKHRoKSJwcmVkaWN0aW9uIHZhbHVlIgogICAgTj0icG9wdWxhdGlvbiBzaXplIgoKKipTdW1tYXJ5Kio6IFJNU0UgaXMgYWxzbyBrbm93biBhcyB0aGUgUm9vdCBNZWFuIFNxdWFyZSBEZXZpYXRpb24gKFJNU0QpLiBHaXZlbiBhIHNldCBvZiBudW1lcmljIG1vZGVsIHByZWRpY3Rpb25zLCBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBvYnNlcnZhdGlvbmFsIHJlc3BvbnNlIHZhbHVlcywgZm9yIGV2ZXJ5IHByZWRpY3Rpb24sIHdlJ3JlIGJhc2ljYWxseSBkaWZmaW5nIGhvdyBmYXIgb2ZmIG91ciBwcmVkaWN0aW9uIGlzLCBzcXVhcmluZyB0aGF0IGRpZmYgdG8gZWxpbWluYXRlIG5lZ2F0aXZlIHNpZ24gaXNzdWVzLCBzdW1taW5nIHVwIGFsbCBvZiB0aGVzZSBhY3Jvc3Mgb3VyIHNldCwgdGFraW5nIHRoZSBtZWFuIG9mIHRoZXNlIHZhbHVlcywgYW5kIGZpbmFsbHkgdGFraW5nIHRoZSBzcXVhcmUgcm9vdCB0byBicmluZyB0aGUgZmluYWwgdmFsdWUgYmFjayBpbnRvIHRoZSBzYW1lIHNjYWxlIGFzIHRoZSBwcmVkaWN0aW9ucyBhbmQgb2JzZXJ2YXRpb25zLgoKKipJbnRlcnByZXRhdGlvbioqOiBOdW1iZXJzIGFyZSBhYnNvbHV0ZSB2YWx1ZXMgaW4gdGhlIHNhbWUgdW5pdCBhcyB0aGUgcHJlZGljdGVkIC8gb2JzZXJ2YXRpb24gdmFsdWVzLiBBcyBhIG1vZGVsIGltcHJvdmVzIGFuZCBtYXR1cmVzLCB5b3VyIFJNU0Ugc2hvdWxkIGdldCBzbWFsbGVyIGFuZCBzbWFsbGVyIGJlY2F1c2UgeW91ciBwcmVkaWN0aW9ucyBzaG91bGQgYmVjb21lIGNsb3NlciBhbmQgY2xvc2VyIHRvIHRoZSBhY3R1YWwgb2JzZXJ2YXRpb25hbCB2YWx1ZXMgKGFzIG1vZGVsZWQgYnkgYSBsaW5lYXIgcmVncmVzc2lvbiwgZXRjLi4uKS4KCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyMjIyBSZXNpZHVhbCBTdW0gb2YgU3F1YXJlcwoKIVtdKGltYWdlcy9wYXN0ZS0yRTk4OURFMi5wbmcpe3dpZHRoPSI1NTAifQoKKipGb3JtdWxhIFNvdXJjZSoqOgoKICAgIFJTUz1zdW1fKGk9MSlebihjb2xvcihyZWQpKHlfaSktY29sb3IoYmx1ZSkoaGF0IHlfaSkpXjIKCiAgICBjb2xvcihyZWQpKHlfaSk9aV4odGgpIm9ic2VydmF0aW9uIHZhbHVlIgogICAgY29sb3IoYmx1ZSkoaGF0IHlfaSk9aV4odGgpInByZWRpY3Rpb24gdmFsdWUiCiAgICBuPSJzYW1wbGUgc2l6ZSIKCioqU3VtbWFyeSoqOgoKKipJbnRlcnByZXRhdGlvbioqOgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMjIFRvdGFsIFN1bSBvZiBTcXVhcmVzCgohW10oaW1hZ2VzL3Bhc3RlLUFBNTBGNzVELnBuZyl7d2lkdGg9IjU1MCJ9CgoqKkZvcm11bGEgU291cmNlKio6CgogICAgVFNTPXN1bV8oaT0xKV5uKGNvbG9yKHJlZCkoeV9pKS1jb2xvcihibHVlKShiYXIgeSkpXjIKCiAgICBjb2xvcihyZWQpKHlfaSk9aV4odGgpIm9ic2VydmF0aW9uIHZhbHVlIgogICAgY29sb3IoYmx1ZSkoYmFyIHkpPSJzYW1wbGUgbWVhbiIKICAgIG49InNhbXBsZSBzaXplIgoKKipTdW1tYXJ5Kio6CgoqKkludGVycHJldGF0aW9uKio6CgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiMjIyMgUi1TcXVhcmVkCgohW10oaW1hZ2VzL3Bhc3RlLTUwQjE5NENBLnBuZyl7d2lkdGg9IjU1MCIgaGVpZ2h0PSI1MSJ9CgoqKkZvcm11bGEgU291cmNlKio6CgogICAgUl4yPTEtKFJTUykvKFRTUykKCioqU3VtbWFyeSoqOiBPdGhlcndpc2Uga25vd24gYXMgdGhlICJDb2VmZmljaWVudCBvZiBEZXRlcm1pbmF0aW9uIiwgdG8gYmUgdXNlZCBmb3IgYXNzZXNzaW5nIG1vZGVsIGFjY3VyYWN5IHdoZXJlIG9ubHkgb25lIGluZGVwZW5kZW50IHZhcmlhYmxlIGlzIHVzZWQgaW4gdGhlIG1vZGVsLiBJZiB5b3UgYWRkIG1vcmUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLCBSLXNxdWFyZWQgd2lsbCBnbyB1cCB3aGljaCBpcyB3aHkgeW91IHNob3VsZCB1c2UgQWRqdXN0ZWQgUi1TcXVhcmVkIGluc3RlYWQgZm9yIHN1Y2ggc2l0dWF0aW9ucyAoc2VlIGJlbG93KS4gRm9yIG5vcm1hbCBSLXNxdWFyZWQsIHlvdSBjYW4gdGhpbmsgb2YgdGhlIG51bWVyYXRvciBhcyAiZXhwbGFpbmVkIHZhcmlhdGlvbiIgYW5kIHRoZSBkZW5vbWluYXRvciBhcyAidG90YWwgdmFyaWF0aW9uIi4KCioqSW50ZXJwcmV0YXRpb24qKjogUmVzdWx0cyBhcmUgYWx3YXlzIGJldHdlZW4gMCBhbmQgMTAwJSwgd2l0aCBoaWdoZXIgKmdlbmVyYWxseSogYmVpbmcgYmV0dGVyLiBUaGF0IGlzLCBoaWdoIFItc3F1YXJlZCBwZXJjZW50YWdlcyBzaWduYWwgYSBwcmVkaWN0aW9uIG1vZGVsIHRoYXQgbGlrZWx5IGZpdHMgKGV4cGxhaW5zKSB0aGUgZGF0YSB3ZWxsLiBUaGVyZSBhcmUgZXhjZXB0aW9ucyB0byB0aGlzIHJ1bGUgaG93ZXZlci4gSXQncyBmYWlybHkgY29tbW9uIGZvciBSLXNxdWFyZWQgcmVzdWx0cyB0byBiZSBoaWdoLCBidXQgd2hlbiB5b3UgbG9vayBjbG9zZWx5IGF0IHRoZSBwcmVkaWN0aW9uIGN1cnZlIG9mIHRoZSBtb2RlbCBjb21wYXJlZCB0byB0aGUgcmVzcG9uc2UgZGF0YSwgdGhlcmUgY2FuIGJlIGEgcGF0dGVybiAoYmlhcykgd2hlcmUgY2VydGFpbiBhcmVhcyBvZiB0aGUgbW9kZWwgY29uc2lzdGVudGx5IHVuZGVyIG9yIG92ZXItcHJlZGljdCByZXNwb25zZSB2YWx1ZXMuIFRoaXMgaXMgY29uZmlybWVkIGJ5IGxvb2tpbmcgYXQgYSAicmVzaWR1YWxzIHZlcnN1cyBmaXRzIiBwbG90IGFuZCBsb29raW5nIGZvciBwYXR0ZXJucyAoeW91IHdhbnQgdG8gc2VlIHJhbmRvbW5lc3MpLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIyMjIEFkanVzdGVkIFItU3F1YXJlZAoKIVtdKGltYWdlcy9wYXN0ZS02REIxMzlERC5wbmcpe3dpZHRoPSI1NTAifQoKKipGb3JtdWxhIFNvdXJjZSoqOgoKICAgIFJfKGFkaileMj0xLSgxLVJeMikoKGNvbG9yKHJlZCluLTEpLyhjb2xvcihyZWQpbi1jb2xvcihibHVlKWstMSkpCgogICAgY29sb3IoYmx1ZSlrPSJudW1iZXIgb2YgaW5kZXBlbmRlbnQgdmFyaWFibGVzLCBleGNsdWRpbmcgY29uc3RhbnQiCiAgICBjb2xvcihyZWQpbj0ic2FtcGxlIHNpemUiCgoqKlN1bW1hcnkqKjogTGlrZSBSLVNxdWFyZWQsIEFkanVzdGVkIFItU3F1YXJlZCBhbHNvIGluZGljYXRlcyBob3cgd2VsbCBhIG1vZGVsIGN1cnZlIGV4cGxhaW5zIHJlc3BvbnNlIHZhbHVlcy4gVW5saWtlIHJlZ3VsYXIgUi1TcXVhcmVkLCB0aGUgQWRqdXN0ZWQgdmVyc2lvbiBoYW5kbGVzIG1vZGVscyB0aGF0IGFyZSBidWlsdCBvbiB0b3Agb2YgbXVsdGlwbGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzLCBhbmQgd2lsbCBwZW5hbGl6ZSB0aGUgc2NvcmUgaWYgYWRkaXRpb25hbCBpbmRlcGVuZGVudCB2YXJpYWJsZXMgZG9uJ3QgYWRkIHRvIHRoZSBtb2RlbCBhY2N1cmFjeS4gQWRqdXN0ZWQgUi1TcXVhcmVkIHZhbHVlcyBjYW4ndCBiZSBoaWdoZXIgdGhhbiByZWd1bGFyIFItU3F1YXJlZC4KCioqSW50ZXJwcmV0YXRpb24qKjogUHJlY2lzZWx5IHRoZSBzYW1lIGFzIG5vcm1hbCBSLVNxdWFyZWQuCgotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0K