In lab exercise

For the in lab exercise we’ll use results derived from. two data sets that are relatively small, 200 individuals and 100 loci. The relatively small number of loci will allow you to analyze the data yourself using Structure if you’re interested in doing so. See the notes at the bottom of this notebook if you’re interested in doing that.

Running Structure Harvester

As you’ll recall from lecture, one thing you’ll need to do is to decide on the K that best describes the structure in your data, recalling that there might not be a single “best” K. There might be a range of them. The easiest way to produce the log probability of the data plot that we’ll use for picking K is to use Structure Harvester, a web application hosted at UCLA. Using it is very simple. Just click on the link, click on the “Choose file” button and navigate to the ZIP file that includes the Structure results, hit the blue “Harvest!” button, wait a little while, and you’ll get a the log proability of the data plat that we’re interested in. You can save the file to a PDF by clicking on the PDF link at the lower left of the plot. You’ll want to save that file in the same directory where you’re writing the R notebook you’ll be using for the lab exercise.

Running CLUMPPAK

To get the barplots of Structure plots point your browser of choice to the CLUMPPAK server. The CLUMMPAK server provides a lot of options, but we’ll use the main pipeline for our analyses. Once you’re there, scroll down to “Run Main Pipeline”, push the “Choose file” option and pick the ZIP file you want to analyze. Then scroll down a bit further and enter your email address. In 10-15 minutes, maybe less, you should receive an email with a link to view results of the analysis. When you follow that link there will be two file links on the page that you visit. One is a summary PDF and one is a ZIP file. We won’t bother with the ZIP file. Just download the PDF and save it in the same directory where you saved the PDF from Structure Harvester. This PDF will show you Structure plots for each of the Ks included in your analysis.1

Suggestions for the lab exercise

For the lab exercise, download the following two ZIP files and put them on you computer somewhere where you can find them. A good approach might be to create a directory somewhere called “Structure-Lab” and put them in there.

Once you’ve got the files there, run analyses for both files in Structure Harvester and CLUMPPAK. In discussing the results you get, you’ll want to know that:

  • These are simulated data, and the simulations included the same number of actual populations, the same population size in every population, and the same mutation rate at every locus in both cases. They differ only in that the data set that begins with m-0.1 had less migration among populations that the one that begins m-0.2.
  • The actual number of populations is the same as the number of populations included in the sample.
  • You might (or might not) also find it helpful to use adegenet to convert the Structure format file into a format that hierfstat can use to estimate FST. Comparing the F-statistics for the two data sets could be informative. If you use hierfstat, you’ll need to know that there are 200 (individuals), 100 markers (loci), column 1 contains the labels for genotypes (individuals), column 2 contains the population factor (the population/locality from which a particular sample was collected), there are no optional columns, there isn’t a row with marker names, and genotypes are coded in two rows.^[Don’t be frightened when you get the following warning message:
In df2genind(X = X, pop = pop, ploidy = 2, sep = sep, ncode = ncode) :
  duplicate labels detected for some individuals; using generic labels

That happens because individuals in different populations have the same label, e.g., there’s an Ind-3 in every population, and the same is true for every individual label within a population. ]

One more thing

When you turn in your project to Nick, you’ll want to include the figures that support your conclusions. You have two choices in how to do that:

  1. The easiest is to give your PDFs an informative name like low-migration-Structure-Harvester.pdf and send the four PDFs to Nick along with your R notebook for the project. You can pick any name that you want, so long as all four PDFs have different names and you tell Nick which file corresponds to which result.

  2. The slightly more difficult, but more elegant, approach is to embed your figures in your R notebook. That’s easier than it sounds. Simply make sure that your R notebook is in the same directory as your figures and include code that looks like this in your R notebook.

![Low migration Structure Harvester results](low-migration-Structure-Harvester.pdf)

The part in square brackets is the text that will appear in the HTML (or the preview in R Studio). The part in parentheses is the name of the file to embed.

Project #1

For Project #1 you’ll repeat exactly what you did in the lab exercise, except that you’ll use two different data sets:

These data sets were generated under precisely the same set of conditions as the two data sets you looked at in lab, except that the sample includes data from 1000 loci in each case instead of only 100. Using results from your analyses of these two data sets answer the following questions:

  1. What K (or Ks) do you think best reflect the structure in each of the data sets?

  2. What do these results tell you about the genetic structure of the underlying population? To make that question a bit more explicit: Structure identifies genetic clusters in the data it analyzes. I’m asking you what can you infer about genetic clusters in the populations from which the data were collected based on the clusters Structure identified in the data.2 You might find it useful to think about how estimates of \(F_{ST}\) differ when the different data sets are used.

  3. I told you that there is more migration, i.e., gene exchange, among populations in the m-0.2 data set than in the m-0.1 data set. How might this help you understand any differences between your results for the two data sets?3

  4. The only difference between the data sets you explored in lab and those that you analzed for this project is that those you explored for this project each had 1000 loci rather than 100 loci. Obviously, more loci means more data, but what does this comparison suggest about how you should approach interpreting the results of Structure analyses?

Generating the results you used in lab

Before you can run the lab exercise, you’ll need to download and install two things:

  1. Structure: The underlying software that will run the analysis.
  2. ParallelStructure: An R package that is a convenient way to run Structure.

Installing Structure

The instructions for installing Structure depend on whether you are running on Windows or on Mac OS X.

Installing Structure on Windows4

Nick is running a Windows machine. If you have problems with installation, he should be able to help you, but installation should be very straightforward. Simply click on the link to download Structure for Windows XP/Vista/Windows 7[^As you can tell from those version numbers, the softward hasn’t been updated in a while.] under “Download package with graphical front end.” Once you’ve done that, simply find the installation package, double click on it, and follow any instructions. You should be all set.

Installing Structure on macOS

The approach I just described should work on macOS, but I haven’t been able to get it to.5 What I did manage to do is to download the C source code and compile it on my MacBook Pro. I’ve uploaded a disk image to the course website. Once you’ve clicked on the link, wait for the disk image to download, open it, and drag the folder called “Structure” to your “Applications” directory.6 Once you’ve done that, you should be all set.

Installing ParallelStructure

Installing ParallelStructure is done in a slightly different way than installing a standard R package. Here’s how you do it:

install.packages("ParallelStructure", repos = "http://R-Forge.R-project.org")

The only difference from the usual approach is specifying a specific repository at R Forge.

Running Structure

Now that you have Structure and ParallelStructure you’re ready to try them out. For the lab exercise, download the following two files and save them somewhere that you can find them:

In addition, download the following file and put it in the same directory as the files you just downloaded:

Once you’ve done that, start up R Studio and use “Session -> Set Working Directory -> Choose Directory” to select the directory in which you saved the files. Now you’re ready to run the analysis using data from the first file, m-0.1-0.01-100-loci.stru:

