Question 1: Cumulative Distribution Function (CDF)
Estimation
The following failure times (in hours) were observed for 8 electronic
components:
23, 45, 67, 89, 112, 156, 189, 245
- Write an R function implementing the ECDF \(\hat{F}_n(t)\) according to its
mathematical definition. Validate your implementation using R’s ecdf()
function on the given data, with comparison based on their step
functions.
x <- c(23, 45, 67, 89, 112, 156, 189, 245)
x
[1] 23 45 67 89 112 156 189 245
# ECDF based on the definition: proportion of failures by time t
Fn_hat <- function(x, t){
n <- length(x) # total number of observations
sum(x <= t) / n # fraction of failures that occur by time t
}
# R's built-in ECDF for comparison
Fn_builtin <- ecdf(x)
# Values of t used to draw the step functions
tgrid <- seq(min(x) - 10, max(x) + 10, by = 1)
# Plot the ECDF from my function
plot(tgrid, sapply(tgrid, function(tt) Fn_hat(x, tt)),
type = "s", lwd = 2, col = "black",
xlab = "t", ylab = expression(hat(F)[n](t)),
main = "ECDF: Custom vs R ecdf()")
# Add R's ECDF to check that the two match
lines(tgrid, Fn_builtin(tgrid),
type = "s", lty = 2, col = "blue", lwd = 2)
# Legend to identify each ECDF
legend("bottomright",
c("Custom ECDF", "R ecdf()"),
lty = c(1, 2),
col = c("black", "blue"),
lwd = 2)

- A colleague claims that the probability of failure before 100 hours
is 0.5 based on these data. Do you agree? Explain your reasoning using
the empirical cumulative distribution function (ECDF).
# ECDF at t = 100 using the definition
sum(x <= 100) / length(x)
[1] 0.5
# Check the same value using R's ECDF
Fn_builtin(100)
[1] 0.5
Using the ECDF, the probability of failure before 100 hours is found
by looking at the proportion of observed failure times that occur by 100
hours. The failure times in this data set show 4 out of 8 occurrences
before reaching 100 hours which results in an ECDF value of 0.5. The
evidence confirms what the colleague has stated.
Question 2: Density Function Estimation
Consider the following failure times from a mechanical system:
12.3, 14.7, 15.2, 16.8, 18.1, 19.4, 20.6, 22.3, 23.9, 25.4
- Create a histogram of the data using 3 equally spaced bins. What is
the estimated density in each bin? Describe the shape of the histogram’s
distribution.
y <- c(12.3, 14.7, 15.2, 16.8, 18.1, 19.4, 20.6, 22.3, 23.9, 25.4)
y
[1] 12.3 14.7 15.2 16.8 18.1 19.4 20.6 22.3 23.9 25.4
# Define break points to create 3 equally spaced bins across the data range
breaks <- seq(min(y), max(y), length.out = 4)
# Plot the histogram on the density scale
hist_y <- hist(y, breaks = breaks, probability = TRUE,
main = "Histogram with 3 Equally Spaced Bins",
xlab = "Failure Time")

# Compute bin width for density calculation
bin_width <- breaks[2] - breaks[1]
# Calculate the estimated density in each bin
density_per_bin <- hist_y$counts / (length(y) * bin_width)
density_per_bin
[1] 0.06870229 0.09160305 0.06870229
The estimated densities for the three equally spaced bins are
approximately 0.0687 for the first bin, which covers failure times from
12.3 to 16.7 hours, 0.0916 for the middle bin, which spans 16.7 to 21.0
hours, and 0.0687 for the final bin, covering 21.0 to 25.4 hours. The
histogram shows a unimodal distribution with the highest density
occurring in the middle bin, indicating that most failures tend to occur
around the center of the observed time range.
- Write an R function that computes kernel density estimates using a
Gaussian kernel with \(h=2\). Validate
your implementation against R’s built-in density() function.
\[
\hat{f}_h(t) = \frac{1}{nh}\sum_{i=1}^n K\left( \frac{t-t_i}{h}\right),
\ \ \text{ where } \ \ K(u) = \frac{1}{\sqrt{2\pi}} e^{-u^2/2}.
\]
# Gaussian kernel density estimator based on the given formula
kde_gaussian <- function(y, t, h = 2){
n <- length(y)
u <- outer(t, y, "-") / h # scaled distances for the kernel
rowSums(dnorm(u)) / (n * h) # average contribution across observations
}
# Grid of values to evaluate the density smoothly
tgrid <- seq(min(y) - 6, max(y) + 6, length.out = 200)
# Density estimate from the custom KDE with h = 2
f_hat <- kde_gaussian(y, tgrid, h = 2)
# R's built-in density estimate using the same bandwidth
f_r <- density(y, bw = 2, kernel = "gaussian",
from = min(tgrid), to = max(tgrid), n = length(tgrid))
# Plot both estimates to compare results
plot(tgrid, f_hat, type = "l", lwd = 2,
xlab = "Failure Time", ylab = "Estimated Density",
main = "Gaussian KDE (h = 2): Custom vs R density()")
lines(f_r$x, f_r$y, lty = 2, lwd = 2)
legend("topright", c("Custom KDE", "R density()"),
lty = c(1, 2), lwd = 2)

