library(tidyr)
Warning messages:
1: The closing backticks on line 162 ("````") in morrisonkondaurova09-explorations-ky.Rmd do not match the opening backticks "```" on line 153. You are recommended to fix either the opening or closing delimiter of the code chunk to use exactly the same numbers of backticks and same level of indentation (or blockquote).
2: The closing backticks on line 162 ("````") in morrisonkondaurova09-explorations-ky.Rmd do not match the opening backticks "```" on line 153. You are recommended to fix either the opening or closing delimiter of the code chunk to use exactly the same numbers of backticks and same level of indentation (or blockquote).
3: The closing backticks on line 162 ("````") in morrisonkondaurova09-explorations-ky.Rmd do not match the opening backticks "```" on line 153. You are recommended to fix either the opening or closing delimiter of the code chunk to use exactly the same numbers of backticks and same level of indentation (or blockquote).
library(ggplot2)
library(dplyr)
This code explores Morrison and
Kondaurova (2009)’s methods paper using the data available from
Morrison’s website.
The introduction of the paper says:
Experiment 1: First-language (L1) English listeners, L1-Spanish
L2-English listeners, and L1-Russian L2-English listeners classified
vowels from an English /i/-/ɪ/ continuum. The continuum consisted of a
99-point two-dimensional grid of linear-predictive-coding resynthesized
/bVt/ tokens, in which the vowel duration ranged from 35 to 275 ms in 30
ms steps, and the vowel formant center frequencies ranged from F1=458Hz,
F2=1876Hz, and F3=2523Hz to F1=326Hz, F2=2056Hz, and F3=2943Hz,
respectively, in equal mel steps. The grid was labeled using reference
numbers where duration and spectral values of 1 refer to the most
/i/-like properties (long duration, and low F1 and high F2) and duration
and spectral values of 9 refer to the most /ɪ/-like properties (short
duration, and high F1 and low F2). The 81 stimuli were each presented
ten times in random order and on each trial the listener classified the
stimulus as either English /bit/ or /bɪt/ (there were a total of 16
L1-English listeners, 18 L1-Spanish listeners, and 19 L1-Russian
listeners).
Read in data and label
dat.eng <- read.table('data/data_English.txt', sep = '\t')
dat.rus <- read.table('data/data_Russian.txt', sep = '\t')
dat.span <- read.table('data/data_Spanish.txt', sep = '\t')
Unfortunately I’m not sure where to find the information about what
the columns mean but we can reverse-engineer:
summary(dat.eng)
V1 V2 V3 V4 V5
Min. : 1.00 Min. :0 Min. :0 Min. : 0.000 Min. : 0.000
1st Qu.: 4.75 1st Qu.:2 1st Qu.:2 1st Qu.: 0.000 1st Qu.: 0.000
Median : 8.50 Median :4 Median :4 Median : 5.000 Median : 5.000
Mean : 8.50 Mean :4 Mean :4 Mean : 4.916 Mean : 5.084
3rd Qu.:12.25 3rd Qu.:6 3rd Qu.:6 3rd Qu.:10.000 3rd Qu.:10.000
Max. :16.00 Max. :8 Max. :8 Max. :10.000 Max. :10.000
apply(dat.eng, 2, unique)
$V1
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
$V2
[1] 0 1 2 3 4 5 6 7 8
$V3
[1] 0 1 2 3 4 5 6 7 8
$V4
[1] 2 4 1 3 8 5 0 7 9 6 10
$V5
[1] 8 6 9 7 2 5 10 3 1 4 0
So the unique values in each column in the English data are: - Col 1:
1-16, in unit increments (must be listener id) - Col 2: 0-8, in unit
increments - Col 3: 0-8, in unit increments - Col 4: 0-10, in unit
increments - Col 5: 0-10, in unit increments
And in Logistic_Regression_input_arguments.txt it
says:
stimcols {‘listener’ ‘spec’ ‘dur’} respcols {‘/I/’ ‘/i/’}
So maybe column 2 is the spectral steps, column 3 is the duration
steps, and column 4 and 5 give how many times listener responded /I/ and
/i/, respectively. Unfortunately, we don’t have trial-by-trial data here
(but we could reconstruct that, except missing block/repetition
number).
So let’s label the data frame accordingly and write a function to do
this for each of the data sets.
load.label.dat <- function(filename, directory = 'data/') {
filepath = paste(directory, filename, sep = '')
dat = read.table(filepath, sep = '\t')
names(dat) = c("listener", "step.spec", "step.dur", "num.ih", "num.iy")
dat$listener = as.factor(dat$listener)
return(dat)
}
and process each data set this way:
dat.eng <- load.label.dat("data_English.txt")
dat.rus <- load.label.dat("data_Russian.txt")
dat.span <- load.label.dat("data_Spanish.txt")
str(dat.eng)
'data.frame': 1296 obs. of 5 variables:
$ listener : Factor w/ 16 levels "1","2","3","4",..: 1 1 1 1 1 1 1 1 1 1 ...
$ step.spec: int 0 0 0 0 0 0 0 0 0 1 ...
$ step.dur : int 0 1 2 3 4 5 6 7 8 0 ...
$ num.ih : int 2 4 1 1 2 4 3 8 5 0 ...
$ num.iy : int 8 6 9 9 8 6 7 2 5 10 ...
Exploratory plots
We can make plots by listener for proportion of /ih/ responses
depending on one kind of step, aggregated over the other kind of step,
like in Figure 1.
Here we aggregate over spectral steps to get by-listener responses
for each duration step.
dat.span %>%
group_by(listener,step.dur) %>%
summarize(num.ih = sum(num.ih),
num.iy = sum(num.iy)) %>%
mutate(prop.ih = num.ih/(num.ih + num.iy)) -> dat.span.by.dur
`summarise()` has grouped output by 'listener'. You can override using the `.groups` argument.
ggplot(data = dat.span.by.dur, aes(x = step.dur, y = prop.ih, group = listener, color = listener)) + geom_line() + ylim(0,1.0) + theme(aspect.ratio=1)

