Ucitavamo potrebne pakete

library(FinCal)
library(financial)

library(YieldCurve)
library(NMOF)

Prvo poglavlje

Zadatak 1.1.

Unutrasnja stopa dobiti je

irr(c(-1e5, 0, 52e3, 0, 54e3))
[1] 0.01955234

na sta cemo se vratiti za koji trenutak.

Pri stopi 10%, investitor biti na gubitku, sto pokazuje sledece…

pv(0.1, 4, -54e3) + pv(0.1, 2, -52e3)
[1] 79857.93

tj. sadasnja vrednost dobitaka je manja od uloga, pri stopi 10%.

drugi nacin…

npv(r = 0.1, c(-1e5, 0, 52e3, 0, 54e3))
[1] -20142.07

Ovaj broj je direktno povezan sa prethodim jer je -20142.07 + 100000 = 79857.93.

Net sadasnja vrednost (Net present value, npv) je u sustini suma sadasnjih vrednosti svih clanova toka novca (zvanicna definicija je malo drugacija, ali funkcija npv u principu radi ovo).

Stoga ovo uopste ne cudi, jer smo prethodno izracunali zbir sadasnjih vrednosti dobitaka.


Da je investitor na gubitku mogli smo da zakljucimo bez racuna, ako se vratimo na definiciju unutrasnje stope dobiti

Unutrasnja stopa dobiti je ona stopa po kojoj je NPV toka novca jednaka 0.

Ovo se da videti na primeru…

npv(irr(c(-1e5, 0, 52e3, 0, 54e3)), c(-1e5, 0, 52e3, 0, 54e3))
[1] 0.005423599

vrednost je 0.005 sto nije bas nula, ali buduci da je skala na kojoj radimo rede valicine sto hiljada, ovo je zanemarljiva razlika pa cemo reci da je 0.

Posto je stopa 10% veca od 2% koja je unutrasnja stopa dobiti, mogli smo da zaklucimo da je investitor na gubitku pri 10%, jer pri toj stopi sadasnja vrednost buducih dobitaka mora da bude manja nego pri stopi 2%, jednostavno jer delimo sa \((1+r)^n\), pa ako je \(r\) vece, sadasnja vrednost je manja, sto smo videli na pocetku.

Zadatak 1.2.

Nema sta da se prica…

cash_flow <- rep(5e5, 20) # 20 godina po 500k
npv(0.1, cash_flow)
[1] 4682460

Naravno, upola manje od 10M koje treba da dobije nagradjeni :)

Zadatak 1.3.

Obuhvaticemo oba slucaja tako sto radimo sa n meseci, pa cemo uzeti 6 ili 12 za potrebe zadatka.

Ako ne menjaju odluku, tok novca ce biti \((\underbrace{1000+1000}_{\text{ depozit + 1. kirija}}, \underbrace{1000,\dots,1000}_{n-1\text{ kirija}}, \underbrace{-1000}_{\text{ vracen depozit}})\)

Ako menjaju odluku, tok novca je \((\underbrace{1000 + 900}_{\text{ depozit + prva kirija}},\underbrace{900,\dots,900}_{n-1\text{ kirija}})\) (U knjizi i na vezbama je drugacije radjeno, ali ja mislim da je ovo tacno, jer kiriju na drugom stanu placamo na pocetku meseca, pa nece proci ceo period kamacenja dok uplatimo kiriju).

Funkcija koja racuna sadasnju vrednost toka novca za obe odluke:

compare_npvs <- function(n) {
  stick_with_it_cashflow <- -c(2e3, rep(1e3, n-1), -1e3)
  change_of_mind_cashflow <- -c(1900, rep(900, n-1))
  
  c("stick with it" = npv(0.12, stick_with_it_cashflow),
    "change of mind" = npv(0.12, change_of_mind_cashflow))
}

Ako uzmemo 6 meseci, rezultat je

compare_npvs(6)
 stick with it change of mind 
     -5098.145      -5144.299 

U slucaju da ne menjamo odluku, potrosimo manje para na stan.

Ako uzimamo na godinu dana…

compare_npvs(12)
 stick with it change of mind 
     -7681.024      -7243.929 

…isplati se da promenimo misljenje.

Zadatak 1.4.

Mozemo da prvo vidimo koliko po kamatnoj stopi 7% investitor dobije nakon 10 godina, pa da to umanjimo za inflaciju

no_inflation <- 5e4 * (1+0.7)^10
with_inflation <- no_inflation / (1+0.3)^10
c(no_inflation, with_inflation)
[1] 10079969.5   731182.3

Dakle, vrednost nakon uzimanja u obzir inflacije je 731,182.3

Drugo poglavlje

Zadatak 2.2.

Ovde je bitna prica o Krivi dobiti (glava 2.6 u knjizi). Ukratko, imamo sledece pojmove:

  • \(B(0,t)\) je fer cena beskuponske obveznice, sa jedinicnom naznacenom cenom
  • \(R(0,t)\) je prosecna kamatna stopa u trenutku \(t\), implicirana cenom beskuponske obveznice.

Tada je, pri slozenom kamacenju, \[B(0,t) = \frac1{(1+R(0,t))^t},\] tj. nominalna cena (= 1), diskontovana za kamatnu stopu \(R(0,t)\) nakon \(t\) vremena.

Ako bismo uveli \(B_N(0,t)\) da je isto sto i \(B(0,t)\), ali za naznacenu cenu \(N\), bilo bi \[B_N(0,t) = \frac{N}{(1+R(0,t))^t},\] iz istog razloga kao malopre. Odatle jednostavnim sredjivanjem dobijamo da je \[R(0,t) = \left(\frac{N}{B_N(0,t)}\right)^{\frac1t} - 1.\] Izvedimo pre resenja zadatka i sadasnju vrednost nekog projekta \(a = (a_0, a_1, \dots, a_n)\), sa trenucima transakcija \((0, t_1, \dots, t_n)\)

Projekat \(a\) mozemo da posmatramo kao kolekciju beskuponskih obveznica, sa trenucima dospeca \(0, t_1, \dots, t_n\), i nominalnim vrednostima \(a_0, a_1, \dots, a_n\), redom. Stoga je sadasnja vrednost projekta suma sadasnjih vrednosti tih obveznica \[\begin{align}&B_{a_0}(0,0) + B_{a_1}(0, t_1) + B_{a_2}(0,t_2) + \dots + B_{a_n}(0, t_n)\\ &=a_0 + a_1B(0, t_1) + a_2B(0,t_2) + \dots + a_nB(0, t_n)\\ &= a_0 + \sum_{k=1}^n \frac{a_k}{(1+R(0,t_k))^{t_k}}.\end{align}\]

Tu formulu cemo koristiti i kasnije.

Dakle da se vratimo zadatku…

Deo a)

Beskuponske stope su…

N <- 10
BN <- c(9.75, 9.5, 9.1, 8.5, 8.3, 8, 7.58, 7.2, 7, 6.8)
t <- c(0.5, 1, 1.5, 1.75, 2, 2.5, 3.1, 4, 5, 6)
R <- (N/BN)^(1/t) - 1
paste(round(R*100, 2), collapse = "% ")
[1] "5.19% 5.26% 6.49% 9.73% 9.76% 9.34% 9.35% 8.56% 7.39% 6.64"
Deo b)

Polinomijalni model je prosto linearni model sto znamo iz LSM-a, prediktori su nam stepeni vremena \(t\), a zavisna promenljiva stopa \(R(0,t)\).

model <- lm(R ~ 1 + t + I(t^2) + I(t^3))
summary(model)

Call:
lm(formula = R ~ 1 + t + I(t^2) + I(t^3))

Residuals:
       Min         1Q     Median         3Q        Max 
-0.0147524 -0.0016656 -0.0001884  0.0065019  0.0124136 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)  
(Intercept)  0.0151311  0.0176166   0.859   0.4234  
t            0.0648462  0.0224535   2.888   0.0278 *
I(t^2)      -0.0162727  0.0080644  -2.018   0.0902 .
I(t^3)       0.0011432  0.0008323   1.374   0.2187  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.01059 on 6 degrees of freedom
Multiple R-squared:  0.7708,    Adjusted R-squared:  0.6562 
F-statistic: 6.726 on 3 and 6 DF,  p-value: 0.02396

Treci stepen nam izgleda nebitan, pa cemo da ga izbacimo…

model2 <- lm(R ~ 1 + t + I(t^2))
summary(model2)

Call:
lm(formula = R ~ 1 + t + I(t^2))

Residuals:
       Min         1Q     Median         3Q        Max 
-0.0119602 -0.0078372  0.0000566  0.0058775  0.0165075 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)  0.033631   0.012052   2.791  0.02689 * 
t            0.036296   0.009012   4.028  0.00501 **
I(t^2)      -0.005335   0.001353  -3.944  0.00557 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.01124 on 7 degrees of freedom
Multiple R-squared:  0.6987,    Adjusted R-squared:  0.6127 
F-statistic: 8.118 on 2 and 7 DF,  p-value: 0.01501

Sad je sve znacajno, i anova nam potvrdjuje da je bolji kvadratni polinom:

anova(model2, model)
Analysis of Variance Table

Model 1: R ~ 1 + t + I(t^2)
Model 2: R ~ 1 + t + I(t^2) + I(t^3)
  Res.Df        RSS Df  Sum of Sq      F Pr(>F)
1      7 0.00088504                            
2      6 0.00067333  1 0.00021171 1.8865 0.2187

P-vrednost je velika, pa ne odbacujemo nultu hipotezu da su modeli u sustini isti.

Napravicemo i Nelson-Zajgelov model:

modelNS <- drop(Nelson.Siegel(R, t))
# za potrebe funkcije NS u nastavku, treba da reparametrizujemo lambda sa 1/lambda
modelNS[4] <- 1/modelNS[4]

Hajde da ispratimo knjigu, pa i da nacrtamo grafike

plot(t, R)
t_axis <- seq(0.5, 6, length.out = 100)
lines(t_axis, predict(model, data.frame(t = t_axis)), col = "blue")
lines(t_axis, predict(model2, data.frame(t = t_axis)), col = "green")
lines(t_axis, NS(modelNS, t_axis), col = "red")

Deo v)

U prethodnom delu smo postavili model zavisnosti kamatne stope od vremena koristeci cene odredjenih obveznica sa trzista. Sada cemo da iskoristimo taj model kamatnih stopa da izracunamo sadasnje vrednosi projekata \(P_1\) i \(P_2\).

Formula po kojoj cemo racunati sadasnju vrednost projekta \((a_0, a_1, \dots, a_n)\), gde su trenuci \((0, t_1, \dots, t_n)\) je izvedena u prici na pocetku zadatka i aproksimiramo je sa: \[a_0 + \sum_{k=1}^n \frac{a_k}{(1+R(0,t_k))^{t_k}}\approx \sum_{k=0}^n \frac{a_k}{(1+\hat R(0,t_k))^{t_k}},\] gde je \(\hat R\) nas model.

p1_t <- 0:4 * 8/12 # 8 meseci je razmak izmedju transakcija
p2_t <- 0:3 * 8/12
p1_R <- predict(model2, data.frame(t = p1_t))
p2_R <- predict(model2, data.frame(t = p2_t))
p1_cf <- c(100, -20, 50, 10, 20)
p2_cf <- c(-20, 100, 10, 30)
# sadasnja vrednost direktno po formuli
p1_pv <- sum(p1_cf / (1 + p1_R)^p1_t)
p2_pv <- sum(p2_cf / (1 + p2_R)^p2_t)
c("P1" = p1_pv, "P2" = p2_pv)
      P1       P2 
150.5437 111.0635 

Dakle, bolji je prvi projekat.

U knjizi pise da bismo mozda hteli da uracunamo i to sto su ova dva projekta na razlicitim vremenskim periodima, pa bismo mogli da koristimo cikluse. To bi podrazumevalo da svedemo oba projekta na jednake vremenske periode, tako sto svaki od njih ponavljamo onoliko puta koliko je potrebno da se dobije jednak vremenski period. Kokretno, ovde je \(P1\) na 4 perioda, a \(P2\) na 3 (ne racuna se nulta transakcija), pa treba da \(P1\) ponovimo 3 puta, a \(P2\) 4 puta. Kod je sledeci, a detalji su objasnjeni u istom.

# ponovimo projekat k puta. cf je tok novca projekta
repeat_project <- function(cf, k) {
  # ako jendom ponavljamo, nemamo sta da radimo
  if(k == 1)
    return(cf)
  
  # definisemo kombinovani tok novca koji ce da sadrzi ciklus
  combined <- cf
  for(i in 2:k) {
    # vrednost kombinovanog toka je kombinovan tok + tok novca koji ponavljamo, pri cemu se
    # poslednja vrednost u toku novca sabira sa nultom vrednoscu toka koji ponavljamo. Na primer,
    # ako ponavljamo (-1, 2, 3) 2 puta, imamo (-1, 2, 3 - 1, 2, 3) = (-1, 2, 2, 2, 3)
    combined <-  c(combined, rep(0, length(cf) - 1)) + c(rep(0, length(combined) - 1), cf)
  }
  
  combined
}

Dakle, ciklicni projekti su