# Numerical check to confirm agreement
max(abs(f_hat - f_r$y))
[1] 5.430381e-06
- Write a custom R function that computes kernel density estimates
using the Epanechnikov kernel with \(h=2\). Validate your implementation by
comparing results with R’s built-in density() function for Gaussian
kernel estimation.
\[
\hat{f}_h(t) = \frac{1}{nh}\sum_{i=1}^n K\left( \frac{t-t_i}{h}\right),
\ \ \text{ where } \ \ K(u) = \frac{3}{4}(1 - u^2) \ \ \text{ for } \ \
|u| \le 1.
\]
# Epanechnikov KDE from the formula in the prompt (use h = 2)
kde_epan <- function(y, t, h = 2){
n <- length(y)
u <- outer(t, y, "-") / h # scale distances by h
K <- 0.75 * (1 - u^2) * (abs(u) <= 1) # Epanechnikov weights
rowSums(K) / (n * h) # average and rescale
}
# Grid to evaluate the density curve
tgrid <- seq(min(y) - 6, max(y) + 6, length.out = 200)
# Custom Epanechnikov KDE with h = 2
f_epan <- kde_epan(y, tgrid, h = 2)
# R's Gaussian KDE with the same bandwidth for comparison
f_gauss_r <- density(y, bw = 2, kernel = "gaussian",
from = min(tgrid), to = max(tgrid), n = length(tgrid))
# Compare kernel choice at the same h
plot(tgrid, f_epan, type = "l", lwd = 2,
xlab = "Failure Time", ylab = "Estimated Density",
main = "KDE (h = 2): Epanechnikov vs Gaussian")
lines(f_gauss_r$x, f_gauss_r$y, lty = 2, lwd = 2)
legend("topright", c("Epanechnikov KDE", "R Gaussian KDE"),
lty = c(1, 2), lwd = 2)
The Epanechnikov kernel density estimate is slightly more peaked in the
center because it uses a fixed range around each data point. The
Gaussian kernel distributes its weight across all observations which
results in a continuous curve that spans the entire range. Given the
limited range of the data, the Epanechnikov kernel places more emphasis
on the central failure times, while the Gaussian kernel spreads
influence more evenly.
- How does the choice of kernel (Gaussian vs. Epanechnikov) affect the
density estimate? For both kernel estimators applied to this dataset,
what happens when we select \(h=1.5\)
versus \(h=2.5\)?
The Gaussian kernel gives weight to all observations and produces a
smoother density estimate, while the Epanechnikov kernel uses a fixed
range and results in a slightly more peaked estimate near the center of
the data. For both kernels, using a smaller bandwidth (h = 1.5) creates
a more detailed and variable density, whereas a larger bandwidth (h =
2.5) smooths the estimate and reduces variability but may hide finer
features of the distribution.
LS0tCnRpdGxlOiAiQXNzaWdubWVudCAxOiBFc3RpbWF0aW5nIENERiBhbmQgUERGIgphdXRob3I6ICJLYXlsYSBEeWVyIgpkYXRlOiAiIER1ZToxLzMvMjYgYnV0IGFwcHJvdmVkIGZvciBsYXRlciBkdWUgZGF0ZS4iCm91dHB1dDoKICBodG1sX2RvY3VtZW50OiAKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIHRvY19mbG9hdDogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IG5vCiAgICB0b2NfY29sbGFwc2VkOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgY29kZV9kb3dubG9hZDogeWVzCiAgICBzbW9vdGhfc2Nyb2xsOiB5ZXMKICAgIHRoZW1lOiBsdW1lbgogIHBkZl9kb2N1bWVudDogCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgZmlnX3dpZHRoOiAzCiAgICBmaWdfaGVpZ2h0OiAzCiAgd29yZF9kb2N1bWVudDogCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICBmaWdfY2FwdGlvbjogeWVzCiAgICBrZWVwX21kOiB5ZXMKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgpgYGB7Y3NzLCBlY2hvID0gRkFMU0V9CiNUT0M6OmJlZm9yZSB7CiAgY29udGVudDogIlRhYmxlIG9mIENvbnRlbnRzIjsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LXNpemU6IDEuMmVtOwogIGRpc3BsYXk6IGJsb2NrOwogIGNvbG9yOiBuYXZ5OwogIG1hcmdpbi1ib3R0b206IDEwcHg7Cn0KCgpkaXYjVE9DIGxpIHsgICAgIC8qIHRhYmxlIG9mIGNvbnRlbnQgICovCiAgICBsaXN0LXN0eWxlOnVwcGVyLXJvbWFuOwogICAgYmFja2dyb3VuZC1pbWFnZTpub25lOwogICAgYmFja2dyb3VuZC1yZXBlYXQ6bm9uZTsKICAgIGJhY2tncm91bmQtcG9zaXRpb246MDsKfQoKaDEudGl0bGUgeyAgICAvKiBsZXZlbCAxIGhlYWRlciBvZiB0aXRsZSAgKi8KICBmb250LXNpemU6IDIycHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgY29sb3I6IERhcmtSZWQ7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsKfQoKaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBhbmQgdGhlIGF1dGhvciBhbmQgZGF0YSBoZWFkZXJzIHVzZSB0aGlzIHRvbyAgKi8KICBmb250LXNpemU6IDE1cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsKICBjb2xvcjogbmF2eTsKICB0ZXh0LWFsaWduOiBjZW50ZXI7Cn0KCmg0LmRhdGUgeyAvKiBIZWFkZXIgNCAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7CiAgY29sb3I6IERhcmtCbHVlOwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKaDEgeyAvKiBIZWFkZXIgMSAtIGFuZCB0aGUgYXV0aG9yIGFuZCBkYXRhIGhlYWRlcnMgdXNlIHRoaXMgdG9vICAqLwogICAgZm9udC1zaXplOiAyMHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBkYXJrcmVkOwogICAgdGV4dC1hbGlnbjogY2VudGVyOwp9CgpoMiB7IC8qIEhlYWRlciAyIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDE4cHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgpoMyB7IC8qIEhlYWRlciAzIC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDE2cHg7CiAgICBmb250LXdlaWdodDogYm9sZDsKICAgIGZvbnQtZmFtaWx5OiAiVGltZXMgTmV3IFJvbWFuIiwgVGltZXMsIHNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgpoNCB7IC8qIEhlYWRlciA0IC0gYW5kIHRoZSBhdXRob3IgYW5kIGRhdGEgaGVhZGVycyB1c2UgdGhpcyB0b28gICovCiAgICBmb250LXNpemU6IDE0cHg7CiAgZm9udC13ZWlnaHQ6IGJvbGQ7CiAgICBmb250LWZhbWlseTogIlRpbWVzIE5ldyBSb21hbiIsIFRpbWVzLCBzZXJpZjsKICAgIGNvbG9yOiBkYXJrcmVkOwogICAgdGV4dC1hbGlnbjogbGVmdDsKfQoKLyogQWRkIGRvdHMgYWZ0ZXIgbnVtYmVyZWQgaGVhZGVycyAqLwouaGVhZGVyLXNlY3Rpb24tbnVtYmVyOjphZnRlciB7CiAgY29udGVudDogIi4iOwoKYm9keSB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0KCi5oaWdobGlnaHRtZSB7IGJhY2tncm91bmQtY29sb3I6eWVsbG93OyB9CgpwIHsgYmFja2dyb3VuZC1jb2xvcjp3aGl0ZTsgfQoKfQpgYGAKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLgppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQogICBsaWJyYXJ5KGtuaXRyKQp9CmlmICghcmVxdWlyZSgicGFuZGVyIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygicGFuZGVyIikKICAgbGlicmFyeShwYW5kZXIpCn0KaWYgKCFyZXF1aXJlKCJnZ3Bsb3QyIikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikKICBsaWJyYXJ5KGdncGxvdDIpCn0KaWYgKCFyZXF1aXJlKCJ0aWR5dmVyc2UiKSkgewogIGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpCiAgbGlicmFyeSh0aWR5dmVyc2UpCn0KCmlmICghcmVxdWlyZSgicGxvdGx5IikpIHsKICBpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQogIGxpYnJhcnkocGxvdGx5KQp9CiMjIyMKa25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCAgICAgICAjIGluY2x1ZGUgY29kZSBjaHVuayBpbiB0aGUgb3V0cHV0IGZpbGUKICAgICAgICAgICAgICAgICAgICAgIHdhcm5pbmcgPSBGQUxTRSwgICAjIHNvbWV0aW1lcywgeW91IGNvZGUgbWF5IHByb2R1Y2Ugd2FybmluZyBtZXNzYWdlcywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHlvdSBjYW4gY2hvb3NlIHRvIGluY2x1ZGUgdGhlIHdhcm5pbmcgbWVzc2FnZXMgaW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHRoZSBvdXRwdXQgZmlsZS4gCiAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzID0gVFJVRSwgICAgIyB5b3UgY2FuIGFsc28gZGVjaWRlIHdoZXRoZXIgdG8gaW5jbHVkZSB0aGUgb3V0cHV0CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBpbiB0aGUgb3V0cHV0IGZpbGUuCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICBjb21tZW50ID0gTkEKICAgICAgICAgICAgICAgICAgICAgICkgIApgYGAKIAogXAogCiMjICoqQXNzaWdubWVudCBPYmplY3RpdmVzKiogCgoqIERldmVsb3AgYSBjbGVhciB0ZWNobmljYWwgdW5kZXJzdGFuZGluZyBvZiBub25wYXJhbWV0cmljIGN1bXVsYXRpdmUgZGlzdHJpYnV0aW9uIGZ1bmN0aW9uIChDREYpIGVzdGltYXRpb24gYW5kIHZhcmlvdXMga2VybmVsIGRlbnNpdHkgZXN0aW1hdG9ycy4KCiogVHJhbnNsYXRlIG1hdGhlbWF0aWNhbCBmb3JtdWxhcyBpbnRvIFIgZnVuY3Rpb25zIGFuZCBhcHBseSB0aGVtIHRvIHNvbHZlIHJlbGF0ZWQgcHJvYmxlbXMuCgoqIENyZWF0ZSBlZmZlY3RpdmUgdmlzdWFsaXphdGlvbnMgdG8gZGVtb25zdHJhdGUgeW91ciB1bmRlcnN0YW5kaW5nIG9mIGtleSBjb25jZXB0cyBpbiB0aGUgZm9sbG93aW5nIHF1ZXN0aW9ucy4KCgoKXAoKIyMgKipRdWVzdGlvbiAxOiBDdW11bGF0aXZlIERpc3RyaWJ1dGlvbiBGdW5jdGlvbiAoQ0RGKSBFc3RpbWF0aW9uKioKClRoZSBmb2xsb3dpbmcgZmFpbHVyZSB0aW1lcyAoaW4gaG91cnMpIHdlcmUgb2JzZXJ2ZWQgZm9yIDggZWxlY3Ryb25pYyBjb21wb25lbnRzOgoKPGNlbnRlcj4gMjMsIDQ1LCA2NywgODksIDExMiwgMTU2LCAxODksIDI0NSAgPC9jZW50ZXI+CgphKSBXcml0ZSBhbiBSIGZ1bmN0aW9uIGltcGxlbWVudGluZyB0aGUgRUNERiAkXGhhdHtGfV9uKHQpJCBhY2NvcmRpbmcgdG8gaXRzIG1hdGhlbWF0aWNhbCBkZWZpbml0aW9uLiBWYWxpZGF0ZSB5b3VyIGltcGxlbWVudGF0aW9uIHVzaW5nIFIncyBlY2RmKCkgZnVuY3Rpb24gb24gdGhlIGdpdmVuIGRhdGEsIHdpdGggY29tcGFyaXNvbiBiYXNlZCBvbiB0aGVpciBzdGVwIGZ1bmN0aW9ucy4KCmBgYHtyfQp4IDwtIGMoMjMsIDQ1LCA2NywgODksIDExMiwgMTU2LCAxODksIDI0NSkKeApgYGAKYGBge3J9CiMgRUNERiBiYXNlZCBvbiB0aGUgZGVmaW5pdGlvbjogcHJvcG9ydGlvbiBvZiBmYWlsdXJlcyBieSB0aW1lIHQKRm5faGF0IDwtIGZ1bmN0aW9uKHgsIHQpewogIG4gPC0gbGVuZ3RoKHgpICAgICAgICAgICAgIyB0b3RhbCBudW1iZXIgb2Ygb2JzZXJ2YXRpb25zCiAgc3VtKHggPD0gdCkgLyBuICAgICAgICAgICAjIGZyYWN0aW9uIG9mIGZhaWx1cmVzIHRoYXQgb2NjdXIgYnkgdGltZSB0Cn0KCiMgUidzIGJ1aWx0LWluIEVDREYgZm9yIGNvbXBhcmlzb24KRm5fYnVpbHRpbiA8LSBlY2RmKHgpCgojIFZhbHVlcyBvZiB0IHVzZWQgdG8gZHJhdyB0aGUgc3RlcCBmdW5jdGlvbnMKdGdyaWQgPC0gc2VxKG1pbih4KSAtIDEwLCBtYXgoeCkgKyAxMCwgYnkgPSAxKQoKIyBQbG90IHRoZSBFQ0RGIGZyb20gbXkgZnVuY3Rpb24KcGxvdCh0Z3JpZCwgc2FwcGx5KHRncmlkLCBmdW5jdGlvbih0dCkgRm5faGF0KHgsIHR0KSksCiAgICAgdHlwZSA9ICJzIiwgbHdkID0gMiwgY29sID0gImJsYWNrIiwKICAgICB4bGFiID0gInQiLCB5bGFiID0gZXhwcmVzc2lvbihoYXQoRilbbl0odCkpLAogICAgIG1haW4gPSAiRUNERjogQ3VzdG9tIHZzIFIgZWNkZigpIikKCiMgQWRkIFIncyBFQ0RGIHRvIGNoZWNrIHRoYXQgdGhlIHR3byBtYXRjaApsaW5lcyh0Z3JpZCwgRm5fYnVpbHRpbih0Z3JpZCksCiAgICAgIHR5cGUgPSAicyIsIGx0eSA9IDIsIGNvbCA9ICJibHVlIiwgbHdkID0gMikKCiMgTGVnZW5kIHRvIGlkZW50aWZ5IGVhY2ggRUNERgpsZWdlbmQoImJvdHRvbXJpZ2h0IiwKICAgICAgIGMoIkN1c3RvbSBFQ0RGIiwgIlIgZWNkZigpIiksCiAgICAgICBsdHkgPSBjKDEsIDIpLAogICAgICAgY29sID0gYygiYmxhY2siLCAiYmx1ZSIpLAogICAgICAgbHdkID0gMikKYGBgCgpiKSBBIGNvbGxlYWd1ZSBjbGFpbXMgdGhhdCB0aGUgcHJvYmFiaWxpdHkgb2YgZmFpbHVyZSBiZWZvcmUgMTAwIGhvdXJzIGlzIDAuNSBiYXNlZCBvbiB0aGVzZSBkYXRhLiBEbyB5b3UgYWdyZWU/IEV4cGxhaW4geW91ciByZWFzb25pbmcgdXNpbmcgdGhlIGVtcGlyaWNhbCBjdW11bGF0aXZlIGRpc3RyaWJ1dGlvbiBmdW5jdGlvbiAoRUNERikuCgpgYGB7cn0KIyBFQ0RGIGF0IHQgPSAxMDAgdXNpbmcgdGhlIGRlZmluaXRpb24Kc3VtKHggPD0gMTAwKSAvIGxlbmd0aCh4KQoKIyBDaGVjayB0aGUgc2FtZSB2YWx1ZSB1c2luZyBSJ3MgRUNERgpGbl9idWlsdGluKDEwMCkKYGBgClVzaW5nIHRoZSBFQ0RGLCB0aGUgcHJvYmFiaWxpdHkgb2YgZmFpbHVyZSBiZWZvcmUgMTAwIGhvdXJzIGlzIGZvdW5kIGJ5IGxvb2tpbmcgYXQgdGhlIHByb3BvcnRpb24gb2Ygb2JzZXJ2ZWQgZmFpbHVyZSB0aW1lcyB0aGF0IG9jY3VyIGJ5IDEwMCBob3Vycy4gVGhlIGZhaWx1cmUgdGltZXMgaW4gdGhpcyBkYXRhIHNldCBzaG93IDQgb3V0IG9mIDggb2NjdXJyZW5jZXMgYmVmb3JlIHJlYWNoaW5nIDEwMCBob3VycyB3aGljaCByZXN1bHRzIGluIGFuIEVDREYgdmFsdWUgb2YgMC41LiBUaGUgZXZpZGVuY2UgY29uZmlybXMgd2hhdCB0aGUgY29sbGVhZ3VlIGhhcyBzdGF0ZWQuCgpcCgojIyAqKlF1ZXN0aW9uIDI6IERlbnNpdHkgRnVuY3Rpb24gRXN0aW1hdGlvbioqCgpDb25zaWRlciB0aGUgZm9sbG93aW5nIGZhaWx1cmUgdGltZXMgZnJvbSBhIG1lY2hhbmljYWwgc3lzdGVtOgoKPGNlbnRlcj4gMTIuMywgMTQuNywgMTUuMiwgMTYuOCwgMTguMSwgMTkuNCwgMjAuNiwgMjIuMywgMjMuOSwgMjUuNCA8L2NlbnRlcj4KCmEpIENyZWF0ZSBhIGhpc3RvZ3JhbSBvZiB0aGUgZGF0YSB1c2luZyAzIGVxdWFsbHkgc3BhY2VkIGJpbnMuIFdoYXQgaXMgdGhlIGVzdGltYXRlZCBkZW5zaXR5IGluIGVhY2ggYmluPyBEZXNjcmliZSB0aGUgc2hhcGUgb2YgdGhlIGhpc3RvZ3JhbSdzIGRpc3RyaWJ1dGlvbi4KCmBgYHtyfQp5IDwtIGMoMTIuMywgMTQuNywgMTUuMiwgMTYuOCwgMTguMSwgMTkuNCwgMjAuNiwgMjIuMywgMjMuOSwgMjUuNCkKeQoKIyBEZWZpbmUgYnJlYWsgcG9pbnRzIHRvIGNyZWF0ZSAzIGVxdWFsbHkgc3BhY2VkIGJpbnMgYWNyb3NzIHRoZSBkYXRhIHJhbmdlCmJyZWFrcyA8LSBzZXEobWluKHkpLCBtYXgoeSksIGxlbmd0aC5vdXQgPSA0KQoKIyBQbG90IHRoZSBoaXN0b2dyYW0gb24gdGhlIGRlbnNpdHkgc2NhbGUKaGlzdF95IDwtIGhpc3QoeSwgYnJlYWtzID0gYnJlYWtzLCBwcm9iYWJpbGl0eSA9IFRSVUUsCiAgICAgICAgICAgICAgIG1haW4gPSAiSGlzdG9ncmFtIHdpdGggMyBFcXVhbGx5IFNwYWNlZCBCaW5zIiwKICAgICAgICAgICAgICAgeGxhYiA9ICJGYWlsdXJlIFRpbWUiKQoKIyBDb21wdXRlIGJpbiB3aWR0aCBmb3IgZGVuc2l0eSBjYWxjdWxhdGlvbgpiaW5fd2lkdGggPC0gYnJlYWtzWzJdIC0gYnJlYWtzWzFdCgojIENhbGN1bGF0ZSB0aGUgZXN0aW1hdGVkIGRlbnNpdHkgaW4gZWFjaCBiaW4KZGVuc2l0eV9wZXJfYmluIDwtIGhpc3RfeSRjb3VudHMgLyAobGVuZ3RoKHkpICogYmluX3dpZHRoKQpkZW5zaXR5X3Blcl9iaW4KYGBgClRoZSBlc3RpbWF0ZWQgZGVuc2l0aWVzIGZvciB0aGUgdGhyZWUgZXF1YWxseSBzcGFjZWQgYmlucyBhcmUgYXBwcm94aW1hdGVseSAwLjA2ODcgZm9yIHRoZSBmaXJzdCBiaW4sIHdoaWNoIGNvdmVycyBmYWlsdXJlIHRpbWVzIGZyb20gMTIuMyB0byAxNi43IGhvdXJzLCAwLjA5MTYgZm9yIHRoZSBtaWRkbGUgYmluLCB3aGljaCBzcGFucyAxNi43IHRvIDIxLjAgaG91cnMsIGFuZCAwLjA2ODcgZm9yIHRoZSBmaW5hbCBiaW4sIGNvdmVyaW5nIDIxLjAgdG8gMjUuNCBob3Vycy4gVGhlIGhpc3RvZ3JhbSBzaG93cyBhIHVuaW1vZGFsIGRpc3RyaWJ1dGlvbiB3aXRoIHRoZSBoaWdoZXN0IGRlbnNpdHkgb2NjdXJyaW5nIGluIHRoZSBtaWRkbGUgYmluLCBpbmRpY2F0aW5nIHRoYXQgbW9zdCBmYWlsdXJlcyB0ZW5kIHRvIG9jY3VyIGFyb3VuZCB0aGUgY2VudGVyIG9mIHRoZSBvYnNlcnZlZCB0aW1lIHJhbmdlLgoKYikgV3JpdGUgYW4gUiBmdW5jdGlvbiB0aGF0IGNvbXB1dGVzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlcyB1c2luZyBhIEdhdXNzaWFuIGtlcm5lbCB3aXRoICRoPTIkLiBWYWxpZGF0ZSB5b3VyIGltcGxlbWVudGF0aW9uIGFnYWluc3QgUidzIGJ1aWx0LWluIGRlbnNpdHkoKSBmdW5jdGlvbi4KCiQkClxoYXR7Zn1faCh0KSA9IFxmcmFjezF9e25ofVxzdW1fe2k9MX1ebiBLXGxlZnQoIFxmcmFje3QtdF9pfXtofVxyaWdodCksIFwgXCBcdGV4dHsgd2hlcmUgfSBcIFwgSyh1KSA9IFxmcmFjezF9e1xzcXJ0ezJccGl9fSBlXnstdV4yLzJ9LgokJApgYGB7cn0KIyBHYXVzc2lhbiBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0b3IgYmFzZWQgb24gdGhlIGdpdmVuIGZvcm11bGEKa2RlX2dhdXNzaWFuIDwtIGZ1bmN0aW9uKHksIHQsIGggPSAyKXsKICBuIDwtIGxlbmd0aCh5KQogIHUgPC0gb3V0ZXIodCwgeSwgIi0iKSAvIGggICAgICAgICAgICMgc2NhbGVkIGRpc3RhbmNlcyBmb3IgdGhlIGtlcm5lbAogIHJvd1N1bXMoZG5vcm0odSkpIC8gKG4gKiBoKSAgICAgICAgICMgYXZlcmFnZSBjb250cmlidXRpb24gYWNyb3NzIG9ic2VydmF0aW9ucwp9CgojIEdyaWQgb2YgdmFsdWVzIHRvIGV2YWx1YXRlIHRoZSBkZW5zaXR5IHNtb290aGx5CnRncmlkIDwtIHNlcShtaW4oeSkgLSA2LCBtYXgoeSkgKyA2LCBsZW5ndGgub3V0ID0gMjAwKQoKIyBEZW5zaXR5IGVzdGltYXRlIGZyb20gdGhlIGN1c3RvbSBLREUgd2l0aCBoID0gMgpmX2hhdCA8LSBrZGVfZ2F1c3NpYW4oeSwgdGdyaWQsIGggPSAyKQoKIyBSJ3MgYnVpbHQtaW4gZGVuc2l0eSBlc3RpbWF0ZSB1c2luZyB0aGUgc2FtZSBiYW5kd2lkdGgKZl9yIDwtIGRlbnNpdHkoeSwgYncgPSAyLCBrZXJuZWwgPSAiZ2F1c3NpYW4iLAogICAgICAgICAgICAgICBmcm9tID0gbWluKHRncmlkKSwgdG8gPSBtYXgodGdyaWQpLCBuID0gbGVuZ3RoKHRncmlkKSkKCiMgUGxvdCBib3RoIGVzdGltYXRlcyB0byBjb21wYXJlIHJlc3VsdHMKcGxvdCh0Z3JpZCwgZl9oYXQsIHR5cGUgPSAibCIsIGx3ZCA9IDIsCiAgICAgeGxhYiA9ICJGYWlsdXJlIFRpbWUiLCB5bGFiID0gIkVzdGltYXRlZCBEZW5zaXR5IiwKICAgICBtYWluID0gIkdhdXNzaWFuIEtERSAoaCA9IDIpOiBDdXN0b20gdnMgUiBkZW5zaXR5KCkiKQpsaW5lcyhmX3IkeCwgZl9yJHksIGx0eSA9IDIsIGx3ZCA9IDIpCgpsZWdlbmQoInRvcHJpZ2h0IiwgYygiQ3VzdG9tIEtERSIsICJSIGRlbnNpdHkoKSIpLAogICAgICAgbHR5ID0gYygxLCAyKSwgbHdkID0gMikKCiMgTnVtZXJpY2FsIGNoZWNrIHRvIGNvbmZpcm0gYWdyZWVtZW50Cm1heChhYnMoZl9oYXQgLSBmX3IkeSkpCmBgYAoKYykgV3JpdGUgYSBjdXN0b20gUiBmdW5jdGlvbiB0aGF0IGNvbXB1dGVzIGtlcm5lbCBkZW5zaXR5IGVzdGltYXRlcyB1c2luZyB0aGUgRXBhbmVjaG5pa292IGtlcm5lbCB3aXRoICRoPTIkLiBWYWxpZGF0ZSB5b3VyIGltcGxlbWVudGF0aW9uIGJ5IGNvbXBhcmluZyByZXN1bHRzIHdpdGggUidzIGJ1aWx0LWluIGRlbnNpdHkoKSBmdW5jdGlvbiBmb3IgR2F1c3NpYW4ga2VybmVsIGVzdGltYXRpb24uCgokJApcaGF0e2Z9X2godCkgPSBcZnJhY3sxfXtuaH1cc3VtX3tpPTF9Xm4gS1xsZWZ0KCBcZnJhY3t0LXRfaX17aH1ccmlnaHQpLCBcIFwgXHRleHR7IHdoZXJlIH0gXCBcIEsodSkgPSBcZnJhY3szfXs0fSgxIC0gdV4yKSBcIFwgXHRleHR7IGZvciB9IFwgXCB8dXwgXGxlIDEuCiQkCmBgYHtyfQojIEVwYW5lY2huaWtvdiBLREUgZnJvbSB0aGUgZm9ybXVsYSBpbiB0aGUgcHJvbXB0ICh1c2UgaCA9IDIpCmtkZV9lcGFuIDwtIGZ1bmN0aW9uKHksIHQsIGggPSAyKXsKICBuIDwtIGxlbmd0aCh5KQogIHUgPC0gb3V0ZXIodCwgeSwgIi0iKSAvIGggICAgICAgICAgICAgICAgICMgc2NhbGUgZGlzdGFuY2VzIGJ5IGgKICBLIDwtIDAuNzUgKiAoMSAtIHVeMikgKiAoYWJzKHUpIDw9IDEpICAgICAjIEVwYW5lY2huaWtvdiB3ZWlnaHRzCiAgcm93U3VtcyhLKSAvIChuICogaCkgICAgICAgICAgICAgICAgICAgICAgIyBhdmVyYWdlIGFuZCByZXNjYWxlCn0KCiMgR3JpZCB0byBldmFsdWF0ZSB0aGUgZGVuc2l0eSBjdXJ2ZQp0Z3JpZCA8LSBzZXEobWluKHkpIC0gNiwgbWF4KHkpICsgNiwgbGVuZ3RoLm91dCA9IDIwMCkKCiMgQ3VzdG9tIEVwYW5lY2huaWtvdiBLREUgd2l0aCBoID0gMgpmX2VwYW4gPC0ga2RlX2VwYW4oeSwgdGdyaWQsIGggPSAyKQoKIyBSJ3MgR2F1c3NpYW4gS0RFIHdpdGggdGhlIHNhbWUgYmFuZHdpZHRoIGZvciBjb21wYXJpc29uCmZfZ2F1c3NfciA8LSBkZW5zaXR5KHksIGJ3ID0gMiwga2VybmVsID0gImdhdXNzaWFuIiwKICAgICAgICAgICAgICAgICAgICAgZnJvbSA9IG1pbih0Z3JpZCksIHRvID0gbWF4KHRncmlkKSwgbiA9IGxlbmd0aCh0Z3JpZCkpCgojIENvbXBhcmUga2VybmVsIGNob2ljZSBhdCB0aGUgc2FtZSBoCnBsb3QodGdyaWQsIGZfZXBhbiwgdHlwZSA9ICJsIiwgbHdkID0gMiwKICAgICB4bGFiID0gIkZhaWx1cmUgVGltZSIsIHlsYWIgPSAiRXN0aW1hdGVkIERlbnNpdHkiLAogICAgIG1haW4gPSAiS0RFIChoID0gMik6IEVwYW5lY2huaWtvdiB2cyBHYXVzc2lhbiIpCmxpbmVzKGZfZ2F1c3NfciR4LCBmX2dhdXNzX3IkeSwgbHR5ID0gMiwgbHdkID0gMikKCmxlZ2VuZCgidG9wcmlnaHQiLCBjKCJFcGFuZWNobmlrb3YgS0RFIiwgIlIgR2F1c3NpYW4gS0RFIiksCiAgICAgICBsdHkgPSBjKDEsIDIpLCBsd2QgPSAyKQpgYGAKVGhlIEVwYW5lY2huaWtvdiBrZXJuZWwgZGVuc2l0eSBlc3RpbWF0ZSBpcyBzbGlnaHRseSBtb3JlIHBlYWtlZCBpbiB0aGUgY2VudGVyIGJlY2F1c2UgaXQgdXNlcyBhIGZpeGVkIHJhbmdlIGFyb3VuZCBlYWNoIGRhdGEgcG9pbnQuIFRoZSBHYXVzc2lhbiBrZXJuZWwgZGlzdHJpYnV0ZXMgaXRzIHdlaWdodCBhY3Jvc3MgYWxsIG9ic2VydmF0aW9ucyB3aGljaCByZXN1bHRzIGluIGEgY29udGludW91cyBjdXJ2ZSB0aGF0IHNwYW5zIHRoZSBlbnRpcmUgcmFuZ2UuIEdpdmVuIHRoZSBsaW1pdGVkIHJhbmdlIG9mIHRoZSBkYXRhLCB0aGUgRXBhbmVjaG5pa292IGtlcm5lbCBwbGFjZXMgbW9yZSBlbXBoYXNpcyBvbiB0aGUgY2VudHJhbCBmYWlsdXJlIHRpbWVzLCB3aGlsZSB0aGUgR2F1c3NpYW4ga2VybmVsIHNwcmVhZHMgaW5mbHVlbmNlIG1vcmUgZXZlbmx5LgoKZCkgSG93IGRvZXMgdGhlIGNob2ljZSBvZiBrZXJuZWwgKEdhdXNzaWFuIHZzLiBFcGFuZWNobmlrb3YpIGFmZmVjdCB0aGUgZGVuc2l0eSBlc3RpbWF0ZT8gRm9yIGJvdGgga2VybmVsIGVzdGltYXRvcnMgYXBwbGllZCB0byB0aGlzIGRhdGFzZXQsIHdoYXQgaGFwcGVucyB3aGVuIHdlIHNlbGVjdCAkaD0xLjUkIHZlcnN1cyAkaD0yLjUkPwoKVGhlIEdhdXNzaWFuIGtlcm5lbCBnaXZlcyB3ZWlnaHQgdG8gYWxsIG9ic2VydmF0aW9ucyBhbmQgcHJvZHVjZXMgYSBzbW9vdGhlciBkZW5zaXR5IGVzdGltYXRlLCB3aGlsZSB0aGUgRXBhbmVjaG5pa292IGtlcm5lbCB1c2VzIGEgZml4ZWQgcmFuZ2UgYW5kIHJlc3VsdHMgaW4gYSBzbGlnaHRseSBtb3JlIHBlYWtlZCBlc3RpbWF0ZSBuZWFyIHRoZSBjZW50ZXIgb2YgdGhlIGRhdGEuIEZvciBib3RoIGtlcm5lbHMsIHVzaW5nIGEgc21hbGxlciBiYW5kd2lkdGggKGggPSAxLjUpIGNyZWF0ZXMgYSBtb3JlIGRldGFpbGVkIGFuZCB2YXJpYWJsZSBkZW5zaXR5LCB3aGVyZWFzIGEgbGFyZ2VyIGJhbmR3aWR0aCAoaCA9IDIuNSkgc21vb3RocyB0aGUgZXN0aW1hdGUgYW5kIHJlZHVjZXMgdmFyaWFiaWxpdHkgYnV0IG1heSBoaWRlIGZpbmVyIGZlYXR1cmVzIG9mIHRoZSBkaXN0cmlidXRpb24uCgoKCgoKCgo=