Using ms
via GSImulator
We are using ms
this way because it is fairly easy to
distribute the binaries in an R package.
library(tidyverse)
library(GSImulator)
ms
is a coalescent simulator written in C by Dick Hudson
at U Chicago. It has been around for a long time, but a paper describing
it came out long after it had been in routine use (Hudson 2002)
It can be downloaded from here.
However, I have wrapped up compiled versions in an R package, so you
needn’t worry about that.
It is quite fast for simulating small segments of DNA without much
recombination. It is worth noting, however, that a more recent program
that implements the whole process more efficiently is available and much
better for whole-genome-scale simulation (Kelleher, Etheridge, and McVean 2016).
Running ms
within R with the system2 command
ms
is a program that runs in the shell. Here we use R’s
system2()
command to run it from within R.
If we invoke ms
with no arguments it gives us a message
about what kinds of arguments one can use:
# ms_binary() gives the path to ms on your system
system2(command = ms_binary(), args = "")
/Users/eriq/Library/R/4.3/library/GSImulator/bin/ms-Darwin
Too few command line arguments
usage: ms nsam howmany
Options:
-t theta (this option and/or the next must be used. Theta = 4*N0*u )
-s segsites ( fixed number of segregating sites)
-T (Output gene tree.)
-F minfreq Output only sites with freq of minor allele >= minfreq.
-r rho nsites (rho here is 4Nc)
-c f track_len (f = ratio of conversion rate to rec rate. tracklen is mean length.)
if rho = 0., f = 4*N0*g, with g the gene conversion rate.
-G alpha ( N(t) = N0*exp(-alpha*t) . alpha = -log(Np/Nr)/t
-I npop n1 n2 ... [mig_rate] (all elements of mig matrix set to mig_rate/(npop-1)
-m i j m_ij (i,j-th element of mig matrix set to m_ij.)
-ma m_11 m_12 m_13 m_21 m_22 m_23 ...(Assign values to elements of migration matrix.)
-n i size_i (popi has size set to size_i*N0
-g i alpha_i (If used must appear after -M option.)
The following options modify parameters at the time 't' specified as the first argument:
-eG t alpha (Modify growth rate of all pop's.)
-eg t i alpha_i (Modify growth rate of pop i.)
-eM t mig_rate (Modify the mig matrix so all elements are mig_rate/(npop-1)
-em t i j m_ij (i,j-th element of mig matrix set to m_ij at time t )
-ema t npop m_11 m_12 m_13 m_21 m_22 m_23 ...(Assign values to elements of migration matrix.)
-eN t size (Modify pop sizes. New sizes = size*N0 )
-en t i size_i (Modify pop size of pop i. New size of popi = size_i*N0 .)
-es t i proportion (Split: pop i -> pop-i + pop-npop, npop increases by 1.
proportion is probability that each lineage stays in pop-i. (p, 1-p are admixt. proport.
Size of pop npop is set to N0 and alpha = 0.0 , size and alpha of pop i are unchanged.
-ej t i j ( Join lineages in pop i and pop j into pop j
size, alpha and M are unchanged.
-f filename ( Read command line arguments from file filename.)
See msdoc.pdf for explanation of these parameters.
That shows a lot of fun things to do. Let’s start by just simulating
coalescent trees and looking at them. In order to do that, you will need
to install another couple packages if you don’t already have them. See
the instructions at: https://eriqande.github.io/coalescent-hands-on/000-prep-for-coalescent.nb.html.
Load the other packages we will use:
library(ape)
library(ggtree)
A basic vanilla tree
Here we simulate a single tree with 10 tips and tell ms
to just print the tree out in Newick format:
system2(command = ms_binary(), args = "10 1 -T")
/Users/eriq/Library/R/4.3/library/GSImulator/bin/ms-Darwin 10 1 -T
17591 45577 21597
//
(((4:0.070,8:0.070):0.057,(5:0.079,(3:0.029,(1:0.023,(6:0.006,9:0.006):0.018):0.006):0.050):0.048):0.822,(7:0.771,(2:0.029,10:0.029):0.742):0.179);
The resulting coalescent tree is written out above in “Newick”
format, which is named after a restaurant (“Newick’s”) in New Hampshire
where a group of phylogeneticist’s sketched it out on a napkin.
It shows the branch tip numbers and the patterns in which branches in
a tree join one another. It also shows the branch lengths in units of
time.
In trees made by ms
, the branch lengths are coalescence
times are in units of \(4N\)
generations. So an ms
time of 0.5 is the expected
coalescence time of a single pair of lineages.
Cool. Now, we can redirect that sort of output into a file, read it
in and plot a tree.
system2(command = ms_binary(), args = "10 1 -T", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
ggtree(ctree, layout = "rectangular") +
geom_tiplab(size = 3) + coord_flip() + scale_x_reverse()

Note that from here on out, we are going to flip our trees sideways,
since it is a little easier to plot them that way with ggtree. Like
this:
p <- ggtree(ctree, layout = "rectangular") +
geom_tiplab(size = 3) +
theme_tree2()
revts(p)

We also put a “timeline” on that one so that the units of time can be
visualized. In this case, time going backwards is depicted as
negative.
Multiple trees
One characteristic of the coalescent process is its variability. Here
we simulate 12 different trees (each with 10 tips) and plot them to
appreciate how variable trees can be, even if simulated from the same
neutral process.
system2(command = ms_binary(), args = "10 12 -T", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:12
ggtree(ctree, layout = "rectangular") +
facet_wrap(~.id, ncol = 3) +
geom_tiplab(size = 2)

Population structure
The standard coalescent can easily be updated to include population
structure. Basically, at the time of sampling (i.e., “the present”), you
specify that your samples are from \(K\) different populations. This is done
with the -I
flag. For example, -I 2 20 30
means that there are 2 subpopulations with the first 20 (haploid)
samples from the first subpopulation, and the next 30 from the second
subpopulation. Note that the nsam parameter (number of samples) must be
50 = 20 + 30 in that case.
After the -I 2 20 30
you then give a number which is the
population scaled migration rate, \(4Nm\), where \(m\) in the per-generation probability that
a parent in the population is an immigrant from a different population.
(You can actually specify a whole migration matrix if you want, but we
won’t worry about that now.) You can specify an arbitrary number of
populations, but we will only focus on two of them in this notebook.
What does the coalescent with migration look like? When everyone gets
down to this point, ask Eric, and he will show you with a small
example.
Think about this: what does \(4Nm\)
mean in terms of how many migrational events you would expect to see in
the history of a pair of gene copies? And why? (Once again, think of
each branch as a bead-string of generations…)
Let’s do two populations, each of 10 chromosomes (\(2N = 10\)), and let the migration rate be
quite low. Like \(4Nm = 0.01\), to see
what we get. Let’s do 6 reps:
system2(command = ms_binary(), args = "20 6 -T -I 2 10 10 0.01", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
facet_wrap(~.id, ncol = 3) +
geom_tiplab(size = 2)

OK, at such low migration rates, we see that all 10 gene copies in
each population have, almost without exception, coalesced with one
another before coalescing with any genes from the other population.
That is not the always the case when migration rate gets higher, for
example \(4Nm = 0.2\).
system2(command = ms_binary(), args = "20 6 -T -I 2 10 10 0.2", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
facet_wrap(~.id, ncol = 3) +
geom_tiplab(size = 2)

By taking the limit as the mutation rate goes to zero, Monty Slatkin,
showed that the parameter \(F_\mathrm{ST}\) can be defined in terms of
the expected coalescent times between pairs of genes drawn within and
between different populations. \[
F_\mathrm{ST} = \frac{\bar{t} - \bar{t}_0}{\bar{t}}
\] where \(\bar{t}_0\) is the
expected coalescence time between two genes drawn at random from within
subpopulations and \(\bar{t}\) is the
expected coalescence time for two gene copies drawn at random from
amongst all those in either subpopulation (Slatkin 2007).
Population growth
As the manual for ms
notes, “The switch -G
[used like ms nsam nreps -t 4 -G a
] is used to specify that
the population has been growing (or shrinking) exponentially. That is,
the population size at time \(t\) in
the past is given by: \(N(t) = N_0
\exp^{-at}\), where \(t\) is the
time before the present, measured in units of \(4N_0\) generations.” Note that \(N_0\) is the size of the population at the
time of sampling. So, if \(a>0\) it
means the population was smaller further back in time.
Let’s make some plots to grok out what this means. First, let’s
pretend that we are thinking about a population that, at the time of
sampling is of size \(N_0 = 10,000\).
And so, if we were interested in what its population size was, say
34,000 generations ago, then that would mean that time, measured in
units of \(4N_0\) generations would be:
\[
t = \frac{34,000}{4N_0} = \frac{34,000}{40,0000} \approx 0.85
\]
So, let’s make a picture of what the population size looks like at
different times going back in the past. You can play with the values of
N_0
and a
below to see what you get
# define parameter values
N_0 <- 10000
a = 5
# make a tibble of different values at different times
ptib <- tibble(
generations = seq(0, 5 * N_0, by = N_0 / 100)
) %>%
mutate(t = generations / (4 * N_0),
Nt = N_0 * exp(-t * a)
)
# make a plot
ggplot(ptib, aes(x = generations, y = Nt)) +
geom_line() +
scale_x_continuous("Time in generations", sec.axis = sec_axis(~ . / (4 * N_0), name = "Time in 4N_0 generations" ))

Population growth can stretch trees out. If a population is growing
exponentially then the terminal branches tend to be longer. Let’s
experiment with that.
system2(command = ms_binary(), args = "10 6 -T -G 5", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
facet_wrap(~.id, ncol = 3) +
geom_tiplab(size = 2)

Yep, longer terminal branches. Play around with different settings
and check out the results.
Instantaneous population size changes
Past changes in the populations are controlled by values of
-eSomething
options. Where the e stands for event. The
simplest of these are instantaneous changes in population size. The
simplest is:
-en t i x
which means “Set subpop \(i\) size to \(x
\times N_0\) at time \(t\) and
growth rate to zero.
So, for example, in our migration model above we could make the two
populations very different sizes and see what the results are. Let’s
make population 2 ten times bigger than population 1 from the present
all the way back into the past…
system2(command = ms_binary(), args = "20 6 -T -I 2 10 10 0.01 -en 0 2 10", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
facet_wrap(~.id, ncol = 3) +
geom_tiplab(size = 2)

Aha! That is interesting. It is hard to tell, because the coalescence
times are so short in population 1, but if you squint, you can convince
yourself that, on average, the trees in population 2 reach a MRCA in
about 10 times the amount of time as the trees in population 1.
The results also show that there is a lot of variability in the
coalescent process.
Population Splitting/Merging
My goodness, there are a lot of options in ms
. To see
the full rundown on all the options, you can read the full
documentation: msdoc.pdf.
But for now, we will just discuss one more, used to join or split two
populations going back in time.
-ej t i j
which means move all lineages in
subpopulation \(i\) into subpopulation
\(j\) at time \(t\) in units of \(4N_0\). The j
means “join”. It
corresponds to populations “joining” while going backward in time. But,
forward in time this corresponds to population
splitting.
-es t i p
which means split subpopulation \(i\) into two subpopulations \(i\) and \(npop +
1\) \(t\) (in units of \(4N_0\)). Lineages currently in \(i\) remain in \(i\) with probability \(p\) and with probability \(1-p\) they get placed into subpopulation
\(npop + 1\). The s
means
split.
It corresponds to populations “joining” while going forward in
time.
Discuss with your partner: What are some
conservation-genetic scenarios that these last two demographic scenarios
might correspond to?
Here is an example of a population join going back in time. We have
10 samples from each population with no migration between them, and the
populations join at time \(2N_0\) in
the past (at which point most will have coalesced within
subpopulations):
system2(command = ms_binary(), args = "20 6 -T -I 2 10 10 0.00 -ej 0.5 1 2", stdout = "out.tree", stderr = FALSE)
ctree <- read.tree("out.tree")
names(ctree) <- 1:6
ggtree(ctree, layout = "rectangular") +
facet_wrap(~.id, ncol = 3) +
geom_tiplab(size = 2)

LS0tCnRpdGxlOiAiVGhlIENvYWxlc2NlbnQgd2l0aCBQb3B1bGF0aW9uIFN0cnVjdHVyZSBhbmQgRGVtb2dyYXBoeSwgZXRjLiIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKYXV0aG9yOiAiRXJpYyBDLiBBbmRlcnNvbiIKYmlibGlvZ3JhcGh5OiByZWZlcmVuY2VzLmJpYgotLS0KCgoKCgojIyBVc2luZyBgbXNgIHZpYSBHU0ltdWxhdG9yCgpXZSBhcmUgdXNpbmcgYG1zYCB0aGlzIHdheSBiZWNhdXNlIGl0IGlzIGZhaXJseSBlYXN5IHRvIGRpc3RyaWJ1dGUgdGhlIGJpbmFyaWVzCmluIGFuIFIgcGFja2FnZS4KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KEdTSW11bGF0b3IpCmBgYAoKYG1zYCBpcyBhIGNvYWxlc2NlbnQgc2ltdWxhdG9yIHdyaXR0ZW4gaW4gQyBieSBEaWNrIEh1ZHNvbiBhdCBVIENoaWNhZ28uICBJdCBoYXMKYmVlbiBhcm91bmQgZm9yIGEgbG9uZyB0aW1lLCBidXQgYSBwYXBlciBkZXNjcmliaW5nIGl0IGNhbWUgb3V0IGxvbmcgYWZ0ZXIgaXQgaGFkIApiZWVuIGluIHJvdXRpbmUgdXNlIFtAaHVkc29uR2VuZXJhdGluZ1NhbXBsZXNXcmlnaHQyMDAyXQoKCkl0IGNhbiBiZSBkb3dubG9hZGVkIGZyb20gW2hlcmVdKGh0dHA6Ly9ob21lLnVjaGljYWdvLmVkdS9yaHVkc29uMS9zb3VyY2UvbWtzYW1wbGVzLmh0bWwpLgpIb3dldmVyLCBJIGhhdmUKd3JhcHBlZCB1cCBjb21waWxlZCB2ZXJzaW9ucyBpbiBhbiBSIHBhY2thZ2UsIHNvIHlvdSBuZWVkbid0IHdvcnJ5IGFib3V0IHRoYXQuCgoKSXQgaXMgcXVpdGUgZmFzdCBmb3Igc2ltdWxhdGluZyBzbWFsbCBzZWdtZW50cyBvZiAKRE5BIHdpdGhvdXQgbXVjaCByZWNvbWJpbmF0aW9uLiAgSXQgaXMgd29ydGggbm90aW5nLCBob3dldmVyLCB0aGF0IAphIG1vcmUgcmVjZW50IHByb2dyYW0gdGhhdCBpbXBsZW1lbnRzIHRoZSB3aG9sZSBwcm9jZXNzIG1vcmUgZWZmaWNpZW50bHkKaXMgYXZhaWxhYmxlIGFuZCBtdWNoIGJldHRlciBmb3Igd2hvbGUtZ2Vub21lLXNjYWxlIHNpbXVsYXRpb24gW0BrZWxsZWhlckVmZmljaWVudENvYWxlc2NlbnRTaW11bGF0aW9uMjAxNl0uCgojIyMgUnVubmluZyBgbXNgIHdpdGhpbiBSIHdpdGggdGhlIHN5c3RlbTIgY29tbWFuZAoKYG1zYCBpcyBhIHByb2dyYW0gdGhhdCBydW5zIGluIHRoZSBzaGVsbC4gIEhlcmUgd2UgdXNlIFIncyBgc3lzdGVtMigpYCBjb21tYW5kIHRvIHJ1biBpdApmcm9tIHdpdGhpbiBSLgoKSWYgd2UgaW52b2tlIGBtc2Agd2l0aCBubyBhcmd1bWVudHMgaXQgZ2l2ZXMgdXMgYSBtZXNzYWdlIGFib3V0IHdoYXQga2luZHMKb2YgYXJndW1lbnRzIG9uZSBjYW4gdXNlOgpgYGB7cn0KIyBtc19iaW5hcnkoKSBnaXZlcyB0aGUgcGF0aCB0byBtcyBvbiB5b3VyIHN5c3RlbQpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIiKQpgYGAKClRoYXQgc2hvd3MgYSBsb3Qgb2YgZnVuIHRoaW5ncyB0byBkby4gIExldCdzIHN0YXJ0IGJ5IGp1c3Qgc2ltdWxhdGluZyBjb2FsZXNjZW50IAp0cmVlcyBhbmQgbG9va2luZyBhdCB0aGVtLiAgSW4gb3JkZXIgdG8gZG8gdGhhdCwgeW91IHdpbGwgbmVlZCB0byBpbnN0YWxsIGFub3RoZXIKY291cGxlIHBhY2thZ2VzIGlmIHlvdSBkb24ndCBhbHJlYWR5IGhhdmUgdGhlbS4gIFNlZSB0aGUgaW5zdHJ1Y3Rpb25zIGF0OiBbaHR0cHM6Ly9lcmlxYW5kZS5naXRodWIuaW8vY29hbGVzY2VudC1oYW5kcy1vbi8wMDAtcHJlcC1mb3ItY29hbGVzY2VudC5uYi5odG1sXShodHRwczovL2VyaXFhbmRlLmdpdGh1Yi5pby9jb2FsZXNjZW50LWhhbmRzLW9uLzAwMC1wcmVwLWZvci1jb2FsZXNjZW50Lm5iLmh0bWwpLgoKTG9hZCB0aGUgb3RoZXIgcGFja2FnZXMgd2Ugd2lsbCB1c2U6CmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpsaWJyYXJ5KGFwZSkKbGlicmFyeShnZ3RyZWUpCmBgYAoKCiMjIyBBIGJhc2ljIHZhbmlsbGEgdHJlZQoKSGVyZSB3ZSBzaW11bGF0ZSBhIHNpbmdsZSB0cmVlIHdpdGggMTAgdGlwcyBhbmQgdGVsbCBgbXNgIHRvIGp1c3QgcHJpbnQgdGhlIHRyZWUgb3V0CmluIE5ld2ljayBmb3JtYXQ6CmBgYHtyfQpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIxMCAxIC1UIikKYGBgCgpUaGUgcmVzdWx0aW5nIGNvYWxlc2NlbnQgdHJlZSBpcyB3cml0dGVuIG91dCBhYm92ZSBpbiAiTmV3aWNrIiBmb3JtYXQsIHdoaWNoIGlzCm5hbWVkIGFmdGVyIGEgcmVzdGF1cmFudCAoIk5ld2ljaydzIikgaW4gTmV3IEhhbXBzaGlyZSB3aGVyZSBhIGdyb3VwIG9mIHBoeWxvZ2VuZXRpY2lzdCdzCnNrZXRjaGVkIGl0IG91dCBvbiBhIG5hcGtpbi4KCkl0IHNob3dzIHRoZSBicmFuY2ggdGlwIG51bWJlcnMgYW5kIHRoZSBwYXR0ZXJucyBpbiB3aGljaApicmFuY2hlcyBpbiBhIHRyZWUgam9pbiBvbmUgYW5vdGhlci4gIEl0IGFsc28gc2hvd3MgdGhlIGJyYW5jaApsZW5ndGhzIGluIHVuaXRzIG9mIHRpbWUuCgpJbiB0cmVlcyBtYWRlIGJ5IGBtc2AsIHRoZSBicmFuY2ggbGVuZ3RocyBhcmUgY29hbGVzY2VuY2UgdGltZXMgYXJlCmluIHVuaXRzIG9mICQ0TiQgZ2VuZXJhdGlvbnMuICBTbyBhbiBgbXNgIHRpbWUgb2YgMC41IGlzIHRoZSBleHBlY3RlZApjb2FsZXNjZW5jZSB0aW1lIG9mIGEgc2luZ2xlIHBhaXIgb2YgbGluZWFnZXMuCgoKCkNvb2wuICBOb3csIHdlIGNhbiByZWRpcmVjdCB0aGF0IHNvcnQgb2Ygb3V0cHV0IGludG8gYSBmaWxlLCByZWFkIGl0IGluIGFuZCBwbG90CmEgdHJlZS4KYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjEwIDEgLVQiLCBzdGRvdXQgPSAib3V0LnRyZWUiLCBzdGRlcnIgPSBGQUxTRSkKY3RyZWUgPC0gcmVhZC50cmVlKCJvdXQudHJlZSIpIApnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBnZW9tX3RpcGxhYihzaXplID0gMykgKyBjb29yZF9mbGlwKCkgKyBzY2FsZV94X3JldmVyc2UoKSAKYGBgCgpOb3RlIHRoYXQgZnJvbSBoZXJlIG9uIG91dCwgd2UgYXJlIGdvaW5nIHRvIGZsaXAgb3VyIHRyZWVzIHNpZGV3YXlzLCBzaW5jZSBpdCBpcyBhIGxpdHRsZQplYXNpZXIgdG8gcGxvdCB0aGVtIHRoYXQgd2F5IHdpdGggZ2d0cmVlLiAgTGlrZSB0aGlzOgpgYGB7cn0KcCA8LSBnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBnZW9tX3RpcGxhYihzaXplID0gMykgKwogIHRoZW1lX3RyZWUyKCkKcmV2dHMocCkKYGBgCgpXZSBhbHNvIHB1dCBhICJ0aW1lbGluZSIgb24gdGhhdCBvbmUgc28gdGhhdCB0aGUgdW5pdHMgb2YgdGltZSBjYW4gYmUgdmlzdWFsaXplZC4KSW4gdGhpcyBjYXNlLCB0aW1lIGdvaW5nIGJhY2t3YXJkcyBpcyBkZXBpY3RlZCBhcyBuZWdhdGl2ZS4KCgojIyMgTXVsdGlwbGUgdHJlZXMKCk9uZSBjaGFyYWN0ZXJpc3RpYyBvZiB0aGUgY29hbGVzY2VudCBwcm9jZXNzIGlzIGl0cyB2YXJpYWJpbGl0eS4gIEhlcmUKd2Ugc2ltdWxhdGUgMTIgZGlmZmVyZW50IHRyZWVzIChlYWNoIHdpdGggMTAgdGlwcykgYW5kIHBsb3QKdGhlbSB0byBhcHByZWNpYXRlIGhvdyB2YXJpYWJsZQp0cmVlcyBjYW4gYmUsIGV2ZW4gaWYgc2ltdWxhdGVkIGZyb20gdGhlIHNhbWUgbmV1dHJhbCBwcm9jZXNzLgoKYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjEwIDEyIC1UIiwgc3Rkb3V0ID0gIm91dC50cmVlIiwgc3RkZXJyID0gRkFMU0UpCmN0cmVlIDwtIHJlYWQudHJlZSgib3V0LnRyZWUiKQpuYW1lcyhjdHJlZSkgPC0gMToxMgpnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBmYWNldF93cmFwKH4uaWQsIG5jb2wgID0gMykgKwogIGdlb21fdGlwbGFiKHNpemUgPSAyKQoKYGBgCgojIyMgUG9wdWxhdGlvbiBzdHJ1Y3R1cmUgCgpUaGUgc3RhbmRhcmQgY29hbGVzY2VudCBjYW4gZWFzaWx5IGJlIHVwZGF0ZWQgdG8gaW5jbHVkZSBwb3B1bGF0aW9uIHN0cnVjdHVyZS4gIEJhc2ljYWxseSwKYXQgdGhlIHRpbWUgb2Ygc2FtcGxpbmcgKGkuZS4sICJ0aGUgcHJlc2VudCIpLCB5b3Ugc3BlY2lmeSB0aGF0IHlvdXIgc2FtcGxlcyBhcmUgZnJvbSAkSyQKZGlmZmVyZW50IHBvcHVsYXRpb25zLiAgVGhpcyBpcyBkb25lIHdpdGggdGhlIGAtSWAgZmxhZy4gIEZvciBleGFtcGxlLCBgLUkgMiAyMCAzMGAgbWVhbnMgdGhhdAp0aGVyZSBhcmUgMiBzdWJwb3B1bGF0aW9ucyB3aXRoCnRoZSBmaXJzdCAyMCAoaGFwbG9pZCkgc2FtcGxlcyBmcm9tIHRoZSBmaXJzdCBzdWJwb3B1bGF0aW9uLCBhbmQgdGhlIG5leHQgMzAgZnJvbSB0aGUgc2Vjb25kCnN1YnBvcHVsYXRpb24uICBOb3RlIHRoYXQgdGhlIG5zYW0gcGFyYW1ldGVyIChudW1iZXIgb2Ygc2FtcGxlcykgbXVzdCBiZSA1MCA9IDIwICsgMzAgaW4gdGhhdCBjYXNlLgoKQWZ0ZXIgdGhlIGAtSSAyIDIwIDMwYCB5b3UgdGhlbiBnaXZlIGEgbnVtYmVyIHdoaWNoIGlzIHRoZSBfcG9wdWxhdGlvbiBzY2FsZWQgbWlncmF0aW9uIHJhdGVfLCAkNE5tJCwgCndoZXJlICRtJCBpbiB0aGUgcGVyLWdlbmVyYXRpb24gcHJvYmFiaWxpdHkgdGhhdCBhIHBhcmVudCBpbiB0aGUgcG9wdWxhdGlvbiBpcyBhbgppbW1pZ3JhbnQgZnJvbSBhIGRpZmZlcmVudCBwb3B1bGF0aW9uLiAgKFlvdSBjYW4gYWN0dWFsbHkgc3BlY2lmeSBhIHdob2xlIG1pZ3JhdGlvbiBtYXRyaXggaWYgeW91CndhbnQsIGJ1dCB3ZSB3b24ndCB3b3JyeSBhYm91dCB0aGF0IG5vdy4pICBZb3UgY2FuIHNwZWNpZnkgYW4gYXJiaXRyYXJ5IG51bWJlciBvZiBwb3B1bGF0aW9ucywKYnV0IHdlIHdpbGwgb25seSBmb2N1cyBvbiB0d28gb2YgdGhlbSBpbiB0aGlzIG5vdGVib29rLiAgCgpXaGF0IGRvZXMgdGhlIGNvYWxlc2NlbnQgd2l0aCBtaWdyYXRpb24gbG9vayBsaWtlPyBXaGVuIGV2ZXJ5b25lIGdldHMgZG93biB0byB0aGlzCnBvaW50LCBhc2sgRXJpYywgYW5kIGhlIHdpbGwgc2hvdyB5b3Ugd2l0aCBhIHNtYWxsIGV4YW1wbGUuICAKClRoaW5rIGFib3V0IHRoaXM6IHdoYXQgZG9lcyAkNE5tJCBtZWFuIGluIHRlcm1zIG9mIGhvdyBtYW55IG1pZ3JhdGlvbmFsIGV2ZW50cyB5b3Ugd291bGQKZXhwZWN0IHRvIHNlZSBpbiB0aGUgaGlzdG9yeSBvZiBhIHBhaXIgb2YgZ2VuZSBjb3BpZXM/IEFuZCB3aHk/IChPbmNlIGFnYWluLCB0aGluayBvZiAKZWFjaCBicmFuY2ggYXMgYSBiZWFkLXN0cmluZyBvZiBnZW5lcmF0aW9ucy4uLikKCkxldCdzIGRvIHR3byBwb3B1bGF0aW9ucywgZWFjaCBvZiAxMCBjaHJvbW9zb21lcyAoJDJOID0gMTAkKSwgYW5kIGxldCB0aGUgbWlncmF0aW9uCnJhdGUgYmUgcXVpdGUgbG93LiAgTGlrZSAkNE5tID0gMC4wMSQsIHRvIHNlZSB3aGF0IHdlIGdldC4gIExldCdzIGRvIDYgcmVwczoKYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjIwIDYgLVQgLUkgMiAxMCAxMCAwLjAxIiwgc3Rkb3V0ID0gIm91dC50cmVlIiwgc3RkZXJyID0gRkFMU0UpCmN0cmVlIDwtIHJlYWQudHJlZSgib3V0LnRyZWUiKQpuYW1lcyhjdHJlZSkgPC0gMTo2CmdndHJlZShjdHJlZSwgbGF5b3V0ID0gInJlY3Rhbmd1bGFyIikgKwogIGZhY2V0X3dyYXAofi5pZCwgbmNvbCAgPSAzKSArCiAgZ2VvbV90aXBsYWIoc2l6ZSA9IDIpCmBgYAoKT0ssIGF0IHN1Y2ggbG93IG1pZ3JhdGlvbiByYXRlcywgd2Ugc2VlIHRoYXQgYWxsIDEwIGdlbmUgY29waWVzIGluIGVhY2ggcG9wdWxhdGlvbiBoYXZlLAphbG1vc3Qgd2l0aG91dCBleGNlcHRpb24sIGNvYWxlc2NlZCB3aXRoIG9uZSBhbm90aGVyIGJlZm9yZSBjb2FsZXNjaW5nIHdpdGggYW55IGdlbmVzIGZyb20KdGhlIG90aGVyIHBvcHVsYXRpb24uICAKClRoYXQgaXMgbm90IHRoZSBhbHdheXMgdGhlIGNhc2Ugd2hlbiBtaWdyYXRpb24gcmF0ZSBnZXRzIGhpZ2hlciwgZm9yIGV4YW1wbGUgJDRObSA9IDAuMiQuICAKYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjIwIDYgLVQgLUkgMiAxMCAxMCAwLjIiLCBzdGRvdXQgPSAib3V0LnRyZWUiLCBzdGRlcnIgPSBGQUxTRSkKY3RyZWUgPC0gcmVhZC50cmVlKCJvdXQudHJlZSIpCm5hbWVzKGN0cmVlKSA8LSAxOjYKZ2d0cmVlKGN0cmVlLCBsYXlvdXQgPSAicmVjdGFuZ3VsYXIiKSArCiAgZmFjZXRfd3JhcCh+LmlkLCBuY29sICA9IDMpICsKICBnZW9tX3RpcGxhYihzaXplID0gMikKYGBgCgpCeSB0YWtpbmcgdGhlIGxpbWl0IGFzIHRoZSBtdXRhdGlvbiByYXRlIGdvZXMgdG8gemVybywgTW9udHkgU2xhdGtpbiwgc2hvd2VkCnRoYXQgdGhlIHBhcmFtZXRlciAkRl9cbWF0aHJte1NUfSQgY2FuIGJlIGRlZmluZWQgaW4gdGVybXMgb2YgdGhlIGV4cGVjdGVkIGNvYWxlc2NlbnQgCnRpbWVzIGJldHdlZW4gcGFpcnMgb2YgZ2VuZXMgZHJhd24gd2l0aGluIGFuZCBiZXR3ZWVuIGRpZmZlcmVudCBwb3B1bGF0aW9ucy4gCiQkCkZfXG1hdGhybXtTVH0gPSBcZnJhY3tcYmFye3R9IC0gXGJhcnt0fV8wfXtcYmFye3R9fQokJAp3aGVyZSAkXGJhcnt0fV8wJCBpcyB0aGUgZXhwZWN0ZWQgY29hbGVzY2VuY2UgdGltZSBiZXR3ZWVuIHR3byBnZW5lcyBkcmF3biBhdCByYW5kb20KZnJvbSB3aXRoaW4gc3VicG9wdWxhdGlvbnMgYW5kICRcYmFye3R9JCBpcyB0aGUgZXhwZWN0ZWQgY29hbGVzY2VuY2UgdGltZSBmb3IgdHdvIGdlbmUKY29waWVzIGRyYXduIGF0IHJhbmRvbSBmcm9tIGFtb25nc3QgYWxsIHRob3NlIGluIGVpdGhlciBzdWJwb3B1bGF0aW9uIFtAc2xhdGtpbkluYnJlZWRpbmdDb2VmZmljaWVudHNDb2FsZXNjZW5jZTIwMDddLgoKIyMjIFBvcHVsYXRpb24gZ3Jvd3RoCgpBcyB0aGUgbWFudWFsIGZvciBgbXNgIG5vdGVzLCAiVGhlIHN3aXRjaCBgLUdgIFt1c2VkIGxpa2UgYG1zIG5zYW0gbnJlcHMgLXQgNCAtRyBhYF0gaXMgdXNlZCB0byBzcGVjaWZ5IHRoYXQgdGhlIHBvcHVsYXRpb24gaGFzIGJlZW4gZ3Jvd2luZyAob3Igc2hyaW5raW5nKSBleHBvbmVudGlhbGx5LiBUaGF0IGlzLCB0aGUgcG9wdWxhdGlvbiBzaXplIGF0IHRpbWUgJHQkIGluIHRoZSBwYXN0IGlzIGdpdmVuIGJ5OiAkTih0KSA9IE5fMCBcZXhwXnstYXR9JCwgd2hlcmUgJHQkIGlzIHRoZSB0aW1lIGJlZm9yZSB0aGUgcHJlc2VudCwgbWVhc3VyZWQgaW4gdW5pdHMgb2YgJDROXzAkIGdlbmVyYXRpb25zLiIgTm90ZSB0aGF0ICROXzAkIGlzIHRoZSBzaXplIG9mIHRoZSBwb3B1bGF0aW9uIGF0IHRoZSB0aW1lIG9mIHNhbXBsaW5nLiBTbywgaWYgJGE+MCQgaXQgbWVhbnMgdGhlIHBvcHVsYXRpb24gd2FzIHNtYWxsZXIgZnVydGhlciBiYWNrIGluIHRpbWUuCgpMZXQncyBtYWtlIHNvbWUgcGxvdHMgdG8gZ3JvayBvdXQgd2hhdCB0aGlzIG1lYW5zLiBGaXJzdCwgbGV0J3MgcHJldGVuZCB0aGF0IHdlIGFyZSB0aGlua2luZyBhYm91dCBhCnBvcHVsYXRpb24gdGhhdCwgYXQgdGhlIHRpbWUgb2Ygc2FtcGxpbmcgaXMgb2Ygc2l6ZSAkTl8wID0gMTAsMDAwJC4gIEFuZCBzbywgaWYgd2Ugd2VyZSBpbnRlcmVzdGVkIGluCndoYXQgaXRzIHBvcHVsYXRpb24gc2l6ZSB3YXMsIHNheSAzNCwwMDAgZ2VuZXJhdGlvbnMgYWdvLCB0aGVuIHRoYXQgd291bGQgbWVhbiB0aGF0IHRpbWUsIG1lYXN1cmVkIGluIHVuaXRzCm9mICQ0Tl8wJCBnZW5lcmF0aW9ucyB3b3VsZCBiZToKJCQKdCA9IFxmcmFjezM0LDAwMH17NE5fMH0gPSBcZnJhY3szNCwwMDB9ezQwLDAwMDB9IFxhcHByb3ggMC44NQokJAoKU28sIGxldCdzIG1ha2UgYSBwaWN0dXJlIG9mIHdoYXQgdGhlIHBvcHVsYXRpb24gc2l6ZSBsb29rcyBsaWtlIGF0IGRpZmZlcmVudCB0aW1lcyBnb2luZyBiYWNrIGluIHRoZSBwYXN0LgpZb3UgY2FuIHBsYXkgd2l0aCB0aGUgdmFsdWVzIG9mIGBOXzBgIGFuZCBgYWAgYmVsb3cgdG8gc2VlIHdoYXQgeW91IGdldCAKYGBge3J9CiMgZGVmaW5lIHBhcmFtZXRlciB2YWx1ZXMKTl8wIDwtIDEwMDAwCmEgPSA1CgojIG1ha2UgYSB0aWJibGUgb2YgZGlmZmVyZW50IHZhbHVlcyBhdCBkaWZmZXJlbnQgdGltZXMKcHRpYiA8LSB0aWJibGUoCiAgZ2VuZXJhdGlvbnMgPSBzZXEoMCwgNSAqIE5fMCwgYnkgPSBOXzAgLyAxMDApCikgJT4lIAogIG11dGF0ZSh0ID0gZ2VuZXJhdGlvbnMgLyAoNCAqIE5fMCksCiAgICAgICAgIE50ID0gTl8wICogZXhwKC10ICogYSkKICAgICAgICAgKQoKIyBtYWtlIGEgcGxvdApnZ3Bsb3QocHRpYiwgYWVzKHggPSBnZW5lcmF0aW9ucywgeSA9IE50KSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoIlRpbWUgaW4gZ2VuZXJhdGlvbnMiLCBzZWMuYXhpcyA9IHNlY19heGlzKH4gLiAvICg0ICogTl8wKSwgbmFtZSA9ICJUaW1lIGluIDROXzAgZ2VuZXJhdGlvbnMiICkpCgpgYGAKClBvcHVsYXRpb24gZ3Jvd3RoIGNhbiBzdHJldGNoIHRyZWVzIG91dC4gIElmIGEgcG9wdWxhdGlvbiBpcyBncm93aW5nIGV4cG9uZW50aWFsbHkKdGhlbiB0aGUgdGVybWluYWwgYnJhbmNoZXMgdGVuZCB0byBiZSBsb25nZXIuICBMZXQncyBleHBlcmltZW50IHdpdGggdGhhdC4KYGBge3J9CnN5c3RlbTIoY29tbWFuZCA9IG1zX2JpbmFyeSgpLCBhcmdzID0gIjEwIDYgLVQgLUcgNSIsIHN0ZG91dCA9ICJvdXQudHJlZSIsIHN0ZGVyciA9IEZBTFNFKQpjdHJlZSA8LSByZWFkLnRyZWUoIm91dC50cmVlIikKbmFtZXMoY3RyZWUpIDwtIDE6NgpnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBmYWNldF93cmFwKH4uaWQsIG5jb2wgID0gMykgKwogIGdlb21fdGlwbGFiKHNpemUgPSAyKQpgYGAKWWVwLCBsb25nZXIgdGVybWluYWwgYnJhbmNoZXMuIFBsYXkgYXJvdW5kIHdpdGggZGlmZmVyZW50IHNldHRpbmdzIGFuZCBjaGVjayBvdXQgdGhlCnJlc3VsdHMuCgojIyMgSW5zdGFudGFuZW91cyBwb3B1bGF0aW9uIHNpemUgY2hhbmdlcwoKUGFzdCBjaGFuZ2VzIGluIHRoZSBwb3B1bGF0aW9ucyBhcmUgY29udHJvbGxlZCBieSB2YWx1ZXMgb2YgYC1lU29tZXRoaW5nYCBvcHRpb25zLiAgV2hlcmUKdGhlIGUgc3RhbmRzIGZvciBldmVudC4gIFRoZSBzaW1wbGVzdCBvZiB0aGVzZSBhcmUgaW5zdGFudGFuZW91cyBjaGFuZ2VzIGluIHBvcHVsYXRpb24Kc2l6ZS4gIFRoZSBzaW1wbGVzdCBpczoKCiogYC1lbiB0IGkgeGAgd2hpY2ggbWVhbnMgIlNldCBzdWJwb3AgJGkkIHNpemUgdG8gJHggXHRpbWVzIE5fMCQgYXQgdGltZSAkdCQgYW5kIGdyb3d0aCByYXRlIHRvIHplcm8uCgpTbywgZm9yIGV4YW1wbGUsIGluIG91ciBtaWdyYXRpb24gbW9kZWwgYWJvdmUgd2UgY291bGQgbWFrZSB0aGUgdHdvIHBvcHVsYXRpb25zIHZlcnkgZGlmZmVyZW50IHNpemVzCmFuZCBzZWUgd2hhdCB0aGUgcmVzdWx0cyBhcmUuICBMZXQncyBtYWtlIHBvcHVsYXRpb24gMiB0ZW4gdGltZXMgYmlnZ2VyIHRoYW4gcG9wdWxhdGlvbiAxIGZyb20KdGhlIHByZXNlbnQgYWxsIHRoZSB3YXkgYmFjayBpbnRvIHRoZSBwYXN0Li4uCmBgYHtyfQpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIyMCA2IC1UIC1JIDIgMTAgMTAgMC4wMSAtZW4gMCAyIDEwIiwgc3Rkb3V0ID0gIm91dC50cmVlIiwgc3RkZXJyID0gRkFMU0UpCmN0cmVlIDwtIHJlYWQudHJlZSgib3V0LnRyZWUiKQpuYW1lcyhjdHJlZSkgPC0gMTo2CmdndHJlZShjdHJlZSwgbGF5b3V0ID0gInJlY3Rhbmd1bGFyIikgKwogIGZhY2V0X3dyYXAofi5pZCwgbmNvbCAgPSAzKSArCiAgZ2VvbV90aXBsYWIoc2l6ZSA9IDIpCmBgYAoKQWhhISBUaGF0IGlzIGludGVyZXN0aW5nLiAgSXQgaXMgaGFyZCB0byB0ZWxsLCBiZWNhdXNlIHRoZSBjb2FsZXNjZW5jZSB0aW1lcyBhcmUgc28gc2hvcnQgaW4gcG9wdWxhdGlvbgoxLCBidXQgaWYgeW91IHNxdWludCwgeW91IGNhbiBjb252aW5jZSB5b3Vyc2VsZiB0aGF0LCBvbiBhdmVyYWdlLCB0aGUgdHJlZXMgaW4gcG9wdWxhdGlvbiAyIHJlYWNoIAphIE1SQ0EgaW4gYWJvdXQgMTAgdGltZXMgdGhlIGFtb3VudCBvZiB0aW1lIGFzIHRoZSB0cmVlcyBpbiBwb3B1bGF0aW9uIDEuCgpUaGUgcmVzdWx0cyBhbHNvIHNob3cgdGhhdCB0aGVyZSBpcyBhIGxvdCBvZiB2YXJpYWJpbGl0eSBpbiB0aGUgY29hbGVzY2VudCBwcm9jZXNzLgoKCgoKIyMjIFBvcHVsYXRpb24gU3BsaXR0aW5nL01lcmdpbmcKCk15IGdvb2RuZXNzLCB0aGVyZSBhcmUgYSBsb3Qgb2Ygb3B0aW9ucyBpbiBgbXNgLiAgVG8gc2VlIHRoZSBmdWxsIHJ1bmRvd24gb24gYWxsIHRoZSBvcHRpb25zLAp5b3UgY2FuIHJlYWQgdGhlIGZ1bGwgZG9jdW1lbnRhdGlvbjogW21zZG9jLnBkZl0oaHR0cHM6Ly9lcmlxYW5kZS5naXRodWIuaW8vY29hbGVzY2VudC1oYW5kcy1vbi9tc2RvYy5wZGYpLiAgQnV0IGZvciBub3csIHdlIHdpbGwKanVzdCBkaXNjdXNzIG9uZSBtb3JlLCB1c2VkIHRvIGpvaW4gb3Igc3BsaXQgdHdvIHBvcHVsYXRpb25zIGdvaW5nIGJhY2sgaW4gdGltZS4KCiogYC1laiB0IGkgamAgd2hpY2ggbWVhbnMgbW92ZSBhbGwgbGluZWFnZXMgaW4gc3VicG9wdWxhdGlvbiAkaSQgaW50byBzdWJwb3B1bGF0aW9uICRqJCBhdCB0aW1lICR0JAppbiB1bml0cyBvZiAkNE5fMCQuICBUaGUgYGpgIG1lYW5zICJqb2luIi4gIEl0IGNvcnJlc3BvbmRzIHRvIHBvcHVsYXRpb25zICJqb2luaW5nIiB3aGlsZSBnb2luZwpiYWNrd2FyZCBpbiB0aW1lLiAgQnV0LCBfZm9yd2FyZCBpbiB0aW1lXyB0aGlzIGNvcnJlc3BvbmRzIHRvIHBvcHVsYXRpb24gX3NwbGl0dGluZ18uXAoKKiBgLWVzIHQgaSBwYCB3aGljaCBtZWFucyBzcGxpdCBzdWJwb3B1bGF0aW9uICRpJCBpbnRvIHR3byBzdWJwb3B1bGF0aW9ucyAkaSQgYW5kICRucG9wICsgMSQgJHQkCihpbiB1bml0cyBvZiAkNE5fMCQpLiBMaW5lYWdlcyBjdXJyZW50bHkgaW4gJGkkIHJlbWFpbiBpbiAkaSQgd2l0aCBwcm9iYWJpbGl0eSAkcCQgYW5kCndpdGggcHJvYmFiaWxpdHkgJDEtcCQgdGhleSBnZXQgcGxhY2VkIGludG8gc3VicG9wdWxhdGlvbiAkbnBvcCArIDEkLiBUaGUgYHNgIG1lYW5zIHNwbGl0LiAgCkl0IGNvcnJlc3BvbmRzIHRvIHBvcHVsYXRpb25zICJqb2luaW5nIiB3aGlsZSBnb2luZyBmb3J3YXJkIGluIHRpbWUuCgoqKkRpc2N1c3Mgd2l0aCB5b3VyIHBhcnRuZXIqKjogV2hhdCBhcmUgc29tZSBjb25zZXJ2YXRpb24tZ2VuZXRpYyBzY2VuYXJpb3MgdGhhdAp0aGVzZSBsYXN0IHR3byBkZW1vZ3JhcGhpYyBzY2VuYXJpb3MgbWlnaHQgY29ycmVzcG9uZCB0bz8KCkhlcmUgaXMgYW4gZXhhbXBsZSBvZiBhIHBvcHVsYXRpb24gam9pbiBnb2luZyBiYWNrIGluIHRpbWUuICBXZSBoYXZlIDEwIHNhbXBsZXMgZnJvbQplYWNoIHBvcHVsYXRpb24gd2l0aCBubyBtaWdyYXRpb24gYmV0d2VlbiB0aGVtLCBhbmQgdGhlIHBvcHVsYXRpb25zIGpvaW4gYXQgdGltZSAkMk5fMCQgaW4gdGhlIApwYXN0IChhdCB3aGljaCBwb2ludCBtb3N0IHdpbGwgaGF2ZSBjb2FsZXNjZWQgd2l0aGluIHN1YnBvcHVsYXRpb25zKToKCmBgYHtyfQpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIyMCA2IC1UIC1JIDIgMTAgMTAgMC4wMCAtZWogMC41IDEgMiIsIHN0ZG91dCA9ICJvdXQudHJlZSIsIHN0ZGVyciA9IEZBTFNFKQpjdHJlZSA8LSByZWFkLnRyZWUoIm91dC50cmVlIikKbmFtZXMoY3RyZWUpIDwtIDE6NgpnZ3RyZWUoY3RyZWUsIGxheW91dCA9ICJyZWN0YW5ndWxhciIpICsKICBmYWNldF93cmFwKH4uaWQsIG5jb2wgID0gMykgKwogIGdlb21fdGlwbGFiKHNpemUgPSAyKQpgYGAKCiMjIFlvdXIgTWlzc2lvbi9Ib21ld29yayEKCkFsbCByaWdodCwgYWZ0ZXIgcGxheWluZyBhcm91bmQgd2l0aCBhbGwgdGhlIGFib3ZlLCBsb29rIGF0IHRoZSB0cmVlIGJlbG93IGFuZCwgd2l0aCB5b3VyCmdyb3VwOgoKMS4gdGhpbmsgYWJvdXQgYW5kIGRpc2N1c3Mgd2hhdCB0aGUgZGVtb2dyYXBoeSBtaWdodCBoYXZlIGxvb2tlZCBsaWtlIHRvIHByb2R1Y2UgdGhlIHRyZWUuClRoaW5rIGFib3V0IGhvdyBkaWZmZXJlbnQgcG9wdWxhdGlvbiBzaXplcyBtdXN0IGhhdmUgYmVlbiBhbmQgYXQgd2hpY2ggdGltZSBwZXJpb2RzIHBvcHVsYXRpb24Kc2l6ZSBjaGFuZ2VzIG1pZ2h0IGhhdmUgaGFwcGVuZWQuICAKCjIuIENoZWNrIHlvdXIgaHlwb3RoZXNlcyBieSBnZW5lcmF0aW5nIHNvbWUgdHJlZXMgd2l0aCBgbXNgLgoKCkhlcmUgaXMgYSBoaW50LiAgVG8gbWFrZSB0aGUgdHJlZXMgYmVsb3csIEkgZGlkbid0IGJvdGhlciB3aXRoIGV4cG9uZW50aWFsCmdyb3d0aCwgSSBqdXN0IHVzZWQgKHF1aXRlIHVucmVhbGlzdGljKSBpbnN0YW50YW5lb3VzIHBvcHVsYXRpb24gc2l6ZSBjaGFuZ2VzLgoKYGBge3IsIGVjaG89RkFMU0V9CiMgVHdvIHN1YnBvcHVsYXRpb25zLiAgVGhlIGZpcnN0IG9uZSBvZiBzaXplIE4wLiAgV2Ugd2FudCB0byBleHBlY3QKIyBUTVJDQSBmb3IgdGhhdCBvbmUgdG8gYmUgWCA9IDROMC4gIEZvciBzdWJwb3AgMiB3ZSB3YW50IHRvIGV4cGVjdCBvbmx5CiMgb25lIGNvYWxlc2NlbmNlIGJ5IDVYLiAgMTAgbGluZWFnZXMgaW4gZWFjaCBzdWJwb3B1bGF0aW9uLCBzbyBuKG4tMSkgaXMKIyA5MC4gIFRoYXQgbWVhbnMgc3VicG9wIDIgbXVzdCBiZSA0NTAgdGltZXMgYmlnZ2VyIHRoYW4gc3VicG9wIDEuICBBdCB0aW1lCiMgNVggd2Ugam9pbiBzdWJwb3BzIDEgYW5kIDIsIGFuZCBzZXQgdGhlIHNpemUgb2YgdGhlIG1lcmdlZCBwb3B1bGF0aW9uIHRvCiMgTjAgc28gd2UgaGF2ZSB0aGUgc2FtZSBleHBlY3RlZCB0aW1lIHRvIE1SQ0EgYXMgd2UgZGlkIHdpdGggc3VicG9wIDEgaW4gdGhlCiMgYmVnaW5uaW5nLgpzeXN0ZW0yKGNvbW1hbmQgPSBtc19iaW5hcnkoKSwgYXJncyA9ICIyMCA2IC1UIC1JIDIgMTAgMTAgMC4wMCAtZW4gMCAyIDQ1MCAtZWogMjAgMiAxIC1lbiAyMC4wMDEgMSAxICAiLCBzdGRvdXQgPSAib3V0LnRyZWUiLCBzdGRlcnIgPSBGQUxTRSkKY3RyZWUgPC0gcmVhZC50cmVlKCJvdXQudHJlZSIpCm5hbWVzKGN0cmVlKSA8LSAxOjYKZ2d0cmVlKGN0cmVlLCBsYXlvdXQgPSAicmVjdGFuZ3VsYXIiKSArCiAgZmFjZXRfd3JhcCh+LmlkLCBuY29sICA9IDMpICsKICBnZW9tX3RpcGxhYihzaXplID0gMikKYGBgCgoKCgojIyBSZWZlcmVuY2VzCgoK