p1c_cf <- repeat_project(p1_cf, 3)
p2c_cf <- repeat_project(p2_cf, 4)
p1c_cf
 [1] 100 -20  50  10 120 -20  50  10 120 -20  50  10  20
p2c_cf
 [1] -20 100  10  10 100  10  10 100  10  10 100  10  30

Vidimo da su na istim vremenskim periodima. Sada je poredjenje sadasnjih vrednosti:

p1c_t <- 0:12 * 8/12 # 8 meseci je razmak izmedju transakcija
p2c_t <- 0:12 * 8/12
p1c_R <- predict(model2, data.frame(t = p1c_t))
p2c_R <- predict(model2, data.frame(t = p2c_t))
# sadasnja vrednost direktno po formuli
p1c_pv <- sum(p1c_cf / (1 + p1c_R)^p1c_t)
p2c_pv <- sum(p2c_cf / (1 + p2c_R)^p2c_t)
c("P1" = p1c_pv, "P2" = p2c_pv)
      P1       P2 
394.7969 390.5011 

Opet je bolji prvi projekat.

Zadatak 2.3.

Dobit do dospeca je unutrasnja stopa dobiti toka novca odredjenog obveznicom.

Taj tok je (- cena obveznice (to placamo), kupon, …, kupon, naznacena vrednost + kupon).

cf <- c(-10100, 1000, 1000, 10100)
irr(cf)
[1] 0.0681619

Zadatak 2.4.

Deo a)

Fer cena je sadasnja vrednost toka novca odredjenog obveznicom. To mozemo izracunati korsteci funkciju npv, ako stavimo da je pocentni ulog 0.

cf <- c(0, 5, 5, 5, 5, 105)
npv(0.0495, cf)
[1] 100.2168
Deo b)

Za ovo samo menjamo kamatu i racunamo isto kao prethodno. Uzecemo granice za stopu (0, 0.3) jer je tako odabrano u knjizi

# srecom, npv je vektorizovana funkcija, pa mozemo da radimo samo curve.
# npv(vec, cf) ce vratiti vektor sadasnjih vrednosti toka cf za svaku od stopa u vec
curve(npv(x, cf), xlim = c(0, 0.3))
points(0.0495,100.2168)

Zadatak 2.6.

Ovde koristimo formulu od ranije za sadasnju vrednost toka sa promenljivom stopom, \(\sum_\limits{k=0}^n \frac{a_k}{(1+R(0,t_k))^{t_k}}.\) Platili bismo:

t <- 1:10 / 2
R <- 0.05 - 0.03 * (1 - exp(-t)) / t
N <- 1e4
cf <- c(rep(250, 9), 10250) # 9 kupona i zadnji kupon + glavnica
# sadasnja vrednost iliti fer cena
sum(cf / (1 + R)^t)
[1] 10306.18

Zadatak 2.17.

Ovde koristimo pojam

Forvardna kriva \(F(0, t, t + \Delta_t)\) nam daje vazecu kamatnu stopu koju ocekujemo da vazi u trenutku \(t\) za period \(\Delta_t\) impliciranu beskuponskom krivom dobiti.

Ovo znaci sledece: Ako imamo beskuponsku krivu dobiti \(R(0,t)\) i imamo jedinicnu sumu novca, buduca vrednost tog novca, tj. faktor kojim umnozavamo vrednost, u trenutku \(t+\Delta_t\) je \((1+R(0, t+\Delta_t))^{t+\Delta_t}\). S druge strane, mozemo i da prvo uzmemo buducu vrednost u trenutku \(t\), tj. \((1+R(0, t))^{t}\), pa nju umnozimo sa odredjenom kamatom za period \(\Delta_t\), da dobijemo buducu vrednost u trenutku \(t+\Delta_t\). Ta odredjena kamatna stopa je \(F(0, t, t + \Delta_t)\). Time dobijamo jednakost \[(1+R(0, t+\Delta_t))^{t+\Delta_t} = (1+R(0, t))^{t}(1+F(0, t, t + \Delta_t))^{\Delta_t},\] odakle je forvardna kriva \[F(0, t, t + \Delta_t) = \left(\frac{(1+R(0, t+\Delta_t))^{t+\Delta_t}}{(1+R(0, t))^{t}}\right)^{1/\Delta_t} - 1.\]

Pa da resimo zadatak…

Deo a)

Kamatne stope kroz pola godine su:

t <- 0.5
M <- seq(0.5, 3, 0.5) # M as in maturities
R <- c(3, 3.5, 3.75, 4, 5.1, 5.25) / 100
delta_t <- M - t # => M = t + delta_t
# forvardna kriva, tj. buduce kamate kroz pola godine
# u ovom slucaju prolazi indeksiranje R[2*M] jer su vremena dospeca razmaknuti
# na pola godine, a t je isto 1/2 pa se sve slozi. Isto, R[1] = R(0, 1/2)
((1 + R[2*M])^M / (1 + R[1])^t)^(1/delta_t) - 1
[1] 0.00000000 0.04002427 0.04127045 0.04335486 0.05631656 0.05705864
Deo b)

Formula kao pre sa pormenljivom kamatom. Fer cena je

cf <- c(4, 4, 4, 4, 4, 104)
sum(cf / (1 + R)^M)
[1] 108.0221

Za fer cenu za godinu dana treba da izracunamo forvardnu krivu za \(t = 1\). Sada racunamo bez prvog elementa \(M\), jer nam ne treba \(R(0, 1/2)\).

t1 <- 1
delta_t1 <- M[-1] - t1
f <- ((1 + R[2*M[-1]])^M[-1] / (1 + R[2])^t1)^(1/delta_t1) - 1
paste(round(f*100, 2), collapse = "% ")
[1] "0% 4.25% 4.5% 6.18% 6.14"

Sa ovim kamatama racunamo fer cenu za godinu dana. I tok novca se menja.

cf <- c(4, 4, 4, 104)
sum(cf / (1 + f[-1])^M[-(1:2)])
[1] 97.84866

Trece poglavlje

Zadatak 3.1.

Ako je \(\omega\) vektor koeficijenata linearne kombinacije instrumenata, da bismo nasli portfolio sa najmanjom disperzijom, treba da resimo optimizacioni problem \[\min_{\omega}\omega^\top \Sigma \omega,\quad \pmb e^\top \omega = 1,\] gde je \(\Sigma\) kovarijaciona matrica, a \(\pmb e = (1, 1, \dots, 1)^\top\).

Resenje ovog optimizacionog problema je \[\omega = \frac{\Sigma^{-1}\pmb e}{\pmb e^\top\Sigma^{-1}\pmb e},\] sto zapravo predstavlja sumu po redovima inverza matrice \(\Sigma\) i sumu svih elemenata tog inverza.

Stoga je optimalni portfolio

Sigma <- matrix(c(1, 0, 0.5, 0, 2, 0.5, 0.5, 0.5, 1), 3, 3)
invSigma <- solve(Sigma)
(omega <- rowSums(invSigma) / sum(invSigma))
[1] 0.50 0.25 0.25

Ocekivani intenzitet dobiti i disperzija ovakvog portfolia su, redom:

t(c(0.1, 0.15, 0.1)) %*% omega
       [,1]
[1,] 0.1125
t(omega) %*% Sigma %*% omega
      [,1]
[1,] 0.625

Zadatak 3.2.

Portfolio sa najmanjom disperzijom odredujemo optimizacijom kao u prethodnom zadatku.

Sigma <- matrix(c(0.07, -0.005, -0.005, 0.013), 2, 2)
invSigma <- solve(Sigma)
(omega <- rowSums(invSigma)/sum(invSigma))
[1] 0.1935484 0.8064516

Karakteristike ovog portfolia su

r <- c(0.175, 0.055)
(rp <- drop(t(omega) %*% r)) # drop svede na vektor
[1] 0.07822581
(sigmap2 <- drop(t(omega) %*% Sigma %*% omega))
[1] 0.009516129

VaR (Value at Risk, vrednost pri riziku) na nivou poverenja 99% je najmanje \(x\) koje zadovoljava \(P(L\geq x)\leq 0.01\), gde je \(L\) gubitak portfolia za naredni dan.

Ako sa \(X(t)\) oznacimo vrednost portfolia u trenutku \(t\), dobit \(R\) mozemo da predstavimo kao \(R = \frac{X(1) - X(0)}{X(0)}\). Odatle je gubitak \[L = -(X(1) - X(0)) = -R\cdot X(0).\]

Ako pretpostavimo da je intenzitet dobiti \(R\) normalno raspodeljen, sa ocekivanjem \(r_p\) i disperzijom \(\sigma_p^2\), racunanje VaR-a se svodi na odredjivanje \(x\) koje zadovoljava \(P(L\geq x) = 0.01\), odakle, jednostavnim transformacijama, dobijamo da je \[\frac{\frac{-x}{X(0)} - r_p}{\sigma_p} = \Phi^{-1}(0.01) = -2.33,\] odnosno, \[VaR = x = X(0)(2.33\sigma_p - r_p).\]

U nasem zadatku, \(X(0) = 100000\), \(r_p \approx 0.0782\), \(\sigma_p^2 \approx 0.0095\), pa je VaR:

1e5 * (2.33*sqrt(sigmap2) - rp)
[1] 14906.72

Graficki cemo predstaviti efikasan portfolio kroz pricu.

Prvo cemo nacrtati grafik zavisnosti ocekivane dobiti od rizika (std. devijacije). To radimo tako sto uzmemo razne vrednosti koeficijenata \(\omega_i\) konveksne kombinacije nasih akcija i racunamo rizik i ocekivani prinos za tu kombinaciju. Ovaj grafik se ispostavlja da je parabola. Da bismo imali celu parabolu na grafiku, dopusticemo kratku prodaju, tj. da neki parametri \(\omega_i\) budu negativni.

# gomila koeficijenata linearne kobinacije akcija
omg1 <- seq(-0.5, 1.5, length.out = 100)
# 2x100 matrica, svaka kolona je vektor koeficijenata
omega_mat <- sapply(omg1, function(om1) c(om1, 1-om1))
rps <- apply(omega_mat, 2, function(omega) t(omega) %*% r)
sps <- apply(omega_mat, 2, function(omega) sqrt(t(omega) %*% Sigma %*% omega))
plot(sps, rps, type = "l", xlim = c(0, 0.3), ylim = c(0, 0.25), lty = 2)
points(sqrt(sigmap2), rp, col = "green", pch = 19)
points(sqrt(Sigma[1]), r[1], pch = 19)
points(sqrt(Sigma[4]), r[2], pch = 19)

Zelenom tackom smo oznacili nas portfolio sa minimalnom disperzijom, a crnim tackama dve akcije od kojih pravimo portfolio konveksnim kombinacijama. Da nismo dozvolili kratku prodaju, imali bismo samo deo parabole izmedju te dve tacke. Portfolio sa najmanjom disperzijom je, prirodno, na temenu te parabole.

Optimalni portfolio je onaj koji za odredjen rizik daje najveci prinos, sto ovde zapravo znaci da optimalni portfoliji jednostavno cine gornju polovinu parabole, sto cemo i nacrtati.

## grafik od malopre da bismo dobili novu sliku
plot(sps, rps, type = "l", xlim = c(0, 0.3), ylim = c(0, 0.25), lty = 2)
points(sqrt(sigmap2), rp, col = "green", pch = 19)
points(sqrt(Sigma[1]), r[1], pch = 19)
points(sqrt(Sigma[4]), r[2], pch = 19)
## optimalni portfolio je gornja polovina parabole, tj. onaj deo pocevsi od temena
lines(sps[rps >= rp], rps[rps >= rp],
      col = "blue", lwd = 2)

Sada pretpostavimo da imamo i obveznicu sa stopom prinosa \(r_f\), tj bezrizican vrednosni papir. Zelimo da napravimo portfolio koji se sastoji od obveznice i rizicnog portfolia (jednog od onih sa parabole npr.). Neka je udeo rizicnog portfolia u tom kombinovanom portfoliju jednak \(\pi\). Tada, ako sa \(r_m\) oznacimo ocekivanu dobit rizicnog portfolija, a sa \(\sigma_m\) standardnu devijaciju rizicnog portfolija, ocekivanje i disperzija kombinovanog portfolija su: \[\begin{align} r_p &= (1-\pi)r_f + \pi r_m\\ \sigma_p^2 &= \pi^2 \sigma_m^2 \end{align}\] odakle se izvodi da je \[r_p = r_f + \frac{r_m - r_f}{\sigma_m}\sigma_p,\] sto je prava koja spaja tacke \((0, r_f)\) i \((\sigma_m, r_m)\), a koeficijent pravca joj je \(\frac{r_m - r_f}{\sigma_m}\). Ova prava se naziva CAL (Capital Allocation Line), a njen koeficijent pravce Sarpov kolicnik (Sharpe ratio). Prava koja ima najveci Sarpov kolicnik se naziva CML (Capital Market Line). CML ce ujedno biti i tangenta na parabolu odredjenu portfolijima. Tacka u kojoj CML sece parabolu je tangentni portfolio.

Pokazuje se da je tangentni portfolio, kao resenje optimizacionog problema \(\max\limits_\omega\frac{r_m - r_f}{\sigma_m} = \max\limits_\omega\frac{\omega^\top r - r_f}{\sqrt{\omega^\top \Sigma \omega}}\), jednak \[\omega = \frac{\Sigma^{-1}(r-r_f\pmb e)}{\pmb e^\top\Sigma^{-1}(r-r_f\pmb e)},\] gde je \(r\) vektor ocekivanih dobiti akcija u rizicnom portfoliju.