NOTE: ParallelStructure doesn’t seem to work properly from an R notebook. You’ll need to copy the code below into a console window and run it from there.

FURTHER NOTE: If you’re running Windows, it’s easier to use the graphical interface. Nick can show you how. If you think you’ll use Structure in. the future, though, it’s worth figuring out how to run ParallelStructure, since it will be very helpful with real data sets that you analyze on a computational cluster.

library(ParallelStructure)

## for macOS: If you're running Windows, comment out the definition of architecture for
## macOS and uncomment the definition for Windows
##
architecture <- "macOS"
## for Windows
##
## architecture <- "Windows"

if (architecture == "macOS") {
  my_path <- "/Applications/Structure/"
} else if (architecture == "Windows") {
  my_path <- ""
} else {
  stop("Architecture not recognized.")
}

## Use parallel_structure() to run the analysis
##
parallel_structure(structure_path = my_path,
                   joblist = "joblist.txt",
                   n_cpu = 4,
                   infile = "m-0.2-100-loci.stru",
                   outpath = "",
                   numinds = 20*10,
                   numloci = 100,
                   printqhat = 0,
                   plot_output = 0)

## You don't need any of this code, since it simply produces the log probability of data
## plot that StructureHarvester produces, but you might find it useful to have around.
## NOTE: This code won't work with results from the Structure GUI on Windows. It assumes that
## you've run the parallel_structure() code and that the CSV file with results are in the 
## directory where you're working.
##
# library(tidyverse)
# library(ggplot2)
# 
# path <- ""
# results <- read_csv(paste(path, "results_summary.csv", sep = ""),
#                     skip = 1, 
#                     col_select = c(k, ln_prob_data),
#                     show_col_types = FALSE) %>%
#   group_by(k) %>%
#   summarize(mean_ln_prob_data = mean(ln_prob_data),
#             sd_ln_prob_data = sd(ln_prob_data),
#             lo = mean_ln_prob_data - 2*sd_ln_prob_data,
#             hi = mean_ln_prob_data + 2*sd_ln_prob_data)
# p <- ggplot(results, aes(x = k, y = mean_ln_prob_data,
#                          ymin = lo, ymax = hi)) +
#   geom_point(size = 3) +
#   geom_line() +
#   geom_errorbar(width = 0.2) +
#   theme_bw() +
#   xlab("K") +
#   ylab("Mean log probability of data")
# p
# ggsave(paste(path, "ln_prob_of_data.pdf", sep = ""))