We can also plot a subplot for each individual listener:
ggplot(data = dat.span.by.dur, aes(x = step.dur, y = prop.ih)) + geom_line() + ylim(0,1.0) + theme(aspect.ratio=1) + facet_wrap(~listener)

Endpoint calculations
In Ref. 3, in Experiment 1, the duration endpoint-difference scores
were calculated as the proportion of /ɪ/ responses for all stimuli with
duration value of 9 minus the proportion of /ɪ/ responses for all
stimuli with duration value of 1. Likewise the spectral
endpoint-difference scores were calculated as the difference in the
proportion of /ɪ/ responses at the two spectral extremes of the stimulus
set.
So we could compute endpoint difference scores with a function like
this. Note that we must hold the step continuum over a single
variable—either spectral quality or duration, but not both—basically we
just drop the information about the other dimension. Or we could set one
of the variables to some constant, e.g., let’s compute endpoint
difference scores for spectral quality, with duration held constant at
step 5.
dat.span.by.dur %>%
dplyr::select(listener,step.dur,prop.ih) %>%
filter(step.dur %in% c(0, 8)) %>%
pivot_wider(names_from = step.dur, names_prefix = "prop.ih.", values_from = prop.ih) %>%
mutate(endpoint_diff = prop.ih.8 - prop.ih.0)
NA
NA
You can write a function to generalize the computations, as I started
to do below.
# compute.endpoint.diff <- function(data = dat.span, step = "step.spec") {
# require(dplyr)
#
# dat.by.step <- dat %>%
# group_by(listener,.data[[step]]) %>%
# summarize(num.ih = sum(num.ih),
# num.iy = sum(num.iy)) %>%
# mutate(prop.ih = num.ih/(num.ih + num.iy))
#
# dat.by.step %>%
Linear discriminant analysis
The authors point out that data from an identification task is not
normally distributed.
Here’s what two normal distributions over steps might look like:
norm_lower = rnorm(n = 1000, mean = 2, sd = 2)
norm_higher = rnorm(n = 1000, mean = 5, sd = 2)
plot(density(norm_lower))
lines(density(norm_higher))