Nacrtajmo CML i tangentni portfolio u nasem slucaju.

## grafik od malopre da bismo dobili novu sliku
plot(sps, rps, type = "l", xlim = c(0, 0.3), ylim = c(0, 0.25), lty = 2)
points(sqrt(sigmap2), rp, col = "green", pch = 19)
points(sqrt(Sigma[1]), r[1], pch = 19)
points(sqrt(Sigma[4]), r[2], pch = 19)
lines(sps[rps >= rp], rps[rps >= rp],
      col = "blue", lwd = 2)
### Trazimo CML i tangentni portfolio
rf <- 0.005
tan_omega <- (invSigma %*% (r - rf)) / sum(invSigma %*% (r - rf))
tan_r <- t(r) %*% tan_omega
tan_s <- sqrt(t(tan_omega) %*% Sigma %*% tan_omega)
points(tan_s, tan_r, col = "red", pch = 19)
points(0, rf, col = "darkgray", pch = 19)
abline(rf, (tan_r - rf)/tan_s, lty = 3)
segments(0, rf, tan_s, tan_r)

Siva tacka je bezrizican vrednosni papir \(r_f\), crvena je tangentni portfolio, tackasta linija je tangenta na parabolu, a crna duz je skup svih kombinovanih portfolija, za razne vrednosti udela rizicnog portfolija \(\pi\).

Primetimo da je, za svako fiksno \(r_p\), kombinovani portfolio sa ove duzi optimalan, tj. bolji od portfolija sa parabole. Samim tim, i tangentni portfolio je optimalan portfolio za ocekivanu dobit koja mu odgovara.

Ocekivana dobit i disperzija optimalnog kombinovanog portfolija sa istom stopom prinosa kao druga firma je tacka u kojoj CML prava (duz) sece pravu \(y = r_2\). Njen rizik je:

(s_opt <- (r[2] - rf) / ((tan_r - rf)/tan_s))
           [,1]
[1,] 0.05899504

Za ovaj izbor portfolija, udeo rizicnog portfolija \(\pi\) je jednak:

s_opt / tan_s
        [,1]
[1,] 0.53563

Zadatak 3.3.

Ovde primenjujemo pricu iz prethodnog zadatka.

Date akcije su zadate sa:

r <- c(0.0427, 0.0016, 0.0285)
Sigma <- matrix(c(0.0100, 0.0018, 0.0011, # prva kolona
                  0.0018, 0.0109, 0.0026,
                  0.0011, 0.0026, 0.0199), 3, 3)

Tangentni portfolio je odredjen kombinacijom:

invSigma <- solve(Sigma)
rf <- 0.005
(tan_omg <- (invSigma %*% (r - rf)) / sum(invSigma %*% (r - rf)))
           [,1]
[1,]  1.0245096
[2,] -0.3230754
[3,]  0.2985658

Njegova disperzija je

t(tan_omg) %*% Sigma %*% tan_omg
           [,1]
[1,] 0.01238761

Disperzija portfolija sa jednakim udelima svih akcija je

omg <- rep(1/3, 3)
t(omg) %*% Sigma %*% omg
            [,1]
[1,] 0.005755556

Ocekivano, manja je disperzija tangentnog portfolija.

Graficki prikaz svih mogucih portfolija je u slucaju tri akcije interesantniji

omg1 <- runif(5e4, -0.5, 1.5) # dozvoljavamo short selling pa cudni omega
omg2 <- runif(5e4, -0.5, 1.5)
omg3 <- 1 - omg1 - omg2
omega_mat <- rbind(omg1, omg2, omg3)
rps <- apply(omega_mat, 2, function(omega) t(omega) %*% r)
sps <- apply(omega_mat, 2, function(omega) sqrt(t(omega) %*% Sigma %*% omega))
plot(sps, rps, pch = ".", xlim = c(0, 0.2), ylim = c(0, 0.06), col = "navy")
points(sqrt(Sigma[1,1]), r[1], pch = 19, col = "red")
points(sqrt(Sigma[2,2]), r[2], pch = 19, col = "red")
points(sqrt(Sigma[3,3]), r[3], pch = 19, col = "red")

Crvene tacke su akcije nase tri firme, a skup sbih konveksnih kombinacija vise nije parabola nego konveksna oblast, oivicena parabolom. Optimalni portfoliji su gornja polovina te parabole, koju ne znam da nacrtam.

Tangentni portfolio i CML se crtaju kao pre

### Prosli grafik
plot(sps, rps, pch = ".", xlim = c(0, 0.2), ylim = c(0, 0.06), col = "navy")
points(sqrt(Sigma[1,1]), r[1], pch = 19, col = "red")
points(sqrt(Sigma[2,2]), r[2], pch = 19, col = "red")
points(sqrt(Sigma[3,3]), r[3], pch = 19, col = "red")
### Trazimo CML i tangentni portfolio
tan_r <- t(r) %*% tan_omg
tan_s <- sqrt(t(tan_omg) %*% Sigma %*% tan_omg)
abline(rf, (tan_r - rf)/tan_s, lty = 3, lwd = 2)
segments(0, rf, tan_s, tan_r, lwd = 2)
points(tan_s, tan_r, col = "green", pch = 19)
points(0, rf, col = "darkgray", pch = 19)

Zelena tacka je tangentni portfolio.

Zadatak 3.8.

Ovo postaje sablon…

r <- c(0.05, 0.12)
Sigma <- matrix(c(0.0064, -0.3*0.08*0.1, -0.3*0.08*0.1, 0.01), 2, 2)
invSigma <- solve(Sigma)
omega <- rowSums(invSigma) / sum(invSigma) # min var
rf <- 0.01
tan_omg <- (invSigma %*% (r - rf)) / sum(invSigma %*% (r - rf))
# ne znam sta je trzisna cena rizika

Peto poglavlje

Zadatak 5.9.

Ovde je bitno da umanjimo trenutnu vrednost akcije za sadasnju vrednost dividendi, pa primenjujemo Black-Scholes-Merton formulu

r <- 0.1
d <- rep(1, 3) # dividende
d_T <- c(1/12, 2/12, 4/12) # vremena dividendi
d_pv <- sum(exp(-r*d_T)*d)
S0 <- 50 - d_pv
K <- 50
vol <- 0.3
# BSM model
callCF(cfBSM, S = S0, X = K, tau = 1/2, r = r, v = vol^2) # v je disperzija, =vol^2
[1] 3.749325
# Drugi nacin
vanillaOptionEuropean(S0, K, 1/2, r, 0, vol^2)$value
[1] 3.749325

Zadatak 5.12.

Ovde treba da odredimo onu volatilnost za koju je Black-Scholes cena opcije jednaka trenutnoj ceni na trzistu. Ako je \(BS(\sigma)\) Black-Scholes cena za volatilnost \(\sigma\), a \(P\) cena opcije na trzistu, resavamo nelinearnu jednacinu \(BS(\sigma) = P\), odnosno trazimo nulu funkcije \(f(\sigma) = BS(\sigma) - P\).

f <- function(vol) {
  callCF(cfBSM, S = 100, X = 110, tau = 1/2, r = 0.05, v = vol^2) - 10
  
  # ili: 
  # vanillaOptionEuropean(100, 110, 1/2, 0.05, 0, vol^2)$value - 10
}
uniroot(f, c(0.001, 1))$root # ako ne radi, probamo da menjamo interval na kom trazimo
[1] 0.4579692
# Drugi nacin (default interval za uniroot je ovde (1e-5, 2))
vanillaOptionImpliedVol("european", 10, 100, 110, 1/2, 0.05)
[1] 0.4580205
# Kad vratimo interval kao pre...
vanillaOptionImpliedVol("european", 10, 100, 110, 1/2, 0.05,
                        uniroot.control = list(interval = c(0.001, 1)))