That code runs for about 30 minutes on my MacBook Pro. When it finishes, you’ll see a bunch of new files in the directory where you have the data. Put all of the results_job_*f files into a ZIP file and you’ll be where we started the lab exercise and assignment.


  1. It will actually show you a bit more than that. Nick will explain it during lab.↩︎

  2. This is analogous to asking what you can infer about \(F_{ST\) in a set of populations from the estimate of \(F_{ST}\) from a set of data.↩︎

  3. Remember, the simulations that produced these results had the same number of populations and the same size for every population when I produced both data sets.↩︎

  4. This approach should work on Linux too, but I haven’t tried it in several years.↩︎

  5. It’s probably related to how old the software on the Structure page is.↩︎

  6. You’ll find a link to the Applications directory in the disk image. You can simply drag it there.↩︎

LS0tCnRpdGxlOiAiRXZhbHVhdGluZyBwb3B1bGF0aW9uIHN0cnVjdHVyZSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBJbiBsYWIgZXhlcmNpc2UKCkZvciB0aGUgaW4gbGFiIGV4ZXJjaXNlIHdlJ2xsIHVzZSByZXN1bHRzIGRlcml2ZWQgZnJvbS4gdHdvIGRhdGEgc2V0cyB0aGF0IGFyZSByZWxhdGl2ZWx5IHNtYWxsLCAyMDAgaW5kaXZpZHVhbHMgYW5kIDEwMCBsb2NpLiBUaGUgcmVsYXRpdmVseSBzbWFsbCBudW1iZXIgb2YgbG9jaSB3aWxsIGFsbG93IHlvdSB0byBhbmFseXplIHRoZSBkYXRhIHlvdXJzZWxmIHVzaW5nIGBTdHJ1Y3R1cmVgIGlmIHlvdSdyZSBpbnRlcmVzdGVkIGluIGRvaW5nIHNvLiBTZWUgdGhlIG5vdGVzIGF0IHRoZSBib3R0b20gb2YgdGhpcyBub3RlYm9vayBpZiB5b3UncmUgaW50ZXJlc3RlZCBpbiBkb2luZyB0aGF0LgoKIyMgUnVubmluZyBTdHJ1Y3R1cmUgSGFydmVzdGVyCgpBcyB5b3UnbGwgcmVjYWxsIGZyb20gbGVjdHVyZSwgb25lIHRoaW5nIHlvdSdsbCBuZWVkIHRvIGRvIGlzIHRvIGRlY2lkZSBvbiB0aGUgYEtgIHRoYXQgYmVzdCBkZXNjcmliZXMgdGhlIHN0cnVjdHVyZSBpbiB5b3VyIGRhdGEsIHJlY2FsbGluZyB0aGF0IHRoZXJlIG1pZ2h0IG5vdCBiZSBhIHNpbmdsZSAiYmVzdCIgYEtgLiBUaGVyZSBtaWdodCBiZSBhIHJhbmdlIG9mIHRoZW0uIFRoZSBlYXNpZXN0IHdheSB0byBwcm9kdWNlIHRoZSBsb2cgcHJvYmFiaWxpdHkgb2YgdGhlIGRhdGEgcGxvdCB0aGF0IHdlJ2xsIHVzZSBmb3IgcGlja2luZyBgS2AgaXMgdG8gdXNlIFtTdHJ1Y3R1cmUgSGFydmVzdGVyXShodHRwczovL3RheWxvcjAuYmlvbG9neS51Y2xhLmVkdS9zdHJ1Y3R1cmVIYXJ2ZXN0ZXIvKSwgYSB3ZWIgYXBwbGljYXRpb24gaG9zdGVkIGF0IFVDTEEuIFVzaW5nIGl0IGlzIHZlcnkgc2ltcGxlLiBKdXN0IGNsaWNrIG9uIHRoZSBsaW5rLCBjbGljayBvbiB0aGUgIkNob29zZSBmaWxlIiBidXR0b24gYW5kIG5hdmlnYXRlIHRvIHRoZSBaSVAgZmlsZSB0aGF0IGluY2x1ZGVzIHRoZSBgU3RydWN0dXJlYCByZXN1bHRzLCBoaXQgdGhlIGJsdWUgIkhhcnZlc3QhIiBidXR0b24sIHdhaXQgYSBsaXR0bGUgd2hpbGUsIGFuZCB5b3UnbGwgZ2V0IGEgdGhlIGxvZyBwcm9hYmlsaXR5IG9mIHRoZSBkYXRhIHBsYXQgdGhhdCB3ZSdyZSBpbnRlcmVzdGVkIGluLiBZb3UgY2FuIHNhdmUgdGhlIGZpbGUgdG8gYSBQREYgYnkgY2xpY2tpbmcgb24gdGhlIFBERiBsaW5rIGF0IHRoZSBsb3dlciBsZWZ0IG9mIHRoZSBwbG90LiBZb3UnbGwgd2FudCB0byBzYXZlIHRoYXQgZmlsZSBpbiB0aGUgc2FtZSBkaXJlY3Rvcnkgd2hlcmUgeW91J3JlIHdyaXRpbmcgdGhlIGBSYCBub3RlYm9vayB5b3UnbGwgYmUgdXNpbmcgZm9yIHRoZSBsYWIgZXhlcmNpc2UuIAoKIyMgUnVubmluZyBDTFVNUFBBSwoKVG8gZ2V0IHRoZSBiYXJwbG90cyBvZiBgU3RydWN0dXJlYCBwbG90cyBwb2ludCB5b3VyIGJyb3dzZXIgb2YgY2hvaWNlIHRvIHRoZSBbYENMVU1QUEFLYCBzZXJ2ZXJdKGh0dHBzOi8vY2x1bXBhay50YXUuYWMuaWwvKS4gVGhlIGBDTFVNTVBBS2Agc2VydmVyIHByb3ZpZGVzIGEgbG90IG9mIG9wdGlvbnMsIGJ1dCB3ZSdsbCB1c2UgdGhlIG1haW4gcGlwZWxpbmUgZm9yIG91ciBhbmFseXNlcy4gT25jZSB5b3UncmUgdGhlcmUsIHNjcm9sbCBkb3duIHRvICJSdW4gTWFpbiBQaXBlbGluZSIsIHB1c2ggdGhlICJDaG9vc2UgZmlsZSIgb3B0aW9uIGFuZCBwaWNrIHRoZSBaSVAgZmlsZSB5b3Ugd2FudCB0byBhbmFseXplLiBUaGVuIHNjcm9sbCBkb3duIGEgYml0IGZ1cnRoZXIgYW5kIGVudGVyIHlvdXIgZW1haWwgYWRkcmVzcy4gSW4gMTAtMTUgbWludXRlcywgbWF5YmUgbGVzcywgeW91IHNob3VsZCByZWNlaXZlIGFuIGVtYWlsIHdpdGggYSBsaW5rIHRvIHZpZXcgcmVzdWx0cyBvZiB0aGUgYW5hbHlzaXMuIFdoZW4geW91IGZvbGxvdyB0aGF0IGxpbmsgdGhlcmUgd2lsbCBiZSB0d28gZmlsZSBsaW5rcyBvbiB0aGUgcGFnZSB0aGF0IHlvdSB2aXNpdC4gT25lIGlzIGEgc3VtbWFyeSBQREYgYW5kIG9uZSBpcyBhIFpJUCBmaWxlLiBXZSB3b24ndCBib3RoZXIgd2l0aCB0aGUgWklQIGZpbGUuIEp1c3QgZG93bmxvYWQgdGhlIFBERiBhbmQgc2F2ZSBpdCBpbiB0aGUgc2FtZSBkaXJlY3Rvcnkgd2hlcmUgeW91IHNhdmVkIHRoZSBQREYgZnJvbSBgU3RydWN0dXJlIEhhcnZlc3RlcmAuIFRoaXMgUERGIHdpbGwgc2hvdyB5b3UgYFN0cnVjdHVyZWAgcGxvdHMgZm9yIGVhY2ggb2YgdGhlIGBLYHMgaW5jbHVkZWQgaW4geW91ciBhbmFseXNpcy5eW0l0IHdpbGwgYWN0dWFsbHkgc2hvdyB5b3UgYSBiaXQgbW9yZSB0aGFuIHRoYXQuIE5pY2sgd2lsbCBleHBsYWluIGl0IGR1cmluZyBsYWIuXQoKIyMgU3VnZ2VzdGlvbnMgZm9yIHRoZSBsYWIgZXhlcmNpc2UKCkZvciB0aGUgbGFiIGV4ZXJjaXNlLCBkb3dubG9hZCB0aGUgZm9sbG93aW5nIHR3byBaSVAgZmlsZXMgYW5kIHB1dCB0aGVtIG9uIHlvdSBjb21wdXRlciBzb21ld2hlcmUgd2hlcmUgeW91IGNhbiBmaW5kIHRoZW0uIEEgZ29vZCBhcHByb2FjaCBtaWdodCBiZSB0byBjcmVhdGUgYSBkaXJlY3Rvcnkgc29tZXdoZXJlIGNhbGxlZCAiU3RydWN0dXJlLUxhYiIgYW5kIHB1dCB0aGVtIGluIHRoZXJlLiAKCi0gTG93IG1pZ3JhdGlvbjogW1pJUCBmaWxlXShodHRwOi8vZGFyd2luLmVlYi51Y29ubi5lZHUvZWViMzQ4LXJlc291cmNlcy9tLTAuMS0xMDAtbG9jaV9yZXN1bHRzLnppcCkgLSBbUmF3IFN0cnVjdHVyZSBkYXRhXShodHRwOi8vZGFyd2luLmVlYi51Y29ubi5lZHUvZWViMzQ4LXJlc291cmNlcy9tLTAuMS0xMDAtbG9jaS5zdHJ1KQotIEhpZ2ggbWlncmF0aW9uOiBbWklQIGZpbGVdKGh0dHA6Ly9kYXJ3aW4uZWViLnVjb25uLmVkdS9lZWIzNDgtcmVzb3VyY2VzL20tMC4yLTEwMC1sb2NpX3Jlc3VsdHMuemlwKSAtIFtSYXcgU3RydWN0dXJlIGRhdGFdKGh0dHA6Ly9kYXJ3aW4uZWViLnVjb25uLmVkdS9lZWIzNDgtcmVzb3VyY2VzL20tMC4yLTEwMC1sb2NpLnN0cnUpCgpPbmNlIHlvdSd2ZSBnb3QgdGhlIGZpbGVzIHRoZXJlLCBydW4gYW5hbHlzZXMgZm9yIGJvdGggZmlsZXMgaW4gYFN0cnVjdHVyZSBIYXJ2ZXN0ZXJgIGFuZCBgQ0xVTVBQQUtgLiBJbiBkaXNjdXNzaW5nIHRoZSByZXN1bHRzIHlvdSBnZXQsIHlvdSdsbCB3YW50IHRvIGtub3cgdGhhdDoKCi0gVGhlc2UgYXJlIHNpbXVsYXRlZCBkYXRhLCBhbmQgdGhlIHNpbXVsYXRpb25zIGluY2x1ZGVkIHRoZSBzYW1lIG51bWJlciBvZiBhY3R1YWwgcG9wdWxhdGlvbnMsIHRoZSBzYW1lIHBvcHVsYXRpb24gc2l6ZSBpbiBldmVyeSBwb3B1bGF0aW9uLCBhbmQgdGhlIHNhbWUgbXV0YXRpb24gcmF0ZSBhdCBldmVyeSBsb2N1cyBpbiBib3RoIGNhc2VzLiBUaGV5IGRpZmZlciBvbmx5IGluIHRoYXQgdGhlIGRhdGEgc2V0IHRoYXQgYmVnaW5zIHdpdGggYG0tMC4xYCBoYWQgbGVzcyBtaWdyYXRpb24gYW1vbmcgcG9wdWxhdGlvbnMgdGhhdCB0aGUgb25lIHRoYXQgYmVnaW5zIGBtLTAuMmAuCi0gVGhlIGFjdHVhbCBudW1iZXIgb2YgcG9wdWxhdGlvbnMgaXMgdGhlIHNhbWUgYXMgdGhlIG51bWJlciBvZiBwb3B1bGF0aW9ucyBpbmNsdWRlZCBpbiB0aGUgc2FtcGxlLgotIFlvdSBtaWdodCAob3IgbWlnaHQgbm90KSBhbHNvIGZpbmQgaXQgaGVscGZ1bCB0byB1c2UgYGFkZWdlbmV0YCB0byBjb252ZXJ0IHRoZSBgU3RydWN0dXJlYCBmb3JtYXQgZmlsZSBpbnRvIGEgZm9ybWF0IHRoYXQgYGhpZXJmc3RhdGAgY2FuIHVzZSB0byBlc3RpbWF0ZSA8ZW0+RjxzdWI+U1Q8L3N1Yj48L2VtPi4gQ29tcGFyaW5nIHRoZSA8ZW0+RjwvZW0+LXN0YXRpc3RpY3MgZm9yIHRoZSB0d28gZGF0YSBzZXRzIGNvdWxkIGJlIGluZm9ybWF0aXZlLiBJZiB5b3UgdXNlIGBoaWVyZnN0YXRgLCB5b3UnbGwgbmVlZCB0byBrbm93IHRoYXQgdGhlcmUgYXJlIDIwMCAoaW5kaXZpZHVhbHMpLCAxMDAgbWFya2VycyAobG9jaSksIGNvbHVtbiAxIGNvbnRhaW5zIHRoZSBsYWJlbHMgZm9yIGdlbm90eXBlcyAoaW5kaXZpZHVhbHMpLCBjb2x1bW4gMiBjb250YWlucyB0aGUgcG9wdWxhdGlvbiBmYWN0b3IgKHRoZSBwb3B1bGF0aW9uL2xvY2FsaXR5IGZyb20gd2hpY2ggYSBwYXJ0aWN1bGFyIHNhbXBsZSB3YXMgY29sbGVjdGVkKSwgdGhlcmUgYXJlIG5vIG9wdGlvbmFsIGNvbHVtbnMsIHRoZXJlIGlzbid0IGEgcm93IHdpdGggbWFya2VyIG5hbWVzLCBhbmQgZ2Vub3R5cGVzIGFyZSBjb2RlZCBpbiB0d28gcm93cy5eW0Rvbid0IGJlIGZyaWdodGVuZWQgd2hlbiB5b3UgZ2V0IHRoZSBmb2xsb3dpbmcgd2FybmluZyBtZXNzYWdlOgpgYGAKSW4gZGYyZ2VuaW5kKFggPSBYLCBwb3AgPSBwb3AsIHBsb2lkeSA9IDIsIHNlcCA9IHNlcCwgbmNvZGUgPSBuY29kZSkgOgogIGR1cGxpY2F0ZSBsYWJlbHMgZGV0ZWN0ZWQgZm9yIHNvbWUgaW5kaXZpZHVhbHM7IHVzaW5nIGdlbmVyaWMgbGFiZWxzCmBgYApUaGF0IGhhcHBlbnMgYmVjYXVzZSBpbmRpdmlkdWFscyBpbiBkaWZmZXJlbnQgcG9wdWxhdGlvbnMgaGF2ZSB0aGUgc2FtZSBsYWJlbCwgZS5nLiwgdGhlcmUncyBhbiBgSW5kLTNgIGluIGV2ZXJ5IHBvcHVsYXRpb24sIGFuZCB0aGUgc2FtZSBpcyB0cnVlIGZvciBldmVyeSBpbmRpdmlkdWFsIGxhYmVsIHdpdGhpbiBhIHBvcHVsYXRpb24uCl0KCiMjIE9uZSBtb3JlIHRoaW5nCgpXaGVuIHlvdSB0dXJuIGluIHlvdXIgcHJvamVjdCB0byBOaWNrLCB5b3UnbGwgd2FudCB0byBpbmNsdWRlIHRoZSBmaWd1cmVzIHRoYXQgc3VwcG9ydCB5b3VyIGNvbmNsdXNpb25zLiBZb3UgaGF2ZSB0d28gY2hvaWNlcyBpbiBob3cgdG8gZG8gdGhhdDoKCjEuIFRoZSBlYXNpZXN0IGlzIHRvIGdpdmUgeW91ciBQREZzIGFuIGluZm9ybWF0aXZlIG5hbWUgbGlrZSBgbG93LW1pZ3JhdGlvbi1TdHJ1Y3R1cmUtSGFydmVzdGVyLnBkZmAgYW5kIHNlbmQgdGhlIGZvdXIgUERGcyB0byBOaWNrIGFsb25nIHdpdGggeW91ciBgUmAgbm90ZWJvb2sgZm9yIHRoZSBwcm9qZWN0LiBZb3UgY2FuIHBpY2sgYW55IG5hbWUgdGhhdCB5b3Ugd2FudCwgc28gbG9uZyBhcyBhbGwgZm91ciBQREZzIGhhdmUgZGlmZmVyZW50IG5hbWVzIGFuZCB5b3UgdGVsbCBOaWNrIHdoaWNoIGZpbGUgY29ycmVzcG9uZHMgdG8gd2hpY2ggcmVzdWx0LgoKMi4gVGhlIHNsaWdodGx5IG1vcmUgZGlmZmljdWx0LCBidXQgbW9yZSBlbGVnYW50LCBhcHByb2FjaCBpcyB0byBlbWJlZCB5b3VyIGZpZ3VyZXMgaW4geW91ciBgUmAgbm90ZWJvb2suIFRoYXQncyBlYXNpZXIgdGhhbiBpdCBzb3VuZHMuIFNpbXBseSBtYWtlIHN1cmUgdGhhdCB5b3VyIGBSYCBub3RlYm9vayBpcyBpbiB0aGUgc2FtZSBkaXJlY3RvcnkgYXMgeW91ciBmaWd1cmVzIGFuZCBpbmNsdWRlIGNvZGUgdGhhdCBsb29rcyBsaWtlIHRoaXMgaW4geW91ciBgUmAgbm90ZWJvb2suCgpgYGAKIVtMb3cgbWlncmF0aW9uIFN0cnVjdHVyZSBIYXJ2ZXN0ZXIgcmVzdWx0c10obG93LW1pZ3JhdGlvbi1TdHJ1Y3R1cmUtSGFydmVzdGVyLnBkZikKYGBgClRoZSBwYXJ0IGluIHNxdWFyZSBicmFja2V0cyBpcyB0aGUgdGV4dCB0aGF0IHdpbGwgYXBwZWFyIGluIHRoZSBIVE1MIChvciB0aGUgcHJldmlldyBpbiBgUmAgU3R1ZGlvKS4gVGhlIHBhcnQgaW4gcGFyZW50aGVzZXMgaXMgdGhlIG5hbWUgb2YgdGhlIGZpbGUgdG8gZW1iZWQuCgojIFByb2plY3QgIzEKCkZvciBQcm9qZWN0ICMxIHlvdSdsbCByZXBlYXQgZXhhY3RseSB3aGF0IHlvdSBkaWQgaW4gdGhlIGxhYiBleGVyY2lzZSwgZXhjZXB0IHRoYXQgeW91J2xsIHVzZSB0d28gZGlmZmVyZW50IGRhdGEgc2V0czoKCi0gTG93IG1pZ3JhdGlvbjogW1pJUCBmaWxlXShodHRwOi8vZGFyd2luLmVlYi51Y29ubi5lZHUvZWViMzQ4LXJlc291cmNlcy9tLTAuMS0xMDAwLWxvY2lfcmVzdWx0cy56aXApIC0gW1JhdyBTdHJ1Y3R1cmUgZGF0YV0oaHR0cDovL2Rhcndpbi5lZWIudWNvbm4uZWR1L2VlYjM0OC1yZXNvdXJjZXMvbS0wLjEtMTAwMC1sb2NpLnN0cnUpCi0gSGlnaCBtaWdyYXRpb246IFtaSVAgZmlsZV0oaHR0cDovL2Rhcndpbi5lZWIudWNvbm4uZWR1L2VlYjM0OC1yZXNvdXJjZXMvbS0wLjItMTAwMC1sb2NpX3Jlc3VsdHMuemlwKSAtIFtSYXcgU3RydWN0dXJlIGRhdGFdKGh0dHA6Ly9kYXJ3aW4uZWViLnVjb25uLmVkdS9lZWIzNDgtcmVzb3VyY2VzL20tMC4yLTEwMDAtbG9jaS5zdHJ1KQoKVGhlc2UgZGF0YSBzZXRzIHdlcmUgZ2VuZXJhdGVkIHVuZGVyIHByZWNpc2VseSB0aGUgc2FtZSBzZXQgb2YgY29uZGl0aW9ucyBhcyB0aGUgdHdvIGRhdGEgc2V0cyB5b3UgbG9va2VkIGF0IGluIGxhYiwgZXhjZXB0IHRoYXQgdGhlIHNhbXBsZSBpbmNsdWRlcyBkYXRhIGZyb20gMTAwMCBsb2NpIGluIGVhY2ggY2FzZSBpbnN0ZWFkIG9mIG9ubHkgMTAwLiBVc2luZyByZXN1bHRzIGZyb20geW91ciBhbmFseXNlcyBvZiB0aGVzZSB0d28gZGF0YSBzZXRzIGFuc3dlciB0aGUgZm9sbG93aW5nIHF1ZXN0aW9uczoKCjEuIFdoYXQgYEtgIChvciBgS2BzKSBkbyB5b3UgdGhpbmsgYmVzdCByZWZsZWN0IHRoZSBzdHJ1Y3R1cmUgaW4gZWFjaCBvZiB0aGUgZGF0YSBzZXRzPyAKCjIuIFdoYXQgZG8gdGhlc2UgcmVzdWx0cyB0ZWxsIHlvdSBhYm91dCB0aGUgZ2VuZXRpYyBzdHJ1Y3R1cmUgb2YgdGhlIHVuZGVybHlpbmcgcG9wdWxhdGlvbj8gVG8gbWFrZSB0aGF0IHF1ZXN0aW9uIGEgYml0IG1vcmUgZXhwbGljaXQ6IGBTdHJ1Y3R1cmVgIGlkZW50aWZpZXMgZ2VuZXRpYyBjbHVzdGVycyAqaW4gdGhlIGRhdGEgaXQgYW5hbHl6ZXMqLiBJJ20gYXNraW5nIHlvdSB3aGF0IGNhbiB5b3UgaW5mZXIgYWJvdXQgZ2VuZXRpYyBjbHVzdGVycyAqaW4gdGhlIHBvcHVsYXRpb25zIGZyb20gd2hpY2ggdGhlIGRhdGEgd2VyZSBjb2xsZWN0ZWQqIGJhc2VkIG9uIHRoZSBjbHVzdGVycyBgU3RydWN0dXJlYCBpZGVudGlmaWVkIGluIHRoZSBkYXRhLl5bVGhpcyBpcyBhbmFsb2dvdXMgdG8gYXNraW5nIHdoYXQgeW91IGNhbiBpbmZlciBhYm91dCAkRl97U1QkIGluIGEgc2V0IG9mIHBvcHVsYXRpb25zIGZyb20gdGhlICplc3RpbWF0ZSogb2YgJEZfe1NUfSQgZnJvbSBhIHNldCBvZiBkYXRhLl0gWW91IG1pZ2h0IGZpbmQgaXQgdXNlZnVsIHRvIHRoaW5rIGFib3V0IGhvdyBlc3RpbWF0ZXMgb2YgJEZfe1NUfSQgZGlmZmVyIHdoZW4gdGhlIGRpZmZlcmVudCBkYXRhIHNldHMgYXJlIHVzZWQuCgozLiBJIHRvbGQgeW91IHRoYXQgdGhlcmUgaXMgbW9yZSBtaWdyYXRpb24sIGkuZS4sIGdlbmUgZXhjaGFuZ2UsIGFtb25nIHBvcHVsYXRpb25zIGluIHRoZSBgbS0wLjJgIGRhdGEgc2V0IHRoYW4gaW4gdGhlIGBtLTAuMWAgZGF0YSBzZXQuIEhvdyBtaWdodCB0aGlzIGhlbHAgeW91IHVuZGVyc3RhbmQgYW55IGRpZmZlcmVuY2VzIGJldHdlZW4geW91ciByZXN1bHRzIGZvciB0aGUgdHdvIGRhdGEgc2V0cz9eW1JlbWVtYmVyLCB0aGUgc2ltdWxhdGlvbnMgdGhhdCBwcm9kdWNlZCB0aGVzZSByZXN1bHRzIGhhZCB0aGUgc2FtZSBudW1iZXIgb2YgcG9wdWxhdGlvbnMgYW5kIHRoZSBzYW1lIHNpemUgZm9yIGV2ZXJ5IHBvcHVsYXRpb24gd2hlbiBJIHByb2R1Y2VkIGJvdGggZGF0YSBzZXRzLl0KCjQuIFRoZSBvbmx5IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgZGF0YSBzZXRzIHlvdSBleHBsb3JlZCBpbiBsYWIgYW5kIHRob3NlIHRoYXQgeW91IGFuYWx6ZWQgZm9yIHRoaXMgcHJvamVjdCBpcyB0aGF0IHRob3NlIHlvdSBleHBsb3JlZCBmb3IgdGhpcyBwcm9qZWN0IGVhY2ggaGFkIDEwMDAgbG9jaSByYXRoZXIgdGhhbiAxMDAgbG9jaS4gT2J2aW91c2x5LCBtb3JlIGxvY2kgbWVhbnMgbW9yZSBkYXRhLCBidXQgd2hhdCBkb2VzIHRoaXMgY29tcGFyaXNvbiBzdWdnZXN0IGFib3V0IGhvdyB5b3Ugc2hvdWxkIGFwcHJvYWNoIGludGVycHJldGluZyB0aGUgcmVzdWx0cyBvZiBgU3RydWN0dXJlYCBhbmFseXNlcz8KCgoKIyBHZW5lcmF0aW5nIHRoZSByZXN1bHRzIHlvdSB1c2VkIGluIGxhYgoKQmVmb3JlIHlvdSBjYW4gcnVuIHRoZSBsYWIgZXhlcmNpc2UsIHlvdSdsbCBuZWVkIHRvIGRvd25sb2FkIGFuZCBpbnN0YWxsIHR3byB0aGluZ3M6CgoxLiBgU3RydWN0dXJlYDogVGhlIHVuZGVybHlpbmcgc29mdHdhcmUgdGhhdCB3aWxsIHJ1biB0aGUgYW5hbHlzaXMuCjIuIGBQYXJhbGxlbFN0cnVjdHVyZWA6IEFuIGBSYCBwYWNrYWdlIHRoYXQgaXMgYSBjb252ZW5pZW50IHdheSB0byBydW4gPHR0PlN0cnVjdHVyZTwvdHQ+LgoKIyMgSW5zdGFsbGluZyBgU3RydWN0dXJlYAoKVGhlIGluc3RydWN0aW9ucyBmb3IgaW5zdGFsbGluZyBgU3RydWN0dXJlYCBkZXBlbmQgb24gd2hldGhlciB5b3UgYXJlIHJ1bm5pbmcgb24gV2luZG93cyBvciBvbiBNYWMgT1MgWC4KCiMjIyBJbnN0YWxsaW5nIGBTdHJ1Y3R1cmVgIG9uIFdpbmRvd3NeW1RoaXMgYXBwcm9hY2ggc2hvdWxkIHdvcmsgb24gTGludXggdG9vLCBidXQgSSBoYXZlbid0IHRyaWVkIGl0IGluIHNldmVyYWwgeWVhcnMuXQoKTmljayBpcyBydW5uaW5nIGEgV2luZG93cyBtYWNoaW5lLiBJZiB5b3UgaGF2ZSBwcm9ibGVtcyB3aXRoIGluc3RhbGxhdGlvbiwgaGUgc2hvdWxkIGJlIGFibGUgdG8gaGVscCB5b3UsIGJ1dCBpbnN0YWxsYXRpb24gc2hvdWxkIGJlIHZlcnkgc3RyYWlnaHRmb3J3YXJkLiBTaW1wbHkgY2xpY2sgb24gdGhlIGxpbmsgdG8gZG93bmxvYWQgPHR0PlN0cnVjdHVyZTwvdHQ+IGZvciBXaW5kb3dzIFhQL1Zpc3RhL1dpbmRvd3MgN1teQXMgeW91IGNhbiB0ZWxsIGZyb20gdGhvc2UgdmVyc2lvbiBudW1iZXJzLCB0aGUgc29mdHdhcmQgaGFzbid0IGJlZW4gdXBkYXRlZCBpbiBhIHdoaWxlLl0gdW5kZXIgIkRvd25sb2FkIHBhY2thZ2Ugd2l0aCBncmFwaGljYWwgZnJvbnQgZW5kLiIgT25jZSB5b3UndmUgZG9uZSB0aGF0LCBzaW1wbHkgZmluZCB0aGUgaW5zdGFsbGF0aW9uIHBhY2thZ2UsIGRvdWJsZSBjbGljayBvbiBpdCwgYW5kIGZvbGxvdyBhbnkgaW5zdHJ1Y3Rpb25zLiBZb3Ugc2hvdWxkIGJlIGFsbCBzZXQuCgojIyMgSW5zdGFsbGluZyBgU3RydWN0dXJlYCBvbiBtYWNPUwoKVGhlIGFwcHJvYWNoIEkganVzdCBkZXNjcmliZWQgKnNob3VsZCogd29yayBvbiBtYWNPUywgYnV0IEkgaGF2ZW4ndCBiZWVuIGFibGUgdG8gZ2V0IGl0IHRvLl5bSXQncyBwcm9iYWJseSByZWxhdGVkIHRvIGhvdyBvbGQgdGhlIHNvZnR3YXJlIG9uIHRoZSBgU3RydWN0dXJlYCBwYWdlIGlzLl0gV2hhdCBJIGRpZCBtYW5hZ2UgdG8gZG8gaXMgdG8gZG93bmxvYWQgdGhlIGBDYCBzb3VyY2UgY29kZSBhbmQgY29tcGlsZSBpdCBvbiBteSBNYWNCb29rIFByby4gSSd2ZSB1cGxvYWRlZCBhIFtkaXNrIGltYWdlXShodHRwOi8vZGFyd2luLmVlYi51Y29ubi5lZHUvZWViMzQ4LXJlc291cmNlcy9TdHJ1Y3R1cmUuZG1nKSB0byB0aGUgY291cnNlIHdlYnNpdGUuIE9uY2UgeW91J3ZlIGNsaWNrZWQgb24gdGhlIGxpbmssIHdhaXQgZm9yIHRoZSBkaXNrIGltYWdlIHRvIGRvd25sb2FkLCBvcGVuIGl0LCBhbmQgZHJhZyB0aGUgZm9sZGVyIGNhbGxlZCAiU3RydWN0dXJlIiB0byB5b3VyICJBcHBsaWNhdGlvbnMiIGRpcmVjdG9yeS5eW1lvdSdsbCBmaW5kIGEgbGluayB0byB0aGUgQXBwbGljYXRpb25zIGRpcmVjdG9yeSBpbiB0aGUgZGlzayBpbWFnZS4gWW91IGNhbiBzaW1wbHkgZHJhZyBpdCB0aGVyZS5dIE9uY2UgeW91J3ZlIGRvbmUgdGhhdCwgeW91IHNob3VsZCBiZSBhbGwgc2V0LgoKIyMjIEluc3RhbGxpbmcgYFBhcmFsbGVsU3RydWN0dXJlYAoKSW5zdGFsbGluZyBgUGFyYWxsZWxTdHJ1Y3R1cmVgIGlzIGRvbmUgaW4gYSBzbGlnaHRseSBkaWZmZXJlbnQgd2F5IHRoYW4gaW5zdGFsbGluZyBhIHN0YW5kYXJkIGBSYCBwYWNrYWdlLiBIZXJlJ3MgaG93IHlvdSBkbyBpdDoKCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCJQYXJhbGxlbFN0cnVjdHVyZSIsIHJlcG9zID0gImh0dHA6Ly9SLUZvcmdlLlItcHJvamVjdC5vcmciKQpgYGAKClRoZSBvbmx5IGRpZmZlcmVuY2UgZnJvbSB0aGUgdXN1YWwgYXBwcm9hY2ggaXMgc3BlY2lmeWluZyBhIHNwZWNpZmljIHJlcG9zaXRvcnkgYXQgYFJgIEZvcmdlLgoKIyMgUnVubmluZyBgU3RydWN0dXJlYAoKTm93IHRoYXQgeW91IGhhdmUgYFN0cnVjdHVyZWAgYW5kIGBQYXJhbGxlbFN0cnVjdHVyZWAgeW91J3JlIHJlYWR5IHRvIHRyeSB0aGVtIG91dC4gRm9yIHRoZSBsYWIgZXhlcmNpc2UsIGRvd25sb2FkIHRoZSBmb2xsb3dpbmcgdHdvIGZpbGVzIGFuZCBzYXZlIHRoZW0gc29tZXdoZXJlIHRoYXQgeW91IGNhbiBmaW5kIHRoZW06CgotIFttLTAuMS0wLjAxLTEwMC1sb2NpLnN0cnVdKGh0dHA6Ly9kYXJ3aW4uZWViLnVjb25uLmVkdS9lZWIzNDgtcmVzb3VyY2VzL20tMC4xLTAuMDEtMTAwLWxvY2kuc3RydSkKLSBbbS0wLjItMC4wMS0xMDAtbG9jaS5zdHJ1XShodHRwOi8vZGFyd2luLmVlYi51Y29ubi5lZHUvZWViMzQ4LXJlc291cmNlcy9tLTAuMi0wLjAxLTEwMC1sb2NpLnN0cnUpCgpJbiBhZGRpdGlvbiwgZG93bmxvYWQgdGhlIGZvbGxvd2luZyBmaWxlIGFuZCBwdXQgaXQgaW4gdGhlIHNhbWUgZGlyZWN0b3J5IGFzIHRoZSBmaWxlcyB5b3UganVzdCBkb3dubG9hZGVkOgoKLSBbam9ibGlzdC50eHRdKGh0dHA6Ly9kYXJ3aW4uZWViLnVjb25uLmVkdS9lZWIzNDgtcmVzb3VyY2VzL2pvYmxpc3QudHh0KQoKT25jZSB5b3UndmUgZG9uZSB0aGF0LCBzdGFydCB1cCBgUmAgU3R1ZGlvIGFuZCB1c2UgIlNlc3Npb24gLT4gU2V0IFdvcmtpbmcgRGlyZWN0b3J5IC0+IENob29zZSBEaXJlY3RvcnkiIHRvIHNlbGVjdCB0aGUgZGlyZWN0b3J5IGluIHdoaWNoIHlvdSBzYXZlZCB0aGUgZmlsZXMuIE5vdyB5b3UncmUgcmVhZHkgdG8gcnVuIHRoZSBhbmFseXNpcyB1c2luZyBkYXRhIGZyb20gdGhlIGZpcnN0IGZpbGUsIGBtLTAuMS0wLjAxLTEwMC1sb2NpLnN0cnVgOgoKKipOT1RFKio6IGBQYXJhbGxlbFN0cnVjdHVyZWAgZG9lc24ndCBzZWVtIHRvIHdvcmsgcHJvcGVybHkgZnJvbSBhbiBgUmAgbm90ZWJvb2suIFlvdSdsbCBuZWVkIHRvIGNvcHkgdGhlIGNvZGUgYmVsb3cgaW50byBhIGNvbnNvbGUgd2luZG93IGFuZCBydW4gaXQgZnJvbSB0aGVyZS4KCioqRlVSVEhFUiBOT1RFKio6IElmIHlvdSdyZSBydW5uaW5nIFdpbmRvd3MsIGl0J3MgZWFzaWVyIHRvIHVzZSB0aGUgZ3JhcGhpY2FsIGludGVyZmFjZS4gTmljayBjYW4gc2hvdyB5b3UgaG93LiBJZiB5b3UgdGhpbmsgeW91J2xsIHVzZSBgU3RydWN0dXJlYCBpbi4gdGhlIGZ1dHVyZSwgdGhvdWdoLCBpdCdzIHdvcnRoIGZpZ3VyaW5nIG91dCBob3cgdG8gcnVuIGBQYXJhbGxlbFN0cnVjdHVyZWAsIHNpbmNlIGl0IHdpbGwgYmUgdmVyeSBoZWxwZnVsIHdpdGggcmVhbCBkYXRhIHNldHMgdGhhdCB5b3UgYW5hbHl6ZSBvbiBhIGNvbXB1dGF0aW9uYWwgY2x1c3Rlci4KCmBgYHtyfQpsaWJyYXJ5KFBhcmFsbGVsU3RydWN0dXJlKQoKIyMgZm9yIG1hY09TOiBJZiB5b3UncmUgcnVubmluZyBXaW5kb3dzLCBjb21tZW50IG91dCB0aGUgZGVmaW5pdGlvbiBvZiBhcmNoaXRlY3R1cmUgZm9yCiMjIG1hY09TIGFuZCB1bmNvbW1lbnQgdGhlIGRlZmluaXRpb24gZm9yIFdpbmRvd3MKIyMKYXJjaGl0ZWN0dXJlIDwtICJtYWNPUyIKIyMgZm9yIFdpbmRvd3MKIyMKIyMgYXJjaGl0ZWN0dXJlIDwtICJXaW5kb3dzIgoKaWYgKGFyY2hpdGVjdHVyZSA9PSAibWFjT1MiKSB7CiAgbXlfcGF0aCA8LSAiL0FwcGxpY2F0aW9ucy9TdHJ1Y3R1cmUvIgp9IGVsc2UgaWYgKGFyY2hpdGVjdHVyZSA9PSAiV2luZG93cyIpIHsKICBteV9wYXRoIDwtICIiCn0gZWxzZSB7CiAgc3RvcCgiQXJjaGl0ZWN0dXJlIG5vdCByZWNvZ25pemVkLiIpCn0KCiMjIFVzZSBwYXJhbGxlbF9zdHJ1Y3R1cmUoKSB0byBydW4gdGhlIGFuYWx5c2lzCiMjCnBhcmFsbGVsX3N0cnVjdHVyZShzdHJ1Y3R1cmVfcGF0aCA9IG15X3BhdGgsCiAgICAgICAgICAgICAgICAgICBqb2JsaXN0ID0gImpvYmxpc3QudHh0IiwKICAgICAgICAgICAgICAgICAgIG5fY3B1ID0gNCwKICAgICAgICAgICAgICAgICAgIGluZmlsZSA9ICJtLTAuMi0xMDAtbG9jaS5zdHJ1IiwKICAgICAgICAgICAgICAgICAgIG91dHBhdGggPSAiIiwKICAgICAgICAgICAgICAgICAgIG51bWluZHMgPSAyMCoxMCwKICAgICAgICAgICAgICAgICAgIG51bWxvY2kgPSAxMDAsCiAgICAgICAgICAgICAgICAgICBwcmludHFoYXQgPSAwLAogICAgICAgICAgICAgICAgICAgcGxvdF9vdXRwdXQgPSAwKQoKIyMgWW91IGRvbid0IG5lZWQgYW55IG9mIHRoaXMgY29kZSwgc2luY2UgaXQgc2ltcGx5IHByb2R1Y2VzIHRoZSBsb2cgcHJvYmFiaWxpdHkgb2YgZGF0YQojIyBwbG90IHRoYXQgU3RydWN0dXJlSGFydmVzdGVyIHByb2R1Y2VzLCBidXQgeW91IG1pZ2h0IGZpbmQgaXQgdXNlZnVsIHRvIGhhdmUgYXJvdW5kLgojIyBOT1RFOiBUaGlzIGNvZGUgd29uJ3Qgd29yayB3aXRoIHJlc3VsdHMgZnJvbSB0aGUgU3RydWN0dXJlIEdVSSBvbiBXaW5kb3dzLiBJdCBhc3N1bWVzIHRoYXQKIyMgeW91J3ZlIHJ1biB0aGUgcGFyYWxsZWxfc3RydWN0dXJlKCkgY29kZSBhbmQgdGhhdCB0aGUgQ1NWIGZpbGUgd2l0aCByZXN1bHRzIGFyZSBpbiB0aGUgCiMjIGRpcmVjdG9yeSB3aGVyZSB5b3UncmUgd29ya2luZy4KIyMKIyBsaWJyYXJ5KHRpZHl2ZXJzZSkKIyBsaWJyYXJ5KGdncGxvdDIpCiMgCiMgcGF0aCA8LSAiIgojIHJlc3VsdHMgPC0gcmVhZF9jc3YocGFzdGUocGF0aCwgInJlc3VsdHNfc3VtbWFyeS5jc3YiLCBzZXAgPSAiIiksCiMgICAgICAgICAgICAgICAgICAgICBza2lwID0gMSwgCiMgICAgICAgICAgICAgICAgICAgICBjb2xfc2VsZWN0ID0gYyhrLCBsbl9wcm9iX2RhdGEpLAojICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2xfdHlwZXMgPSBGQUxTRSkgJT4lCiMgICBncm91cF9ieShrKSAlPiUKIyAgIHN1bW1hcml6ZShtZWFuX2xuX3Byb2JfZGF0YSA9IG1lYW4obG5fcHJvYl9kYXRhKSwKIyAgICAgICAgICAgICBzZF9sbl9wcm9iX2RhdGEgPSBzZChsbl9wcm9iX2RhdGEpLAojICAgICAgICAgICAgIGxvID0gbWVhbl9sbl9wcm9iX2RhdGEgLSAyKnNkX2xuX3Byb2JfZGF0YSwKIyAgICAgICAgICAgICBoaSA9IG1lYW5fbG5fcHJvYl9kYXRhICsgMipzZF9sbl9wcm9iX2RhdGEpCiMgcCA8LSBnZ3Bsb3QocmVzdWx0cywgYWVzKHggPSBrLCB5ID0gbWVhbl9sbl9wcm9iX2RhdGEsCiMgICAgICAgICAgICAgICAgICAgICAgICAgIHltaW4gPSBsbywgeW1heCA9IGhpKSkgKwojICAgZ2VvbV9wb2ludChzaXplID0gMykgKwojICAgZ2VvbV9saW5lKCkgKwojICAgZ2VvbV9lcnJvcmJhcih3aWR0aCA9IDAuMikgKwojICAgdGhlbWVfYncoKSArCiMgICB4bGFiKCJLIikgKwojICAgeWxhYigiTWVhbiBsb2cgcHJvYmFiaWxpdHkgb2YgZGF0YSIpCiMgcAojIGdnc2F2ZShwYXN0ZShwYXRoLCAibG5fcHJvYl9vZl9kYXRhLnBkZiIsIHNlcCA9ICIiKSkKYGBgClRoYXQgY29kZSBydW5zIGZvciBhYm91dCAzMCBtaW51dGVzIG9uIG15IE1hY0Jvb2sgUHJvLiBXaGVuIGl0IGZpbmlzaGVzLCB5b3UnbGwgc2VlIGEgYnVuY2ggb2YgbmV3IGZpbGVzIGluIHRoZSBkaXJlY3Rvcnkgd2hlcmUgeW91IGhhdmUgdGhlIGRhdGEuIFB1dCBhbGwgb2YgdGhlIGByZXN1bHRzX2pvYl8qZmAgZmlsZXMgaW50byBhIFpJUCBmaWxlIGFuZCB5b3UnbGwgYmUgd2hlcmUgd2Ugc3RhcnRlZCB0aGUgbGFiIGV4ZXJjaXNlIGFuZCBhc3NpZ25tZW50LiAKCg==