NA
NA
Compare to the sigmoidal identification curves:
sigmoid = function(x) {
1 / (1 + exp(-x))
}
x1 <- seq(-5, 5, 0.1)
plot(x1, sigmoid(x1),pch = '.')
points(x1+2, sigmoid(x1), pch = '.')

Why do the authors say that LDA assumes a normal distribution? This
comes from thinking about LDA as a special case of Bayes
classification….
LS0tCnRpdGxlOiAiTW9ycmlzb24gYW5kIEtvbmRhdXJvdmEgKDIwMDkpIGludmVzdGlnYXRpb25zIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpgYGB7ciBpbXBvcnQtbGlic30KbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRwbHlyKQpgYGAKClRoaXMgY29kZSBleHBsb3JlcyBbTW9ycmlzb24gYW5kIEtvbmRhdXJvdmEgKDIwMDkpJ3MgbWV0aG9kcyBwYXBlcl0oaHR0cHM6Ly9hc2Euc2NpdGF0aW9uLm9yZy9kb2kvMTAuMTEyMS8xLjMyMTY5MTcpIHVzaW5nIFt0aGUgZGF0YSBhdmFpbGFibGUgZnJvbSBNb3JyaXNvbidzIHdlYnNpdGVdKGh0dHBzOi8vZ2VvZmYtbW9ycmlzb24ubmV0LyNMb2dSZWcyMDA5KS4KClRoZSBpbnRyb2R1Y3Rpb24gb2YgdGhlIHBhcGVyIHNheXM6Cgo+IEV4cGVyaW1lbnQgMTogRmlyc3QtbGFuZ3VhZ2UgKEwxKSBFbmdsaXNoIGxpc3RlbmVycywgTDEtU3BhbmlzaCBMMi1FbmdsaXNoIGxpc3RlbmVycywgYW5kIEwxLVJ1c3NpYW4gTDItRW5nbGlzaCBsaXN0ZW5lcnMgY2xhc3NpZmllZCB2b3dlbHMgZnJvbSBhbiBFbmdsaXNoIC9pLy0vyaovIGNvbnRpbnV1bS4gVGhlIGNvbnRpbnV1bSBjb25zaXN0ZWQgb2YgYSA5OS1wb2ludCB0d28tZGltZW5zaW9uYWwgZ3JpZCBvZiBsaW5lYXItcHJlZGljdGl2ZS1jb2RpbmcgcmVzeW50aGVzaXplZCAvYlZ0LyB0b2tlbnMsIGluIHdoaWNoIHRoZSB2b3dlbCBkdXJhdGlvbiByYW5nZWQgZnJvbSAzNSB0byAyNzUgbXMgaW4gMzAgbXMgc3RlcHMsIGFuZCB0aGUgdm93ZWwgZm9ybWFudCBjZW50ZXIgZnJlcXVlbmNpZXMgcmFuZ2VkIGZyb20gRjE9NDU4SHosIEYyPTE4NzZIeiwgYW5kIEYzPTI1MjNIeiB0byBGMT0zMjZIeiwgRjI9MjA1Nkh6LCBhbmQgRjM9Mjk0M0h6LCByZXNwZWN0aXZlbHksIGluIGVxdWFsIG1lbCBzdGVwcy4gVGhlIGdyaWQgd2FzIGxhYmVsZWQgdXNpbmcgcmVmZXJlbmNlIG51bWJlcnMgd2hlcmUgZHVyYXRpb24gYW5kIHNwZWN0cmFsIHZhbHVlcyBvZiAxIHJlZmVyIHRvIHRoZSBtb3N0IC9pLy1saWtlIHByb3BlcnRpZXMgKGxvbmcgZHVyYXRpb24sIGFuZCBsb3cgRjEgYW5kIGhpZ2ggRjIpIGFuZCBkdXJhdGlvbiBhbmQgc3BlY3RyYWwgdmFsdWVzIG9mIDkgcmVmZXIgdG8gdGhlIG1vc3QgL8mqLy1saWtlIHByb3BlcnRpZXMgKHNob3J0IGR1cmF0aW9uLCBhbmQgaGlnaCBGMSBhbmQgbG93IEYyKS4gVGhlIDgxIHN0aW11bGkgd2VyZSBlYWNoIHByZXNlbnRlZCB0ZW4gdGltZXMgaW4gcmFuZG9tIG9yZGVyIGFuZCBvbiBlYWNoIHRyaWFsIHRoZSBsaXN0ZW5lciBjbGFzc2lmaWVkIHRoZSBzdGltdWx1cyBhcyBlaXRoZXIgRW5nbGlzaCAvYml0LyBvciAvYsmqdC8gKHRoZXJlIHdlcmUgYSB0b3RhbCBvZiAxNiBMMS1FbmdsaXNoIGxpc3RlbmVycywgMTggTDEtU3BhbmlzaCBsaXN0ZW5lcnMsIGFuZCAxOSBMMS1SdXNzaWFuIGxpc3RlbmVycykuCgojIFJlYWQgaW4gZGF0YSBhbmQgbGFiZWwKCmBgYHtyIHJlYWQtaW59CmRhdC5lbmcgPC0gcmVhZC50YWJsZSgnZGF0YS9kYXRhX0VuZ2xpc2gudHh0Jywgc2VwID0gJ1x0JykKZGF0LnJ1cyA8LSByZWFkLnRhYmxlKCdkYXRhL2RhdGFfUnVzc2lhbi50eHQnLCBzZXAgPSAnXHQnKQpkYXQuc3BhbiA8LSByZWFkLnRhYmxlKCdkYXRhL2RhdGFfU3BhbmlzaC50eHQnLCBzZXAgPSAnXHQnKQoKYGBgCgpVbmZvcnR1bmF0ZWx5IEknbSBub3Qgc3VyZSB3aGVyZSB0byBmaW5kIHRoZSBpbmZvcm1hdGlvbiBhYm91dCB3aGF0IHRoZSBjb2x1bW5zIG1lYW4gYnV0IHdlIGNhbiByZXZlcnNlLWVuZ2luZWVyOgoKYGBge3IgbGFiZWwtY29sc30KCnN1bW1hcnkoZGF0LmVuZykKYXBwbHkoZGF0LmVuZywgMiwgdW5pcXVlKQoKYGBgCgpTbyB0aGUgdW5pcXVlIHZhbHVlcyBpbiBlYWNoIGNvbHVtbiBpbiB0aGUgRW5nbGlzaCBkYXRhIGFyZToKLSBDb2wgMTogMS0xNiwgaW4gdW5pdCBpbmNyZW1lbnRzIChtdXN0IGJlIGxpc3RlbmVyIGlkKQotIENvbCAyOiAwLTgsIGluIHVuaXQgaW5jcmVtZW50cwotIENvbCAzOiAwLTgsIGluIHVuaXQgaW5jcmVtZW50cwotIENvbCA0OiAwLTEwLCBpbiB1bml0IGluY3JlbWVudHMKLSBDb2wgNTogMC0xMCwgaW4gdW5pdCBpbmNyZW1lbnRzCgpBbmQgaW4gYExvZ2lzdGljX1JlZ3Jlc3Npb25faW5wdXRfYXJndW1lbnRzLnR4dGAgaXQgc2F5czoKCj4gc3RpbWNvbHMgICAgICAgIHsnbGlzdGVuZXInICdzcGVjJyAnZHVyJ30KcmVzcGNvbHMgICAgICAgIHsnL0kvJyAnL2kvJ30KClNvIG1heWJlIGNvbHVtbiAyIGlzIHRoZSBzcGVjdHJhbCBzdGVwcywgY29sdW1uIDMgaXMgdGhlIGR1cmF0aW9uIHN0ZXBzLCBhbmQgY29sdW1uIDQgYW5kIDUgZ2l2ZSBob3cgbWFueSB0aW1lcyBsaXN0ZW5lciByZXNwb25kZWQgL0kvIGFuZCAvaS8sIHJlc3BlY3RpdmVseS4gIFVuZm9ydHVuYXRlbHksIHdlIGRvbid0IGhhdmUgdHJpYWwtYnktdHJpYWwgZGF0YSBoZXJlIChidXQgd2UgY291bGQgcmVjb25zdHJ1Y3QgdGhhdCwgZXhjZXB0IG1pc3NpbmcgYmxvY2svcmVwZXRpdGlvbiBudW1iZXIpLgoKU28gbGV0J3MgbGFiZWwgdGhlIGRhdGEgZnJhbWUgYWNjb3JkaW5nbHkgYW5kIHdyaXRlIGEgZnVuY3Rpb24gdG8gZG8gdGhpcyBmb3IgZWFjaCBvZiB0aGUgZGF0YSBzZXRzLgoKYGBge3IgZnhuLWxvYWQtbGFiZWwtZGF0YX0KCmxvYWQubGFiZWwuZGF0IDwtIGZ1bmN0aW9uKGZpbGVuYW1lLCBkaXJlY3RvcnkgPSAnZGF0YS8nKSB7CiAgZmlsZXBhdGggPSBwYXN0ZShkaXJlY3RvcnksIGZpbGVuYW1lLCBzZXAgPSAnJykKICBkYXQgPSByZWFkLnRhYmxlKGZpbGVwYXRoLCBzZXAgPSAnXHQnKQogIG5hbWVzKGRhdCkgPSBjKCJsaXN0ZW5lciIsICJzdGVwLnNwZWMiLCAic3RlcC5kdXIiLCAibnVtLmloIiwgIm51bS5peSIpCiAgZGF0JGxpc3RlbmVyID0gYXMuZmFjdG9yKGRhdCRsaXN0ZW5lcikKICByZXR1cm4oZGF0KQp9CmBgYAoKYW5kIHByb2Nlc3MgZWFjaCBkYXRhIHNldCB0aGlzIHdheToKCmBgYHtyfQoKZGF0LmVuZyA8LSBsb2FkLmxhYmVsLmRhdCgiZGF0YV9FbmdsaXNoLnR4dCIpCmRhdC5ydXMgPC0gbG9hZC5sYWJlbC5kYXQoImRhdGFfUnVzc2lhbi50eHQiKQpkYXQuc3BhbiA8LSBsb2FkLmxhYmVsLmRhdCgiZGF0YV9TcGFuaXNoLnR4dCIpCgpzdHIoZGF0LmVuZykKYGBgCgojIEV4cGxvcmF0b3J5IHBsb3RzCgpXZSBjYW4gbWFrZSBwbG90cyBieSBsaXN0ZW5lciBmb3IgcHJvcG9ydGlvbiBvZiAvaWgvIHJlc3BvbnNlcyBkZXBlbmRpbmcgb24gb25lIGtpbmQgb2Ygc3RlcCwgYWdncmVnYXRlZCBvdmVyIHRoZSBvdGhlciBraW5kIG9mIHN0ZXAsIGxpa2UgaW4gRmlndXJlIDEuCgpIZXJlIHdlIGFnZ3JlZ2F0ZSBvdmVyIHNwZWN0cmFsIHN0ZXBzIHRvIGdldCBieS1saXN0ZW5lciByZXNwb25zZXMgZm9yIGVhY2ggZHVyYXRpb24gc3RlcC4KCmBgYHtyIGRhdC1pZC1jdXJ2ZXMtYnktc3BlY30KCmRhdC5zcGFuICU+JQogIGdyb3VwX2J5KGxpc3RlbmVyLHN0ZXAuZHVyKSAlPiUKICBzdW1tYXJpemUobnVtLmloID0gc3VtKG51bS5paCksCiAgICAgICAgICAgIG51bS5peSA9IHN1bShudW0uaXkpKSAlPiUKICBtdXRhdGUocHJvcC5paCA9IG51bS5paC8obnVtLmloICsgbnVtLml5KSkgLT4gZGF0LnNwYW4uYnkuZHVyCgoKYGBgCgoKCgoKYGBge3IgcGxvdC1pZC1jdXJ2ZXMtZHVyfQoKZ2dwbG90KGRhdGEgPSBkYXQuc3Bhbi5ieS5kdXIsIGFlcyh4ID0gc3RlcC5kdXIsIHkgPSBwcm9wLmloLCBncm91cCA9IGxpc3RlbmVyLCBjb2xvciA9IGxpc3RlbmVyKSkgKyBnZW9tX2xpbmUoKSArIHlsaW0oMCwxLjApICsgdGhlbWUoYXNwZWN0LnJhdGlvPTEpCgpgYGAKCldlIGNhbiBhbHNvIHBsb3QgYSBzdWJwbG90IGZvciBlYWNoIGluZGl2aWR1YWwgbGlzdGVuZXI6CgpgYGB7ciBwbG90LWlkLWN1cnZlcy1kdXItc3Vian0KCmdncGxvdChkYXRhID0gZGF0LnNwYW4uYnkuZHVyLCBhZXMoeCA9IHN0ZXAuZHVyLCB5ID0gcHJvcC5paCkpICsgZ2VvbV9saW5lKCkgKyB5bGltKDAsMS4wKSArIHRoZW1lKGFzcGVjdC5yYXRpbz0xKSArIGZhY2V0X3dyYXAofmxpc3RlbmVyKQoKYGBgCgoKIyBFbmRwb2ludCBjYWxjdWxhdGlvbnMKCj4gSW4gUmVmLiAzLCBpbiBFeHBlcmltZW50IDEsIHRoZSBkdXJhdGlvbiBlbmRwb2ludC1kaWZmZXJlbmNlIHNjb3JlcyB3ZXJlIGNhbGN1bGF0ZWQgYXMgdGhlIHByb3BvcnRpb24gb2YgL8mqLyByZXNwb25zZXMgZm9yIGFsbCBzdGltdWxpIHdpdGggZHVyYXRpb24gdmFsdWUgb2YgOSBtaW51cyB0aGUgcHJvcG9ydGlvbiBvZiAvyaovIHJlc3BvbnNlcyBmb3IgYWxsIHN0aW11bGkgd2l0aCBkdXJhdGlvbiB2YWx1ZSBvZiAxLiBMaWtld2lzZSB0aGUgc3BlY3RyYWwgZW5kcG9pbnQtZGlmZmVyZW5jZSBzY29yZXMgd2VyZSBjYWxjdWxhdGVkIGFzIHRoZSBkaWZmZXJlbmNlIGluIHRoZSBwcm9wb3J0aW9uIG9mIC/Jqi8gcmVzcG9uc2VzIGF0IHRoZSB0d28gc3BlY3RyYWwgZXh0cmVtZXMgb2YgdGhlIHN0aW11bHVzIHNldC4KClNvIHdlIGNvdWxkIGNvbXB1dGUgZW5kcG9pbnQgZGlmZmVyZW5jZSBzY29yZXMgd2l0aCBhIGZ1bmN0aW9uIGxpa2UgdGhpcy4gTm90ZSB0aGF0IHdlIG11c3QgaG9sZCB0aGUgc3RlcCBjb250aW51dW0gb3ZlciBhIHNpbmdsZSB2YXJpYWJsZS0tLWVpdGhlciBzcGVjdHJhbCBxdWFsaXR5IG9yIGR1cmF0aW9uLCBidXQgbm90IGJvdGgtLS1iYXNpY2FsbHkgd2UganVzdCBkcm9wIHRoZSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgb3RoZXIgZGltZW5zaW9uLiBPciB3ZSBjb3VsZCBzZXQgb25lIG9mIHRoZSB2YXJpYWJsZXMgdG8gc29tZSBjb25zdGFudCwgZS5nLiwgbGV0J3MgY29tcHV0ZSBlbmRwb2ludCBkaWZmZXJlbmNlIHNjb3JlcyBmb3Igc3BlY3RyYWwgcXVhbGl0eSwgd2l0aCBkdXJhdGlvbiBoZWxkIGNvbnN0YW50IGF0IHN0ZXAgNS4KCmBgYHtyIGV4YW1wbGUtY29tcHV0ZS1lbmRwb2ludC1kaWZmfQoKZGF0LnNwYW4uYnkuZHVyICU+JQogIGRwbHlyOjpzZWxlY3QobGlzdGVuZXIsc3RlcC5kdXIscHJvcC5paCkgJT4lCiAgZmlsdGVyKHN0ZXAuZHVyICVpbiUgYygwLCA4KSkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHN0ZXAuZHVyLCBuYW1lc19wcmVmaXggPSAicHJvcC5paC4iLCB2YWx1ZXNfZnJvbSA9IHByb3AuaWgpICU+JQogIG11dGF0ZShlbmRwb2ludF9kaWZmID0gcHJvcC5paC44IC0gcHJvcC5paC4wKQoKCmBgYAoKWW91IGNhbiB3cml0ZSBhIGZ1bmN0aW9uIHRvIGdlbmVyYWxpemUgdGhlIGNvbXB1dGF0aW9ucywgYXMgSSBzdGFydGVkIHRvIGRvIGJlbG93LgoKYGBge3IgZnhuLWNvbXB1dGUtZW5kcG9pbnQtZGlmZn0KCiMgY29tcHV0ZS5lbmRwb2ludC5kaWZmIDwtIGZ1bmN0aW9uKGRhdGEgPSBkYXQuc3Bhbiwgc3RlcCA9ICJzdGVwLnNwZWMiKSB7CiMgICByZXF1aXJlKGRwbHlyKQojICAgCiMgICBkYXQuYnkuc3RlcCA8LSBkYXQgJT4lCiMgICAgIGdyb3VwX2J5KGxpc3RlbmVyLC5kYXRhW1tzdGVwXV0pICU+JQojICAgICBzdW1tYXJpemUobnVtLmloID0gc3VtKG51bS5paCksCiMgICAgICAgICAgICAgbnVtLml5ID0gc3VtKG51bS5peSkpICU+JQojICAgICBtdXRhdGUocHJvcC5paCA9IG51bS5paC8obnVtLmloICsgbnVtLml5KSkgCiMgICAKIyAgIGRhdC5ieS5zdGVwICU+JQogICAgCgoKYGBgCgoKIyBMaW5lYXIgZGlzY3JpbWluYW50IGFuYWx5c2lzCgpUaGUgYXV0aG9ycyBwb2ludCBvdXQgdGhhdCBkYXRhIGZyb20gYW4gaWRlbnRpZmljYXRpb24gdGFzayBpcyBub3Qgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuCgpIZXJlJ3Mgd2hhdCB0d28gbm9ybWFsIGRpc3RyaWJ1dGlvbnMgb3ZlciBzdGVwcyBtaWdodCBsb29rIGxpa2U6CgpgYGB7cn0KCm5vcm1fbG93ZXIgPSBybm9ybShuID0gMTAwMCwgbWVhbiA9IDIsIHNkID0gMikKbm9ybV9oaWdoZXIgPSBybm9ybShuID0gMTAwMCwgbWVhbiA9IDUsIHNkID0gMikKCnBsb3QoZGVuc2l0eShub3JtX2xvd2VyKSkKbGluZXMoZGVuc2l0eShub3JtX2hpZ2hlcikpCgoKYGBgYAoKQ29tcGFyZSB0byB0aGUgc2lnbW9pZGFsIGlkZW50aWZpY2F0aW9uIGN1cnZlczoKCmBgYHtyIHBsb3Qtc2lnbW9pZHN9CgpzaWdtb2lkID0gZnVuY3Rpb24oeCkgewogICAxIC8gKDEgKyBleHAoLXgpKQp9Cgp4MSA8LSBzZXEoLTUsIDUsIDAuMSkKcGxvdCh4MSwgc2lnbW9pZCh4MSkscGNoID0gJy4nKQpwb2ludHMoeDErMiwgc2lnbW9pZCh4MSksIHBjaCA9ICcuJykKYGBgCgpXaHkgZG8gdGhlIGF1dGhvcnMgc2F5IHRoYXQgTERBIGFzc3VtZXMgYSBub3JtYWwgZGlzdHJpYnV0aW9uPwpUaGlzIGNvbWVzIGZyb20gdGhpbmtpbmcgYWJvdXQgTERBIGFzIGEgc3BlY2lhbCBjYXNlIG9mIEJheWVzIGNsYXNzaWZpY2F0aW9uLi4uLgoKCgoKCgoKCgoKCgoKCgo=