[1] 0.4579692
LS0tCnRpdGxlOiAiVmV6YmUgaXogZmluYW5zaWpza2UiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYyA6IHRydWUKICAgIHRvY19kZXB0aCA6IDMKICAgIHRvY19mbG9hdCA6IAogICAgICBjb2xsYXBzZWQgOiB0cnVlCi0tLQpVY2l0YXZhbW8gcG90cmVibmUgcGFrZXRlCmBgYHtyLCBldmFsPUZBTFNFLCB3YXJuaW5ncz1GQUxTRX0KbGlicmFyeShGaW5DYWwpCmxpYnJhcnkoZmluYW5jaWFsKQoKbGlicmFyeShZaWVsZEN1cnZlKQpsaWJyYXJ5KE5NT0YpCmBgYAoKIyBQcnZvIHBvZ2xhdmxqZQoKIyMjIFphZGF0YWsgMS4xLgoKVW51dHJhc25qYSBzdG9wYSBkb2JpdGkgamUKYGBge3J9CmlycihjKC0xZTUsIDAsIDUyZTMsIDAsIDU0ZTMpKQpgYGAKbmEgc3RhIGNlbW8gc2UgdnJhdGl0aSB6YSBrb2ppIHRyZW51dGFrLgoKUHJpIHN0b3BpIDEwJSwgaW52ZXN0aXRvciBiaXRpIG5hIGd1Yml0a3UsIHN0byBwb2thenVqZSBzbGVkZWNlLi4uCmBgYHtyfQpwdigwLjEsIDQsIC01NGUzKSArIHB2KDAuMSwgMiwgLTUyZTMpCmBgYAp0ai4gc2FkYXNuamEgdnJlZG5vc3QgZG9iaXRha2EgamUgbWFuamEgb2QgdWxvZ2EsIHByaSBzdG9waSAxMCUuCgpkcnVnaSBuYWNpbi4uLgpgYGB7cn0KbnB2KHIgPSAwLjEsIGMoLTFlNSwgMCwgNTJlMywgMCwgNTRlMykpCmBgYApPdmFqIGJyb2ogamUgZGlyZWt0bm8gcG92ZXphbiBzYSBwcmV0aG9kaW0gamVyIGplIC0yMDE0Mi4wNyArIDEwMDAwMCA9IDc5ODU3LjkzLgoKPiBOZXQgc2FkYXNuamEgdnJlZG5vc3QgKE5ldCBwcmVzZW50IHZhbHVlLCBgbnB2YCkgamUgdSBzdXN0aW5pIHN1bWEgc2FkYXNuamloIHZyZWRub3N0aSBzdmloIGNsYW5vdmEgdG9rYSBub3ZjYSAoenZhbmljbmEgZGVmaW5pY2lqYSBqZSBtYWxvIGRydWdhY2lqYSwgYWxpIGZ1bmtjaWphIGBucHZgIHUgcHJpbmNpcHUgcmFkaSBvdm8pLgoKU3RvZ2Egb3ZvIHVvcHN0ZSBuZSBjdWRpLCBqZXIgc21vIHByZXRob2RubyBpenJhY3VuYWxpIHpiaXIgc2FkYXNuamloIHZyZWRub3N0aSBkb2JpdGFrYS4KCi0tLS0tLS0tLQoKRGEgamUgaW52ZXN0aXRvciBuYSBndWJpdGt1IG1vZ2xpIHNtbyBkYSB6YWtsanVjaW1vIGJleiByYWN1bmEsIGFrbyBzZSB2cmF0aW1vIG5hIGRlZmluaWNpanUgdW51dHJhc25qZSBzdG9wZSBkb2JpdGkKCj4gVW51dHJhc25qYSBzdG9wYSBkb2JpdGkgamUgb25hIHN0b3BhIHBvIGtvam9qIGplIE5QViB0b2thIG5vdmNhIGplZG5ha2EgMC4KCk92byBzZSBkYSB2aWRldGkgbmEgcHJpbWVydS4uLgpgYGB7cn0KbnB2KGlycihjKC0xZTUsIDAsIDUyZTMsIDAsIDU0ZTMpKSwgYygtMWU1LCAwLCA1MmUzLCAwLCA1NGUzKSkKYGBgCnZyZWRub3N0IGplIDAuMDA1IHN0byBuaWplIGJhcyBudWxhLCBhbGkgYnVkdWNpIGRhIGplIHNrYWxhIG5hIGtvam9qIHJhZGltbwpyZWRlIHZhbGljaW5lIHN0byBoaWxqYWRhLCBvdm8gamUgemFuZW1hcmxqaXZhIHJhemxpa2EgcGEgY2VtbyByZWNpIGRhIGplIDAuCgpQb3N0byBqZSBzdG9wYSAxMCUgdmVjYSBvZCAyJSBrb2phIGplIHVudXRyYXNuamEgc3RvcGEgZG9iaXRpLCBtb2dsaSBzbW8gZGEgemFrbHVjaW1vIGRhIGplIGludmVzdGl0b3IgbmEgZ3ViaXRrdSBwcmkgMTAlLCBqZXIgcHJpIHRvaiBzdG9waSBzYWRhc25qYSB2cmVkbm9zdCBidWR1Y2loIGRvYml0YWthIG1vcmEgZGEgYnVkZSBtYW5qYSBuZWdvIHByaSBzdG9waSAyJSwgamVkbm9zdGF2bm8gamVyIGRlbGltbyBzYSAkKDErcilebiQsIHBhIGFrbyBqZSAkciQgdmVjZSwgc2FkYXNuamEgdnJlZG5vc3QgamUgbWFuamEsIHN0byBzbW8gdmlkZWxpIG5hIHBvY2V0a3UuCgojIyMgWmFkYXRhayAxLjIuCgpOZW1hIHN0YSBkYSBzZSBwcmljYS4uLgpgYGB7cn0KY2FzaF9mbG93IDwtIHJlcCg1ZTUsIDIwKSAjIDIwIGdvZGluYSBwbyA1MDBrCm5wdigwLjEsIGNhc2hfZmxvdykKYGBgCk5hcmF2bm8sIHVwb2xhIG1hbmplIG9kIDEwTSBrb2plIHRyZWJhIGRhIGRvYmlqZSBuYWdyYWRqZW5pIDopCgojIyMgWmFkYXRhayAxLjMuCgpPYnVodmF0aWNlbW8gb2JhIHNsdWNhamEgdGFrbyBzdG8gcmFkaW1vIHNhIGBuYCBtZXNlY2ksIHBhIGNlbW8gdXpldGkgNiBpbGkgMTIgemEgcG90cmViZSB6YWRhdGthLgoKQWtvIG5lIG1lbmphanUgb2RsdWt1LCB0b2sgbm92Y2EgY2UgYml0aSAkKFx1bmRlcmJyYWNlezEwMDArMTAwMH1fe1x0ZXh0eyBkZXBveml0ICsgMS4ga2lyaWphfX0sIFx1bmRlcmJyYWNlezEwMDAsXGRvdHMsMTAwMH1fe24tMVx0ZXh0eyBraXJpamF9fSwgXHVuZGVyYnJhY2V7LTEwMDB9X3tcdGV4dHsgdnJhY2VuIGRlcG96aXR9fSkkCgpBa28gbWVuamFqdSBvZGx1a3UsIHRvayBub3ZjYSBqZSAkKFx1bmRlcmJyYWNlezEwMDAgKyA5MDB9X3tcdGV4dHsgZGVwb3ppdCArIHBydmEga2lyaWphfX0sXHVuZGVyYnJhY2V7OTAwLFxkb3RzLDkwMH1fe24tMVx0ZXh0eyBraXJpamF9fSkkIChVIGtuaml6aSBpIG5hIHZlemJhbWEgamUgZHJ1Z2FjaWplIHJhZGplbm8sIGFsaSBqYSBtaXNsaW0gZGEgamUgb3ZvIHRhY25vLCBqZXIga2lyaWp1IG5hIGRydWdvbSBzdGFudSBwbGFjYW1vIG5hIHBvY2V0a3UgbWVzZWNhLCBwYSBuZWNlIHByb2NpIGNlbyBwZXJpb2Qga2FtYWNlbmphIGRvayB1cGxhdGltbyBraXJpanUpLgoKRnVua2NpamEga29qYSByYWN1bmEgc2FkYXNuanUgdnJlZG5vc3QgdG9rYSBub3ZjYSB6YSBvYmUgb2RsdWtlOgpgYGB7cn0KY29tcGFyZV9ucHZzIDwtIGZ1bmN0aW9uKG4pIHsKICBzdGlja193aXRoX2l0X2Nhc2hmbG93IDwtIC1jKDJlMywgcmVwKDFlMywgbi0xKSwgLTFlMykKICBjaGFuZ2Vfb2ZfbWluZF9jYXNoZmxvdyA8LSAtYygxOTAwLCByZXAoOTAwLCBuLTEpKQogIAogIGMoInN0aWNrIHdpdGggaXQiID0gbnB2KDAuMTIsIHN0aWNrX3dpdGhfaXRfY2FzaGZsb3cpLAogICAgImNoYW5nZSBvZiBtaW5kIiA9IG5wdigwLjEyLCBjaGFuZ2Vfb2ZfbWluZF9jYXNoZmxvdykpCn0KYGBgCgpBa28gdXptZW1vIDYgbWVzZWNpLCByZXp1bHRhdCBqZQpgYGB7cn0KY29tcGFyZV9ucHZzKDYpCmBgYApVIHNsdWNhanUgZGEgbmUgbWVuamFtbyBvZGx1a3UsIHBvdHJvc2ltbyBtYW5qZSBwYXJhIG5hIHN0YW4uCgpBa28gdXppbWFtbyBuYSBnb2RpbnUgZGFuYS4uLgoKYGBge3J9CmNvbXBhcmVfbnB2cygxMikKYGBgCi4uLmlzcGxhdGkgc2UgZGEgcHJvbWVuaW1vIG1pc2xqZW5qZS4KCiMjIyBaYWRhdGFrIDEuNC4KCk1vemVtbyBkYSBwcnZvIHZpZGltbyBrb2xpa28gcG8ga2FtYXRub2ogc3RvcGkgNyUgaW52ZXN0aXRvciBkb2JpamUgbmFrb24gMTAgZ29kaW5hLCBwYSBkYSB0byB1bWFuamltbyB6YSBpbmZsYWNpanUKYGBge3J9Cm5vX2luZmxhdGlvbiA8LSA1ZTQgKiAoMSswLjcpXjEwCndpdGhfaW5mbGF0aW9uIDwtIG5vX2luZmxhdGlvbiAvICgxKzAuMyleMTAKCmMobm9faW5mbGF0aW9uLCB3aXRoX2luZmxhdGlvbikKYGBgCgpEYWtsZSwgdnJlZG5vc3QgbmFrb24gdXppbWFuamEgdSBvYnppciBpbmZsYWNpamUgamUgNzMxLDE4Mi4zCgoKIyBEcnVnbyBwb2dsYXZsamUKCiMjIyBaYWRhdGFrIDIuMi4KCk92ZGUgamUgYml0bmEgcHJpY2EgbyBLcml2aSBkb2JpdGkgKGdsYXZhIDIuNiB1IGtuaml6aSkuIFVrcmF0a28sIGltYW1vIHNsZWRlY2UgcG9qbW92ZToKCi0gJEIoMCx0KSQgamUgZmVyIGNlbmEgKipiZXNrdXBvbnNrZSoqIG9idmV6bmljZSwgc2EgKipqZWRpbmljbm9tKiogbmF6bmFjZW5vbSBjZW5vbQotICRSKDAsdCkkIGplIHByb3NlY25hIGthbWF0bmEgc3RvcGEgdSB0cmVudXRrdSAkdCQsIGltcGxpY2lyYW5hIGNlbm9tIGJlc2t1cG9uc2tlIG9idmV6bmljZS4KClRhZGEgamUsIHByaSBzbG96ZW5vbSBrYW1hY2VuanUsICQkQigwLHQpID0gXGZyYWMxeygxK1IoMCx0KSledH0sJCQgdGouIG5vbWluYWxuYSBjZW5hICg9IDEpLCBkaXNrb250b3ZhbmEgemEga2FtYXRudSBzdG9wdSAkUigwLHQpJCBuYWtvbiAkdCQgdnJlbWVuYS4KCkFrbyBiaXNtbyB1dmVsaSAkQl9OKDAsdCkkIGRhIGplIGlzdG8gc3RvIGkgJEIoMCx0KSQsIGFsaSB6YSBuYXpuYWNlbnUgY2VudSAkTiQsIGJpbG8gYmkKJCRCX04oMCx0KSA9IFxmcmFje059eygxK1IoMCx0KSledH0sJCQKaXogaXN0b2cgcmF6bG9nYSBrYW8gbWFsb3ByZS4gT2RhdGxlIGplZG5vc3Rhdm5pbSBzcmVkaml2YW5qZW0gZG9iaWphbW8gZGEgamUKJCRSKDAsdCkgPSBcbGVmdChcZnJhY3tOfXtCX04oMCx0KX1ccmlnaHQpXntcZnJhYzF0fSAtIDEuJCQKSXp2ZWRpbW8gcHJlIHJlc2VuamEgemFkYXRrYSBpIHNhZGFzbmp1IHZyZWRub3N0IG5la29nIHByb2pla3RhICRhID0gKGFfMCwgYV8xLCBcZG90cywgYV9uKSQsIHNhIHRyZW51Y2ltYSB0cmFuc2FrY2lqYSAkKDAsIHRfMSwgXGRvdHMsIHRfbikkCgpQcm9qZWthdCAkYSQgbW96ZW1vIGRhIHBvc21hdHJhbW8ga2FvIGtvbGVrY2lqdSAqKmJlc2t1cG9uc2tpaCoqIG9idmV6bmljYSwgc2EgdHJlbnVjaW1hIGRvc3BlY2EgJDAsIHRfMSwgXGRvdHMsIHRfbiQsIGkgbm9taW5hbG5pbSB2cmVkbm9zdGltYSAkYV8wLCBhXzEsIFxkb3RzLCBhX24kLCByZWRvbS4gU3RvZ2EgamUgc2FkYXNuamEgdnJlZG5vc3QgcHJvamVrdGEgc3VtYSBzYWRhc25qaWggdnJlZG5vc3RpIHRpaCBvYnZlem5pY2EgXGJlZ2lue2FsaWdufSZCX3thXzB9KDAsMCkgKyBCX3thXzF9KDAsIHRfMSkgKyBCX3thXzJ9KDAsdF8yKSArIFxkb3RzICsgQl97YV9ufSgwLCB0X24pXFwgJj1hXzAgKyBhXzFCKDAsIHRfMSkgKyBhXzJCKDAsdF8yKSArIFxkb3RzICsgYV9uQigwLCB0X24pXFwKJj0gYV8wICsgXHN1bV97az0xfV5uIFxmcmFje2Ffa317KDErUigwLHRfaykpXnt0X2t9fS5cZW5ke2FsaWdufQoKVHUgZm9ybXVsdSBjZW1vIGtvcmlzdGl0aSBpIGthc25pamUuCgpEYWtsZSBkYSBzZSB2cmF0aW1vIHphZGF0a3UuLi4KCiMjIyMjIERlbyBhKQpCZXNrdXBvbnNrZSBzdG9wZSBzdS4uLgpgYGB7cn0KTiA8LSAxMApCTiA8LSBjKDkuNzUsIDkuNSwgOS4xLCA4LjUsIDguMywgOCwgNy41OCwgNy4yLCA3LCA2LjgpCnQgPC0gYygwLjUsIDEsIDEuNSwgMS43NSwgMiwgMi41LCAzLjEsIDQsIDUsIDYpCgpSIDwtIChOL0JOKV4oMS90KSAtIDEKcGFzdGUocm91bmQoUioxMDAsIDIpLCBjb2xsYXBzZSA9ICIlICIpCmBgYAoKIyMjIyMgRGVvIGIpCgpQb2xpbm9taWphbG5pIG1vZGVsIGplIHByb3N0byBsaW5lYXJuaSBtb2RlbCBzdG8gem5hbW8gaXogTFNNLWEsIHByZWRpa3Rvcmkgc3UgbmFtIHN0ZXBlbmkgdnJlbWVuYSAkdCQsIGEgemF2aXNuYSBwcm9tZW5saml2YSBzdG9wYSAkUigwLHQpJC4KYGBge3J9Cm1vZGVsIDwtIGxtKFIgfiAxICsgdCArIEkodF4yKSArIEkodF4zKSkKc3VtbWFyeShtb2RlbCkKYGBgClRyZWNpIHN0ZXBlbiBuYW0gaXpnbGVkYSBuZWJpdGFuLCBwYSBjZW1vIGRhIGdhIGl6YmFjaW1vLi4uCmBgYHtyfQptb2RlbDIgPC0gbG0oUiB+IDEgKyB0ICsgSSh0XjIpKQpzdW1tYXJ5KG1vZGVsMikKYGBgClNhZCBqZSBzdmUgem5hY2Fqbm8sIGkgYW5vdmEgbmFtIHBvdHZyZGp1amUgZGEgamUgYm9samkga3ZhZHJhdG5pIHBvbGlub206CmBgYHtyfQphbm92YShtb2RlbDIsIG1vZGVsKQpgYGAKUC12cmVkbm9zdCBqZSB2ZWxpa2EsIHBhIG5lIG9kYmFjdWplbW8gbnVsdHUgaGlwb3RlenUgZGEgc3UgbW9kZWxpIHUgc3VzdGluaSBpc3RpLgoKTmFwcmF2aWNlbW8gaSBOZWxzb24tWmFqZ2Vsb3YgbW9kZWw6CmBgYHtyfQptb2RlbE5TIDwtIGRyb3AoTmVsc29uLlNpZWdlbChSLCB0KSkKIyB6YSBwb3RyZWJlIGZ1bmtjaWplIE5TIHUgbmFzdGF2a3UsIHRyZWJhIGRhIHJlcGFyYW1ldHJpenVqZW1vIGxhbWJkYSBzYSAxL2xhbWJkYQptb2RlbE5TWzRdIDwtIDEvbW9kZWxOU1s0XQpgYGAKCkhhamRlIGRhIGlzcHJhdGltbyBrbmppZ3UsIHBhIGkgZGEgbmFjcnRhbW8gZ3JhZmlrZQpgYGB7cn0KcGxvdCh0LCBSKQp0X2F4aXMgPC0gc2VxKDAuNSwgNiwgbGVuZ3RoLm91dCA9IDEwMCkKbGluZXModF9heGlzLCBwcmVkaWN0KG1vZGVsLCBkYXRhLmZyYW1lKHQgPSB0X2F4aXMpKSwgY29sID0gImJsdWUiKQpsaW5lcyh0X2F4aXMsIHByZWRpY3QobW9kZWwyLCBkYXRhLmZyYW1lKHQgPSB0X2F4aXMpKSwgY29sID0gImdyZWVuIikKbGluZXModF9heGlzLCBOUyhtb2RlbE5TLCB0X2F4aXMpLCBjb2wgPSAicmVkIikKYGBgCgojIyMjIyBEZW8gdikKClUgcHJldGhvZG5vbSBkZWx1IHNtbyBwb3N0YXZpbGkgbW9kZWwgemF2aXNub3N0aSBrYW1hdG5lIHN0b3BlIG9kIHZyZW1lbmEga29yaXN0ZWNpIGNlbmUgb2RyZWRqZW5paCBvYnZlem5pY2Egc2EgdHJ6aXN0YS4gU2FkYSBjZW1vIGRhIGlza29yaXN0aW1vIHRhaiBtb2RlbCBrYW1hdG5paCBzdG9wYSBkYSBpenJhY3VuYW1vIHNhZGFzbmplIHZyZWRub3NpIHByb2pla2F0YSAkUF8xJCBpICRQXzIkLgoKRm9ybXVsYSBwbyBrb2pvaiBjZW1vIHJhY3VuYXRpIHNhZGFzbmp1IHZyZWRub3N0IHByb2pla3RhICQoYV8wLCBhXzEsIFxkb3RzLCBhX24pJCwgZ2RlIHN1IHRyZW51Y2kgJCgwLCB0XzEsIFxkb3RzLCB0X24pJCBqZSBpenZlZGVuYSB1IHByaWNpIG5hIHBvY2V0a3UgemFkYXRrYSBpIGFwcm9rc2ltaXJhbW8gamUgc2E6CiQkYV8wICsgXHN1bV97az0xfV5uIFxmcmFje2Ffa317KDErUigwLHRfaykpXnt0X2t9fVxhcHByb3ggXHN1bV97az0wfV5uIFxmcmFje2Ffa317KDErXGhhdCBSKDAsdF9rKSlee3Rfa319LCQkIGdkZSBqZSAkXGhhdCBSJCBuYXMgbW9kZWwuCgpgYGB7cn0KcDFfdCA8LSAwOjQgKiA4LzEyICMgOCBtZXNlY2kgamUgcmF6bWFrIGl6bWVkanUgdHJhbnNha2NpamEKcDJfdCA8LSAwOjMgKiA4LzEyCgpwMV9SIDwtIHByZWRpY3QobW9kZWwyLCBkYXRhLmZyYW1lKHQgPSBwMV90KSkKcDJfUiA8LSBwcmVkaWN0KG1vZGVsMiwgZGF0YS5mcmFtZSh0ID0gcDJfdCkpCgpwMV9jZiA8LSBjKDEwMCwgLTIwLCA1MCwgMTAsIDIwKQpwMl9jZiA8LSBjKC0yMCwgMTAwLCAxMCwgMzApCgojIHNhZGFzbmphIHZyZWRub3N0IGRpcmVrdG5vIHBvIGZvcm11bGkKcDFfcHYgPC0gc3VtKHAxX2NmIC8gKDEgKyBwMV9SKV5wMV90KQpwMl9wdiA8LSBzdW0ocDJfY2YgLyAoMSArIHAyX1IpXnAyX3QpCgpjKCJQMSIgPSBwMV9wdiwgIlAyIiA9IHAyX3B2KQpgYGAKCkRha2xlLCBib2xqaSBqZSBwcnZpIHByb2pla2F0LgoKVSBrbmppemkgcGlzZSBkYSBiaXNtbyBtb3pkYSBodGVsaSBkYSB1cmFjdW5hbW8gaSB0byBzdG8gc3Ugb3ZhIGR2YSBwcm9qZWt0YSBuYSByYXpsaWNpdGltIHZyZW1lbnNraW0gcGVyaW9kaW1hLCBwYSBiaXNtbyBtb2dsaSBkYSBrb3Jpc3RpbW8gY2lrbHVzZS4gVG8gYmkgcG9kcmF6dW1ldmFsbyBkYSBzdmVkZW1vIG9iYSBwcm9qZWt0YSBuYSBqZWRuYWtlIHZyZW1lbnNrZSBwZXJpb2RlLCB0YWtvIHN0byBzdmFraSBvZCBuamloIHBvbmF2bGphbW8gb25vbGlrbyBwdXRhIGtvbGlrbyBqZSBwb3RyZWJubyBkYSBzZSBkb2JpamUgamVkbmFrIHZyZW1lbnNraSBwZXJpb2QuIEtva3JldG5vLCBvdmRlIGplICRQMSQgbmEgNCBwZXJpb2RhLCBhICRQMiQgbmEgMyAobmUgcmFjdW5hIHNlIG51bHRhIHRyYW5zYWtjaWphKSwgcGEgdHJlYmEgZGEgJFAxJCBwb25vdmltbyAzIHB1dGEsIGEgJFAyJCA0IHB1dGEuIEtvZCBqZSBzbGVkZWNpLCBhIGRldGFsamkgc3Ugb2JqYXNuamVuaSB1IGlzdG9tLgpgYGB7cn0KIyBwb25vdmltbyBwcm9qZWthdCBrIHB1dGEuIGNmIGplIHRvayBub3ZjYSBwcm9qZWt0YQpyZXBlYXRfcHJvamVjdCA8LSBmdW5jdGlvbihjZiwgaykgewogICMgYWtvIGplbmRvbSBwb25hdmxqYW1vLCBuZW1hbW8gc3RhIGRhIHJhZGltbwogIGlmKGsgPT0gMSkKICAgIHJldHVybihjZikKICAKICAjIGRlZmluaXNlbW8ga29tYmlub3ZhbmkgdG9rIG5vdmNhIGtvamkgY2UgZGEgc2FkcnppIGNpa2x1cwogIGNvbWJpbmVkIDwtIGNmCiAgZm9yKGkgaW4gMjprKSB7CiAgICAjIHZyZWRub3N0IGtvbWJpbm92YW5vZyB0b2thIGplIGtvbWJpbm92YW4gdG9rICsgdG9rIG5vdmNhIGtvamkgcG9uYXZsamFtbywgcHJpIGNlbXUgc2UKICAgICMgcG9zbGVkbmphIHZyZWRub3N0IHUgdG9rdSBub3ZjYSBzYWJpcmEgc2EgbnVsdG9tIHZyZWRub3NjdSB0b2thIGtvamkgcG9uYXZsamFtby4gTmEgcHJpbWVyLAogICAgIyBha28gcG9uYXZsamFtbyAoLTEsIDIsIDMpIDIgcHV0YSwgaW1hbW8gKC0xLCAyLCAzIC0gMSwgMiwgMykgPSAoLTEsIDIsIDIsIDIsIDMpCiAgICBjb21iaW5lZCA8LSAgYyhjb21iaW5lZCwgcmVwKDAsIGxlbmd0aChjZikgLSAxKSkgKyBjKHJlcCgwLCBsZW5ndGgoY29tYmluZWQpIC0gMSksIGNmKQogIH0KICAKICBjb21iaW5lZAp9CmBgYAoKRGFrbGUsIGNpa2xpY25pIHByb2pla3RpIHN1CmBgYHtyfQpwMWNfY2YgPC0gcmVwZWF0X3Byb2plY3QocDFfY2YsIDMpCnAyY19jZiA8LSByZXBlYXRfcHJvamVjdChwMl9jZiwgNCkKcDFjX2NmCnAyY19jZgpgYGAKClZpZGltbyBkYSBzdSBuYSBpc3RpbSB2cmVtZW5za2ltIHBlcmlvZGltYS4gU2FkYSBqZSBwb3JlZGplbmplIHNhZGFzbmppaCB2cmVkbm9zdGk6CmBgYHtyfQpwMWNfdCA8LSAwOjEyICogOC8xMiAjIDggbWVzZWNpIGplIHJhem1hayBpem1lZGp1IHRyYW5zYWtjaWphCnAyY190IDwtIDA6MTIgKiA4LzEyCgpwMWNfUiA8LSBwcmVkaWN0KG1vZGVsMiwgZGF0YS5mcmFtZSh0ID0gcDFjX3QpKQpwMmNfUiA8LSBwcmVkaWN0KG1vZGVsMiwgZGF0YS5mcmFtZSh0ID0gcDJjX3QpKQoKIyBzYWRhc25qYSB2cmVkbm9zdCBkaXJla3RubyBwbyBmb3JtdWxpCnAxY19wdiA8LSBzdW0ocDFjX2NmIC8gKDEgKyBwMWNfUilecDFjX3QpCnAyY19wdiA8LSBzdW0ocDJjX2NmIC8gKDEgKyBwMmNfUilecDJjX3QpCgpjKCJQMSIgPSBwMWNfcHYsICJQMiIgPSBwMmNfcHYpCmBgYAoKT3BldCBqZSBib2xqaSBwcnZpIHByb2pla2F0LgoKIyMjIFphZGF0YWsgMi4zLgoKPiBEb2JpdCBkbyBkb3NwZWNhIGplIHVudXRyYXNuamEgc3RvcGEgZG9iaXRpIHRva2Egbm92Y2Egb2RyZWRqZW5vZyBvYnZlem5pY29tLgoKVGFqIHRvayBqZSAoLSBjZW5hIG9idmV6bmljZSAodG8gcGxhY2FtbyksIGt1cG9uLCAuLi4sIGt1cG9uLCBuYXpuYWNlbmEgdnJlZG5vc3QgKyBrdXBvbikuCgpgYGB7cn0KY2YgPC0gYygtMTAxMDAsIDEwMDAsIDEwMDAsIDEwMTAwKQppcnIoY2YpCmBgYAoKIyMjIFphZGF0YWsgMi40LgoKIyMjIyMgRGVvIGEpCgpGZXIgY2VuYSBqZSBzYWRhc25qYSB2cmVkbm9zdCB0b2thIG5vdmNhIG9kcmVkamVub2cgb2J2ZXpuaWNvbS4gVG8gbW96ZW1vIGl6cmFjdW5hdGkga29yc3RlY2kgZnVua2NpanUgYG5wdmAsIGFrbyBzdGF2aW1vIGRhIGplIHBvY2VudG5pIHVsb2cgMC4KCmBgYHtyfQpjZiA8LSBjKDAsIDUsIDUsIDUsIDUsIDEwNSkKbnB2KDAuMDQ5NSwgY2YpCmBgYAoKIyMjIyMgRGVvIGIpCgpaYSBvdm8gc2FtbyBtZW5qYW1vIGthbWF0dSBpIHJhY3VuYW1vIGlzdG8ga2FvIHByZXRob2Ruby4gVXplY2VtbyBncmFuaWNlIHphIHN0b3B1ICgwLCAwLjMpIGplciBqZSB0YWtvIG9kYWJyYW5vIHUga25qaXppCgpgYGB7cn0KIyBzcmVjb20sIG5wdiBqZSB2ZWt0b3Jpem92YW5hIGZ1bmtjaWphLCBwYSBtb3plbW8gZGEgcmFkaW1vIHNhbW8gY3VydmUuCiMgbnB2KHZlYywgY2YpIGNlIHZyYXRpdGkgdmVrdG9yIHNhZGFzbmppaCB2cmVkbm9zdGkgdG9rYSBjZiB6YSBzdmFrdSBvZCBzdG9wYSB1IHZlYwpjdXJ2ZShucHYoeCwgY2YpLCB4bGltID0gYygwLCAwLjMpKQpwb2ludHMoMC4wNDk1LDEwMC4yMTY4KQpgYGAKCiMjIyBaYWRhdGFrIDIuNi4KCk92ZGUga29yaXN0aW1vIGZvcm11bHUgb2QgcmFuaWplIHphIHNhZGFzbmp1IHZyZWRub3N0IHRva2Egc2EgcHJvbWVubGppdm9tIHN0b3BvbSwgJFxzdW1fXGxpbWl0c3trPTB9Xm4gXGZyYWN7YV9rfXsoMStSKDAsdF9rKSlee3Rfa319LiQgUGxhdGlsaSBiaXNtbzoKYGBge3J9CnQgPC0gMToxMCAvIDIKUiA8LSAwLjA1IC0gMC4wMyAqICgxIC0gZXhwKC10KSkgLyB0Ck4gPC0gMWU0CmNmIDwtIGMocmVwKDI1MCwgOSksIDEwMjUwKSAjIDkga3Vwb25hIGkgemFkbmppIGt1cG9uICsgZ2xhdm5pY2EKIyBzYWRhc25qYSB2cmVkbm9zdCBpbGl0aSBmZXIgY2VuYQpzdW0oY2YgLyAoMSArIFIpXnQpCmBgYAoKIyMjIFphZGF0YWsgMi4xNy4KCk92ZGUga29yaXN0aW1vIHBvamFtCgo+IEZvcnZhcmRuYSBrcml2YSAkRigwLCB0LCB0ICsgXERlbHRhX3QpJCBuYW0gZGFqZSB2YXplY3Uga2FtYXRudSBzdG9wdSBrb2p1IG9jZWt1amVtbyBkYSB2YXppIHUgdHJlbnV0a3UgJHQkIHphIHBlcmlvZCAkXERlbHRhX3QkIGltcGxpY2lyYW51IGJlc2t1cG9uc2tvbSBrcml2b20gZG9iaXRpLgoKT3ZvIHpuYWNpIHNsZWRlY2U6IEFrbyBpbWFtbyBiZXNrdXBvbnNrdSBrcml2dSBkb2JpdGkgJFIoMCx0KSQgaSBpbWFtbyBqZWRpbmljbnUgc3VtdSBub3ZjYSwgYnVkdWNhIHZyZWRub3N0IHRvZyBub3ZjYSwgdGouIGZha3RvciBrb2ppbSB1bW5vemF2YW1vIHZyZWRub3N0LCB1IHRyZW51dGt1ICR0K1xEZWx0YV90JCBqZSAkKDErUigwLCB0K1xEZWx0YV90KSlee3QrXERlbHRhX3R9JC4gUyBkcnVnZSBzdHJhbmUsIG1vemVtbyBpIGRhIHBydm8gdXptZW1vIGJ1ZHVjdSB2cmVkbm9zdCB1IHRyZW51dGt1ICR0JCwgdGouICQoMStSKDAsIHQpKV57dH0kLCBwYSBuanUgdW1ub3ppbW8gc2Egb2RyZWRqZW5vbSBrYW1hdG9tIHphIHBlcmlvZCAkXERlbHRhX3QkLCBkYSBkb2JpamVtbyBidWR1Y3UgdnJlZG5vc3QgdSB0cmVudXRrdSAkdCtcRGVsdGFfdCQuIFRhIG9kcmVkamVuYSBrYW1hdG5hIHN0b3BhIGplICRGKDAsIHQsIHQgKyBcRGVsdGFfdCkkLiBUaW1lIGRvYmlqYW1vIGplZG5ha29zdAokJCgxK1IoMCwgdCtcRGVsdGFfdCkpXnt0K1xEZWx0YV90fSA9ICgxK1IoMCwgdCkpXnt0fSgxK0YoMCwgdCwgdCArIFxEZWx0YV90KSlee1xEZWx0YV90fSwkJCBvZGFrbGUgamUgZm9ydmFyZG5hIGtyaXZhCiQkRigwLCB0LCB0ICsgXERlbHRhX3QpID0gXGxlZnQoXGZyYWN7KDErUigwLCB0K1xEZWx0YV90KSlee3QrXERlbHRhX3R9fXsoMStSKDAsIHQpKV57dH19XHJpZ2h0KV57MS9cRGVsdGFfdH0gLSAxLiQkCgpQYSBkYSByZXNpbW8gemFkYXRhay4uLiAKCiMjIyMjIERlbyBhKQoKS2FtYXRuZSBzdG9wZSBrcm96IHBvbGEgZ29kaW5lIHN1OgoKYGBge3J9CnQgPC0gMC41Ck0gPC0gc2VxKDAuNSwgMywgMC41KSAjIE0gYXMgaW4gbWF0dXJpdGllcwpSIDwtIGMoMywgMy41LCAzLjc1LCA0LCA1LjEsIDUuMjUpIC8gMTAwCmRlbHRhX3QgPC0gTSAtIHQgIyA9PiBNID0gdCArIGRlbHRhX3QKCiMgZm9ydmFyZG5hIGtyaXZhLCB0ai4gYnVkdWNlIGthbWF0ZSBrcm96IHBvbGEgZ29kaW5lCiMgdSBvdm9tIHNsdWNhanUgcHJvbGF6aSBpbmRla3NpcmFuamUgUlsyKk1dIGplciBzdSB2cmVtZW5hIGRvc3BlY2EgcmF6bWFrbnV0aQojIG5hIHBvbGEgZ29kaW5lLCBhIHQgamUgaXN0byAxLzIgcGEgc2Ugc3ZlIHNsb3ppLiBJc3RvLCBSWzFdID0gUigwLCAxLzIpCigoMSArIFJbMipNXSleTSAvICgxICsgUlsxXSledCleKDEvZGVsdGFfdCkgLSAxCmBgYAoKIyMjIyMgRGVvIGIpCgpGb3JtdWxhIGthbyBwcmUgc2EgcG9ybWVubGppdm9tIGthbWF0b20uIEZlciBjZW5hIGplCgpgYGB7cn0KY2YgPC0gYyg0LCA0LCA0LCA0LCA0LCAxMDQpCgpzdW0oY2YgLyAoMSArIFIpXk0pCmBgYAoKWmEgZmVyIGNlbnUgemEgZ29kaW51IGRhbmEgdHJlYmEgZGEgaXpyYWN1bmFtbyBmb3J2YXJkbnUga3JpdnUgemEgJHQgPSAxJC4gU2FkYSByYWN1bmFtbyBiZXogcHJ2b2cgZWxlbWVudGEgJE0kLCBqZXIgbmFtIG5lIHRyZWJhICRSKDAsIDEvMikkLgpgYGB7cn0KdDEgPC0gMQpkZWx0YV90MSA8LSBNWy0xXSAtIHQxCgpmIDwtICgoMSArIFJbMipNWy0xXV0pXk1bLTFdIC8gKDEgKyBSWzJdKV50MSleKDEvZGVsdGFfdDEpIC0gMQpwYXN0ZShyb3VuZChmKjEwMCwgMiksIGNvbGxhcHNlID0gIiUgIikKYGBgCgpTYSBvdmltIGthbWF0YW1hIHJhY3VuYW1vIGZlciBjZW51IHphIGdvZGludSBkYW5hLiBJIHRvayBub3ZjYSBzZSBtZW5qYS4KYGBge3J9CmNmIDwtIGMoNCwgNCwgNCwgMTA0KQoKc3VtKGNmIC8gKDEgKyBmWy0xXSleTVstKDE6MildKQpgYGAKCiMgVHJlY2UgcG9nbGF2bGplCgojIyMgWmFkYXRhayAzLjEuCgpBa28gamUgJFxvbWVnYSQgdmVrdG9yIGtvZWZpY2lqZW5hdGEgbGluZWFybmUga29tYmluYWNpamUgaW5zdHJ1bWVuYXRhLCBkYSBiaXNtbyBuYXNsaSBwb3J0Zm9saW8gc2EgbmFqbWFuam9tIGRpc3Blcnppam9tLCB0cmViYSBkYSByZXNpbW8gb3B0aW1pemFjaW9uaSBwcm9ibGVtICQkXG1pbl97XG9tZWdhfVxvbWVnYV5cdG9wIFxTaWdtYSBcb21lZ2EsXHF1YWQgXHBtYiBlXlx0b3AgXG9tZWdhID0gMSwkJCBnZGUgamUgJFxTaWdtYSQga292YXJpamFjaW9uYSBtYXRyaWNhLCBhICRccG1iIGUgPSAoMSwgMSwgXGRvdHMsIDEpXlx0b3AkLgoKUmVzZW5qZSBvdm9nIG9wdGltaXphY2lvbm9nIHByb2JsZW1hIGplICQkXG9tZWdhID0gXGZyYWN7XFNpZ21hXnstMX1ccG1iIGV9e1xwbWIgZV5cdG9wXFNpZ21hXnstMX1ccG1iIGV9LCQkIHN0byB6YXByYXZvIHByZWRzdGF2bGphIHN1bXUgcG8gcmVkb3ZpbWEgaW52ZXJ6YSBtYXRyaWNlICRcU2lnbWEkIGkgc3VtdSBzdmloIGVsZW1lbmF0YSB0b2cgaW52ZXJ6YS4KClN0b2dhIGplIG9wdGltYWxuaSBwb3J0Zm9saW8KYGBge3J9ClNpZ21hIDwtIG1hdHJpeChjKDEsIDAsIDAuNSwgMCwgMiwgMC41LCAwLjUsIDAuNSwgMSksIDMsIDMpCmludlNpZ21hIDwtIHNvbHZlKFNpZ21hKQoob21lZ2EgPC0gcm93U3VtcyhpbnZTaWdtYSkgLyBzdW0oaW52U2lnbWEpKQpgYGAKCk9jZWtpdmFuaSBpbnRlbnppdGV0IGRvYml0aSBpIGRpc3BlcnppamEgb3Zha3ZvZyBwb3J0Zm9saWEgc3UsIHJlZG9tOgpgYGB7cn0KdChjKDAuMSwgMC4xNSwgMC4xKSkgJSolIG9tZWdhCnQob21lZ2EpICUqJSBTaWdtYSAlKiUgb21lZ2EKYGBgCgoKIyMjIFphZGF0YWsgMy4yLgoKUG9ydGZvbGlvIHNhIG5ham1hbmpvbSBkaXNwZXJ6aWpvbSBvZHJlZHVqZW1vIG9wdGltaXphY2lqb20ga2FvIHUgcHJldGhvZG5vbSB6YWRhdGt1LgoKYGBge3J9ClNpZ21hIDwtIG1hdHJpeChjKDAuMDcsIC0wLjAwNSwgLTAuMDA1LCAwLjAxMyksIDIsIDIpCmludlNpZ21hIDwtIHNvbHZlKFNpZ21hKQoob21lZ2EgPC0gcm93U3VtcyhpbnZTaWdtYSkvc3VtKGludlNpZ21hKSkKYGBgCgpLYXJha3RlcmlzdGlrZSBvdm9nIHBvcnRmb2xpYSBzdQpgYGB7cn0KciA8LSBjKDAuMTc1LCAwLjA1NSkKKHJwIDwtIGRyb3AodChvbWVnYSkgJSolIHIpKSAjIGRyb3Agc3ZlZGUgbmEgdmVrdG9yCihzaWdtYXAyIDwtIGRyb3AodChvbWVnYSkgJSolIFNpZ21hICUqJSBvbWVnYSkpCmBgYAoKPiBWYVIgKFZhbHVlIGF0IFJpc2ssIHZyZWRub3N0IHByaSByaXppa3UpIG5hIG5pdm91IHBvdmVyZW5qYSA5OSUgamUgKm5ham1hbmplKiAkeCQga29qZSB6YWRvdm9samF2YSAkUChMXGdlcSB4KVxsZXEgMC4wMSQsIGdkZSBqZSAkTCQgZ3ViaXRhayBwb3J0Zm9saWEgemEgbmFyZWRuaSBkYW4uCgpBa28gc2EgJFgodCkkIG96bmFjaW1vIHZyZWRub3N0IHBvcnRmb2xpYSB1IHRyZW51dGt1ICR0JCwgZG9iaXQgJFIkIG1vemVtbyBkYSBwcmVkc3RhdmltbyBrYW8gJFIgPSBcZnJhY3tYKDEpIC0gWCgwKX17WCgwKX0kLiBPZGF0bGUgamUgZ3ViaXRhayAkJEwgPSAtKFgoMSkgLSBYKDApKSA9IC1SXGNkb3QgWCgwKS4kJAoKQWtvIHByZXRwb3N0YXZpbW8gZGEgamUgaW50ZW56aXRldCBkb2JpdGkgJFIkIG5vcm1hbG5vIHJhc3BvZGVsamVuLCBzYSBvY2VraXZhbmplbSAkcl9wJCBpIGRpc3Blcnppam9tICRcc2lnbWFfcF4yJCwgcmFjdW5hbmplIFZhUi1hIHNlIHN2b2RpIG5hIG9kcmVkaml2YW5qZSAkeCQga29qZSB6YWRvdm9samF2YSAkUChMXGdlcSB4KSA9IDAuMDEkLCBvZGFrbGUsIGplZG5vc3Rhdm5pbSB0cmFuc2Zvcm1hY2lqYW1hLCBkb2JpamFtbyBkYSBqZSAkJFxmcmFje1xmcmFjey14fXtYKDApfSAtIHJfcH17XHNpZ21hX3B9ID0gXFBoaV57LTF9KDAuMDEpID0gLTIuMzMsJCQKb2Rub3NubywgJCRWYVIgPSB4ID0gWCgwKSgyLjMzXHNpZ21hX3AgLSByX3ApLiQkCgpVIG5hc2VtIHphZGF0a3UsICRYKDApID0gMTAwMDAwJCwgJHJfcCBcYXBwcm94IDAuMDc4MiQsICRcc2lnbWFfcF4yIFxhcHByb3ggMC4wMDk1JCwgcGEgamUgVmFSOgpgYGB7cn0KMWU1ICogKDIuMzMqc3FydChzaWdtYXAyKSAtIHJwKQpgYGAKCkdyYWZpY2tpIGNlbW8gcHJlZHN0YXZpdGkgZWZpa2FzYW4gcG9ydGZvbGlvIGtyb3ogcHJpY3UuCgpQcnZvIGNlbW8gbmFjcnRhdGkgZ3JhZmlrIHphdmlzbm9zdGkgb2Nla2l2YW5lIGRvYml0aSBvZCByaXppa2EgKHN0ZC4gZGV2aWphY2lqZSkuIFRvIHJhZGltbyB0YWtvIHN0byB1em1lbW8gcmF6bmUgdnJlZG5vc3RpIGtvZWZpY2lqZW5hdGEgJFxvbWVnYV9pJCBrb252ZWtzbmUga29tYmluYWNpamUgbmFzaWggYWtjaWphIGkgcmFjdW5hbW8gcml6aWsgaSBvY2VraXZhbmkgcHJpbm9zIHphIHR1IGtvbWJpbmFjaWp1LiBPdmFqIGdyYWZpayBzZSBpc3Bvc3RhdmxqYSBkYSBqZSBwYXJhYm9sYS4gRGEgYmlzbW8gaW1hbGkgY2VsdSBwYXJhYm9sdSBuYSBncmFmaWt1LCBkb3B1c3RpY2VtbyBrcmF0a3UgcHJvZGFqdSwgdGouIGRhIG5la2kgcGFyYW1ldHJpICRcb21lZ2FfaSQgYnVkdSBuZWdhdGl2bmkuCmBgYHtyfQojIGdvbWlsYSBrb2VmaWNpamVuYXRhIGxpbmVhcm5lIGtvYmluYWNpamUgYWtjaWphCm9tZzEgPC0gc2VxKC0wLjUsIDEuNSwgbGVuZ3RoLm91dCA9IDEwMCkKCiMgMngxMDAgbWF0cmljYSwgc3Zha2Ega29sb25hIGplIHZla3RvciBrb2VmaWNpamVuYXRhCm9tZWdhX21hdCA8LSBzYXBwbHkob21nMSwgZnVuY3Rpb24ob20xKSBjKG9tMSwgMS1vbTEpKQoKcnBzIDwtIGFwcGx5KG9tZWdhX21hdCwgMiwgZnVuY3Rpb24ob21lZ2EpIHQob21lZ2EpICUqJSByKQpzcHMgPC0gYXBwbHkob21lZ2FfbWF0LCAyLCBmdW5jdGlvbihvbWVnYSkgc3FydCh0KG9tZWdhKSAlKiUgU2lnbWEgJSolIG9tZWdhKSkKCnBsb3Qoc3BzLCBycHMsIHR5cGUgPSAibCIsIHhsaW0gPSBjKDAsIDAuMyksIHlsaW0gPSBjKDAsIDAuMjUpLCBsdHkgPSAyKQpwb2ludHMoc3FydChzaWdtYXAyKSwgcnAsIGNvbCA9ICJncmVlbiIsIHBjaCA9IDE5KQpwb2ludHMoc3FydChTaWdtYVsxXSksIHJbMV0sIHBjaCA9IDE5KQpwb2ludHMoc3FydChTaWdtYVs0XSksIHJbMl0sIHBjaCA9IDE5KQpgYGAKWmVsZW5vbSB0YWNrb20gc21vIG96bmFjaWxpIG5hcyBwb3J0Zm9saW8gc2EgbWluaW1hbG5vbSBkaXNwZXJ6aWpvbSwgYSBjcm5pbSB0YWNrYW1hIGR2ZSBha2NpamUgb2Qga29qaWggcHJhdmltbyBwb3J0Zm9saW8ga29udmVrc25pbSBrb21iaW5hY2lqYW1hLiBEYSBuaXNtbyBkb3p2b2xpbGkga3JhdGt1IHByb2RhanUsIGltYWxpIGJpc21vIHNhbW8gZGVvIHBhcmFib2xlIGl6bWVkanUgdGUgZHZlIHRhY2tlLiBQb3J0Zm9saW8gc2EgbmFqbWFuam9tIGRpc3Blcnppam9tIGplLCBwcmlyb2RubywgbmEgdGVtZW51IHRlIHBhcmFib2xlLgoKT3B0aW1hbG5pIHBvcnRmb2xpbyBqZSBvbmFqIGtvamkgemEgb2RyZWRqZW4gcml6aWsgZGFqZSBuYWp2ZWNpIHByaW5vcywgc3RvIG92ZGUgemFwcmF2byB6bmFjaSBkYSBvcHRpbWFsbmkgcG9ydGZvbGlqaSBqZWRub3N0YXZubyBjaW5lIGdvcm5qdSBwb2xvdmludSBwYXJhYm9sZSwgc3RvIGNlbW8gaSBuYWNydGF0aS4KYGBge3J9CiMjIGdyYWZpayBvZCBtYWxvcHJlIGRhIGJpc21vIGRvYmlsaSBub3Z1IHNsaWt1CnBsb3Qoc3BzLCBycHMsIHR5cGUgPSAibCIsIHhsaW0gPSBjKDAsIDAuMyksIHlsaW0gPSBjKDAsIDAuMjUpLCBsdHkgPSAyKQpwb2ludHMoc3FydChzaWdtYXAyKSwgcnAsIGNvbCA9ICJncmVlbiIsIHBjaCA9IDE5KQpwb2ludHMoc3FydChTaWdtYVsxXSksIHJbMV0sIHBjaCA9IDE5KQpwb2ludHMoc3FydChTaWdtYVs0XSksIHJbMl0sIHBjaCA9IDE5KQoKIyMgb3B0aW1hbG5pIHBvcnRmb2xpbyBqZSBnb3JuamEgcG9sb3ZpbmEgcGFyYWJvbGUKbGluZXMoc3BzW3JwcyA+PSBycF0sIHJwc1tycHMgPj0gcnBdLCBjb2wgPSAiYmx1ZSIsIGx3ZCA9IDIpCmBgYAoKU2FkYSBwcmV0cG9zdGF2aW1vIGRhIGltYW1vIGkgb2J2ZXpuaWN1IHNhIHN0b3BvbSBwcmlub3NhICRyX2YkLCB0aiBiZXpyaXppY2FuIHZyZWRub3NuaSBwYXBpci4gWmVsaW1vIGRhIG5hcHJhdmltbyBwb3J0Zm9saW8ga29qaSBzZSBzYXN0b2ppIG9kIG9idmV6bmljZSBpIHJpemljbm9nIHBvcnRmb2xpYSAoamVkbm9nIG9kIG9uaWggc2EgcGFyYWJvbGUgbnByLikuIE5la2EgamUgdWRlbyByaXppY25vZyBwb3J0Zm9saWEgdSB0b20ga29tYmlub3Zhbm9tIHBvcnRmb2xpanUgamVkbmFrICRccGkkLiBUYWRhLCBha28gc2EgJHJfbSQgb3puYWNpbW8gb2Nla2l2YW51IGRvYml0IHJpemljbm9nIHBvcnRmb2xpamEsIGEgc2EgJFxzaWdtYV9tJCBzdGFuZGFyZG51IGRldmlqYWNpanUgcml6aWNub2cgcG9ydGZvbGlqYSwgb2Nla2l2YW5qZSBpIGRpc3BlcnppamEga29tYmlub3Zhbm9nIHBvcnRmb2xpamEgc3U6ClxiZWdpbnthbGlnbn0Kcl9wICY9ICgxLVxwaSlyX2YgKyBccGkgcl9tXFwKXHNpZ21hX3BeMiAmPSBccGleMiBcc2lnbWFfbV4yClxlbmR7YWxpZ259Cm9kYWtsZSBzZSBpenZvZGkgZGEgamUgJCRyX3AgPSByX2YgKyBcZnJhY3tyX20gLSByX2Z9e1xzaWdtYV9tfVxzaWdtYV9wLCQkCnN0byBqZSBwcmF2YSBrb2phIHNwYWphIHRhY2tlICQoMCwgcl9mKSQgaSAkKFxzaWdtYV9tLCByX20pJCwgYSBrb2VmaWNpamVudCBwcmF2Y2Egam9qIGplICAkXGZyYWN7cl9tIC0gcl9mfXtcc2lnbWFfbX0kLiBPdmEgcHJhdmEgc2UgbmF6aXZhIENBTCAoQ2FwaXRhbCBBbGxvY2F0aW9uIExpbmUpLCBhIG5qZW4ga29lZmljaWplbnQgcHJhdmNlIFNhcnBvdiBrb2xpY25payAoU2hhcnBlIHJhdGlvKS4gUHJhdmEga29qYSBpbWEgbmFqdmVjaSBTYXJwb3Yga29saWNuaWsgc2UgbmF6aXZhIENNTCAoQ2FwaXRhbCBNYXJrZXQgTGluZSkuIENNTCBjZSB1amVkbm8gYml0aSBpIHRhbmdlbnRhIG5hIHBhcmFib2x1IG9kcmVkamVudSBwb3J0Zm9saWppbWEuIFRhY2thIHUga29qb2ogQ01MIHNlY2UgcGFyYWJvbHUgamUgKip0YW5nZW50bmkgcG9ydGZvbGlvKiouCgpQb2thenVqZSBzZSBkYSBqZSB0YW5nZW50bmkgcG9ydGZvbGlvLCBrYW8gcmVzZW5qZSBvcHRpbWl6YWNpb25vZyBwcm9ibGVtYSAkXG1heFxsaW1pdHNfXG9tZWdhXGZyYWN7cl9tIC0gcl9mfXtcc2lnbWFfbX0gPSBcbWF4XGxpbWl0c19cb21lZ2FcZnJhY3tcb21lZ2FeXHRvcCByIC0gcl9mfXtcc3FydHtcb21lZ2FeXHRvcCBcU2lnbWEgXG9tZWdhfX0kLCBqZWRuYWsKJCRcb21lZ2EgPSBcZnJhY3tcU2lnbWFeey0xfShyLXJfZlxwbWIgZSl9e1xwbWIgZV5cdG9wXFNpZ21hXnstMX0oci1yX2ZccG1iIGUpfSwkJCBnZGUgamUgJHIkIHZla3RvciBvY2VraXZhbmloIGRvYml0aSBha2NpamEgdSByaXppY25vbSBwb3J0Zm9saWp1LgoKTmFjcnRham1vIENNTCBpIHRhbmdlbnRuaSBwb3J0Zm9saW8gdSBuYXNlbSBzbHVjYWp1LgpgYGB7cn0KIyMgZ3JhZmlrIG9kIG1hbG9wcmUgZGEgYmlzbW8gZG9iaWxpIG5vdnUgc2xpa3UKcGxvdChzcHMsIHJwcywgdHlwZSA9ICJsIiwgeGxpbSA9IGMoMCwgMC4zKSwgeWxpbSA9IGMoMCwgMC4yNSksIGx0eSA9IDIpCnBvaW50cyhzcXJ0KHNpZ21hcDIpLCBycCwgY29sID0gImdyZWVuIiwgcGNoID0gMTkpCnBvaW50cyhzcXJ0KFNpZ21hWzFdKSwgclsxXSwgcGNoID0gMTkpCnBvaW50cyhzcXJ0KFNpZ21hWzRdKSwgclsyXSwgcGNoID0gMTkpCmxpbmVzKHNwc1tycHMgPj0gcnBdLCBycHNbcnBzID49IHJwXSwKICAgICAgY29sID0gImJsdWUiLCBsd2QgPSAyKQoKIyMjIFRyYXppbW8gQ01MIGkgdGFuZ2VudG5pIHBvcnRmb2xpbwpyZiA8LSAwLjAwNQp0YW5fb21lZ2EgPC0gKGludlNpZ21hICUqJSAociAtIHJmKSkgLyBzdW0oaW52U2lnbWEgJSolIChyIC0gcmYpKQp0YW5fciA8LSB0KHIpICUqJSB0YW5fb21lZ2EKdGFuX3MgPC0gc3FydCh0KHRhbl9vbWVnYSkgJSolIFNpZ21hICUqJSB0YW5fb21lZ2EpCgpwb2ludHModGFuX3MsIHRhbl9yLCBjb2wgPSAicmVkIiwgcGNoID0gMTkpCnBvaW50cygwLCByZiwgY29sID0gImRhcmtncmF5IiwgcGNoID0gMTkpCmFibGluZShyZiwgKHRhbl9yIC0gcmYpL3Rhbl9zLCBsdHkgPSAzKQpzZWdtZW50cygwLCByZiwgdGFuX3MsIHRhbl9yKQpgYGAKClNpdmEgdGFja2EgamUgYmV6cml6aWNhbiB2cmVkbm9zbmkgcGFwaXIgJHJfZiQsIGNydmVuYSBqZSB0YW5nZW50bmkgcG9ydGZvbGlvLCB0YWNrYXN0YSBsaW5pamEgamUgdGFuZ2VudGEgbmEgcGFyYWJvbHUsIGEgY3JuYSBkdXogamUgc2t1cCBzdmloIGtvbWJpbm92YW5paCBwb3J0Zm9saWphLCB6YSByYXpuZSB2cmVkbm9zdGkgdWRlbGEgcml6aWNub2cgcG9ydGZvbGlqYSAkXHBpJC4KClByaW1ldGltbyBkYSBqZSwgemEgc3Zha28gZmlrc25vICRyX3AkLCBrb21iaW5vdmFuaSBwb3J0Zm9saW8gc2Egb3ZlIGR1emkgb3B0aW1hbGFuLCB0ai4gYm9samkgb2QgcG9ydGZvbGlqYSBzYSBwYXJhYm9sZS4gU2FtaW0gdGltLCBpIHRhbmdlbnRuaSBwb3J0Zm9saW8gamUgb3B0aW1hbGFuIHBvcnRmb2xpbyB6YSBvY2VraXZhbnUgZG9iaXQga29qYSBtdSBvZGdvdmFyYS4KCk9jZWtpdmFuYSBkb2JpdCBpIGRpc3BlcnppamEgb3B0aW1hbG5vZyBrb21iaW5vdmFub2cgcG9ydGZvbGlqYSBzYSBpc3RvbSBzdG9wb20gcHJpbm9zYSBrYW8gZHJ1Z2EgZmlybWEgamUgdGFja2EgdSBrb2pvaiBDTUwgcHJhdmEgKGR1eikgc2VjZSBwcmF2dSAkeSA9IHJfMiQuIE5qZW4gcml6aWsgamU6CmBgYHtyfQooc19vcHQgPC0gKHJbMl0gLSByZikgLyAoKHRhbl9yIC0gcmYpL3Rhbl9zKSkKYGBgClphIG92YWogaXpib3IgcG9ydGZvbGlqYSwgdWRlbyByaXppY25vZyBwb3J0Zm9saWphICRccGkkIGplIGplZG5hazoKYGBge3J9CnNfb3B0IC8gdGFuX3MKYGBgCgojIyMgWmFkYXRhayAzLjMuCgpPdmRlIHByaW1lbmp1amVtbyBwcmljdSBpeiBwcmV0aG9kbm9nIHphZGF0a2EuCgpEYXRlIGFrY2lqZSBzdSB6YWRhdGUgc2E6CmBgYHtyfQpyIDwtIGMoMC4wNDI3LCAwLjAwMTYsIDAuMDI4NSkKU2lnbWEgPC0gbWF0cml4KGMoMC4wMTAwLCAwLjAwMTgsIDAuMDAxMSwgIyBwcnZhIGtvbG9uYQogICAgICAgICAgICAgICAgICAwLjAwMTgsIDAuMDEwOSwgMC4wMDI2LAogICAgICAgICAgICAgICAgICAwLjAwMTEsIDAuMDAyNiwgMC4wMTk5KSwgMywgMykKYGBgClRhbmdlbnRuaSBwb3J0Zm9saW8gamUgb2RyZWRqZW4ga29tYmluYWNpam9tOgpgYGB7cn0KaW52U2lnbWEgPC0gc29sdmUoU2lnbWEpCnJmIDwtIDAuMDA1Cih0YW5fb21nIDwtIChpbnZTaWdtYSAlKiUgKHIgLSByZikpIC8gc3VtKGludlNpZ21hICUqJSAociAtIHJmKSkpCmBgYApOamVnb3ZhIGRpc3BlcnppamEgamUKYGBge3J9CnQodGFuX29tZykgJSolIFNpZ21hICUqJSB0YW5fb21nCmBgYApEaXNwZXJ6aWphIHBvcnRmb2xpamEgc2EgamVkbmFraW0gdWRlbGltYSBzdmloIGFrY2lqYSBqZQpgYGB7cn0Kb21nIDwtIHJlcCgxLzMsIDMpCnQob21nKSAlKiUgU2lnbWEgJSolIG9tZwpgYGAKT2Nla2l2YW5vLCBtYW5qYSBqZSBkaXNwZXJ6aWphIHRhbmdlbnRub2cgcG9ydGZvbGlqYS4KCkdyYWZpY2tpIHByaWtheiBzdmloIG1vZ3VjaWggcG9ydGZvbGlqYSBqZSB1IHNsdWNhanUgdHJpIGFrY2lqZSBpbnRlcmVzYW50bmlqaQoKYGBge3J9Cm9tZzEgPC0gcnVuaWYoNWU0LCAtMC41LCAxLjUpICMgZG96dm9samF2YW1vIHNob3J0IHNlbGxpbmcgcGEgY3Vkbmkgb21lZ2EKb21nMiA8LSBydW5pZig1ZTQsIC0wLjUsIDEuNSkKb21nMyA8LSAxIC0gb21nMSAtIG9tZzIKb21lZ2FfbWF0IDwtIHJiaW5kKG9tZzEsIG9tZzIsIG9tZzMpCgpycHMgPC0gYXBwbHkob21lZ2FfbWF0LCAyLCBmdW5jdGlvbihvbWVnYSkgdChvbWVnYSkgJSolIHIpCnNwcyA8LSBhcHBseShvbWVnYV9tYXQsIDIsIGZ1bmN0aW9uKG9tZWdhKSBzcXJ0KHQob21lZ2EpICUqJSBTaWdtYSAlKiUgb21lZ2EpKQpwbG90KHNwcywgcnBzLCBwY2ggPSAiLiIsIHhsaW0gPSBjKDAsIDAuMiksIHlsaW0gPSBjKDAsIDAuMDYpLCBjb2wgPSAibmF2eSIpCnBvaW50cyhzcXJ0KFNpZ21hWzEsMV0pLCByWzFdLCBwY2ggPSAxOSwgY29sID0gInJlZCIpCnBvaW50cyhzcXJ0KFNpZ21hWzIsMl0pLCByWzJdLCBwY2ggPSAxOSwgY29sID0gInJlZCIpCnBvaW50cyhzcXJ0KFNpZ21hWzMsM10pLCByWzNdLCBwY2ggPSAxOSwgY29sID0gInJlZCIpCmBgYApDcnZlbmUgdGFja2Ugc3UgYWtjaWplIG5hc2UgdHJpIGZpcm1lLCBhIHNrdXAgc2JpaCBrb252ZWtzbmloIGtvbWJpbmFjaWphIHZpc2UgbmlqZSBwYXJhYm9sYSBuZWdvIGtvbnZla3NuYSBvYmxhc3QsIG9pdmljZW5hIHBhcmFib2xvbS4gT3B0aW1hbG5pIHBvcnRmb2xpamkgc3UgZ29ybmphIHBvbG92aW5hIHRlIHBhcmFib2xlLCBrb2p1IG5lIHpuYW0gZGEgbmFjcnRhbS4KClRhbmdlbnRuaSBwb3J0Zm9saW8gaSBDTUwgc2UgY3J0YWp1IGthbyBwcmUKYGBge3J9CiMjIyBQcm9zbGkgZ3JhZmlrCnBsb3Qoc3BzLCBycHMsIHBjaCA9ICIuIiwgeGxpbSA9IGMoMCwgMC4yKSwgeWxpbSA9IGMoMCwgMC4wNiksIGNvbCA9ICJuYXZ5IikKcG9pbnRzKHNxcnQoU2lnbWFbMSwxXSksIHJbMV0sIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKcG9pbnRzKHNxcnQoU2lnbWFbMiwyXSksIHJbMl0sIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKcG9pbnRzKHNxcnQoU2lnbWFbMywzXSksIHJbM10sIHBjaCA9IDE5LCBjb2wgPSAicmVkIikKCiMjIyBUcmF6aW1vIENNTCBpIHRhbmdlbnRuaSBwb3J0Zm9saW8KdGFuX3IgPC0gdChyKSAlKiUgdGFuX29tZwp0YW5fcyA8LSBzcXJ0KHQodGFuX29tZykgJSolIFNpZ21hICUqJSB0YW5fb21nKQoKYWJsaW5lKHJmLCAodGFuX3IgLSByZikvdGFuX3MsIGx0eSA9IDMsIGx3ZCA9IDIpCnNlZ21lbnRzKDAsIHJmLCB0YW5fcywgdGFuX3IsIGx3ZCA9IDIpCnBvaW50cyh0YW5fcywgdGFuX3IsIGNvbCA9ICJncmVlbiIsIHBjaCA9IDE5KQpwb2ludHMoMCwgcmYsIGNvbCA9ICJkYXJrZ3JheSIsIHBjaCA9IDE5KQpgYGAKClplbGVuYSB0YWNrYSBqZSB0YW5nZW50bmkgcG9ydGZvbGlvLgoKIyMjIFphZGF0YWsgMy44LgoKT3ZvIHBvc3RhamUgc2FibG9uLi4uCmBgYHtyfQpyIDwtIGMoMC4wNSwgMC4xMikKU2lnbWEgPC0gbWF0cml4KGMoMC4wMDY0LCAtMC4zKjAuMDgqMC4xLCAtMC4zKjAuMDgqMC4xLCAwLjAxKSwgMiwgMikKaW52U2lnbWEgPC0gc29sdmUoU2lnbWEpCm9tZWdhIDwtIHJvd1N1bXMoaW52U2lnbWEpIC8gc3VtKGludlNpZ21hKSAjIG1pbiB2YXIKCnJmIDwtIDAuMDEKdGFuX29tZyA8LSAoaW52U2lnbWEgJSolIChyIC0gcmYpKSAvIHN1bShpbnZTaWdtYSAlKiUgKHIgLSByZikpCgojIG5lIHpuYW0gc3RhIGplIHRyemlzbmEgY2VuYSByaXppa2EKYGBgCgojIFBldG8gcG9nbGF2bGplCgojIyMgWmFkYXRhayA1LjkuCgpPdmRlIGplIGJpdG5vIGRhIHVtYW5qaW1vIHRyZW51dG51IHZyZWRub3N0IGFrY2lqZSB6YSBzYWRhc25qdSB2cmVkbm9zdCBkaXZpZGVuZGksIHBhIHByaW1lbmp1amVtbyBCbGFjay1TY2hvbGVzLU1lcnRvbiBmb3JtdWx1CgpgYGB7cn0KciA8LSAwLjEKZCA8LSByZXAoMSwgMykgIyBkaXZpZGVuZGUKZF9UIDwtIGMoMS8xMiwgMi8xMiwgNC8xMikgIyB2cmVtZW5hIGRpdmlkZW5kaQpkX3B2IDwtIHN1bShleHAoLXIqZF9UKSpkKQoKUzAgPC0gNTAgLSBkX3B2CksgPC0gNTAKdm9sIDwtIDAuMwoKIyBCU00gbW9kZWwKY2FsbENGKGNmQlNNLCBTID0gUzAsIFggPSBLLCB0YXUgPSAxLzIsIHIgPSByLCB2ID0gdm9sXjIpICMgdiBqZSBkaXNwZXJ6aWphLCA9dm9sXjIKCiMgRHJ1Z2kgbmFjaW4gKE92YSBmdW5rY2lqYSBwcmlodmF0YSBpIGFyZ3VtZW50IHR5cGU9YygiY2FsbCIsICJwdXQiKSkKdmFuaWxsYU9wdGlvbkV1cm9wZWFuKFMwLCBLLCAxLzIsIHIsIDAsIHZvbF4yKSR2YWx1ZQpgYGAKCiMjIyBaYWRhdGFrIDUuMTIuCgpPdmRlIHRyZWJhIGRhIG9kcmVkaW1vIG9udSB2b2xhdGlsbm9zdCB6YSBrb2p1IGplIEJsYWNrLVNjaG9sZXMgY2VuYSBvcGNpamUgamVkbmFrYSB0cmVudXRub2ogY2VuaSBuYSB0cnppc3R1LiBBa28gamUgJEJTKFxzaWdtYSkkIEJsYWNrLVNjaG9sZXMgY2VuYSB6YSB2b2xhdGlsbm9zdCAkXHNpZ21hJCwgYSAkUCQgY2VuYSBvcGNpamUgbmEgdHJ6aXN0dSwgcmVzYXZhbW8gbmVsaW5lYXJudSBqZWRuYWNpbnUgJEJTKFxzaWdtYSkgPSBQJCwgb2Rub3NubyB0cmF6aW1vIG51bHUgZnVua2NpamUgJGYoXHNpZ21hKSA9IEJTKFxzaWdtYSkgLSBQJC4KYGBge3J9CmYgPC0gZnVuY3Rpb24odm9sKSB7CiAgY2FsbENGKGNmQlNNLCBTID0gMTAwLCBYID0gMTEwLCB0YXUgPSAxLzIsIHIgPSAwLjA1LCB2ID0gdm9sXjIpIC0gMTAKICAKICAjIGlsaTogCiAgIyB2YW5pbGxhT3B0aW9uRXVyb3BlYW4oMTAwLCAxMTAsIDEvMiwgMC4wNSwgMCwgdm9sXjIpJHZhbHVlIC0gMTAKfQoKdW5pcm9vdChmLCBjKDAuMDAxLCAxKSkkcm9vdCAjIGFrbyBuZSByYWRpLCBwcm9iYW1vIGRhIG1lbmphbW8gaW50ZXJ2YWwgbmEga29tIHRyYXppbW8KCgojIERydWdpIG5hY2luIChkZWZhdWx0IGludGVydmFsIHphIHVuaXJvb3QgamUgb3ZkZSAoMWUtNSwgMikpCnZhbmlsbGFPcHRpb25JbXBsaWVkVm9sKCJldXJvcGVhbiIsIDEwLCAxMDAsIDExMCwgMS8yLCAwLjA1KQoKIyBLYWQgdnJhdGltbyBpbnRlcnZhbCBrYW8gcHJlLi4uCnZhbmlsbGFPcHRpb25JbXBsaWVkVm9sKCJldXJvcGVhbiIsIDEwLCAxMDAsIDExMCwgMS8yLCAwLjA1LAogICAgICAgICAgICAgICAgICAgICAgICB1bmlyb290LmNvbnRyb2wgPSBsaXN0KGludGVydmFsID0gYygwLjAwMSwgMSkpKQpgYGAKCgoKCg==