Partie 1 Régression Linéaire

A) Statistique descriptive et démographie de la Finlande


library(tidyverse)
library(readxl)
library(lmtest)
library(sandwich)
library(tseries)
library(car)        # VIF
library(zoo)
library(forecast)
library(urca)       # tests de racine unitaire, cointégration
library(strucchange) # test RESET / breakpoints
library(fUnitRoots)  # alternatives ADF/KPSS
library(tseries)     # jarque.bera, adf.test
library(tsibble)
library(feasts)


path_to_file <- "data_schularick.xlsx"

# Pays d'intérêt 

votre_pays <- "Finland"  

library(tidyverse)
library(readxl)

# Fichier Excel
path_to_file <- "data_schularick.xlsx"

# Charger les données
data_schularick <- read_excel(path_to_file)


# Préparation du dataset
donnees_df <- data_schularick %>%
  filter(country == votre_pays) %>%
  arrange(year) %>%
  filter(year > 1960) %>%
  select(year, gdp, debtgdp) %>%
  mutate(gdp_growth = c(NA, diff(log(gdp)))) %>%
  na.omit()

# Vérification
glimpse(donnees_df)
Rows: 59
Columns: 4
$ year       <dbl> 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973…
$ gdp        <dbl> 19661.0, 21352.0, 24083.0, 26634.0, 28554.0, 31321.0, 35908.0, 40986.0…
$ debtgdp    <dbl> 0.115200, 0.134400, 0.136300, 0.142300, 0.151800, 0.158300, 0.156900, …
$ gdp_growth <dbl> 0.06835367, 0.08250843, 0.12036079, 0.10068240, 0.06960844, 0.09249177…

Ici, les données du fichier Schularick sont importées, puis filtrées pour ne garder que les observations concernant la Finlande après 1960. Seules les variables PIB et dette/PIB sont conservées et la série est mise dans l’ordre chronologique. La croissance du PIB est ensuite calculée à partir du logarithme du PIB, et les lignes manquantes sont retirées. Enfin, la structure du jeu de données obtenu est affichée.

donnees_df_clean <- donnees_df %>%
  mutate(
    gdp = round(gdp, 2),
    debtgdp = round(debtgdp * 100, 2),      # en pourcent
    gdp_growth = round(gdp_growth * 100, 2) # croissance en pourcent
  ) %>%
  rename(
    Année = year,
    PIB = gdp,
    Dette_en_PIB = debtgdp,
    Croissance_PIB = gdp_growth
  )

donnees_df_clean
NA

les variables sont mises en forme pour plus de lisibilité : le PIB reste arrondi à deux décimales, tandis que le ratio dette/PIB et la croissance du PIB sont convertis en pourcentages et arrondis. Les colonnes sont ensuite renommées avec des intitulés explicites en français, et le jeu de données final est affiché.

# Statistiques de base

donnees_df %>%
summarize(
n = n(),
year_start = min(year),
year_end = max(year),
mean_gdp = mean(gdp),
sd_gdp = sd(gdp),
mean_grow = mean(gdp_growth),
sd_grow = sd(gdp_growth),
mean_debt = mean(debtgdp),
sd_debt = sd(debtgdp)
) %>% knitr::kable(digits=4)
n year_start year_end mean_gdp sd_gdp mean_grow sd_grow mean_debt sd_debt
59 1962 2020 582241.6 467227.3 0.0736 0.0566 0.3088 0.2

# Table et graphiques

donnees_df %>%
select(year, gdp_growth, debtgdp) %>%
pivot_longer(-year) %>%
ggplot(aes(x = year, y = value)) +
geom_line() +
facet_wrap(~name, scales = "free_y") +
theme_minimal() +
labs(title = paste("Évolution de gdp_growth et debtgdp -", votre_pays))

Des statistiques descriptives sont produites pour le PIB, la croissance du PIB et le ratio dette/PIB, incluant le nombre d’observations, les années de début et de fin, ainsi que les moyennes et écarts-types. Les séries temporelles de la croissance du PIB et de la dette sont ensuite tracées, ce qui permet de visualiser leur évolution et de repérer d’éventuelles tendances ou fluctuations au fil du temps.

range(donnees_df$year)
[1] 1962 2020

La plage des années présentes dans les données est calculée, permettant de connaître l’année de début et l’année de fin de la série temporelle utilisée pour l’analyse.

library(ggplot2)

# Graphique de l'évolution du PIB de la Finlande
plot_PIB <- ggplot(donnees_df_clean, aes(x = Année, y = PIB)) +
  geom_line(lty = 1, lwd = 1, color = "steelblue") +
  labs(
    x = "Année",
    y = "PIB (en millions)",
    title = paste("Évolution du PIB ", votre_pays)
  ) +
  theme_bw() +
  theme(
    plot.title = element_text(size = 20, face = "bold"),
    axis.title = element_text(size = 18),
    axis.text = element_text(size = 14, colour = "black")
  )

# Affichage
plot_PIB

Le graphique montre une forte hausse du PIB de la Finlande sur le long terme (1960–2020). La croissance est continue, avec quelques ralentissements notables au début des années 1990 et autour de 2009, puis une reprise soutenue jusqu’à un pic récent, suivie d’une légère baisse en fin de période.


library(tidyverse)

# Sélection de la population et calcul du taux de croissance pour 1960 a 2020
donnees_pop_finlande <- data_schularick %>%
  filter(country == "Finland") %>%              # filtrer le pays
  filter(year >= 1960 & year <= 2020) %>%      # filtrer les années 1960 à 2020
  select(year, pop) %>%                         # sélectionner année et population
  arrange(year) %>%
  mutate(
    croissance_pop = (log(pop) - lag(log(pop))) * 100,    # taux de croissance
    croissance_pop_alt = c(0, diff(log(pop)) * 100)      # première année = 0 pourcent
  ) %>%
  round(4)

# Affichage des premières lignes
head(donnees_pop_finlande)

# Vérifier la dernière ligne pour s'assurer que 2020 est incluse
tail(donnees_pop_finlande)
NA
NA
NA

Les données de population de la Finlande sont extraites pour la période 1960-2020. Le taux de croissance de la population est calculé à partir du logarithme de la population, avec deux variantes : l’une utilisant la différence avec l’année précédente et l’autre en remplaçant la première valeur par zéro. Les résultats sont arrondis et les premières et dernières lignes sont affichées pour vérifier la cohérence de la série.

# Calcul de la moyenne du taux de croissance de la population
moyenne <- mean(donnees_pop_finlande$croissance_pop, na.rm = TRUE)  # retirer les NA si présents
print(moyenne)
[1] 0.3647017

La moyenne du taux de croissance annuel de la population de la Finlande entre 1960 et 2020 est calculée, en ignorant les valeurs manquantes, afin d’obtenir une estimation générale de l’évolution démographique sur cette période.

library(ggplot2)

# Graphique du taux de croissance de la population en Finlande
donnees_pop_finlande %>%
  ggplot(aes(x = year, y = croissance_pop)) +
  geom_line() +
  geom_hline(yintercept = 0, lty = 2) +                # ligne horizontale à 0 pourcent
  geom_hline(yintercept = moyenne, lty = 2, color = "red") +  # moyenne en rouge
  labs(
    x = "Année",
    y = "Taux de croissance (pourcentage)",
    title = "Taux de croissance de la population en Finlande"
  ) +
  theme_bw()

Le graphique représente l’évolution du taux de croissance de la population en Finlande de 1960 à 2020. Une ligne horizontale à 0 indique le seuil de croissance nulle, tandis qu’une ligne rouge montre le taux moyen sur la période, permettant de visualiser les fluctuations annuelles autour de cette moyenne.

# Calcul de la moyenne du taux de croissance
moyenne <- mean(donnees_pop_finlande$croissance_pop, na.rm = TRUE)

# Préparation du dataframe pour le graphique
df <- donnees_pop_finlande %>%
  arrange(year) %>%
  mutate(
    moyenne = moyenne,
    ymin = pmin(croissance_pop, moyenne),
    ymax = pmax(croissance_pop, moyenne)
  )

# Graphique avec bande grisée
ggplot(df, aes(x = year)) +
  geom_ribbon(aes(ymin = ymin, ymax = ymax), fill = "grey10", alpha = 0.25) +
  geom_line(aes(y = croissance_pop), color = "black") +
  geom_hline(yintercept = 0, lty = 2) +
  geom_hline(yintercept = moyenne, lty = 2, color = "red") +
  labs(
    x = "Année",
    y = "Taux de croissance (pourcentage)",
    title = "Taux de croissance de la population écart à la moyenne (Finlande)"
  ) +
  theme_bw()

Le graphique montre un taux de croissance de la population finlandaise globalement positif, mais irrégulier. Après une forte chute ponctuelle au début des années 1970, la croissance oscille autour de la moyenne (ligne rouge), avec une tendance à l’affaiblissement depuis les années 2000, indiquant un ralentissement démographique.

# Écart type du taux de croissance de la population
sd_croissance <- sd(donnees_pop_finlande$croissance_pop, na.rm = TRUE)
print(sd_croissance)
[1] 0.2017861

L’écart type du taux de croissance annuel de la population en Finlande est calculé, ce qui permet de mesurer la dispersion des variations annuelles autour de la moyenne et d’évaluer la stabilité démographique sur la période 1960-2020.

# Résumé statistique de la population Finlande 1960-2020
summary(donnees_pop_finlande)
      year           pop       croissance_pop    croissance_pop_alt
 Min.   :1960   Min.   :4446   Min.   :-0.4112   Min.   :-0.4112   
 1st Qu.:1975   1st Qu.:4720   1st Qu.: 0.2691   1st Qu.: 0.2657   
 Median :1990   Median :4998   Median : 0.3683   Median : 0.3616   
 Mean   :1990   Mean   :5003   Mean   : 0.3647   Mean   : 0.3587   
 3rd Qu.:2005   3rd Qu.:5256   3rd Qu.: 0.4839   3rd Qu.: 0.4832   
 Max.   :2020   Max.   :5534   Max.   : 0.7168   Max.   : 0.7168   
                               NA's   :1                           

Un résumé statistique de la population de la Finlande entre 1960 et 2020 est produit, présentant les principales caractéristiques des variables : minimum, maximum, médiane, moyenne et quartiles, ainsi que les valeurs manquantes éventuelles, afin de donner une vue d’ensemble de l’évolution démographique sur la période.

# Statistiques descriptives de la croissance de la population Finlande 1960-2020
donnees_pop_finlande %>%
  summarize(
    "Moyenne" = mean(croissance_pop, na.rm = TRUE),
    "Ecart-Type" = sd(croissance_pop, na.rm = TRUE),
    "Variance" = var(croissance_pop, na.rm = TRUE),
    "Minimum" = min(croissance_pop, na.rm = TRUE),
    "Maximum" = max(croissance_pop, na.rm = TRUE)
  ) %>%
  round(2)
NA

Des statistiques descriptives sont calculées pour le taux de croissance de la population en Finlande sur la période 1960-2020, incluant la moyenne, l’écart-type, la variance, le minimum et le maximum, offrant ainsi une synthèse de la tendance centrale et de la dispersion des variations annuelles.

# Charger le package zoo pour les fonctions de moyenne/variance mobile
require(zoo)

# Calcul des moyennes et variances mobiles sur 5 ans
donnees_pop_finlande2 <- donnees_pop_finlande %>%
  mutate(
    roll_mean = rollapply(croissance_pop, FUN = mean, width = 5, fill = NA, align = "center"),
    roll_var  = rollapply(croissance_pop, FUN = var,  width = 5, fill = NA, align = "center")
  )

# Affichage des premières lignes
head(donnees_pop_finlande2)
NA

Des moyennes et variances mobiles sur 5 ans sont calculées pour le taux de croissance de la population en Finlande, permettant d’observer les tendances et la volatilité à moyen terme, en lissant les fluctuations annuelles. Les premières lignes du jeu de données enrichi sont affichées pour vérifier le calcul.

library(ggplot2)

# Graphique de la croissance de la population avec moyenne mobile
donnees_pop_finlande2 %>%
  ggplot(aes(x = year, y = croissance_pop)) +
  geom_line(color = "black") +                        # courbe de croissance réelle
  geom_line(aes(y = roll_mean), color = "steelblue", lwd = 1) +  # moyenne mobile
  labs(
    x = "Année",
    y = "Taux de croissance (pourcentage)",
    title = "Taux de croissance de la population Finlande avec moyenne mobile"
  ) +
  theme_bw()

Le graphique représente le taux de croissance annuel de la population en Finlande, avec la courbe noire montrant les valeurs réelles et la courbe bleue représentant la moyenne mobile sur 5 ans. Cela permet de visualiser plus clairement les tendances à moyen terme en lissant les fluctuations annuelles.

library(ggplot2)

# Graphique de la variance mobile de la croissance de la population
donnees_pop_finlande2 %>%
  ggplot(aes(x = year, y = roll_var)) +
  geom_line(lwd = 1, color = "darkred") +
  labs(
    x = "Année",
    y = "Variance mobile (5 ans)",
    title = "Variance mobile du taux de croissance de la population Finlande"
  ) +
  theme_bw()

Le graphique montre la variance mobile sur 5 ans du taux de croissance de la population en Finlande, permettant d’observer comment la volatilité démographique évolue au fil du temps et d’identifier les périodes de fluctuations plus ou moins importantes.

# Calcul de la croissance de la population "detrendée" (hors tendance)
test <- donnees_pop_finlande2 %>%
  mutate(detrended_pop_growth = croissance_pop - roll_mean)

# Affichage des premières lignes
head(test)

La croissance de la population est ici « détendancée » en soustrayant la moyenne mobile sur 5 ans à la croissance réelle, ce qui permet d’isoler les fluctuations annuelles par rapport à la tendance à moyen terme. Les premières lignes du jeu de données modifié sont affichées pour vérifier le calcul.

library(ggplot2)

# Graphique de la croissance de la population détendancée (hors tendance)
test %>%
  ggplot(aes(x = year, y = detrended_pop_growth)) +
  geom_line(lwd = 1, color = "darkgreen") +
  labs(
    x = "Année",
    y = "Croissance détendancée (pourcentage)",
    title = "Croissance de la population Finlande (hors tendance)"
  ) +
  theme_bw()

Le graphique présente la croissance de la population en Finlande « détendancée », c’est-à-dire les variations annuelles après avoir retiré la tendance à moyen terme. La courbe permet de visualiser les fluctuations ponctuelles autour de la tendance démographique.

B) Pré-régression et régression sur la Finlande en se concentrant sur gdp (PIB) et debtgdp (dette publique en % du PIB)


# Stratégie économétrique (résumé)


# Objectif : mesurer l’effet de la dette publique (debtgdp)
# sur la croissance du PIB (gdp_growth = Var log(gdp)).

# Variables :
# - Dépendante : gdp_growth.
# - Explicative : debtgdp (à mettre en pourcentage si nécessaire).
# - Contrôles possibles : inflation, chômage, crédit, dépenses publiques, etc.

# Étape 1 — Stationnarité :
# - Tester gdp_growth (normalement I(0)).
# - Tester debtgdp (souvent I(1)) via ADF / KPSS.
# - Si debtgdp non stationnaire :
#       -> utiliser Var debtgdp si pas de cointégration,
#       -> sinon tester cointégration avec log(gdp) et passer à un ECM.

# Étape 2 — Modèles :
# - Baseline : gdp_growth_t = alpha + beta * debtgdp t-1 + erreur.
# - Avec contrôles : ajouter gdpgrowth t-1 + variables Xt.

# Étape 3 — Estimation :
# - Utiliser erreurs standards robustes (HC) ou Newey–West
#   pour corriger autocorrélation et hétéroscédasticité.

# Préparation des séries pour la Finlande


donnees_finlande <- donnees_df %>%
  select(year, gdp, debtgdp) %>%
  arrange(year) %>%
  mutate(
    # taux de croissance du PIB en pourcentage
    gdp_growth = (log(gdp) - lag(log(gdp))) * 100,
    # différences premières
    dgdp = gdp - lag(gdp),
    ddgdp = dgdp - lag(dgdp),
    # différences premières du taux de croissance
    dgdp_growth = gdp_growth - lag(gdp_growth)
  ) %>%
  filter(year >= 1960) %>%
  na.omit()

# Vérification
head(donnees_finlande)


# Graphique de la série du PIB


ggplot(donnees_finlande, aes(x = year, y = gdp)) +
  geom_line(lwd = 1, color = "steelblue") +
  labs(
    x = "Année",
    y = "PIB (en millions)",
    title = "Évolution du PIB  Finlande"
  ) +
  theme_bw()



# Autocorrélogramme pour vérifier dépendance temporelle


acf(donnees_finlande$gdp, main = "ACF du PIB Finlande")

Les séries temporelles pour la Finlande sont préparées : le taux de croissance du PIB en pourcentage est calculé, ainsi que les premières et secondes différences du PIB et de sa croissance pour détecter les variations et faciliter l’analyse de stationnarité. La série est ensuite filtrée pour les années à partir de 1960 et les valeurs manquantes sont supprimées. La série du PIB est visualisée avec un graphique en ligne, et l’autocorrélogramme (ACF) est tracé pour examiner la dépendance temporelle et identifier d’éventuelles autocorrélations.

# RAPPEL
#Chaque barre du graphique correspond à un lag (décalage dans le temps).

#Lag 1  corrélation entre la série et elle-même décalée d’1 période.

#Lag 2  corrélation avec elle-même décalée de 2 périodes, etc.

#Valeurs élevées proches de 1 ou -1 → forte corrélation avec les valeurs passées.

#Décroissance lente des barres  signe que la série n’est pas stationnaire (la moyenne ou la variance changent dans le temps).

#Décroissance rapide vers zéro  signe que la série est stationnaire.

#L’ACF du PIB Finlande montre des autocorrélations élevées qui décroissent lentement → la série n’est pas stationnaire (moyenne et variance changent dans le temps).

#Forte autocorrélation sur plusieurs lags  série intégrée d’ordre 1 (I(1)), typique pour le PIB en niveau.

#Implications :

#On ne peut pas régressser directement le PIB en niveau sur la dette (risque de régression spurious).

#Il faut utiliser plutôt :

#Var log(PIB) (ou gdpgrowth) comme variable dépendante  normalement stationnaire (I(0))

#Var (debt/PIB) ou tester la cointégration entre PIB et dette.
# Packages nécessaires

library(urca)
library(tseries)
library(ggplot2)
library(dplyr)
library(forecast)

# 
#  Tests de stationnarité
# 

# ADF (Dickey Fuller augmenté) 
adf_gdp <- ur.df(donnees_finlande$gdp_growth, type = "none", selectlags = "AIC")
summary(adf_gdp)

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression none 


Call:
lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.6425 -1.2790  0.4766  2.6643 10.5518 

Coefficients:
           Estimate Std. Error t value Pr(>|t|)  
z.lag.1    -0.09712    0.05392  -1.801   0.0774 .
z.diff.lag  0.10344    0.13560   0.763   0.4489  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.685 on 53 degrees of freedom
Multiple R-squared:  0.06146,   Adjusted R-squared:  0.02604 
F-statistic: 1.735 on 2 and 53 DF,  p-value: 0.1862


Value of test-statistic is: -1.8011 

Critical values for test statistics: 
     1pct  5pct 10pct
tau1 -2.6 -1.95 -1.61
adf_debt <- ur.df(donnees_finlande$debtgdp, type = "trend", selectlags = "AIC")
summary(adf_debt)

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression trend 


Call:
lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.051040 -0.017297 -0.006527  0.012446  0.102362 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.0025354  0.0088025  -0.288  0.77449    
z.lag.1     -0.1552357  0.0455093  -3.411  0.00127 ** 
tt           0.0019082  0.0005511   3.463  0.00109 ** 
z.diff.lag   0.6727209  0.1079508   6.232 8.88e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.03134 on 51 degrees of freedom
Multiple R-squared:  0.4779,    Adjusted R-squared:  0.4472 
F-statistic: 15.56 on 3 and 51 DF,  p-value: 2.593e-07


Value of test-statistic is: -3.4111 4.6339 6.307 

Critical values for test statistics: 
      1pct  5pct 10pct
tau3 -4.04 -3.45 -3.15
phi2  6.50  4.88  4.16
phi3  8.73  6.49  5.47
#KPSS (stationnarité autour de la moyenne ou trend) 
kpss.test(donnees_finlande$gdp_growth)  # H0 = stationnaire

    KPSS Test for Level Stationarity

data:  donnees_finlande$gdp_growth
KPSS Level = 1.1113, Truncation lag parameter = 3, p-value = 0.01
kpss.test(donnees_finlande$debtgdp)     # H0 = stationnaire

    KPSS Test for Level Stationarity

data:  donnees_finlande$debtgdp
KPSS Level = 1.2635, Truncation lag parameter = 3, p-value = 0.01
#  Si debtgdp non-stationnaire différences premières

donnees_finlande <- donnees_finlande %>%
  mutate(d_debtgdp = debtgdp - lag(debtgdp)) %>%
  na.omit()

# Vérification ACF pour gdp_growth et d_debtgdp
acf(donnees_finlande$gdp_growth, main = "ACF de la croissance du PIB (gdpgrowth)")

acf(donnees_finlande$d_debtgdp, main = "ACF des différences de la dette/PIB (ddebtgdp)")



#  Graphiques rapides

# Croissance du PIB
ggplot(donnees_finlande, aes(x = year, y = gdp_growth)) +
  geom_line(color = "steelblue") +
  labs(title = "Croissance du PIB Finlande", x = "Année", y = "gdp_growth (pourcentage)") +
  theme_minimal()


# Différences de la dette / PIB
ggplot(donnees_finlande, aes(x = year, y = d_debtgdp)) +
  geom_line(color = "darkred") +
  labs(title = "Différences de la dette/PIB Finlande", x = "Année", y = " Var debtgdp (pourcentage)") +
  theme_minimal()

Des tests de stationnarité sont réalisés pour la Finlande : le test ADF indique si les séries sont stationnaires ou non, et le test KPSS complète l’analyse en testant l’hypothèse nulle de stationnarité. La croissance du PIB apparaît généralement stationnaire, tandis que le ratio dette/PIB est transformé en différences premières si nécessaire pour obtenir une série stationnaire. Les autocorrélogrammes (ACF) sont tracés pour vérifier la dépendance temporelle de ces séries transformées. Enfin, des graphiques illustrent l’évolution de la croissance du PIB et des variations annuelles du ratio dette/PIB, permettant de visualiser les tendances et fluctuations. Le graphique montre des variations du ratio dette/PIB généralement faibles, mais avec des pics marqués en période de crise, notamment au début des années 1990 et après 2008. Cela indique que la dette augmente surtout lors des chocs économiques, puis se stabilise ou recule ensuite.

library(urca)

# Test ADF sur gdp_growth (croissance du PIB)
adf_gdp <- ur.df(donnees_finlande$gdp_growth, type = "none", selectlags = "AIC")
summary(adf_gdp)

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression none 


Call:
lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.6888 -1.0060  0.5275  2.6560 10.5091 

Coefficients:
           Estimate Std. Error t value Pr(>|t|)  
z.lag.1     -0.0925     0.0550  -1.682   0.0986 .
z.diff.lag   0.0964     0.1372   0.703   0.4854  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.711 on 52 degrees of freedom
Multiple R-squared:  0.05454,   Adjusted R-squared:  0.01818 
F-statistic:   1.5 on 2 and 52 DF,  p-value: 0.2326


Value of test-statistic is: -1.6818 

Critical values for test statistics: 
     1pct  5pct 10pct
tau1 -2.6 -1.95 -1.61
# Test ADF sur debtgdp (dette / PIB)
adf_debt <- ur.df(donnees_finlande$debtgdp, type = "trend", selectlags = "AIC")
summary(adf_debt)

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression trend 


Call:
lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.050995 -0.016076 -0.006455  0.011127  0.102230 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept) -0.0026642  0.0089100  -0.299 0.766174    
z.lag.1     -0.1624772  0.0463422  -3.506 0.000970 ***
tt           0.0020421  0.0005728   3.565 0.000811 ***
z.diff.lag   0.6744327  0.1082044   6.233  9.5e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.03141 on 50 degrees of freedom
Multiple R-squared:  0.4859,    Adjusted R-squared:  0.455 
F-statistic: 15.75 on 3 and 50 DF,  p-value: 2.436e-07


Value of test-statistic is: -3.506 4.8621 6.6679 

Critical values for test statistics: 
      1pct  5pct 10pct
tau3 -4.04 -3.45 -3.15
phi2  6.50  4.88  4.16
phi3  8.73  6.49  5.47

La croissance du PIB (gdp_growth) n’est pas strictement stationnaire : le test ADF ne rejette pas l’hypothèse de racine unitaire, ce qui signifie que la série peut contenir des variations persistantes dans le temps. En revanche, le ratio dette/PIB (debtgdp) est stationnaire autour d’une tendance : le test ADF avec tendance rejette la racine unitaire, indiquant que la série est stable une fois la tendance prise en compte. Concrètement, la croissance du PIB peut être utilisée telle quelle pour des modèles ARIMA, tandis que la dette/PIB devra être différenciée ou modélisée avec la tendance dans un ECM ou un modèle de cointégration.

# Le package 'urca' permet de faire le test ADF pour vérifier si une série est stationnaire.
# Ici, le test ADF sur 'gdp_growth' (sans constante ni tendance) donne tau1 = -1.682.
# Comme c'est plus grand que la valeur critique à 5% (-1.95), on ne rejette pas l'hypothèse de racine unitaire.
# Conclusion : la série pourrait ne pas être strictement stationnaire, mais la croissance du PIB est généralement considérée comme I(0),
# c’est-à-dire stationnaire autour d’une moyenne stable, avec variance constante, et utilisable directement en régression.
# Le package 'urca' permet de faire le test ADF pour vérifier si une série est stationnaire.
# Ici, le test ADF sur la série (avec constante et tendance, type = "trend") donne tau3 = -3.506.
# On compare à la valeur critique à 5% (-3.45) : tau3 < -3.45, donc on peut **rejeter l'hypothèse nulle** de racine unitaire.
# Conclusion : la série est stationnaire autour d’une tendance. 
# Pour rappel, une série stationnaire (I(0)) a une moyenne et une variance constantes dans le temps, 
# et peut être utilisée directement en régression sans créer de régression spurious.

Modèle économètrique


# Modèle baseline corrigé (Finlande)



library(dplyr)
library(lmtest)
library(sandwich)

# 1) Préparer le dataset à partir de donneesdf (déjà Finlande)

donnees_finlande <- donnees_df %>%
mutate(
d_debtgdp    = debtgdp - lag(debtgdp),              # variation dette/PIB
lag_d_debtgdp = lag(d_debtgdp, 1)                  # lag de var dette
) %>%
na.omit()  # supprime NA introduits par lag

# 2) Estimation du modèle baseline

modele_baseline <- lm(gdp_growth ~ lag_d_debtgdp, data = donnees_finlande)

# 3) Résumé classique

summary(modele_baseline)

Call:
lm(formula = gdp_growth ~ lag_d_debtgdp, data = donnees_finlande)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.147086 -0.041163 -0.002353  0.040427  0.150932 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)    
(Intercept)    0.076236   0.007685   9.920 7.43e-14 ***
lag_d_debtgdp -0.315856   0.191364  -1.651    0.105    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.05673 on 55 degrees of freedom
Multiple R-squared:  0.0472,    Adjusted R-squared:  0.02987 
F-statistic: 2.724 on 1 and 55 DF,  p-value: 0.1045
# 4) Résumé avec erreurs robustes de type HC

coeftest(modele_baseline, vcov = vcovHC(modele_baseline, type = "HC1"))

t test of coefficients:

                Estimate Std. Error t value  Pr(>|t|)    
(Intercept)    0.0762356  0.0079742  9.5602 2.725e-13 ***
lag_d_debtgdp -0.3158556  0.1312503 -2.4065   0.01949 *  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Un modèle de base est estimé pour mesurer l’effet de la variation laguée du ratio dette/PIB sur la croissance du PIB en Finlande. La variable explicative est la variation de la dette/PIB de l’année précédente. Le résumé classique du modèle fournit les coefficients et leur significativité standard, tandis que l’estimation avec erreurs robustes de type HC ajuste les écarts-types pour corriger d’éventuelles hétéroscédasticités, offrant des tests de significativité plus fiables.

Le modèle montre que la variation laguée de la dette/PIB a un effet négatif sur la croissance du PIB : le coefficient est estimé à -0,316. Selon le résumé classique, ce coefficient n’est pas significatif au seuil de 5 % (p environ 0,105), mais en utilisant les erreurs robustes de type HC, il devient significatif (p environ 0,019), ce qui suggère qu’une augmentation de la dette/PIB l’année précédente tend à réduire légèrement la croissance du PIB. L’ajustement global du modèle est faible (R² environ 0,047), indiquant que la variation de la dette seule explique une petite part de la variance de la croissance. L’intercept est positif et fortement significatif, reflétant la croissance moyenne du PIB lorsque la variation de la dette est nulle.

# Modèle avec contrôles : ajout du lag de gdpgrowth
donnees_finlande <- donnees_finlande %>%
  mutate(lag_gdp_growth = lag(gdp_growth, 1)) %>%
  na.omit()

modele_controles <- lm(gdp_growth ~ lag(d_debtgdp, 1) + lag_gdp_growth, data = donnees_finlande)
summary(modele_controles)

Call:
lm(formula = gdp_growth ~ lag(d_debtgdp, 1) + lag_gdp_growth, 
    data = donnees_finlande)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.097664 -0.018120 -0.000574  0.016839  0.070242 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)       0.0002814  0.0089727   0.031   0.9751    
lag(d_debtgdp, 1) 0.3573424  0.1349348   2.648   0.0107 *  
lag_gdp_growth    0.9294411  0.0950089   9.783 2.21e-13 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.0343 on 52 degrees of freedom
  (1 observation deleted due to missingness)
Multiple R-squared:  0.6653,    Adjusted R-squared:  0.6524 
F-statistic: 51.67 on 2 and 52 DF,  p-value: 4.387e-13
coeftest(modele_controles, vcov = vcovHC(modele_controles, type = "HC1"))

t test of coefficients:

                   Estimate Std. Error t value  Pr(>|t|)    
(Intercept)       0.0002814  0.0099872  0.0282  0.977630    
lag(d_debtgdp, 1) 0.3573424  0.1142349  3.1281  0.002881 ** 
lag_gdp_growth    0.9294411  0.1040177  8.9354 4.369e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Un modèle enrichi inclut désormais la croissance du PIB de l’année précédente comme variable de contrôle, capturant l’effet persistant de la croissance passée (autoregression). Les résultats montrent que la croissance passée a un effet positif et très fort sur la croissance actuelle (coefficient environ 0,93). La variation laguée de la dette/PIB reste significative après correction des erreurs robustes : une hausse d’un point de pourcentage de la dette l’année précédente est associée à une légère augmentation de la croissance du PIB (environ 0,36 point). Le modèle est ainsi plus complet, intégrant l’autocorrélation naturelle du PIB et fournissant des estimations plus fiables de l’effet de la dette.

C) Analyse des résidus

library(dplyr)  # nécessaire pour %>%
library(ggplot2)

# Créer le dataframe utilisé par le modèle (supprime les NA introduits par les lags)
df_model <- donnees_finlande %>%
  mutate(
    lag_d_debtgdp = lag(d_debtgdp, 1),
    lag_gdp_growth = lag(gdp_growth, 1)
  ) %>%
  na.omit()

# Extraire valeurs ajustées et résidus
fitted_val <- modele_controles$fitted.values
residuals <- modele_controles$residuals

# Ajouter au dataframe
donnees_finlande_residus <- df_model %>%
  mutate(fitted_val = fitted_val,
         residuals = residuals)

# Graphique
ggplot(donnees_finlande_residus, aes(x = year, y = gdp_growth)) +
  geom_line(lwd = 1, color = "black") +                             # série réelle
  geom_line(aes(y = fitted_val), color = "red", lty = 2, lwd = 1) + # série ajustée
  labs(
    x = "Année",
    y = "Croissance du PIB (%)",
    title = "Croissance du PIB Finlande : valeurs réelles vs ajustées"
  ) +
  theme_bw()

Le graphique compare la croissance réelle du PIB en Finlande avec les valeurs ajustées par le modèle incluant la dette laguée et la croissance passée. La courbe noire montre les observations réelles, tandis que la courbe rouge en pointillés représente les prédictions du modèle, permettant de visualiser la qualité de l’ajustement et les écarts entre le modèle et les données observées (résidus). Le modèle est plutôt précis.

# Graphique des résidus dans le temps pour vérifier l'homoscédasticité
ggplot(donnees_finlande_residus, aes(x = year, y = residuals)) +
  geom_line(lwd = 1, color = "darkgreen") +
  geom_hline(yintercept = 0, lty = 2, color = "red") +
  labs(
    x = "Année",
    y = "Résidus",
    title = "Résidus du modèle Finlande dans le temps"
  ) +
  theme_bw()

Le graphique montre l’évolution des résidus du modèle dans le temps pour la Finlande. La ligne verte trace les écarts entre les valeurs observées et ajustées, tandis que la ligne rouge à zéro sert de référence. Cela permet de vérifier visuellement l’homoscédasticité et l’absence de motifs systématiques dans les erreurs. Les résidus oscillent globalement autour de zéro, ce qui indique pas de biais systématique du modèle. Cependant, on observe quelques chocs marqués (années avec forts résidus négatifs et positifs), suggérant des événements exceptionnels mal captés par le modèle. Pas de tendance claire ni de structure persistante → ajustement global correct, mais sensibilité aux crises.

library(lmtest)

# Test de Breusch-Pagan pour homoscédasticité
# Ici on teste si la variance des résidus dépend des variables explicatives du modèle
bptest(modele_controles)

    studentized Breusch-Pagan test

data:  modele_controles
BP = 0.56306, df = 2, p-value = 0.7546

Le test de Breusch-Pagan montre un BP = 0,56 avec un p-value de 0,75. Comme le p-value est très supérieur à 0,05, on ne rejette pas l’hypothèse nulle d’homoscédasticité. Cela signifie que la variance des résidus du modèle ne dépend pas des variables explicatives et que l’hypothèse d’homoscédasticité est vérifiée.

library(ggplot2)

# Graphique de densité pour vérifier la normalité des résidus
ggplot(donnees_finlande_residus, aes(x = residuals)) +
  geom_density(fill = "grey60", alpha = 0.7) +
  labs(
    title = "Densité des résidus du modèle Finlande",
    x = "Résidus",
    y = "Densité"
  ) +
  theme_bw()

Ce graphique représente la densité des résidus du modèle appliqué à la Finlande. La distribution montre une concentration importante des résidus autour de 0, ce qui est généralement positif : cela indique que, pour la majorité des observations, le modèle ne produit pas de grandes erreurs et que les prévisions sont globalement proches des valeurs observées.

Cependant, la densité présente également une asymétrie légère et des queues plus épaisses, notamment du côté négatif (jusqu’à environ –10) et du côté positif (jusqu’à environ +7). Cela suggère la présence de quelques erreurs atypiques ou de non-normalité des résidus, ce qui peut signaler :une possible hétéroscédasticité, des valeurs aberrantes, ou une spécification du modèle qui pourrait être améliorée (variables manquantes, forme fonctionnelle

shapiro.test(donnees_finlande_residus$residuals)

    Shapiro-Wilk normality test

data:  donnees_finlande_residus$residuals
W = 0.95212, p-value = 0.02855

Le test de Shapiro-Wilk sur les résidus du modèle donne un W = 0,952 et un p-value de 0,029. Comme le p-value est inférieur à 0,05, on rejette l’hypothèse nulle de normalité : les résidus ne suivent pas parfaitement une distribution normale. Cela indique que certaines précautions doivent être prises pour l’interprétation des intervalles de confiance et des tests statistiques classiques.

acf(donnees_finlande_residus$residuals, main = "ACF des résidus Finlande")

La présence d’une autocorrélation significative au lag 1 indique que les résidus présentent encore un peu de dépendance temporelle

Box.test(donnees_finlande_residus$residuals, lag = 10, type = "Ljung-Box")

    Box-Ljung test

data:  donnees_finlande_residus$residuals
X-squared = 6.2917, df = 10, p-value = 0.7902

Le test de Ljung-Box appliqué aux résidus donne un X² = 6,29 avec un p-value de 0,79. Comme le p-value est largement supérieur à 0,05, on ne rejette pas l’hypothèse nulle d’absence d’autocorrélation des résidus. Cela indique que les erreurs du modèle ne présentent pas de dépendance temporelle significative et que l’autocorrélation est correctement prise en compte.

require(forecast)

Le package forecast est chargé, ce qui permet d’accéder aux fonctions pour l’estimation et la prévision de modèles de séries temporelles, notamment ARIMA, ETS et autres outils de prévision.

checkresiduals(modele_controles)

    Breusch-Godfrey test for serial correlation of order up to 10

data:  Residuals
LM test = 5.6322, df = 10, p-value = 0.8452

Le graphique montre que les résidus sont globalement centrés autour de zéro sans tendance particulière dans le temps. L’ACF ne présente pas d’autocorrélations significatives, ce qui indique une absence de dépendance sérieuse entre les résidus. L’histogramme suggère une distribution à peu près normale, même si l’on observe quelques valeurs extrêmes.

Partie 2 Prévision avec ARIMA



library(tidyverse)
library(readxl)
library(forecast)
library(tseries)
library(lmtest)
library(urca)
library(zoo)


votre_pays <- "Finland"



donnees_cpi <- data_schularick %>%
filter(country == votre_pays) %>%
arrange(year) %>%
filter(year > 1960) %>%
select(year, cpi) %>%
mutate(
cpi_growth = (log(cpi) - lag(log(cpi))) * 100  # inflation en %
) %>%
na.omit()



glimpse(donnees_cpi)
Rows: 59
Columns: 3
$ year       <dbl> 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973…
$ cpi        <dbl> 11.771, 12.344, 13.622, 14.278, 14.840, 15.676, 17.116, 17.494, 17.972…
$ cpi_growth <dbl> 4.367203, 4.753124, 9.851602, 4.703376, 3.860635, 5.480464, 8.788282, …
print(range(donnees_cpi$year))
[1] 1962 2020
start_year <- min(donnees_cpi$year)
infl_ts <- ts(donnees_cpi$cpi_growth, start = start_year, frequency = 1)



autoplot(infl_ts) + ggtitle(paste("Inflation (taux de croissance CPI %) ", votre_pays)) + ylab("Inflation (%)") + xlab("Année")




adf_res <- ur.df(as.numeric(infl_ts), type = "drift", selectlags = "AIC")
summary(adf_res)

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression drift 


Call:
lm(formula = z.diff ~ z.lag.1 + 1 + z.diff.lag)

Residuals:
    Min      1Q  Median      3Q     Max 
-6.2482 -1.0520 -0.2422  0.8877  5.5730 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)  0.60287    0.43714   1.379   0.1735  
z.lag.1     -0.14663    0.07262  -2.019   0.0485 *
z.diff.lag   0.09979    0.13664   0.730   0.4684  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 2.111 on 54 degrees of freedom
Multiple R-squared:  0.07069,   Adjusted R-squared:  0.03627 
F-statistic: 2.054 on 2 and 54 DF,  p-value: 0.1381


Value of test-statistic is: -2.0191 2.0747 

Critical values for test statistics: 
      1pct  5pct 10pct
tau2 -3.51 -2.89 -2.58
phi1  6.70  4.71  3.86
kpss_res <- tseries::kpss.test(as.numeric(infl_ts))
kpss_res

    KPSS Test for Level Stationarity

data:  as.numeric(infl_ts)
KPSS Level = 0.92642, Truncation lag parameter = 3, p-value = 0.01
best_arima <- forecast::auto.arima(infl_ts,
seasonal = FALSE,
stepwise = FALSE,
approximation = FALSE,
trace = TRUE,
ic = "aicc")

 ARIMA(0,1,0)                    : 253.5706
 ARIMA(0,1,0) with drift         : 255.6561
 ARIMA(0,1,1)                    : 255.6586
 ARIMA(0,1,1) with drift         : 257.8277
 ARIMA(0,1,2)                    : 254.3472
 ARIMA(0,1,2) with drift         : 256.4388
 ARIMA(0,1,3)                    : 255.3156
 ARIMA(0,1,3) with drift         : 257.337
 ARIMA(0,1,4)                    : 256.6294
 ARIMA(0,1,4) with drift         : 258.8168
 ARIMA(0,1,5)                    : 255.4213
 ARIMA(0,1,5) with drift         : Inf
 ARIMA(1,1,0)                    : 255.6846
 ARIMA(1,1,0) with drift         : 257.8522
 ARIMA(1,1,1)                    : 257.3202
 ARIMA(1,1,1) with drift         : Inf
 ARIMA(1,1,2)                    : 255.551
 ARIMA(1,1,2) with drift         : Inf
 ARIMA(1,1,3)                    : 255.1177
 ARIMA(1,1,3) with drift         : 257.3329
 ARIMA(1,1,4)                    : 257.5963
 ARIMA(1,1,4) with drift         : 259.9205
 ARIMA(2,1,0)                    : 254.6209
 ARIMA(2,1,0) with drift         : 256.7809
 ARIMA(2,1,1)                    : 255.934
 ARIMA(2,1,1) with drift         : 257.9872
 ARIMA(2,1,2)                    : Inf
 ARIMA(2,1,2) with drift         : Inf
 ARIMA(2,1,3)                    : 257.5816
 ARIMA(2,1,3) with drift         : Inf
 ARIMA(3,1,0)                    : 256.9288
 ARIMA(3,1,0) with drift         : 259.1762
 ARIMA(3,1,1)                    : 258.7003
 ARIMA(3,1,1) with drift         : 261.0408
 ARIMA(3,1,2)                    : 260.2664
 ARIMA(3,1,2) with drift         : Inf
 ARIMA(4,1,0)                    : 259.0477
 ARIMA(4,1,0) with drift         : 261.3666
 ARIMA(4,1,1)                    : 259.3938
 ARIMA(4,1,1) with drift         : Inf
 ARIMA(5,1,0)                    : 253.0197
 ARIMA(5,1,0) with drift         : 255.1949



 Best model: ARIMA(5,1,0)                    
best_arima
Series: infl_ts 
ARIMA(5,1,0) 

Coefficients:
         ar1      ar2      ar3      ar4      ar5
      0.0018  -0.2636  -0.0988  -0.0169  -0.3977
s.e.  0.1202   0.1250   0.1364   0.1321   0.1285

sigma^2 = 3.904:  log likelihood = -119.69
AIC=251.37   AICc=253.02   BIC=263.74
checkresiduals(best_arima)  # diagnostic : ACF, histogramme, test Ljung-Box

    Ljung-Box test

data:  Residuals from ARIMA(5,1,0)
Q* = 1.4507, df = 5, p-value = 0.9187

Model df: 5.   Total lags used: 10

lb <- Box.test(residuals(best_arima), lag = 10, type = "Ljung-Box", fitdf = length(best_arima$coef))
library(FinTS)

arch_test <- ArchTest(residuals(best_arima), lag = 1)
arch_test

    ARCH LM-test; Null hypothesis: no ARCH effects

data:  residuals(best_arima)
Chi-squared = 1.4145, df = 1, p-value = 0.2343
h <- 5  # 5 années
fc <- forecast(best_arima, h = h, level = c(80, 95))


fc_df <- data.frame(
Year = (max(donnees_cpi$year) + 1):(max(donnees_cpi$year) + h),
Mean_FC = round(fc$mean, 2),
Lo_80 = round(fc$lower[,1], 2),
Hi_80 = round(fc$upper[,1], 2),
Lo_95 = round(fc$lower[,2], 2),
Hi_95 = round(fc$upper[,2], 2)
)
fc_df %>% knitr::kable(col.names = c("Année", "Prévision moyenne (%)", "Borne 80% inf", "Borne 80% sup", "Borne 95% inf", "Borne 95% sup"))
Année Prévision moyenne (%) Borne 80% inf Borne 80% sup Borne 95% inf Borne 95% sup
2021 0.13 -2.40 2.67 -3.74 4.01
2022 0.15 -3.43 3.73 -5.33 5.63
2023 0.16 -3.88 4.20 -6.02 6.34
2024 0.21 -4.15 4.56 -6.45 6.86
2025 0.50 -4.19 5.19 -6.67 7.68



autoplot(fc) +
autolayer(infl_ts, series = "Historique") +
ggtitle(paste("Prévision de l'inflation ", votre_pays, "(h =", h, "ans)")) +
ylab("Inflation (%)") + xlab("Année")




fc_boot <- forecast::forecast(best_arima, h = h, boot = TRUE, level = c(80,95), npaths = 2000)



plot(fc_boot, main = paste("Prévisions (bootstrap) ", votre_pays))




in_sample_accuracy <- accuracy(best_arima)
in_sample_accuracy
                     ME     RMSE      MAE       MPE    MAPE     MASE       ACF1
Training set -0.1338607 1.872766 1.330039 -15.46903 78.9688 0.889866 0.02097769

Les données d’inflation pour la Finlande après 1960 sont extraites et transformées en taux de croissance annuel du CPI. La série temporelle est convertie en objet ts et visualisée pour observer son évolution dans le temps.

Des tests de stationnarité sont réalisés : le test ADF avec constante (drift) et le test KPSS permettent de vérifier si la série peut être modélisée directement ou si une différenciation est nécessaire.

La fonction auto.arima identifie le meilleur modèle ARIMA pour la série non saisonnière selon le critère AICc. Les résidus du modèle sont contrôlés via checkresiduals, le test de Ljung-Box et un test ARCH, afin de vérifier l’absence d’autocorrélation et d’hétéroscédasticité.

Des prévisions sur 5 ans sont produites avec intervalles de confiance à 80 % et 95 %, présentées sous forme de tableau et de graphique. Une prévision bootstrap est également réalisée pour visualiser l’incertitude de manière plus robuste. Enfin, la précision du modèle sur l’échantillon historique est évaluée avec la fonction accuracy.

Cette approche permet de justifier le choix d’ARIMA, de produire des prévisions fiables et de détecter les limites liées aux résidus ou à la variabilité future de l’inflation.

Partie 3 - Modèle à Correction d’Erreurs


library(readxl)
library(tidyverse)
library(urca)       # ur.df, ca.jo
library(tseries)    # kpss.test, jarque.bera.test
library(forecast)   # auto.arima (diagnostic)
library(lmtest)     # bgtest, bptest
library(sandwich)   # NeweyWest / vcovHAC
library(zoo)

# Paramètres

votre_pays <- "Finland"    
               



data_schularick <- read_excel("data_schularick.xlsx")

donnees_ecm <- data_schularick %>%
filter(country == votre_pays) %>%
arrange(year) %>%
filter(year > 1960) %>%
select(year, wage, gdp, revenue, expenditure, unemp) %>%
mutate(
# logs niveaux (pour test de I(1) et relation long terme)
log_wage = if_else(!is.na(wage), log(wage), NA_real_),
log_gdp  = if_else(!is.na(gdp),  log(gdp),  NA_real_),
log_revenue = if_else(!is.na(revenue), log(revenue), NA_real_),
log_expenditure = if_else(!is.na(expenditure), log(expenditure), NA_real_)
) %>%

# taux de croissance ( Var log *100)

mutate(
wage_growth = if_else(!is.na(log_wage), (log_wage - lag(log_wage)) * 100, NA_real_),
gdp_growth  = if_else(!is.na(log_gdp),  (log_gdp  - lag(log_gdp))  * 100, NA_real_),
revenue_growth = if_else(!is.na(log_revenue),    (log_revenue - lag(log_revenue)) * 100, NA_real_),
expenditure_growth = if_else(!is.na(log_expenditure), (log_expenditure - lag(log_expenditure)) * 100, NA_real_)
) %>%
na.omit()

glimpse(donnees_ecm)
Rows: 59
Columns: 14
$ year               <dbl> 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 19…
$ wage               <dbl> 5.735482, 6.276230, 7.116268, 7.723319, 8.292159, 9.024999, 10…
$ gdp                <dbl> 19661.0, 21352.0, 24083.0, 26634.0, 28554.0, 31321.0, 35908.0,…
$ revenue            <dbl> 3660.00, 3500.00, 4400.00, 4900.00, 5500.00, 6500.00, 7700.00,…
$ expenditure        <dbl> 4970.00, 4900.00, 5700.00, 6800.00, 7200.00, 8100.00, 9800.00,…
$ unemp              <dbl> 1.300, 1.500, 1.500, 1.400, 1.500, 2.900, 3.900, 2.830, 1.890,…
$ log_wage           <dbl> 1.746672, 1.836770, 1.962383, 2.044244, 2.115310, 2.199998, 2.…
$ log_gdp            <dbl> 9.886392, 9.968901, 10.089261, 10.189944, 10.259552, 10.352044…
$ log_revenue        <dbl> 8.205218, 8.160518, 8.389360, 8.496990, 8.612503, 8.779557, 8.…
$ log_expenditure    <dbl> 8.511175, 8.496990, 8.648221, 8.824678, 8.881836, 8.999619, 9.…
$ wage_growth        <dbl> 5.736166, 9.009769, 12.561393, 8.186074, 7.106617, 8.468804, 1…
$ gdp_growth         <dbl> 6.835367, 8.250843, 12.036079, 10.068240, 6.960844, 9.249177, …
$ revenue_growth     <dbl> 10.961973, -4.470018, 22.884157, 10.763066, 11.551289, 16.7054…
$ expenditure_growth <dbl> 10.603143, -1.418463, 15.123097, 17.645644, 5.715841, 11.77830…
print(range(donnees_ecm$year))
[1] 1962 2020

Les données pour la Finlande après 1960 sont préparées pour un modèle à correction d’erreurs (ECM). Les variables de salaire, PIB, recettes et dépenses publiques sont transformées en logarithmes pour tester la cointégration et les relations de long terme. Les taux de croissance correspondants sont calculés à partir des différences logarithmiques, exprimés en pourcentage. Les observations manquantes sont supprimées et la structure finale du jeu de données est affichée, permettant de vérifier la cohérence et la continuité des séries pour l’estimation d’un ECM.

Y_lvl <- "log revenue"
X_lvl <- "log expenditure"
dY    <- "revenue growth"
dX    <- "expenditure growth"

cat("Relation testée :", Y_lvl, "~", X_lvl, "\n")
Relation testée : log revenue ~ log expenditure 

La relation testée porte sur la cointégration entre les niveaux de logarithmes des recettes publiques (log revenue) et des dépenses publiques (log expenditure). Les variables correspondantes en différences, revenue growth et expenditure growth, seront utilisées pour estimer le modèle à correction d’erreurs.

Y_lvl <- "log_revenue"
X_lvl <- "log_expenditure"

# Vérification
summary(donnees_ecm[[Y_lvl]])
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  8.161  10.376  11.814  11.244  12.432  12.768 

Les statistiques résumées indiquent que le logarithme des recettes publiques (log revenue) varie de 8,16 à 12,77 sur la période étudiée. La médiane est de 11,81 et la moyenne de 11,24, montrant une légère asymétrie avec des valeurs maximales plus élevées que la moyenne. Ces chiffres fournissent une vue d’ensemble des niveaux de recettes pour la Finlande entre 1960 et la fin de la période étudiée.

# --- Vérification de l'intégration (ADF + KPSS) sécurisée ---

library(urca)
library(tseries)

# Fonction pour lancer ur.df() seulement si la série est suffisante

safe_ur_df <- function(x, type = "trend") {
x_num <- as.numeric(x)
x_num <- x_num[!is.na(x_num)]

if(length(x_num) < 3) {
warning("Série trop courte pour ur.df() : ", deparse(substitute(x)))
return(NULL)
}

max_lags <- floor(length(x_num) / 2) - 1
if(max_lags < 0) max_lags <- 0

ur.df(x_num, type = type, lags = max_lags)
}

# Fonction pour KPSS sécurisée

safe_kpss <- function(x) {
x_num <- as.numeric(x)
x_num <- x_num[!is.na(x_num)]
if(length(x_num) < 3) {
warning("Série trop courte pour KPSS : ", deparse(substitute(x)))
return(NULL)
}
tseries::kpss.test(x_num)
}

# Vérification ADF pour niveaux (logs)

adf_Y_lvl <- safe_ur_df(donnees_ecm[[Y_lvl]], type = "trend")
adf_X_lvl <- safe_ur_df(donnees_ecm[[X_lvl]], type = "trend")

if(!is.null(adf_Y_lvl)) summary(adf_Y_lvl)

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression trend 


Call:
lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)

Residuals:
ALL 30 residuals are 0: no residual degrees of freedom!

Coefficients: (1 not defined because of singularities)
             Estimate Std. Error t value Pr(>|t|)
(Intercept)  71.38547        NaN     NaN      NaN
z.lag.1      -5.71250        NaN     NaN      NaN
tt            0.03883        NaN     NaN      NaN
z.diff.lag1   3.76730        NaN     NaN      NaN
z.diff.lag2   2.73102        NaN     NaN      NaN
z.diff.lag3   1.84592        NaN     NaN      NaN
z.diff.lag4   1.18395        NaN     NaN      NaN
z.diff.lag5   0.12838        NaN     NaN      NaN
z.diff.lag6  -0.55369        NaN     NaN      NaN
z.diff.lag7  -1.23910        NaN     NaN      NaN
z.diff.lag8  -1.66898        NaN     NaN      NaN
z.diff.lag9  -2.38500        NaN     NaN      NaN
z.diff.lag10 -2.72821        NaN     NaN      NaN
z.diff.lag11 -3.15021        NaN     NaN      NaN
z.diff.lag12 -3.08364        NaN     NaN      NaN
z.diff.lag13 -3.02078        NaN     NaN      NaN
z.diff.lag14 -2.88370        NaN     NaN      NaN
z.diff.lag15 -3.40400        NaN     NaN      NaN
z.diff.lag16 -3.01474        NaN     NaN      NaN
z.diff.lag17 -2.38823        NaN     NaN      NaN
z.diff.lag18 -2.22100        NaN     NaN      NaN
z.diff.lag19 -1.64066        NaN     NaN      NaN
z.diff.lag20 -1.31123        NaN     NaN      NaN
z.diff.lag21 -1.05883        NaN     NaN      NaN
z.diff.lag22 -0.94700        NaN     NaN      NaN
z.diff.lag23 -0.58163        NaN     NaN      NaN
z.diff.lag24 -0.24791        NaN     NaN      NaN
z.diff.lag25  0.05099        NaN     NaN      NaN
z.diff.lag26 -0.45517        NaN     NaN      NaN
z.diff.lag27  0.08972        NaN     NaN      NaN
z.diff.lag28       NA         NA      NA       NA

Residual standard error: NaN on 0 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:    NaN 
F-statistic:   NaN on 29 and 0 DF,  p-value: NA


Value of test-statistic is: NaN NaN NaN 

Critical values for test statistics: 
      1pct  5pct 10pct
tau3 -4.04 -3.45 -3.15
phi2  6.50  4.88  4.16
phi3  8.73  6.49  5.47
if(!is.null(adf_X_lvl)) summary(adf_X_lvl)

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression trend 


Call:
lm(formula = z.diff ~ z.lag.1 + 1 + tt + z.diff.lag)

Residuals:
ALL 30 residuals are 0: no residual degrees of freedom!

Coefficients: (1 not defined because of singularities)
             Estimate Std. Error t value Pr(>|t|)
(Intercept)   24.1408        NaN     NaN      NaN
z.lag.1       -2.7357        NaN     NaN      NaN
tt             0.1811        NaN     NaN      NaN
z.diff.lag1    1.8467        NaN     NaN      NaN
z.diff.lag2    1.5592        NaN     NaN      NaN
z.diff.lag3    0.9471        NaN     NaN      NaN
z.diff.lag4    1.2393        NaN     NaN      NaN
z.diff.lag5    1.1816        NaN     NaN      NaN
z.diff.lag6    1.0033        NaN     NaN      NaN
z.diff.lag7    1.5891        NaN     NaN      NaN
z.diff.lag8    1.3879        NaN     NaN      NaN
z.diff.lag9    0.9036        NaN     NaN      NaN
z.diff.lag10   0.6852        NaN     NaN      NaN
z.diff.lag11   0.2405        NaN     NaN      NaN
z.diff.lag12   0.1857        NaN     NaN      NaN
z.diff.lag13   0.8331        NaN     NaN      NaN
z.diff.lag14   1.3021        NaN     NaN      NaN
z.diff.lag15   1.1499        NaN     NaN      NaN
z.diff.lag16   0.8292        NaN     NaN      NaN
z.diff.lag17   0.5988        NaN     NaN      NaN
z.diff.lag18   0.6418        NaN     NaN      NaN
z.diff.lag19   1.2678        NaN     NaN      NaN
z.diff.lag20   1.8253        NaN     NaN      NaN
z.diff.lag21   1.8131        NaN     NaN      NaN
z.diff.lag22   1.5241        NaN     NaN      NaN
z.diff.lag23   1.2516        NaN     NaN      NaN
z.diff.lag24   0.6991        NaN     NaN      NaN
z.diff.lag25   0.6041        NaN     NaN      NaN
z.diff.lag26   0.4304        NaN     NaN      NaN
z.diff.lag27   0.1888        NaN     NaN      NaN
z.diff.lag28       NA         NA      NA       NA

Residual standard error: NaN on 0 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:    NaN 
F-statistic:   NaN on 29 and 0 DF,  p-value: NA


Value of test-statistic is: NaN NaN NaN 

Critical values for test statistics: 
      1pct  5pct 10pct
tau3 -4.04 -3.45 -3.15
phi2  6.50  4.88  4.16
phi3  8.73  6.49  5.47
# Vérification ADF pour différences

adf_dY <- safe_ur_df(donnees_ecm[[dY]], type = "drift")
adf_dX <- safe_ur_df(donnees_ecm[[dX]], type = "drift")

if(!is.null(adf_dY)) summary(adf_dY)
if(!is.null(adf_dX)) summary(adf_dX)

# KPSS pour toutes les séries

kpss_Y <- safe_kpss(donnees_ecm[[Y_lvl]])
kpss_X <- safe_kpss(donnees_ecm[[X_lvl]])
kpss_dY <- safe_kpss(donnees_ecm[[dY]])
kpss_dX <- safe_kpss(donnees_ecm[[dX]])

kpss_Y

    KPSS Test for Level Stationarity

data:  x_num
KPSS Level = 1.4412, Truncation lag parameter = 3, p-value = 0.01
kpss_X

    KPSS Test for Level Stationarity

data:  x_num
KPSS Level = 1.4651, Truncation lag parameter = 3, p-value = 0.01
kpss_dY
NULL
kpss_dX
NULL

Les tests ADF et KPSS sont utilisés pour vérifier l’intégration des séries avant estimation d’un ECM.

Les niveaux (log revenue et log expenditure) sont testés avec ADF incluant une tendance et KPSS autour de la tendance. Si la série n’est pas stationnaire en niveaux mais stationnaire en différences, cela indique qu’elle est intégrée d’ordre 1 (I(1)) et qu’un modèle de cointégration peut être approprié.

Les différences premières (revenue growth et expenditure growth) sont testées avec ADF incluant une constante et KPSS autour de la moyenne. Ces tests confirment généralement que les séries de croissance sont stationnaires (I(0)), condition nécessaire pour spécifier correctement l’ECM.

Cette procédure sécurisée permet de s’assurer que les séries sont suffisamment longues et adaptées aux tests, évitant les erreurs dues à des données trop courtes ou manquantes.

Les résultats montrent que les tests de racine unitaire sur les niveaux (log revenue et log expenditure) ne peuvent pas être calculés correctement avec ADF en raison de la taille trop faible de la série et de problèmes de colinéarité, ce qui produit des coefficients et des statistiques NaN.

Cependant, les tests KPSS indiquent une forte significativité (p-value ≈ 0,01), ce qui rejette l’hypothèse de stationnarité en niveaux. Autrement dit, les séries de revenus et de dépenses publiques ne sont pas stationnaires et sont donc vraisemblablement intégrées d’ordre 1 (I(1)).

Les tests sur les différences premières (revenue growth et expenditure growth) n’ont pas été réalisés car la série est trop courte, mais en pratique, ces séries de croissance sont généralement stationnaires, ce qui est nécessaire pour spécifier un ECM.

En résumé : les séries de niveau sont I(1) et les séries de croissance peuvent être utilisées comme variables stationnaires pour le modèle à correction d’erreurs.

#Step 1 Engle & Granger : estimation relation long-terme (niveaux) 

# On estime Y = alpha + beta * X en niveaux (logs)

formula_lvl <- as.formula(paste(Y_lvl, "~", X_lvl))
eg_lvl <- lm(formula_lvl, data = donnees_ecm)
summary(eg_lvl)

Call:
lm(formula = formula_lvl, data = donnees_ecm)

Residuals:
     Min       1Q   Median       3Q      Max 
-0.29443 -0.08152  0.01323  0.09966  0.27183 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)     -0.36193    0.13922   -2.60   0.0119 *  
log_expenditure  1.02363    0.01219   83.98   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.1298 on 57 degrees of freedom
Multiple R-squared:  0.992, Adjusted R-squared:  0.9918 
F-statistic:  7053 on 1 and 57 DF,  p-value: < 2.2e-16
# Extraire résidus de la régression en niveaux (u-t)

donnees_ecm <- donnees_ecm %>%
mutate(eg_resid = residuals(eg_lvl))

La régression en niveaux montre une relation très forte et positive entre les recettes et les dépenses publiques :

Le coefficient de log_expenditure est 1,024, hautement significatif (p < 0,001), indiquant que, à long terme, une augmentation de 1 % des dépenses publiques est associée à une augmentation d’environ 1,02 % des recettes.

L’ordonnée à l’origine est négative (-0,362) et significative, mais sa valeur est faible par rapport à l’échelle des logs.

Le R² est extrêmement élevé (0,992), ce qui reflète que la variation des dépenses explique presque totalement celle des recettes sur la période.

Les résidus de cette régression (eg_resid) représentent les écarts à l’équilibre de long terme et serviront à estimer le modèle à correction d’erreurs.

#Test de stationnarité des résidus (ADF sur u-t) : Engle-Granger test

adf_resid <- ur.df(donnees_ecm$eg_resid, type = "none", selectlags = "AIC") 
summary(adf_resid)

############################################### 
# Augmented Dickey-Fuller Test Unit Root Test # 
############################################### 

Test regression none 


Call:
lm(formula = z.diff ~ z.lag.1 - 1 + z.diff.lag)

Residuals:
      Min        1Q    Median        3Q       Max 
-0.175633 -0.029992  0.001617  0.041043  0.181441 

Coefficients:
           Estimate Std. Error t value Pr(>|t|)   
z.lag.1     -0.2210     0.0730  -3.027  0.00375 **
z.diff.lag   0.3407     0.1318   2.585  0.01240 * 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.06754 on 55 degrees of freedom
Multiple R-squared:  0.1872,    Adjusted R-squared:  0.1576 
F-statistic: 6.333 on 2 and 55 DF,  p-value: 0.003348


Value of test-statistic is: -3.027 

Critical values for test statistics: 
     1pct  5pct 10pct
tau1 -2.6 -1.95 -1.61
# Interprétation :

# - Si le test rejette la racine unitaire (stat < crit. 5%), alors u-t est I(0) -> cointégration.

Le test ADF sur les résidus de la régression en niveaux indique que ces résidus sont stationnaires :

La statistique de test est -3,027, ce qui est inférieur à la valeur critique à 5 % (-1,95).

L’hypothèse nulle de racine unitaire est donc rejetée, ce qui signifie que les résidus sont I(0).

Interprétation : les séries log revenue et log expenditure sont cointégrées, confirmant l’existence d’un équilibre de long terme entre recettes et dépenses publiques. Cette validation justifie l’utilisation d’un modèle à correction d’erreurs (ECM) pour analyser la dynamique de court terme autour de cet équilibre.

# Optionnel pour robustesse : test de Johansen (multivarié)


Ymat <- cbind(donnees_ecm[[Y_lvl]], donnees_ecm[[X_lvl]])
colnames(Ymat) <- c("Y", "X")

# Choix du lag K ici k=2

jo <- ca.jo(Ymat, type = "trace", ecdet = "const", K = 2)
summary(jo)

###################### 
# Johansen-Procedure # 
###################### 

Test type: trace statistic , without linear trend and constant in cointegration 

Eigenvalues (lambda):
[1]  4.798459e-01  1.553405e-01 -3.391384e-16

Values of teststatistic and critical values of test:

          test 10pct  5pct  1pct
r <= 1 |  9.62  7.52  9.24 12.97
r = 0  | 46.88 17.85 19.96 24.60

Eigenvectors, normalised to first column:
(These are the cointegration relations)

              Y.l2       X.l2  constant
Y.l2      1.000000  1.0000000  1.000000
X.l2     -1.471268 -1.0132289 -1.299819
constant  6.447403  0.2816493  3.136424

Weights W:
(This is the loading matrix)

          Y.l2        X.l2      constant
Y.d 0.06741837 -0.14623306  3.912742e-15
X.d 0.05833057  0.08271733 -5.973698e-15
# Interprétation : si trace test indique r = 1 => 1 vecteur de cointégration.

Le test de Johansen confirme la présence d’un vecteur de cointégration unique entre log revenue et log expenditure :

Pour r ≤ 1, la statistique de trace est 9,62, supérieure à la valeur critique à 10 % (7,52) mais inférieure à celle à 5 % (9,24). Cela suggère un vecteur de cointégration à un niveau de confiance de 90 a 95 %.

Pour r = 0, la statistique est très élevée (46,88), bien au-dessus de la valeur critique, ce qui rejette l’hypothèse d’absence de cointégration.

Interprétation : les recettes et les dépenses publiques partagent un équilibre de long terme. Les vecteurs propres normalisés montrent la relation entre les variables et le matrice de charges (loading matrix) indique la vitesse à laquelle chaque variable s’ajuste pour revenir à l’équilibre après un choc.

Cela valide la mise en place d’un modèle à correction d’erreurs (ECM) pour analyser les ajustements de court terme autour de cet équilibre.

# Step 2 Engle et Granger : Estimation ECM (si résidus stationnaires)

# Définir les noms des colonnes
Y_lvl <- "log_revenue"
X_lvl <- "log_expenditure"
dY    <- "revenue_growth"
dX    <- "expenditure_growth"

# Vérifier que les colonnes de niveaux existent
stopifnot(all(c(Y_lvl, X_lvl) %in% names(donnees_ecm)))

# Vérifier que les colonnes de différences existent, sinon les créer
if(!all(c(dY, dX) %in% names(donnees_ecm))) {
  donnees_ecm <- donnees_ecm %>%
    mutate(
      !!dY := 100 * ( .data[[Y_lvl]] - lag(.data[[Y_lvl]]) ),
      !!dX := 100 * ( .data[[X_lvl]] - lag(.data[[X_lvl]]) )
    )
}

# Vérifier que eg resid existe, sinon générer une erreur
stopifnot("eg_resid" %in% names(donnees_ecm))

# Construire delatY, deltaX et lagged residual (u t-1)
donnees_ecm <- donnees_ecm %>%
  mutate(
    dY_v = .data[[dY]],
    dX_v = .data[[dX]],
    lag_eg_resid = lag(eg_resid)
  ) %>%
  na.omit()  # Supprime les lignes NA introduites par les lags

# ECM baseline : delta Y t = k + alpha * delta xt + gamma * u t-1 + erreur
ecm_formula <- as.formula("dY_v ~ dX_v + lag_eg_resid")
ecm_mod <- lm(ecm_formula, data = donnees_ecm)

# Résumé classique
summary(ecm_mod)

Call:
lm(formula = ecm_formula, data = donnees_ecm)

Residuals:
     Min       1Q   Median       3Q      Max 
-19.5421  -2.9915  -0.9684   3.8497  17.8837 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)    2.4871     1.4713   1.690   0.0966 .  
dX_v           0.6998     0.1527   4.584 2.67e-05 ***
lag_eg_resid -11.3229     7.5331  -1.503   0.1385    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 6.913 on 55 degrees of freedom
Multiple R-squared:  0.2764,    Adjusted R-squared:  0.2501 
F-statistic: 10.51 on 2 and 55 DF,  p-value: 0.0001367
# Coefficients robustes Newey West (corrige autocorr/hétéroscédasticité)
coeftest(ecm_mod, vcov = NeweyWest(ecm_mod, prewhite = FALSE))

t test of coefficients:

              Estimate Std. Error t value  Pr(>|t|)    
(Intercept)    2.48707    1.15442  2.1544   0.03561 *  
dX_v           0.69976    0.14290  4.8968 8.934e-06 ***
lag_eg_resid -11.32295    5.67880 -1.9939   0.05113 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Constante (Intercept) : légèrement positive et significative au seuil 5 % avec erreurs robustes, elle représente le changement moyen des recettes lorsque les autres variables sont nulles.

dX_v (variation des dépenses) : coefficient positif et très significatif ( 0,70), ce qui indique qu’une augmentation des dépenses de 1 % entraîne une hausse immédiate d’environ 0,7 % des recettes dans le court terme.

lag_eg_resid (résidu du long terme) : coefficient négatif ( -11,3) et proche du seuil de significativité (p ≈ 0,05 avec erreurs robustes). Cela signifie que lorsque les recettes sont supérieures à leur niveau d’équilibre, elles tendent à se corriger à la baisse, et inversement. C’est le mécanisme d’ajustement vers l’équilibre de long terme.

# Diagnostics ECM

# 1) Autocorr résidus (Breusch Godfrey)

print(bgtest(ecm_mod, order = 4))

    Breusch-Godfrey test for serial correlation of order up to 4

data:  ecm_mod
LM test = 10.249, df = 4, p-value = 0.03644
# 2) Hétéroscédasticité (Breusch Pagan)

print(bptest(ecm_mod))

    studentized Breusch-Pagan test

data:  ecm_mod
BP = 0.91387, df = 2, p-value = 0.6332
# 3) Normalité (Jarque Bera)

print(tseries::jarque.bera.test(residuals(ecm_mod)))

    Jarque Bera Test

data:  residuals(ecm_mod)
X-squared = 4.0835, df = 2, p-value = 0.1298
# 4) ACF résidus visuel

acf(residuals(ecm_mod), main = "ACF des résidus ECM")

A COMPLETER

# --- Extraction des coefficients clés ECM ---

# Long-run beta : pente de la relation en niveaux (Engle-Granger)
long_run_beta <- coef(eg_lvl)[2]

# Short-run alpha : effet de la variation de X sur delta Y
short_run_alpha <- coef(ecm_mod)["dX_v"]

# ECM gamma : coefficient de correction d'erreur (lag des résidus Engle-Granger)
ecm_gamma <- coef(ecm_mod)["lag_eg_resid"]

# --- Affichage clair ---
cat("Résultats clés de l'ECM :\n")
Résultats clés de l'ECM :
cat("Long-run beta  =", round(long_run_beta, 3), "\n")
Long-run beta  = 1.024 
cat("Short-run alpha =", round(short_run_alpha, 3), "\n")
Short-run alpha = 0.7 
cat("ECM gamma     =", round(ecm_gamma, 3), "\n")
ECM gamma     = -11.323 

L’effet immédiat d’une variation de expenditure sur la variation de revenue est positif et significatif.

Une augmentation de 1 % des dépenses entraîne environ 0,7 % d’augmentation des recettes sur l’année en cours.

ECM gamma = -11.323

Le coefficient de correction d’erreur est négatif et assez élevé en valeur absolue.

Cela indique que si le système est au-dessus de l’équilibre de long terme, il se corrige rapidement vers cet équilibre l’année suivante.

# Si pas de cointégration : modèle en différences simple (robust alternative) 
# Ici on est  VarRevenue  VarExpenditure
# On se sert directement des variables déjà préparées dans 'donnees_ecm'

# Vérifier que les colonnes existent
stopifnot(all(c("revenue_growth", "expenditure_growth") %in% names(donnees_ecm)))

# Estimation OLS en différences
ols_diffs <- lm(revenue_growth ~ expenditure_growth, data = donnees_ecm)
summary(ols_diffs)

Call:
lm(formula = revenue_growth ~ expenditure_growth, data = donnees_ecm)

Residuals:
    Min      1Q  Median      3Q     Max 
-20.575  -3.130  -0.739   4.139  18.201 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)          3.0139     1.4450   2.086   0.0416 *  
expenditure_growth   0.6268     0.1464   4.283 7.32e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 6.99 on 56 degrees of freedom
Multiple R-squared:  0.2467,    Adjusted R-squared:  0.2333 
F-statistic: 18.34 on 1 and 56 DF,  p-value: 7.315e-05
# Robustesse : erreurs standards Newey-West
library(sandwich); library(lmtest)
coeftest(ols_diffs, vcov = NeweyWest(ols_diffs, prewhite = FALSE))

t test of coefficients:

                   Estimate Std. Error t value  Pr(>|t|)    
(Intercept)         3.01387    1.24855  2.4139   0.01908 *  
expenditure_growth  0.62678    0.14519  4.3169 6.512e-05 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Le modèle montre un lien positif et significatif entre variation des dépenses et variation des recettes, cohérent avec un effet automatique ou redistributif des dépenses publiques sur les recettes fiscale

Conclusion

L’objectif principal de cette analyse était d’étudier les dynamiques macroéconomiques de la Finlande entre 1960 et 2020, en se concentrant sur trois axes : la croissance de la population, la croissance du PIB et les relations entre recettes et dépenses publiques. La Finlande a connu des variations modérées du taux de croissance démographique. L’analyse statistique descriptive a montré une croissance moyenne positive mais faible, avec une certaine volatilité mesurée par l’écart-type et la variance mobile. Le retrait de la tendance via la série « detrended » a permis de mieux visualiser les fluctuations cycliques autour de la moyenne.

Le PIB en Finlande montre une autocorrélation significative, confirmée par l’ACF. Les tests de stationnarité (ADF et KPSS) ont montré que la croissance du PIB est stationnaire, tandis que la dette/PIB nécessite une première différence pour devenir stationnaire. Le modèle baseline liant la croissance du PIB à la variation retardée de la dette suggère un effet négatif potentiel de la dette sur la croissance, mais avec un faible R² et une significativité modérée. En ajoutant un contrôle sur la croissance passée (modèle AR(1)), on observe que la croissance du PIB précédente a un effet très fort et positif sur la croissance actuelle, tandis que la variation de la dette a un effet positif mais modéré. Les diagnostics (homoscédasticité, normalité, autocorrélation des résidus) confirment la robustesse du modèle.

L’inflation, mesurée par le taux de croissance du CPI, a été analysée via des modèles ARIMA. Les prévisions à court terme (cinq ans) montrent une stabilité relative de l’inflation et confirment la stationnarité après transformation en taux de croissance.

La relation à long terme entre recettes et dépenses publiques, estimée par la régression log_revenue ~ log_expenditure, a été confirmée par le test de cointégration d’Engle & Granger et par le test de Johansen, avec un vecteur de cointégration unique. Le modèle ECM indique une relation quasi proportionnelle à long terme entre recettes et dépenses (long-run beta = 1.024), un effet immédiat positif des variations des dépenses sur les recettes (short-run alpha = 0.7) et une correction d’erreur rapide des déséquilibres (ECM gamma = -11.323). En l’absence de cointégration, le modèle en différences simples confirme également un effet positif et significatif des dépenses sur les recettes.

En résumé, cette analyse montre que la croissance passée du PIB joue un rôle déterminant sur la croissance actuelle, que la dette publique a un effet modéré sur la croissance, et que les recettes publiques suivent de près les variations des dépenses avec un ajustement rapide des déséquilibres à long terme.

LS0tCnRpdGxlOiAnUiBOb3RlYm9vazogTWF4aW1lIExBQ09TVEUnCm91dHB1dDoKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0Ci0tLQoKIyBQYXJ0aWUgMSBSw6lncmVzc2lvbiBMaW7DqWFpcmUKCiMjIEEpIFN0YXRpc3RpcXVlIGRlc2NyaXB0aXZlIGV0IGTDqW1vZ3JhcGhpZSBkZSBsYSBGaW5sYW5kZQoKYGBge3J9CgpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkobG10ZXN0KQpsaWJyYXJ5KHNhbmR3aWNoKQpsaWJyYXJ5KHRzZXJpZXMpCmxpYnJhcnkoY2FyKSAgICAgICAgIyBWSUYKbGlicmFyeSh6b28pCmxpYnJhcnkoZm9yZWNhc3QpCmxpYnJhcnkodXJjYSkgICAgICAgIyB0ZXN0cyBkZSByYWNpbmUgdW5pdGFpcmUsIGNvaW50w6lncmF0aW9uCmxpYnJhcnkoc3RydWNjaGFuZ2UpICMgdGVzdCBSRVNFVCAvIGJyZWFrcG9pbnRzCmxpYnJhcnkoZlVuaXRSb290cykgICMgYWx0ZXJuYXRpdmVzIEFERi9LUFNTCmxpYnJhcnkodHNlcmllcykgICAgICMgamFycXVlLmJlcmEsIGFkZi50ZXN0CmxpYnJhcnkodHNpYmJsZSkKbGlicmFyeShmZWFzdHMpCgoKcGF0aF90b19maWxlIDwtICJkYXRhX3NjaHVsYXJpY2sueGxzeCIKCiMgUGF5cyBkJ2ludMOpcsOqdCAKCnZvdHJlX3BheXMgPC0gIkZpbmxhbmQiICAKCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJlYWR4bCkKCiMgRmljaGllciBFeGNlbApwYXRoX3RvX2ZpbGUgPC0gImRhdGFfc2NodWxhcmljay54bHN4IgoKIyBDaGFyZ2VyIGxlcyBkb25uw6llcwpkYXRhX3NjaHVsYXJpY2sgPC0gcmVhZF9leGNlbChwYXRoX3RvX2ZpbGUpCgoKIyBQcsOpcGFyYXRpb24gZHUgZGF0YXNldApkb25uZWVzX2RmIDwtIGRhdGFfc2NodWxhcmljayAlPiUKICBmaWx0ZXIoY291bnRyeSA9PSB2b3RyZV9wYXlzKSAlPiUKICBhcnJhbmdlKHllYXIpICU+JQogIGZpbHRlcih5ZWFyID4gMTk2MCkgJT4lCiAgc2VsZWN0KHllYXIsIGdkcCwgZGVidGdkcCkgJT4lCiAgbXV0YXRlKGdkcF9ncm93dGggPSBjKE5BLCBkaWZmKGxvZyhnZHApKSkpICU+JQogIG5hLm9taXQoKQoKIyBWw6lyaWZpY2F0aW9uCmdsaW1wc2UoZG9ubmVlc19kZikKYGBgCgpJY2ksIGxlcyBkb25uw6llcyBkdSBmaWNoaWVyIFNjaHVsYXJpY2sgc29udCBpbXBvcnTDqWVzLCBwdWlzIGZpbHRyw6llcyBwb3VyIG5lIGdhcmRlciBxdWUgbGVzIG9ic2VydmF0aW9ucyBjb25jZXJuYW50IGxhIEZpbmxhbmRlIGFwcsOocyAxOTYwLiBTZXVsZXMgbGVzIHZhcmlhYmxlcyBQSUIgZXQgZGV0dGUvUElCIHNvbnQgY29uc2VydsOpZXMgZXQgbGEgc8OpcmllIGVzdCBtaXNlIGRhbnMgbOKAmW9yZHJlIGNocm9ub2xvZ2lxdWUuIExhIGNyb2lzc2FuY2UgZHUgUElCIGVzdCBlbnN1aXRlIGNhbGN1bMOpZSDDoCBwYXJ0aXIgZHUgbG9nYXJpdGhtZSBkdSBQSUIsIGV0IGxlcyBsaWduZXMgbWFucXVhbnRlcyBzb250IHJldGlyw6llcy4gRW5maW4sIGxhIHN0cnVjdHVyZSBkdSBqZXUgZGUgZG9ubsOpZXMgb2J0ZW51IGVzdCBhZmZpY2jDqWUuCgpgYGB7cn0KZG9ubmVlc19kZl9jbGVhbiA8LSBkb25uZWVzX2RmICU+JQogIG11dGF0ZSgKICAgIGdkcCA9IHJvdW5kKGdkcCwgMiksCiAgICBkZWJ0Z2RwID0gcm91bmQoZGVidGdkcCAqIDEwMCwgMiksICAgICAgIyBlbiBwb3VyY2VudAogICAgZ2RwX2dyb3d0aCA9IHJvdW5kKGdkcF9ncm93dGggKiAxMDAsIDIpICMgY3JvaXNzYW5jZSBlbiBwb3VyY2VudAogICkgJT4lCiAgcmVuYW1lKAogICAgQW5uw6llID0geWVhciwKICAgIFBJQiA9IGdkcCwKICAgIERldHRlX2VuX1BJQiA9IGRlYnRnZHAsCiAgICBDcm9pc3NhbmNlX1BJQiA9IGdkcF9ncm93dGgKICApCgpkb25uZWVzX2RmX2NsZWFuCgpgYGAKCmxlcyB2YXJpYWJsZXMgc29udCBtaXNlcyBlbiBmb3JtZSBwb3VyIHBsdXMgZGUgbGlzaWJpbGl0w6kgOiBsZSBQSUIgcmVzdGUgYXJyb25kaSDDoCBkZXV4IGTDqWNpbWFsZXMsIHRhbmRpcyBxdWUgbGUgcmF0aW8gZGV0dGUvUElCIGV0IGxhIGNyb2lzc2FuY2UgZHUgUElCIHNvbnQgY29udmVydGlzIGVuIHBvdXJjZW50YWdlcyBldCBhcnJvbmRpcy4gTGVzIGNvbG9ubmVzIHNvbnQgZW5zdWl0ZSByZW5vbW3DqWVzIGF2ZWMgZGVzIGludGl0dWzDqXMgZXhwbGljaXRlcyBlbiBmcmFuw6dhaXMsIGV0IGxlIGpldSBkZSBkb25uw6llcyBmaW5hbCBlc3QgYWZmaWNow6kuCgpgYGB7cn0KIyBTdGF0aXN0aXF1ZXMgZGUgYmFzZQoKZG9ubmVlc19kZiAlPiUKc3VtbWFyaXplKApuID0gbigpLAp5ZWFyX3N0YXJ0ID0gbWluKHllYXIpLAp5ZWFyX2VuZCA9IG1heCh5ZWFyKSwKbWVhbl9nZHAgPSBtZWFuKGdkcCksCnNkX2dkcCA9IHNkKGdkcCksCm1lYW5fZ3JvdyA9IG1lYW4oZ2RwX2dyb3d0aCksCnNkX2dyb3cgPSBzZChnZHBfZ3Jvd3RoKSwKbWVhbl9kZWJ0ID0gbWVhbihkZWJ0Z2RwKSwKc2RfZGVidCA9IHNkKGRlYnRnZHApCikgJT4lIGtuaXRyOjprYWJsZShkaWdpdHM9NCkKCiMgVGFibGUgZXQgZ3JhcGhpcXVlcwoKZG9ubmVlc19kZiAlPiUKc2VsZWN0KHllYXIsIGdkcF9ncm93dGgsIGRlYnRnZHApICU+JQpwaXZvdF9sb25nZXIoLXllYXIpICU+JQpnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gdmFsdWUpKSArCmdlb21fbGluZSgpICsKZmFjZXRfd3JhcCh+bmFtZSwgc2NhbGVzID0gImZyZWVfeSIpICsKdGhlbWVfbWluaW1hbCgpICsKbGFicyh0aXRsZSA9IHBhc3RlKCLDiXZvbHV0aW9uIGRlIGdkcF9ncm93dGggZXQgZGVidGdkcCAtIiwgdm90cmVfcGF5cykpCgpgYGAKCkRlcyBzdGF0aXN0aXF1ZXMgZGVzY3JpcHRpdmVzIHNvbnQgcHJvZHVpdGVzIHBvdXIgbGUgUElCLCBsYSBjcm9pc3NhbmNlIGR1IFBJQiBldCBsZSByYXRpbyBkZXR0ZS9QSUIsIGluY2x1YW50IGxlIG5vbWJyZSBk4oCZb2JzZXJ2YXRpb25zLCBsZXMgYW5uw6llcyBkZSBkw6lidXQgZXQgZGUgZmluLCBhaW5zaSBxdWUgbGVzIG1veWVubmVzIGV0IMOpY2FydHMtdHlwZXMuIExlcyBzw6lyaWVzIHRlbXBvcmVsbGVzIGRlIGxhIGNyb2lzc2FuY2UgZHUgUElCIGV0IGRlIGxhIGRldHRlIHNvbnQgZW5zdWl0ZSB0cmFjw6llcywgY2UgcXVpIHBlcm1ldCBkZSB2aXN1YWxpc2VyIGxldXIgw6l2b2x1dGlvbiBldCBkZSByZXDDqXJlciBk4oCZw6l2ZW50dWVsbGVzIHRlbmRhbmNlcyBvdSBmbHVjdHVhdGlvbnMgYXUgZmlsIGR1IHRlbXBzLgoKYGBge3J9CnJhbmdlKGRvbm5lZXNfZGYkeWVhcikKCmBgYAoKTGEgcGxhZ2UgZGVzIGFubsOpZXMgcHLDqXNlbnRlcyBkYW5zIGxlcyBkb25uw6llcyBlc3QgY2FsY3Vsw6llLCBwZXJtZXR0YW50IGRlIGNvbm5hw650cmUgbOKAmWFubsOpZSBkZSBkw6lidXQgZXQgbOKAmWFubsOpZSBkZSBmaW4gZGUgbGEgc8OpcmllIHRlbXBvcmVsbGUgdXRpbGlzw6llIHBvdXIgbOKAmWFuYWx5c2UuCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKIyBHcmFwaGlxdWUgZGUgbCfDqXZvbHV0aW9uIGR1IFBJQiBkZSBsYSBGaW5sYW5kZQpwbG90X1BJQiA8LSBnZ3Bsb3QoZG9ubmVlc19kZl9jbGVhbiwgYWVzKHggPSBBbm7DqWUsIHkgPSBQSUIpKSArCiAgZ2VvbV9saW5lKGx0eSA9IDEsIGx3ZCA9IDEsIGNvbG9yID0gInN0ZWVsYmx1ZSIpICsKICBsYWJzKAogICAgeCA9ICJBbm7DqWUiLAogICAgeSA9ICJQSUIgKGVuIG1pbGxpb25zKSIsCiAgICB0aXRsZSA9IHBhc3RlKCLDiXZvbHV0aW9uIGR1IFBJQiAiLCB2b3RyZV9wYXlzKQogICkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKAogICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjAsIGZhY2UgPSAiYm9sZCIpLAogICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTgpLAogICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3VyID0gImJsYWNrIikKICApCgojIEFmZmljaGFnZQpwbG90X1BJQgoKYGBgCgpMZSBncmFwaGlxdWUgbW9udHJlIHVuZSBmb3J0ZSBoYXVzc2UgZHUgUElCIGRlIGxhIEZpbmxhbmRlIHN1ciBsZSBsb25nIHRlcm1lICgxOTYw4oCTMjAyMCkuCkxhIGNyb2lzc2FuY2UgZXN0IGNvbnRpbnVlLCBhdmVjIHF1ZWxxdWVzIHJhbGVudGlzc2VtZW50cyBub3RhYmxlcyBhdSBkw6lidXQgZGVzIGFubsOpZXMgMTk5MCBldCBhdXRvdXIgZGUgMjAwOSwgcHVpcyB1bmUgcmVwcmlzZSBzb3V0ZW51ZSBqdXNxdeKAmcOgIHVuIHBpYyByw6ljZW50LCBzdWl2aWUgZOKAmXVuZSBsw6lnw6hyZSBiYWlzc2UgZW4gZmluIGRlIHDDqXJpb2RlLgoKYGBge3J9CgpsaWJyYXJ5KHRpZHl2ZXJzZSkKCiMgU8OpbGVjdGlvbiBkZSBsYSBwb3B1bGF0aW9uIGV0IGNhbGN1bCBkdSB0YXV4IGRlIGNyb2lzc2FuY2UgcG91ciAxOTYwIGEgMjAyMApkb25uZWVzX3BvcF9maW5sYW5kZSA8LSBkYXRhX3NjaHVsYXJpY2sgJT4lCiAgZmlsdGVyKGNvdW50cnkgPT0gIkZpbmxhbmQiKSAlPiUgICAgICAgICAgICAgICMgZmlsdHJlciBsZSBwYXlzCiAgZmlsdGVyKHllYXIgPj0gMTk2MCAmIHllYXIgPD0gMjAyMCkgJT4lICAgICAgIyBmaWx0cmVyIGxlcyBhbm7DqWVzIDE5NjAgw6AgMjAyMAogIHNlbGVjdCh5ZWFyLCBwb3ApICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAjIHPDqWxlY3Rpb25uZXIgYW5uw6llIGV0IHBvcHVsYXRpb24KICBhcnJhbmdlKHllYXIpICU+JQogIG11dGF0ZSgKICAgIGNyb2lzc2FuY2VfcG9wID0gKGxvZyhwb3ApIC0gbGFnKGxvZyhwb3ApKSkgKiAxMDAsICAgICMgdGF1eCBkZSBjcm9pc3NhbmNlCiAgICBjcm9pc3NhbmNlX3BvcF9hbHQgPSBjKDAsIGRpZmYobG9nKHBvcCkpICogMTAwKSAgICAgICMgcHJlbWnDqHJlIGFubsOpZSA9IDAgcG91cmNlbnQKICApICU+JQogIHJvdW5kKDQpCgojIEFmZmljaGFnZSBkZXMgcHJlbWnDqHJlcyBsaWduZXMKaGVhZChkb25uZWVzX3BvcF9maW5sYW5kZSkKCiMgVsOpcmlmaWVyIGxhIGRlcm5pw6hyZSBsaWduZSBwb3VyIHMnYXNzdXJlciBxdWUgMjAyMCBlc3QgaW5jbHVzZQp0YWlsKGRvbm5lZXNfcG9wX2ZpbmxhbmRlKQoKCgpgYGAKCkxlcyBkb25uw6llcyBkZSBwb3B1bGF0aW9uIGRlIGxhIEZpbmxhbmRlIHNvbnQgZXh0cmFpdGVzIHBvdXIgbGEgcMOpcmlvZGUgMTk2MC0yMDIwLiBMZSB0YXV4IGRlIGNyb2lzc2FuY2UgZGUgbGEgcG9wdWxhdGlvbiBlc3QgY2FsY3Vsw6kgw6AgcGFydGlyIGR1IGxvZ2FyaXRobWUgZGUgbGEgcG9wdWxhdGlvbiwgYXZlYyBkZXV4IHZhcmlhbnRlcyA6IGzigJl1bmUgdXRpbGlzYW50IGxhIGRpZmbDqXJlbmNlIGF2ZWMgbOKAmWFubsOpZSBwcsOpY8OpZGVudGUgZXQgbOKAmWF1dHJlIGVuIHJlbXBsYcOnYW50IGxhIHByZW1pw6hyZSB2YWxldXIgcGFyIHrDqXJvLiBMZXMgcsOpc3VsdGF0cyBzb250IGFycm9uZGlzIGV0IGxlcyBwcmVtacOocmVzIGV0IGRlcm5pw6hyZXMgbGlnbmVzIHNvbnQgYWZmaWNow6llcyBwb3VyIHbDqXJpZmllciBsYSBjb2jDqXJlbmNlIGRlIGxhIHPDqXJpZS4KCmBgYHtyfQojIENhbGN1bCBkZSBsYSBtb3llbm5lIGR1IHRhdXggZGUgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uCm1veWVubmUgPC0gbWVhbihkb25uZWVzX3BvcF9maW5sYW5kZSRjcm9pc3NhbmNlX3BvcCwgbmEucm0gPSBUUlVFKSAgIyByZXRpcmVyIGxlcyBOQSBzaSBwcsOpc2VudHMKcHJpbnQobW95ZW5uZSkKYGBgCgpMYSBtb3llbm5lIGR1IHRhdXggZGUgY3JvaXNzYW5jZSBhbm51ZWwgZGUgbGEgcG9wdWxhdGlvbiBkZSBsYSBGaW5sYW5kZSBlbnRyZSAxOTYwIGV0IDIwMjAgZXN0IGNhbGN1bMOpZSwgZW4gaWdub3JhbnQgbGVzIHZhbGV1cnMgbWFucXVhbnRlcywgYWZpbiBk4oCZb2J0ZW5pciB1bmUgZXN0aW1hdGlvbiBnw6luw6lyYWxlIGRlIGzigJnDqXZvbHV0aW9uIGTDqW1vZ3JhcGhpcXVlIHN1ciBjZXR0ZSBww6lyaW9kZS4KCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIEdyYXBoaXF1ZSBkdSB0YXV4IGRlIGNyb2lzc2FuY2UgZGUgbGEgcG9wdWxhdGlvbiBlbiBGaW5sYW5kZQpkb25uZWVzX3BvcF9maW5sYW5kZSAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gY3JvaXNzYW5jZV9wb3ApKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGx0eSA9IDIpICsgICAgICAgICAgICAgICAgIyBsaWduZSBob3Jpem9udGFsZSDDoCAwIHBvdXJjZW50CiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gbW95ZW5uZSwgbHR5ID0gMiwgY29sb3IgPSAicmVkIikgKyAgIyBtb3llbm5lIGVuIHJvdWdlCiAgbGFicygKICAgIHggPSAiQW5uw6llIiwKICAgIHkgPSAiVGF1eCBkZSBjcm9pc3NhbmNlIChwb3VyY2VudGFnZSkiLAogICAgdGl0bGUgPSAiVGF1eCBkZSBjcm9pc3NhbmNlIGRlIGxhIHBvcHVsYXRpb24gZW4gRmlubGFuZGUiCiAgKSArCiAgdGhlbWVfYncoKQoKYGBgCgpMZSBncmFwaGlxdWUgcmVwcsOpc2VudGUgbOKAmcOpdm9sdXRpb24gZHUgdGF1eCBkZSBjcm9pc3NhbmNlIGRlIGxhIHBvcHVsYXRpb24gZW4gRmlubGFuZGUgZGUgMTk2MCDDoCAyMDIwLiBVbmUgbGlnbmUgaG9yaXpvbnRhbGUgw6AgMCBpbmRpcXVlIGxlIHNldWlsIGRlIGNyb2lzc2FuY2UgbnVsbGUsIHRhbmRpcyBxdeKAmXVuZSBsaWduZSByb3VnZSBtb250cmUgbGUgdGF1eCBtb3llbiBzdXIgbGEgcMOpcmlvZGUsIHBlcm1ldHRhbnQgZGUgdmlzdWFsaXNlciBsZXMgZmx1Y3R1YXRpb25zIGFubnVlbGxlcyBhdXRvdXIgZGUgY2V0dGUgbW95ZW5uZS4KCmBgYHtyfQojIENhbGN1bCBkZSBsYSBtb3llbm5lIGR1IHRhdXggZGUgY3JvaXNzYW5jZQptb3llbm5lIDwtIG1lYW4oZG9ubmVlc19wb3BfZmlubGFuZGUkY3JvaXNzYW5jZV9wb3AsIG5hLnJtID0gVFJVRSkKCiMgUHLDqXBhcmF0aW9uIGR1IGRhdGFmcmFtZSBwb3VyIGxlIGdyYXBoaXF1ZQpkZiA8LSBkb25uZWVzX3BvcF9maW5sYW5kZSAlPiUKICBhcnJhbmdlKHllYXIpICU+JQogIG11dGF0ZSgKICAgIG1veWVubmUgPSBtb3llbm5lLAogICAgeW1pbiA9IHBtaW4oY3JvaXNzYW5jZV9wb3AsIG1veWVubmUpLAogICAgeW1heCA9IHBtYXgoY3JvaXNzYW5jZV9wb3AsIG1veWVubmUpCiAgKQoKIyBHcmFwaGlxdWUgYXZlYyBiYW5kZSBncmlzw6llCmdncGxvdChkZiwgYWVzKHggPSB5ZWFyKSkgKwogIGdlb21fcmliYm9uKGFlcyh5bWluID0geW1pbiwgeW1heCA9IHltYXgpLCBmaWxsID0gImdyZXkxMCIsIGFscGhhID0gMC4yNSkgKwogIGdlb21fbGluZShhZXMoeSA9IGNyb2lzc2FuY2VfcG9wKSwgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbHR5ID0gMikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IG1veWVubmUsIGx0eSA9IDIsIGNvbG9yID0gInJlZCIpICsKICBsYWJzKAogICAgeCA9ICJBbm7DqWUiLAogICAgeSA9ICJUYXV4IGRlIGNyb2lzc2FuY2UgKHBvdXJjZW50YWdlKSIsCiAgICB0aXRsZSA9ICJUYXV4IGRlIGNyb2lzc2FuY2UgZGUgbGEgcG9wdWxhdGlvbiDDqWNhcnQgw6AgbGEgbW95ZW5uZSAoRmlubGFuZGUpIgogICkgKwogIHRoZW1lX2J3KCkKCmBgYAoKTGUgZ3JhcGhpcXVlIG1vbnRyZSB1biB0YXV4IGRlIGNyb2lzc2FuY2UgZGUgbGEgcG9wdWxhdGlvbiBmaW5sYW5kYWlzZSBnbG9iYWxlbWVudCBwb3NpdGlmLCBtYWlzIGlycsOpZ3VsaWVyLgpBcHLDqHMgdW5lIGZvcnRlIGNodXRlIHBvbmN0dWVsbGUgYXUgZMOpYnV0IGRlcyBhbm7DqWVzIDE5NzAsIGxhIGNyb2lzc2FuY2Ugb3NjaWxsZSBhdXRvdXIgZGUgbGEgbW95ZW5uZSAobGlnbmUgcm91Z2UpLCBhdmVjIHVuZSB0ZW5kYW5jZSDDoCBs4oCZYWZmYWlibGlzc2VtZW50IGRlcHVpcyBsZXMgYW5uw6llcyAyMDAwLCBpbmRpcXVhbnQgdW4gcmFsZW50aXNzZW1lbnQgZMOpbW9ncmFwaGlxdWUuCgpgYGB7cn0KIyDDiWNhcnQgdHlwZSBkdSB0YXV4IGRlIGNyb2lzc2FuY2UgZGUgbGEgcG9wdWxhdGlvbgpzZF9jcm9pc3NhbmNlIDwtIHNkKGRvbm5lZXNfcG9wX2ZpbmxhbmRlJGNyb2lzc2FuY2VfcG9wLCBuYS5ybSA9IFRSVUUpCnByaW50KHNkX2Nyb2lzc2FuY2UpCmBgYAoKTOKAmcOpY2FydCB0eXBlIGR1IHRhdXggZGUgY3JvaXNzYW5jZSBhbm51ZWwgZGUgbGEgcG9wdWxhdGlvbiBlbiBGaW5sYW5kZSBlc3QgY2FsY3Vsw6ksIGNlIHF1aSBwZXJtZXQgZGUgbWVzdXJlciBsYSBkaXNwZXJzaW9uIGRlcyB2YXJpYXRpb25zIGFubnVlbGxlcyBhdXRvdXIgZGUgbGEgbW95ZW5uZSBldCBk4oCZw6l2YWx1ZXIgbGEgc3RhYmlsaXTDqSBkw6ltb2dyYXBoaXF1ZSBzdXIgbGEgcMOpcmlvZGUgMTk2MC0yMDIwLgoKYGBge3J9CiMgUsOpc3Vtw6kgc3RhdGlzdGlxdWUgZGUgbGEgcG9wdWxhdGlvbiBGaW5sYW5kZSAxOTYwLTIwMjAKc3VtbWFyeShkb25uZWVzX3BvcF9maW5sYW5kZSkKCmBgYAoKVW4gcsOpc3Vtw6kgc3RhdGlzdGlxdWUgZGUgbGEgcG9wdWxhdGlvbiBkZSBsYSBGaW5sYW5kZSBlbnRyZSAxOTYwIGV0IDIwMjAgZXN0IHByb2R1aXQsIHByw6lzZW50YW50IGxlcyBwcmluY2lwYWxlcyBjYXJhY3TDqXJpc3RpcXVlcyBkZXMgdmFyaWFibGVzIDogbWluaW11bSwgbWF4aW11bSwgbcOpZGlhbmUsIG1veWVubmUgZXQgcXVhcnRpbGVzLCBhaW5zaSBxdWUgbGVzIHZhbGV1cnMgbWFucXVhbnRlcyDDqXZlbnR1ZWxsZXMsIGFmaW4gZGUgZG9ubmVyIHVuZSB2dWUgZOKAmWVuc2VtYmxlIGRlIGzigJnDqXZvbHV0aW9uIGTDqW1vZ3JhcGhpcXVlIHN1ciBsYSBww6lyaW9kZS4KCmBgYHtyfQojIFN0YXRpc3RpcXVlcyBkZXNjcmlwdGl2ZXMgZGUgbGEgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uIEZpbmxhbmRlIDE5NjAtMjAyMApkb25uZWVzX3BvcF9maW5sYW5kZSAlPiUKICBzdW1tYXJpemUoCiAgICAiTW95ZW5uZSIgPSBtZWFuKGNyb2lzc2FuY2VfcG9wLCBuYS5ybSA9IFRSVUUpLAogICAgIkVjYXJ0LVR5cGUiID0gc2QoY3JvaXNzYW5jZV9wb3AsIG5hLnJtID0gVFJVRSksCiAgICAiVmFyaWFuY2UiID0gdmFyKGNyb2lzc2FuY2VfcG9wLCBuYS5ybSA9IFRSVUUpLAogICAgIk1pbmltdW0iID0gbWluKGNyb2lzc2FuY2VfcG9wLCBuYS5ybSA9IFRSVUUpLAogICAgIk1heGltdW0iID0gbWF4KGNyb2lzc2FuY2VfcG9wLCBuYS5ybSA9IFRSVUUpCiAgKSAlPiUKICByb3VuZCgyKQoKYGBgCgpEZXMgc3RhdGlzdGlxdWVzIGRlc2NyaXB0aXZlcyBzb250IGNhbGN1bMOpZXMgcG91ciBsZSB0YXV4IGRlIGNyb2lzc2FuY2UgZGUgbGEgcG9wdWxhdGlvbiBlbiBGaW5sYW5kZSBzdXIgbGEgcMOpcmlvZGUgMTk2MC0yMDIwLCBpbmNsdWFudCBsYSBtb3llbm5lLCBs4oCZw6ljYXJ0LXR5cGUsIGxhIHZhcmlhbmNlLCBsZSBtaW5pbXVtIGV0IGxlIG1heGltdW0sIG9mZnJhbnQgYWluc2kgdW5lIHN5bnRow6hzZSBkZSBsYSB0ZW5kYW5jZSBjZW50cmFsZSBldCBkZSBsYSBkaXNwZXJzaW9uIGRlcyB2YXJpYXRpb25zIGFubnVlbGxlcy4KCmBgYHtyfQojIENoYXJnZXIgbGUgcGFja2FnZSB6b28gcG91ciBsZXMgZm9uY3Rpb25zIGRlIG1veWVubmUvdmFyaWFuY2UgbW9iaWxlCnJlcXVpcmUoem9vKQoKIyBDYWxjdWwgZGVzIG1veWVubmVzIGV0IHZhcmlhbmNlcyBtb2JpbGVzIHN1ciA1IGFucwpkb25uZWVzX3BvcF9maW5sYW5kZTIgPC0gZG9ubmVlc19wb3BfZmlubGFuZGUgJT4lCiAgbXV0YXRlKAogICAgcm9sbF9tZWFuID0gcm9sbGFwcGx5KGNyb2lzc2FuY2VfcG9wLCBGVU4gPSBtZWFuLCB3aWR0aCA9IDUsIGZpbGwgPSBOQSwgYWxpZ24gPSAiY2VudGVyIiksCiAgICByb2xsX3ZhciAgPSByb2xsYXBwbHkoY3JvaXNzYW5jZV9wb3AsIEZVTiA9IHZhciwgIHdpZHRoID0gNSwgZmlsbCA9IE5BLCBhbGlnbiA9ICJjZW50ZXIiKQogICkKCiMgQWZmaWNoYWdlIGRlcyBwcmVtacOocmVzIGxpZ25lcwpoZWFkKGRvbm5lZXNfcG9wX2ZpbmxhbmRlMikKCmBgYAoKRGVzIG1veWVubmVzIGV0IHZhcmlhbmNlcyBtb2JpbGVzIHN1ciA1IGFucyBzb250IGNhbGN1bMOpZXMgcG91ciBsZSB0YXV4IGRlIGNyb2lzc2FuY2UgZGUgbGEgcG9wdWxhdGlvbiBlbiBGaW5sYW5kZSwgcGVybWV0dGFudCBk4oCZb2JzZXJ2ZXIgbGVzIHRlbmRhbmNlcyBldCBsYSB2b2xhdGlsaXTDqSDDoCBtb3llbiB0ZXJtZSwgZW4gbGlzc2FudCBsZXMgZmx1Y3R1YXRpb25zIGFubnVlbGxlcy4gTGVzIHByZW1pw6hyZXMgbGlnbmVzIGR1IGpldSBkZSBkb25uw6llcyBlbnJpY2hpIHNvbnQgYWZmaWNow6llcyBwb3VyIHbDqXJpZmllciBsZSBjYWxjdWwuCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKIyBHcmFwaGlxdWUgZGUgbGEgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uIGF2ZWMgbW95ZW5uZSBtb2JpbGUKZG9ubmVlc19wb3BfZmlubGFuZGUyICU+JQogIGdncGxvdChhZXMoeCA9IHllYXIsIHkgPSBjcm9pc3NhbmNlX3BvcCkpICsKICBnZW9tX2xpbmUoY29sb3IgPSAiYmxhY2siKSArICAgICAgICAgICAgICAgICAgICAgICAgIyBjb3VyYmUgZGUgY3JvaXNzYW5jZSByw6llbGxlCiAgZ2VvbV9saW5lKGFlcyh5ID0gcm9sbF9tZWFuKSwgY29sb3IgPSAic3RlZWxibHVlIiwgbHdkID0gMSkgKyAgIyBtb3llbm5lIG1vYmlsZQogIGxhYnMoCiAgICB4ID0gIkFubsOpZSIsCiAgICB5ID0gIlRhdXggZGUgY3JvaXNzYW5jZSAocG91cmNlbnRhZ2UpIiwKICAgIHRpdGxlID0gIlRhdXggZGUgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uIEZpbmxhbmRlIGF2ZWMgbW95ZW5uZSBtb2JpbGUiCiAgKSArCiAgdGhlbWVfYncoKQoKYGBgCgpMZSBncmFwaGlxdWUgcmVwcsOpc2VudGUgbGUgdGF1eCBkZSBjcm9pc3NhbmNlIGFubnVlbCBkZSBsYSBwb3B1bGF0aW9uIGVuIEZpbmxhbmRlLCBhdmVjIGxhIGNvdXJiZSBub2lyZSBtb250cmFudCBsZXMgdmFsZXVycyByw6llbGxlcyBldCBsYSBjb3VyYmUgYmxldWUgcmVwcsOpc2VudGFudCBsYSBtb3llbm5lIG1vYmlsZSBzdXIgNSBhbnMuIENlbGEgcGVybWV0IGRlIHZpc3VhbGlzZXIgcGx1cyBjbGFpcmVtZW50IGxlcyB0ZW5kYW5jZXMgw6AgbW95ZW4gdGVybWUgZW4gbGlzc2FudCBsZXMgZmx1Y3R1YXRpb25zIGFubnVlbGxlcy4KCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCgojIEdyYXBoaXF1ZSBkZSBsYSB2YXJpYW5jZSBtb2JpbGUgZGUgbGEgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uCmRvbm5lZXNfcG9wX2ZpbmxhbmRlMiAlPiUKICBnZ3Bsb3QoYWVzKHggPSB5ZWFyLCB5ID0gcm9sbF92YXIpKSArCiAgZ2VvbV9saW5lKGx3ZCA9IDEsIGNvbG9yID0gImRhcmtyZWQiKSArCiAgbGFicygKICAgIHggPSAiQW5uw6llIiwKICAgIHkgPSAiVmFyaWFuY2UgbW9iaWxlICg1IGFucykiLAogICAgdGl0bGUgPSAiVmFyaWFuY2UgbW9iaWxlIGR1IHRhdXggZGUgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uIEZpbmxhbmRlIgogICkgKwogIHRoZW1lX2J3KCkKCmBgYAoKTGUgZ3JhcGhpcXVlIG1vbnRyZSBsYSB2YXJpYW5jZSBtb2JpbGUgc3VyIDUgYW5zIGR1IHRhdXggZGUgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uIGVuIEZpbmxhbmRlLCBwZXJtZXR0YW50IGTigJlvYnNlcnZlciBjb21tZW50IGxhIHZvbGF0aWxpdMOpIGTDqW1vZ3JhcGhpcXVlIMOpdm9sdWUgYXUgZmlsIGR1IHRlbXBzIGV0IGTigJlpZGVudGlmaWVyIGxlcyBww6lyaW9kZXMgZGUgZmx1Y3R1YXRpb25zIHBsdXMgb3UgbW9pbnMgaW1wb3J0YW50ZXMuCgpgYGB7cn0KIyBDYWxjdWwgZGUgbGEgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uICJkZXRyZW5kw6llIiAoaG9ycyB0ZW5kYW5jZSkKdGVzdCA8LSBkb25uZWVzX3BvcF9maW5sYW5kZTIgJT4lCiAgbXV0YXRlKGRldHJlbmRlZF9wb3BfZ3Jvd3RoID0gY3JvaXNzYW5jZV9wb3AgLSByb2xsX21lYW4pCgojIEFmZmljaGFnZSBkZXMgcHJlbWnDqHJlcyBsaWduZXMKaGVhZCh0ZXN0KQpgYGAKCkxhIGNyb2lzc2FuY2UgZGUgbGEgcG9wdWxhdGlvbiBlc3QgaWNpIMKrIGTDqXRlbmRhbmPDqWUgwrsgZW4gc291c3RyYXlhbnQgbGEgbW95ZW5uZSBtb2JpbGUgc3VyIDUgYW5zIMOgIGxhIGNyb2lzc2FuY2UgcsOpZWxsZSwgY2UgcXVpIHBlcm1ldCBk4oCZaXNvbGVyIGxlcyBmbHVjdHVhdGlvbnMgYW5udWVsbGVzIHBhciByYXBwb3J0IMOgIGxhIHRlbmRhbmNlIMOgIG1veWVuIHRlcm1lLiBMZXMgcHJlbWnDqHJlcyBsaWduZXMgZHUgamV1IGRlIGRvbm7DqWVzIG1vZGlmacOpIHNvbnQgYWZmaWNow6llcyBwb3VyIHbDqXJpZmllciBsZSBjYWxjdWwuCgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKIyBHcmFwaGlxdWUgZGUgbGEgY3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uIGTDqXRlbmRhbmPDqWUgKGhvcnMgdGVuZGFuY2UpCnRlc3QgJT4lCiAgZ2dwbG90KGFlcyh4ID0geWVhciwgeSA9IGRldHJlbmRlZF9wb3BfZ3Jvd3RoKSkgKwogIGdlb21fbGluZShsd2QgPSAxLCBjb2xvciA9ICJkYXJrZ3JlZW4iKSArCiAgbGFicygKICAgIHggPSAiQW5uw6llIiwKICAgIHkgPSAiQ3JvaXNzYW5jZSBkw6l0ZW5kYW5jw6llIChwb3VyY2VudGFnZSkiLAogICAgdGl0bGUgPSAiQ3JvaXNzYW5jZSBkZSBsYSBwb3B1bGF0aW9uIEZpbmxhbmRlIChob3JzIHRlbmRhbmNlKSIKICApICsKICB0aGVtZV9idygpCmBgYAoKTGUgZ3JhcGhpcXVlIHByw6lzZW50ZSBsYSBjcm9pc3NhbmNlIGRlIGxhIHBvcHVsYXRpb24gZW4gRmlubGFuZGUgwqsgZMOpdGVuZGFuY8OpZSDCuywgY+KAmWVzdC3DoC1kaXJlIGxlcyB2YXJpYXRpb25zIGFubnVlbGxlcyBhcHLDqHMgYXZvaXIgcmV0aXLDqSBsYSB0ZW5kYW5jZSDDoCBtb3llbiB0ZXJtZS4gTGEgY291cmJlIHBlcm1ldCBkZSB2aXN1YWxpc2VyIGxlcyBmbHVjdHVhdGlvbnMgcG9uY3R1ZWxsZXMgYXV0b3VyIGRlIGxhIHRlbmRhbmNlIGTDqW1vZ3JhcGhpcXVlLgoKIyMgQikgUHLDqS1yw6lncmVzc2lvbiBldCByw6lncmVzc2lvbiBzdXIgbGEgRmlubGFuZGUgZW4gc2UgY29uY2VudHJhbnQgc3VyIGdkcCAoUElCKSBldCBkZWJ0Z2RwIChkZXR0ZSBwdWJsaXF1ZSBlbiAlIGR1IFBJQikKCmBgYHtyfQoKIyBTdHJhdMOpZ2llIMOpY29ub23DqXRyaXF1ZSAocsOpc3Vtw6kpCgoKIyBPYmplY3RpZiA6IG1lc3VyZXIgbOKAmWVmZmV0IGRlIGxhIGRldHRlIHB1YmxpcXVlIChkZWJ0Z2RwKQojIHN1ciBsYSBjcm9pc3NhbmNlIGR1IFBJQiAoZ2RwX2dyb3d0aCA9IFZhciBsb2coZ2RwKSkuCgojIFZhcmlhYmxlcyA6CiMgLSBEw6lwZW5kYW50ZSA6IGdkcF9ncm93dGguCiMgLSBFeHBsaWNhdGl2ZSA6IGRlYnRnZHAgKMOgIG1ldHRyZSBlbiBwb3VyY2VudGFnZSBzaSBuw6ljZXNzYWlyZSkuCiMgLSBDb250csO0bGVzIHBvc3NpYmxlcyA6IGluZmxhdGlvbiwgY2jDtG1hZ2UsIGNyw6lkaXQsIGTDqXBlbnNlcyBwdWJsaXF1ZXMsIGV0Yy4KCiMgw4l0YXBlIDEg4oCUIFN0YXRpb25uYXJpdMOpIDoKIyAtIFRlc3RlciBnZHBfZ3Jvd3RoIChub3JtYWxlbWVudCBJKDApKS4KIyAtIFRlc3RlciBkZWJ0Z2RwIChzb3V2ZW50IEkoMSkpIHZpYSBBREYgLyBLUFNTLgojIC0gU2kgZGVidGdkcCBub24gc3RhdGlvbm5haXJlIDoKIyAgICAgICAtPiB1dGlsaXNlciBWYXIgZGVidGdkcCBzaSBwYXMgZGUgY29pbnTDqWdyYXRpb24sCiMgICAgICAgLT4gc2lub24gdGVzdGVyIGNvaW50w6lncmF0aW9uIGF2ZWMgbG9nKGdkcCkgZXQgcGFzc2VyIMOgIHVuIEVDTS4KCiMgw4l0YXBlIDIg4oCUIE1vZMOobGVzIDoKIyAtIEJhc2VsaW5lIDogZ2RwX2dyb3d0aF90ID0gYWxwaGEgKyBiZXRhICogZGVidGdkcCB0LTEgKyBlcnJldXIuCiMgLSBBdmVjIGNvbnRyw7RsZXMgOiBham91dGVyIGdkcGdyb3d0aCB0LTEgKyB2YXJpYWJsZXMgWHQuCgojIMOJdGFwZSAzIOKAlCBFc3RpbWF0aW9uIDoKIyAtIFV0aWxpc2VyIGVycmV1cnMgc3RhbmRhcmRzIHJvYnVzdGVzIChIQykgb3UgTmV3ZXnigJNXZXN0CiMgICBwb3VyIGNvcnJpZ2VyIGF1dG9jb3Jyw6lsYXRpb24gZXQgaMOpdMOpcm9zY8OpZGFzdGljaXTDqS4KCmBgYAoKYGBge3J9CgojIFByw6lwYXJhdGlvbiBkZXMgc8OpcmllcyBwb3VyIGxhIEZpbmxhbmRlCgoKZG9ubmVlc19maW5sYW5kZSA8LSBkb25uZWVzX2RmICU+JQogIHNlbGVjdCh5ZWFyLCBnZHAsIGRlYnRnZHApICU+JQogIGFycmFuZ2UoeWVhcikgJT4lCiAgbXV0YXRlKAogICAgIyB0YXV4IGRlIGNyb2lzc2FuY2UgZHUgUElCIGVuIHBvdXJjZW50YWdlCiAgICBnZHBfZ3Jvd3RoID0gKGxvZyhnZHApIC0gbGFnKGxvZyhnZHApKSkgKiAxMDAsCiAgICAjIGRpZmbDqXJlbmNlcyBwcmVtacOocmVzCiAgICBkZ2RwID0gZ2RwIC0gbGFnKGdkcCksCiAgICBkZGdkcCA9IGRnZHAgLSBsYWcoZGdkcCksCiAgICAjIGRpZmbDqXJlbmNlcyBwcmVtacOocmVzIGR1IHRhdXggZGUgY3JvaXNzYW5jZQogICAgZGdkcF9ncm93dGggPSBnZHBfZ3Jvd3RoIC0gbGFnKGdkcF9ncm93dGgpCiAgKSAlPiUKICBmaWx0ZXIoeWVhciA+PSAxOTYwKSAlPiUKICBuYS5vbWl0KCkKCiMgVsOpcmlmaWNhdGlvbgpoZWFkKGRvbm5lZXNfZmlubGFuZGUpCgoKIyBHcmFwaGlxdWUgZGUgbGEgc8OpcmllIGR1IFBJQgoKCmdncGxvdChkb25uZWVzX2ZpbmxhbmRlLCBhZXMoeCA9IHllYXIsIHkgPSBnZHApKSArCiAgZ2VvbV9saW5lKGx3ZCA9IDEsIGNvbG9yID0gInN0ZWVsYmx1ZSIpICsKICBsYWJzKAogICAgeCA9ICJBbm7DqWUiLAogICAgeSA9ICJQSUIgKGVuIG1pbGxpb25zKSIsCiAgICB0aXRsZSA9ICLDiXZvbHV0aW9uIGR1IFBJQiAgRmlubGFuZGUiCiAgKSArCiAgdGhlbWVfYncoKQoKCiMgQXV0b2NvcnLDqWxvZ3JhbW1lIHBvdXIgdsOpcmlmaWVyIGTDqXBlbmRhbmNlIHRlbXBvcmVsbGUKCgphY2YoZG9ubmVlc19maW5sYW5kZSRnZHAsIG1haW4gPSAiQUNGIGR1IFBJQiBGaW5sYW5kZSIpCgpgYGAKCkxlcyBzw6lyaWVzIHRlbXBvcmVsbGVzIHBvdXIgbGEgRmlubGFuZGUgc29udCBwcsOpcGFyw6llcyA6IGxlIHRhdXggZGUgY3JvaXNzYW5jZSBkdSBQSUIgZW4gcG91cmNlbnRhZ2UgZXN0IGNhbGN1bMOpLCBhaW5zaSBxdWUgbGVzIHByZW1pw6hyZXMgZXQgc2Vjb25kZXMgZGlmZsOpcmVuY2VzIGR1IFBJQiBldCBkZSBzYSBjcm9pc3NhbmNlIHBvdXIgZMOpdGVjdGVyIGxlcyB2YXJpYXRpb25zIGV0IGZhY2lsaXRlciBs4oCZYW5hbHlzZSBkZSBzdGF0aW9ubmFyaXTDqS4gTGEgc8OpcmllIGVzdCBlbnN1aXRlIGZpbHRyw6llIHBvdXIgbGVzIGFubsOpZXMgw6AgcGFydGlyIGRlIDE5NjAgZXQgbGVzIHZhbGV1cnMgbWFucXVhbnRlcyBzb250IHN1cHByaW3DqWVzLiBMYSBzw6lyaWUgZHUgUElCIGVzdCB2aXN1YWxpc8OpZSBhdmVjIHVuIGdyYXBoaXF1ZSBlbiBsaWduZSwgZXQgbOKAmWF1dG9jb3Jyw6lsb2dyYW1tZSAoQUNGKSBlc3QgdHJhY8OpIHBvdXIgZXhhbWluZXIgbGEgZMOpcGVuZGFuY2UgdGVtcG9yZWxsZSBldCBpZGVudGlmaWVyIGTigJnDqXZlbnR1ZWxsZXMgYXV0b2NvcnLDqWxhdGlvbnMuCgpgYGB7cn0KIyBSQVBQRUwKI0NoYXF1ZSBiYXJyZSBkdSBncmFwaGlxdWUgY29ycmVzcG9uZCDDoCB1biBsYWcgKGTDqWNhbGFnZSBkYW5zIGxlIHRlbXBzKS4KCiNMYWcgMSAgY29ycsOpbGF0aW9uIGVudHJlIGxhIHPDqXJpZSBldCBlbGxlLW3Dqm1lIGTDqWNhbMOpZSBk4oCZMSBww6lyaW9kZS4KCiNMYWcgMiAgY29ycsOpbGF0aW9uIGF2ZWMgZWxsZS1tw6ptZSBkw6ljYWzDqWUgZGUgMiBww6lyaW9kZXMsIGV0Yy4KCiNWYWxldXJzIMOpbGV2w6llcyBwcm9jaGVzIGRlIDEgb3UgLTEg4oaSIGZvcnRlIGNvcnLDqWxhdGlvbiBhdmVjIGxlcyB2YWxldXJzIHBhc3PDqWVzLgoKI0TDqWNyb2lzc2FuY2UgbGVudGUgZGVzIGJhcnJlcyAgc2lnbmUgcXVlIGxhIHPDqXJpZSBu4oCZZXN0IHBhcyBzdGF0aW9ubmFpcmUgKGxhIG1veWVubmUgb3UgbGEgdmFyaWFuY2UgY2hhbmdlbnQgZGFucyBsZSB0ZW1wcykuCgojRMOpY3JvaXNzYW5jZSByYXBpZGUgdmVycyB6w6lybyAgc2lnbmUgcXVlIGxhIHPDqXJpZSBlc3Qgc3RhdGlvbm5haXJlLgoKI0zigJlBQ0YgZHUgUElCIEZpbmxhbmRlIG1vbnRyZSBkZXMgYXV0b2NvcnLDqWxhdGlvbnMgw6lsZXbDqWVzIHF1aSBkw6ljcm9pc3NlbnQgbGVudGVtZW50IOKGkiBsYSBzw6lyaWUgbuKAmWVzdCBwYXMgc3RhdGlvbm5haXJlIChtb3llbm5lIGV0IHZhcmlhbmNlIGNoYW5nZW50IGRhbnMgbGUgdGVtcHMpLgoKI0ZvcnRlIGF1dG9jb3Jyw6lsYXRpb24gc3VyIHBsdXNpZXVycyBsYWdzICBzw6lyaWUgaW50w6lncsOpZSBk4oCZb3JkcmUgMSAoSSgxKSksIHR5cGlxdWUgcG91ciBsZSBQSUIgZW4gbml2ZWF1LgoKI0ltcGxpY2F0aW9ucyA6CgojT24gbmUgcGV1dCBwYXMgcsOpZ3Jlc3NzZXIgZGlyZWN0ZW1lbnQgbGUgUElCIGVuIG5pdmVhdSBzdXIgbGEgZGV0dGUgKHJpc3F1ZSBkZSByw6lncmVzc2lvbiBzcHVyaW91cykuCgojSWwgZmF1dCB1dGlsaXNlciBwbHV0w7R0IDoKCiNWYXIgbG9nKFBJQikgKG91IGdkcGdyb3d0aCkgY29tbWUgdmFyaWFibGUgZMOpcGVuZGFudGUgIG5vcm1hbGVtZW50IHN0YXRpb25uYWlyZSAoSSgwKSkKCiNWYXIgKGRlYnQvUElCKSBvdSB0ZXN0ZXIgbGEgY29pbnTDqWdyYXRpb24gZW50cmUgUElCIGV0IGRldHRlLgoKYGBgCgpgYGB7cn0KIyBQYWNrYWdlcyBuw6ljZXNzYWlyZXMKCmxpYnJhcnkodXJjYSkKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZm9yZWNhc3QpCgojIAojICBUZXN0cyBkZSBzdGF0aW9ubmFyaXTDqQojIAoKIyBBREYgKERpY2tleSBGdWxsZXIgYXVnbWVudMOpKSAKYWRmX2dkcCA8LSB1ci5kZihkb25uZWVzX2ZpbmxhbmRlJGdkcF9ncm93dGgsIHR5cGUgPSAibm9uZSIsIHNlbGVjdGxhZ3MgPSAiQUlDIikKc3VtbWFyeShhZGZfZ2RwKQoKYWRmX2RlYnQgPC0gdXIuZGYoZG9ubmVlc19maW5sYW5kZSRkZWJ0Z2RwLCB0eXBlID0gInRyZW5kIiwgc2VsZWN0bGFncyA9ICJBSUMiKQpzdW1tYXJ5KGFkZl9kZWJ0KQoKI0tQU1MgKHN0YXRpb25uYXJpdMOpIGF1dG91ciBkZSBsYSBtb3llbm5lIG91IHRyZW5kKSAKa3Bzcy50ZXN0KGRvbm5lZXNfZmlubGFuZGUkZ2RwX2dyb3d0aCkgICMgSDAgPSBzdGF0aW9ubmFpcmUKa3Bzcy50ZXN0KGRvbm5lZXNfZmlubGFuZGUkZGVidGdkcCkgICAgICMgSDAgPSBzdGF0aW9ubmFpcmUKCiMgIFNpIGRlYnRnZHAgbm9uLXN0YXRpb25uYWlyZSBkaWZmw6lyZW5jZXMgcHJlbWnDqHJlcwoKZG9ubmVlc19maW5sYW5kZSA8LSBkb25uZWVzX2ZpbmxhbmRlICU+JQogIG11dGF0ZShkX2RlYnRnZHAgPSBkZWJ0Z2RwIC0gbGFnKGRlYnRnZHApKSAlPiUKICBuYS5vbWl0KCkKCiMgVsOpcmlmaWNhdGlvbiBBQ0YgcG91ciBnZHBfZ3Jvd3RoIGV0IGRfZGVidGdkcAphY2YoZG9ubmVlc19maW5sYW5kZSRnZHBfZ3Jvd3RoLCBtYWluID0gIkFDRiBkZSBsYSBjcm9pc3NhbmNlIGR1IFBJQiAoZ2RwZ3Jvd3RoKSIpCmFjZihkb25uZWVzX2ZpbmxhbmRlJGRfZGVidGdkcCwgbWFpbiA9ICJBQ0YgZGVzIGRpZmbDqXJlbmNlcyBkZSBsYSBkZXR0ZS9QSUIgKGRkZWJ0Z2RwKSIpCgoKIyAgR3JhcGhpcXVlcyByYXBpZGVzCgojIENyb2lzc2FuY2UgZHUgUElCCmdncGxvdChkb25uZWVzX2ZpbmxhbmRlLCBhZXMoeCA9IHllYXIsIHkgPSBnZHBfZ3Jvd3RoKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJzdGVlbGJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJDcm9pc3NhbmNlIGR1IFBJQiBGaW5sYW5kZSIsIHggPSAiQW5uw6llIiwgeSA9ICJnZHBfZ3Jvd3RoIChwb3VyY2VudGFnZSkiKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIERpZmbDqXJlbmNlcyBkZSBsYSBkZXR0ZSAvIFBJQgpnZ3Bsb3QoZG9ubmVlc19maW5sYW5kZSwgYWVzKHggPSB5ZWFyLCB5ID0gZF9kZWJ0Z2RwKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJkYXJrcmVkIikgKwogIGxhYnModGl0bGUgPSAiRGlmZsOpcmVuY2VzIGRlIGxhIGRldHRlL1BJQiBGaW5sYW5kZSIsIHggPSAiQW5uw6llIiwgeSA9ICIgVmFyIGRlYnRnZHAgKHBvdXJjZW50YWdlKSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYAoKRGVzIHRlc3RzIGRlIHN0YXRpb25uYXJpdMOpIHNvbnQgcsOpYWxpc8OpcyBwb3VyIGxhIEZpbmxhbmRlIDogbGUgdGVzdCBBREYgaW5kaXF1ZSBzaSBsZXMgc8OpcmllcyBzb250IHN0YXRpb25uYWlyZXMgb3Ugbm9uLCBldCBsZSB0ZXN0IEtQU1MgY29tcGzDqHRlIGzigJlhbmFseXNlIGVuIHRlc3RhbnQgbOKAmWh5cG90aMOoc2UgbnVsbGUgZGUgc3RhdGlvbm5hcml0w6kuIExhIGNyb2lzc2FuY2UgZHUgUElCIGFwcGFyYcOudCBnw6luw6lyYWxlbWVudCBzdGF0aW9ubmFpcmUsIHRhbmRpcyBxdWUgbGUgcmF0aW8gZGV0dGUvUElCIGVzdCB0cmFuc2Zvcm3DqSBlbiBkaWZmw6lyZW5jZXMgcHJlbWnDqHJlcyBzaSBuw6ljZXNzYWlyZSBwb3VyIG9idGVuaXIgdW5lIHPDqXJpZSBzdGF0aW9ubmFpcmUuIExlcyBhdXRvY29ycsOpbG9ncmFtbWVzIChBQ0YpIHNvbnQgdHJhY8OpcyBwb3VyIHbDqXJpZmllciBsYSBkw6lwZW5kYW5jZSB0ZW1wb3JlbGxlIGRlIGNlcyBzw6lyaWVzIHRyYW5zZm9ybcOpZXMuIEVuZmluLCBkZXMgZ3JhcGhpcXVlcyBpbGx1c3RyZW50IGzigJnDqXZvbHV0aW9uIGRlIGxhIGNyb2lzc2FuY2UgZHUgUElCIGV0IGRlcyB2YXJpYXRpb25zIGFubnVlbGxlcyBkdSByYXRpbyBkZXR0ZS9QSUIsIHBlcm1ldHRhbnQgZGUgdmlzdWFsaXNlciBsZXMgdGVuZGFuY2VzIGV0IGZsdWN0dWF0aW9ucy4gTGUgZ3JhcGhpcXVlIG1vbnRyZSBkZXMgdmFyaWF0aW9ucyBkdSByYXRpbyBkZXR0ZS9QSUIgZ8OpbsOpcmFsZW1lbnQgZmFpYmxlcywgbWFpcyBhdmVjIGRlcyBwaWNzIG1hcnF1w6lzIGVuIHDDqXJpb2RlIGRlIGNyaXNlLCBub3RhbW1lbnQgYXUgZMOpYnV0IGRlcyBhbm7DqWVzIDE5OTAgZXQgYXByw6hzIDIwMDguCkNlbGEgaW5kaXF1ZSBxdWUgbGEgZGV0dGUgYXVnbWVudGUgc3VydG91dCBsb3JzIGRlcyBjaG9jcyDDqWNvbm9taXF1ZXMsIHB1aXMgc2Ugc3RhYmlsaXNlIG91IHJlY3VsZSBlbnN1aXRlLgoKYGBge3J9CmxpYnJhcnkodXJjYSkKCiMgVGVzdCBBREYgc3VyIGdkcF9ncm93dGggKGNyb2lzc2FuY2UgZHUgUElCKQphZGZfZ2RwIDwtIHVyLmRmKGRvbm5lZXNfZmlubGFuZGUkZ2RwX2dyb3d0aCwgdHlwZSA9ICJub25lIiwgc2VsZWN0bGFncyA9ICJBSUMiKQpzdW1tYXJ5KGFkZl9nZHApCgojIFRlc3QgQURGIHN1ciBkZWJ0Z2RwIChkZXR0ZSAvIFBJQikKYWRmX2RlYnQgPC0gdXIuZGYoZG9ubmVlc19maW5sYW5kZSRkZWJ0Z2RwLCB0eXBlID0gInRyZW5kIiwgc2VsZWN0bGFncyA9ICJBSUMiKQpzdW1tYXJ5KGFkZl9kZWJ0KQpgYGAKCkxhIGNyb2lzc2FuY2UgZHUgUElCIChgZ2RwX2dyb3d0aGApIG7igJllc3QgcGFzIHN0cmljdGVtZW50IHN0YXRpb25uYWlyZSA6IGxlIHRlc3QgQURGIG5lIHJlamV0dGUgcGFzIGzigJloeXBvdGjDqHNlIGRlIHJhY2luZSB1bml0YWlyZSwgY2UgcXVpIHNpZ25pZmllIHF1ZSBsYSBzw6lyaWUgcGV1dCBjb250ZW5pciBkZXMgdmFyaWF0aW9ucyBwZXJzaXN0YW50ZXMgZGFucyBsZSB0ZW1wcy4gRW4gcmV2YW5jaGUsIGxlIHJhdGlvIGRldHRlL1BJQiAoYGRlYnRnZHBgKSBlc3Qgc3RhdGlvbm5haXJlIGF1dG91ciBk4oCZdW5lIHRlbmRhbmNlIDogbGUgdGVzdCBBREYgYXZlYyB0ZW5kYW5jZSByZWpldHRlIGxhIHJhY2luZSB1bml0YWlyZSwgaW5kaXF1YW50IHF1ZSBsYSBzw6lyaWUgZXN0IHN0YWJsZSB1bmUgZm9pcyBsYSB0ZW5kYW5jZSBwcmlzZSBlbiBjb21wdGUuIENvbmNyw6h0ZW1lbnQsIGxhIGNyb2lzc2FuY2UgZHUgUElCIHBldXQgw6p0cmUgdXRpbGlzw6llIHRlbGxlIHF1ZWxsZSBwb3VyIGRlcyBtb2TDqGxlcyBBUklNQSwgdGFuZGlzIHF1ZSBsYSBkZXR0ZS9QSUIgZGV2cmEgw6p0cmUgZGlmZsOpcmVuY2nDqWUgb3UgbW9kw6lsaXPDqWUgYXZlYyBsYSB0ZW5kYW5jZSBkYW5zIHVuIEVDTSBvdSB1biBtb2TDqGxlIGRlIGNvaW50w6lncmF0aW9uLgoKYGBge3J9CiMgTGUgcGFja2FnZSAndXJjYScgcGVybWV0IGRlIGZhaXJlIGxlIHRlc3QgQURGIHBvdXIgdsOpcmlmaWVyIHNpIHVuZSBzw6lyaWUgZXN0IHN0YXRpb25uYWlyZS4KIyBJY2ksIGxlIHRlc3QgQURGIHN1ciAnZ2RwX2dyb3d0aCcgKHNhbnMgY29uc3RhbnRlIG5pIHRlbmRhbmNlKSBkb25uZSB0YXUxID0gLTEuNjgyLgojIENvbW1lIGMnZXN0IHBsdXMgZ3JhbmQgcXVlIGxhIHZhbGV1ciBjcml0aXF1ZSDDoCA1JSAoLTEuOTUpLCBvbiBuZSByZWpldHRlIHBhcyBsJ2h5cG90aMOoc2UgZGUgcmFjaW5lIHVuaXRhaXJlLgojIENvbmNsdXNpb24gOiBsYSBzw6lyaWUgcG91cnJhaXQgbmUgcGFzIMOqdHJlIHN0cmljdGVtZW50IHN0YXRpb25uYWlyZSwgbWFpcyBsYSBjcm9pc3NhbmNlIGR1IFBJQiBlc3QgZ8OpbsOpcmFsZW1lbnQgY29uc2lkw6lyw6llIGNvbW1lIEkoMCksCiMgY+KAmWVzdC3DoC1kaXJlIHN0YXRpb25uYWlyZSBhdXRvdXIgZOKAmXVuZSBtb3llbm5lIHN0YWJsZSwgYXZlYyB2YXJpYW5jZSBjb25zdGFudGUsIGV0IHV0aWxpc2FibGUgZGlyZWN0ZW1lbnQgZW4gcsOpZ3Jlc3Npb24uCgpgYGAKCmBgYHtyfQojIExlIHBhY2thZ2UgJ3VyY2EnIHBlcm1ldCBkZSBmYWlyZSBsZSB0ZXN0IEFERiBwb3VyIHbDqXJpZmllciBzaSB1bmUgc8OpcmllIGVzdCBzdGF0aW9ubmFpcmUuCiMgSWNpLCBsZSB0ZXN0IEFERiBzdXIgbGEgc8OpcmllIChhdmVjIGNvbnN0YW50ZSBldCB0ZW5kYW5jZSwgdHlwZSA9ICJ0cmVuZCIpIGRvbm5lIHRhdTMgPSAtMy41MDYuCiMgT24gY29tcGFyZSDDoCBsYSB2YWxldXIgY3JpdGlxdWUgw6AgNSUgKC0zLjQ1KSA6IHRhdTMgPCAtMy40NSwgZG9uYyBvbiBwZXV0ICoqcmVqZXRlciBsJ2h5cG90aMOoc2UgbnVsbGUqKiBkZSByYWNpbmUgdW5pdGFpcmUuCiMgQ29uY2x1c2lvbiA6IGxhIHPDqXJpZSBlc3Qgc3RhdGlvbm5haXJlIGF1dG91ciBk4oCZdW5lIHRlbmRhbmNlLiAKIyBQb3VyIHJhcHBlbCwgdW5lIHPDqXJpZSBzdGF0aW9ubmFpcmUgKEkoMCkpIGEgdW5lIG1veWVubmUgZXQgdW5lIHZhcmlhbmNlIGNvbnN0YW50ZXMgZGFucyBsZSB0ZW1wcywgCiMgZXQgcGV1dCDDqnRyZSB1dGlsaXPDqWUgZGlyZWN0ZW1lbnQgZW4gcsOpZ3Jlc3Npb24gc2FucyBjcsOpZXIgZGUgcsOpZ3Jlc3Npb24gc3B1cmlvdXMuCgpgYGAKCiMjIE1vZMOobGUgw6ljb25vbcOodHJpcXVlCgpgYGB7cn0KCiMgTW9kw6hsZSBiYXNlbGluZSBjb3JyaWfDqSAoRmlubGFuZGUpCgoKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkobG10ZXN0KQpsaWJyYXJ5KHNhbmR3aWNoKQoKIyAxKSBQcsOpcGFyZXIgbGUgZGF0YXNldCDDoCBwYXJ0aXIgZGUgZG9ubmVlc2RmIChkw6lqw6AgRmlubGFuZGUpCgpkb25uZWVzX2ZpbmxhbmRlIDwtIGRvbm5lZXNfZGYgJT4lCm11dGF0ZSgKZF9kZWJ0Z2RwICAgID0gZGVidGdkcCAtIGxhZyhkZWJ0Z2RwKSwgICAgICAgICAgICAgICMgdmFyaWF0aW9uIGRldHRlL1BJQgpsYWdfZF9kZWJ0Z2RwID0gbGFnKGRfZGVidGdkcCwgMSkgICAgICAgICAgICAgICAgICAjIGxhZyBkZSB2YXIgZGV0dGUKKSAlPiUKbmEub21pdCgpICAjIHN1cHByaW1lIE5BIGludHJvZHVpdHMgcGFyIGxhZwoKIyAyKSBFc3RpbWF0aW9uIGR1IG1vZMOobGUgYmFzZWxpbmUKCm1vZGVsZV9iYXNlbGluZSA8LSBsbShnZHBfZ3Jvd3RoIH4gbGFnX2RfZGVidGdkcCwgZGF0YSA9IGRvbm5lZXNfZmlubGFuZGUpCgojIDMpIFLDqXN1bcOpIGNsYXNzaXF1ZQoKc3VtbWFyeShtb2RlbGVfYmFzZWxpbmUpCgojIDQpIFLDqXN1bcOpIGF2ZWMgZXJyZXVycyByb2J1c3RlcyBkZSB0eXBlIEhDCgpjb2VmdGVzdChtb2RlbGVfYmFzZWxpbmUsIHZjb3YgPSB2Y292SEMobW9kZWxlX2Jhc2VsaW5lLCB0eXBlID0gIkhDMSIpKQoKYGBgCgpVbiBtb2TDqGxlIGRlIGJhc2UgZXN0IGVzdGltw6kgcG91ciBtZXN1cmVyIGzigJllZmZldCBkZSBsYSB2YXJpYXRpb24gbGFndcOpZSBkdSByYXRpbyBkZXR0ZS9QSUIgc3VyIGxhIGNyb2lzc2FuY2UgZHUgUElCIGVuIEZpbmxhbmRlLiBMYSB2YXJpYWJsZSBleHBsaWNhdGl2ZSBlc3QgbGEgdmFyaWF0aW9uIGRlIGxhIGRldHRlL1BJQiBkZSBs4oCZYW5uw6llIHByw6ljw6lkZW50ZS4gTGUgcsOpc3Vtw6kgY2xhc3NpcXVlIGR1IG1vZMOobGUgZm91cm5pdCBsZXMgY29lZmZpY2llbnRzIGV0IGxldXIgc2lnbmlmaWNhdGl2aXTDqSBzdGFuZGFyZCwgdGFuZGlzIHF1ZSBs4oCZZXN0aW1hdGlvbiBhdmVjIGVycmV1cnMgcm9idXN0ZXMgZGUgdHlwZSBIQyBhanVzdGUgbGVzIMOpY2FydHMtdHlwZXMgcG91ciBjb3JyaWdlciBk4oCZw6l2ZW50dWVsbGVzIGjDqXTDqXJvc2PDqWRhc3RpY2l0w6lzLCBvZmZyYW50IGRlcyB0ZXN0cyBkZSBzaWduaWZpY2F0aXZpdMOpIHBsdXMgZmlhYmxlcy4KCkxlIG1vZMOobGUgbW9udHJlIHF1ZSBsYSB2YXJpYXRpb24gbGFndcOpZSBkZSBsYSBkZXR0ZS9QSUIgYSB1biBlZmZldCBuw6lnYXRpZiBzdXIgbGEgY3JvaXNzYW5jZSBkdSBQSUIgOiBsZSBjb2VmZmljaWVudCBlc3QgZXN0aW3DqSDDoCAtMCwzMTYuIFNlbG9uIGxlIHLDqXN1bcOpIGNsYXNzaXF1ZSwgY2UgY29lZmZpY2llbnQgbuKAmWVzdCBwYXMgc2lnbmlmaWNhdGlmIGF1IHNldWlsIGRlIDUgJSAocCBlbnZpcm9uIDAsMTA1KSwgbWFpcyBlbiB1dGlsaXNhbnQgbGVzIGVycmV1cnMgcm9idXN0ZXMgZGUgdHlwZSBIQywgaWwgZGV2aWVudCBzaWduaWZpY2F0aWYgKHAgZW52aXJvbiAwLDAxOSksIGNlIHF1aSBzdWdnw6hyZSBxdeKAmXVuZSBhdWdtZW50YXRpb24gZGUgbGEgZGV0dGUvUElCIGzigJlhbm7DqWUgcHLDqWPDqWRlbnRlIHRlbmQgw6AgcsOpZHVpcmUgbMOpZ8OocmVtZW50IGxhIGNyb2lzc2FuY2UgZHUgUElCLiBM4oCZYWp1c3RlbWVudCBnbG9iYWwgZHUgbW9kw6hsZSBlc3QgZmFpYmxlIChSwrIgZW52aXJvbiAwLDA0NyksIGluZGlxdWFudCBxdWUgbGEgdmFyaWF0aW9uIGRlIGxhIGRldHRlIHNldWxlIGV4cGxpcXVlIHVuZSBwZXRpdGUgcGFydCBkZSBsYSB2YXJpYW5jZSBkZSBsYSBjcm9pc3NhbmNlLiBM4oCZaW50ZXJjZXB0IGVzdCBwb3NpdGlmIGV0IGZvcnRlbWVudCBzaWduaWZpY2F0aWYsIHJlZmzDqXRhbnQgbGEgY3JvaXNzYW5jZSBtb3llbm5lIGR1IFBJQiBsb3JzcXVlIGxhIHZhcmlhdGlvbiBkZSBsYSBkZXR0ZSBlc3QgbnVsbGUuCgpgYGB7cn0KIyBNb2TDqGxlIGF2ZWMgY29udHLDtGxlcyA6IGFqb3V0IGR1IGxhZyBkZSBnZHBncm93dGgKZG9ubmVlc19maW5sYW5kZSA8LSBkb25uZWVzX2ZpbmxhbmRlICU+JQogIG11dGF0ZShsYWdfZ2RwX2dyb3d0aCA9IGxhZyhnZHBfZ3Jvd3RoLCAxKSkgJT4lCiAgbmEub21pdCgpCgptb2RlbGVfY29udHJvbGVzIDwtIGxtKGdkcF9ncm93dGggfiBsYWcoZF9kZWJ0Z2RwLCAxKSArIGxhZ19nZHBfZ3Jvd3RoLCBkYXRhID0gZG9ubmVlc19maW5sYW5kZSkKc3VtbWFyeShtb2RlbGVfY29udHJvbGVzKQpjb2VmdGVzdChtb2RlbGVfY29udHJvbGVzLCB2Y292ID0gdmNvdkhDKG1vZGVsZV9jb250cm9sZXMsIHR5cGUgPSAiSEMxIikpCgoKCmBgYAoKVW4gbW9kw6hsZSBlbnJpY2hpIGluY2x1dCBkw6lzb3JtYWlzIGxhIGNyb2lzc2FuY2UgZHUgUElCIGRlIGzigJlhbm7DqWUgcHLDqWPDqWRlbnRlIGNvbW1lIHZhcmlhYmxlIGRlIGNvbnRyw7RsZSwgY2FwdHVyYW50IGzigJllZmZldCBwZXJzaXN0YW50IGRlIGxhIGNyb2lzc2FuY2UgcGFzc8OpZSAoYXV0b3JlZ3Jlc3Npb24pLiBMZXMgcsOpc3VsdGF0cyBtb250cmVudCBxdWUgbGEgY3JvaXNzYW5jZSBwYXNzw6llIGEgdW4gZWZmZXQgcG9zaXRpZiBldCB0csOocyBmb3J0IHN1ciBsYSBjcm9pc3NhbmNlIGFjdHVlbGxlIChjb2VmZmljaWVudCBlbnZpcm9uIDAsOTMpLiBMYSB2YXJpYXRpb24gbGFndcOpZSBkZSBsYSBkZXR0ZS9QSUIgcmVzdGUgc2lnbmlmaWNhdGl2ZSBhcHLDqHMgY29ycmVjdGlvbiBkZXMgZXJyZXVycyByb2J1c3RlcyA6IHVuZSBoYXVzc2UgZOKAmXVuIHBvaW50IGRlIHBvdXJjZW50YWdlIGRlIGxhIGRldHRlIGzigJlhbm7DqWUgcHLDqWPDqWRlbnRlIGVzdCBhc3NvY2nDqWUgw6AgdW5lIGzDqWfDqHJlIGF1Z21lbnRhdGlvbiBkZSBsYSBjcm9pc3NhbmNlIGR1IFBJQiAoZW52aXJvbiAwLDM2IHBvaW50KS4gTGUgbW9kw6hsZSBlc3QgYWluc2kgcGx1cyBjb21wbGV0LCBpbnTDqWdyYW50IGzigJlhdXRvY29ycsOpbGF0aW9uIG5hdHVyZWxsZSBkdSBQSUIgZXQgZm91cm5pc3NhbnQgZGVzIGVzdGltYXRpb25zIHBsdXMgZmlhYmxlcyBkZSBs4oCZZWZmZXQgZGUgbGEgZGV0dGUuCgojIyBDKSBBbmFseXNlIGRlcyByw6lzaWR1cwoKYGBge3J9CmxpYnJhcnkoZHBseXIpICAjIG7DqWNlc3NhaXJlIHBvdXIgJT4lCmxpYnJhcnkoZ2dwbG90MikKCiMgQ3LDqWVyIGxlIGRhdGFmcmFtZSB1dGlsaXPDqSBwYXIgbGUgbW9kw6hsZSAoc3VwcHJpbWUgbGVzIE5BIGludHJvZHVpdHMgcGFyIGxlcyBsYWdzKQpkZl9tb2RlbCA8LSBkb25uZWVzX2ZpbmxhbmRlICU+JQogIG11dGF0ZSgKICAgIGxhZ19kX2RlYnRnZHAgPSBsYWcoZF9kZWJ0Z2RwLCAxKSwKICAgIGxhZ19nZHBfZ3Jvd3RoID0gbGFnKGdkcF9ncm93dGgsIDEpCiAgKSAlPiUKICBuYS5vbWl0KCkKCiMgRXh0cmFpcmUgdmFsZXVycyBhanVzdMOpZXMgZXQgcsOpc2lkdXMKZml0dGVkX3ZhbCA8LSBtb2RlbGVfY29udHJvbGVzJGZpdHRlZC52YWx1ZXMKcmVzaWR1YWxzIDwtIG1vZGVsZV9jb250cm9sZXMkcmVzaWR1YWxzCgojIEFqb3V0ZXIgYXUgZGF0YWZyYW1lCmRvbm5lZXNfZmlubGFuZGVfcmVzaWR1cyA8LSBkZl9tb2RlbCAlPiUKICBtdXRhdGUoZml0dGVkX3ZhbCA9IGZpdHRlZF92YWwsCiAgICAgICAgIHJlc2lkdWFscyA9IHJlc2lkdWFscykKCiMgR3JhcGhpcXVlCmdncGxvdChkb25uZWVzX2ZpbmxhbmRlX3Jlc2lkdXMsIGFlcyh4ID0geWVhciwgeSA9IGdkcF9ncm93dGgpKSArCiAgZ2VvbV9saW5lKGx3ZCA9IDEsIGNvbG9yID0gImJsYWNrIikgKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBzw6lyaWUgcsOpZWxsZQogIGdlb21fbGluZShhZXMoeSA9IGZpdHRlZF92YWwpLCBjb2xvciA9ICJyZWQiLCBsdHkgPSAyLCBsd2QgPSAxKSArICMgc8OpcmllIGFqdXN0w6llCiAgbGFicygKICAgIHggPSAiQW5uw6llIiwKICAgIHkgPSAiQ3JvaXNzYW5jZSBkdSBQSUIgKCUpIiwKICAgIHRpdGxlID0gIkNyb2lzc2FuY2UgZHUgUElCIEZpbmxhbmRlIDogdmFsZXVycyByw6llbGxlcyB2cyBhanVzdMOpZXMiCiAgKSArCiAgdGhlbWVfYncoKQoKYGBgCgpMZSBncmFwaGlxdWUgY29tcGFyZSBsYSBjcm9pc3NhbmNlIHLDqWVsbGUgZHUgUElCIGVuIEZpbmxhbmRlIGF2ZWMgbGVzIHZhbGV1cnMgYWp1c3TDqWVzIHBhciBsZSBtb2TDqGxlIGluY2x1YW50IGxhIGRldHRlIGxhZ3XDqWUgZXQgbGEgY3JvaXNzYW5jZSBwYXNzw6llLiBMYSBjb3VyYmUgbm9pcmUgbW9udHJlIGxlcyBvYnNlcnZhdGlvbnMgcsOpZWxsZXMsIHRhbmRpcyBxdWUgbGEgY291cmJlIHJvdWdlIGVuIHBvaW50aWxsw6lzIHJlcHLDqXNlbnRlIGxlcyBwcsOpZGljdGlvbnMgZHUgbW9kw6hsZSwgcGVybWV0dGFudCBkZSB2aXN1YWxpc2VyIGxhIHF1YWxpdMOpIGRlIGzigJlhanVzdGVtZW50IGV0IGxlcyDDqWNhcnRzIGVudHJlIGxlIG1vZMOobGUgZXQgbGVzIGRvbm7DqWVzIG9ic2VydsOpZXMgKHLDqXNpZHVzKS4gTGUgbW9kw6hsZSBlc3QgcGx1dMO0dCBwcsOpY2lzLgoKYGBge3J9CiMgR3JhcGhpcXVlIGRlcyByw6lzaWR1cyBkYW5zIGxlIHRlbXBzIHBvdXIgdsOpcmlmaWVyIGwnaG9tb3Njw6lkYXN0aWNpdMOpCmdncGxvdChkb25uZWVzX2ZpbmxhbmRlX3Jlc2lkdXMsIGFlcyh4ID0geWVhciwgeSA9IHJlc2lkdWFscykpICsKICBnZW9tX2xpbmUobHdkID0gMSwgY29sb3IgPSAiZGFya2dyZWVuIikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGx0eSA9IDIsIGNvbG9yID0gInJlZCIpICsKICBsYWJzKAogICAgeCA9ICJBbm7DqWUiLAogICAgeSA9ICJSw6lzaWR1cyIsCiAgICB0aXRsZSA9ICJSw6lzaWR1cyBkdSBtb2TDqGxlIEZpbmxhbmRlIGRhbnMgbGUgdGVtcHMiCiAgKSArCiAgdGhlbWVfYncoKQoKYGBgCgpMZSBncmFwaGlxdWUgbW9udHJlIGzigJnDqXZvbHV0aW9uIGRlcyByw6lzaWR1cyBkdSBtb2TDqGxlIGRhbnMgbGUgdGVtcHMgcG91ciBsYSBGaW5sYW5kZS4gTGEgbGlnbmUgdmVydGUgdHJhY2UgbGVzIMOpY2FydHMgZW50cmUgbGVzIHZhbGV1cnMgb2JzZXJ2w6llcyBldCBhanVzdMOpZXMsIHRhbmRpcyBxdWUgbGEgbGlnbmUgcm91Z2Ugw6AgesOpcm8gc2VydCBkZSByw6lmw6lyZW5jZS4gQ2VsYSBwZXJtZXQgZGUgdsOpcmlmaWVyIHZpc3VlbGxlbWVudCBs4oCZaG9tb3Njw6lkYXN0aWNpdMOpIGV0IGzigJlhYnNlbmNlIGRlIG1vdGlmcyBzeXN0w6ltYXRpcXVlcyBkYW5zIGxlcyBlcnJldXJzLiBMZXMgcsOpc2lkdXMgb3NjaWxsZW50IGdsb2JhbGVtZW50IGF1dG91ciBkZSB6w6lybywgY2UgcXVpIGluZGlxdWUgcGFzIGRlIGJpYWlzIHN5c3TDqW1hdGlxdWUgZHUgbW9kw6hsZS4KQ2VwZW5kYW50LCBvbiBvYnNlcnZlIHF1ZWxxdWVzIGNob2NzIG1hcnF1w6lzIChhbm7DqWVzIGF2ZWMgZm9ydHMgcsOpc2lkdXMgbsOpZ2F0aWZzIGV0IHBvc2l0aWZzKSwgc3VnZ8OpcmFudCBkZXMgw6l2w6luZW1lbnRzIGV4Y2VwdGlvbm5lbHMgbWFsIGNhcHTDqXMgcGFyIGxlIG1vZMOobGUuClBhcyBkZSB0ZW5kYW5jZSBjbGFpcmUgbmkgZGUgc3RydWN0dXJlIHBlcnNpc3RhbnRlIOKGkiBhanVzdGVtZW50IGdsb2JhbCBjb3JyZWN0LCBtYWlzIHNlbnNpYmlsaXTDqSBhdXggY3Jpc2VzLgoKYGBge3J9CmxpYnJhcnkobG10ZXN0KQoKIyBUZXN0IGRlIEJyZXVzY2gtUGFnYW4gcG91ciBob21vc2PDqWRhc3RpY2l0w6kKIyBJY2kgb24gdGVzdGUgc2kgbGEgdmFyaWFuY2UgZGVzIHLDqXNpZHVzIGTDqXBlbmQgZGVzIHZhcmlhYmxlcyBleHBsaWNhdGl2ZXMgZHUgbW9kw6hsZQpicHRlc3QobW9kZWxlX2NvbnRyb2xlcykKCmBgYAoKTGUgdGVzdCBkZSBCcmV1c2NoLVBhZ2FuIG1vbnRyZSB1biBCUCA9IDAsNTYgYXZlYyB1biBwLXZhbHVlIGRlIDAsNzUuIENvbW1lIGxlIHAtdmFsdWUgZXN0IHRyw6hzIHN1cMOpcmlldXIgw6AgMCwwNSwgb24gKipuZSByZWpldHRlIHBhcyBs4oCZaHlwb3Row6hzZSBudWxsZSoqIGTigJlob21vc2PDqWRhc3RpY2l0w6kuIENlbGEgc2lnbmlmaWUgcXVlIGxhIHZhcmlhbmNlIGRlcyByw6lzaWR1cyBkdSBtb2TDqGxlIG5lIGTDqXBlbmQgcGFzIGRlcyB2YXJpYWJsZXMgZXhwbGljYXRpdmVzIGV0IHF1ZSBs4oCZaHlwb3Row6hzZSBk4oCZaG9tb3Njw6lkYXN0aWNpdMOpIGVzdCB2w6lyaWZpw6llLgoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCiMgR3JhcGhpcXVlIGRlIGRlbnNpdMOpIHBvdXIgdsOpcmlmaWVyIGxhIG5vcm1hbGl0w6kgZGVzIHLDqXNpZHVzCmdncGxvdChkb25uZWVzX2ZpbmxhbmRlX3Jlc2lkdXMsIGFlcyh4ID0gcmVzaWR1YWxzKSkgKwogIGdlb21fZGVuc2l0eShmaWxsID0gImdyZXk2MCIsIGFscGhhID0gMC43KSArCiAgbGFicygKICAgIHRpdGxlID0gIkRlbnNpdMOpIGRlcyByw6lzaWR1cyBkdSBtb2TDqGxlIEZpbmxhbmRlIiwKICAgIHggPSAiUsOpc2lkdXMiLAogICAgeSA9ICJEZW5zaXTDqSIKICApICsKICB0aGVtZV9idygpCgpgYGAKCkNlIGdyYXBoaXF1ZSByZXByw6lzZW50ZSBsYSBkZW5zaXTDqSBkZXMgcsOpc2lkdXMgZHUgbW9kw6hsZSBhcHBsaXF1w6kgw6AgbGEgRmlubGFuZGUuIExhIGRpc3RyaWJ1dGlvbiBtb250cmUgdW5lIGNvbmNlbnRyYXRpb24gaW1wb3J0YW50ZSBkZXMgcsOpc2lkdXMgYXV0b3VyIGRlIDAsIGNlIHF1aSBlc3QgZ8OpbsOpcmFsZW1lbnQgcG9zaXRpZiA6IGNlbGEgaW5kaXF1ZSBxdWUsIHBvdXIgbGEgbWFqb3JpdMOpIGRlcyBvYnNlcnZhdGlvbnMsIGxlIG1vZMOobGUgbmUgcHJvZHVpdCBwYXMgZGUgZ3JhbmRlcyBlcnJldXJzIGV0IHF1ZSBsZXMgcHLDqXZpc2lvbnMgc29udCBnbG9iYWxlbWVudCBwcm9jaGVzIGRlcyB2YWxldXJzIG9ic2VydsOpZXMuCgpDZXBlbmRhbnQsIGxhIGRlbnNpdMOpIHByw6lzZW50ZSDDqWdhbGVtZW50IHVuZSBhc3ltw6l0cmllIGzDqWfDqHJlIGV0IGRlcyBxdWV1ZXMgcGx1cyDDqXBhaXNzZXMsIG5vdGFtbWVudCBkdSBjw7R0w6kgbsOpZ2F0aWYgKGp1c3F14oCZw6AgZW52aXJvbiDigJMxMCkgZXQgZHUgY8O0dMOpIHBvc2l0aWYgKGp1c3F14oCZw6AgZW52aXJvbiArNykuIENlbGEgc3VnZ8OocmUgbGEgcHLDqXNlbmNlIGRlIHF1ZWxxdWVzIGVycmV1cnMgYXR5cGlxdWVzIG91IGRlIG5vbi1ub3JtYWxpdMOpIGRlcyByw6lzaWR1cywgY2UgcXVpIHBldXQgc2lnbmFsZXIgOnVuZSBwb3NzaWJsZSBow6l0w6lyb3Njw6lkYXN0aWNpdMOpLCBkZXMgdmFsZXVycyBhYmVycmFudGVzLCBvdSB1bmUgc3DDqWNpZmljYXRpb24gZHUgbW9kw6hsZSBxdWkgcG91cnJhaXQgw6p0cmUgYW3DqWxpb3LDqWUgKHZhcmlhYmxlcyBtYW5xdWFudGVzLCBmb3JtZSBmb25jdGlvbm5lbGxlCgpgYGB7cn0Kc2hhcGlyby50ZXN0KGRvbm5lZXNfZmlubGFuZGVfcmVzaWR1cyRyZXNpZHVhbHMpCmBgYAoKTGUgdGVzdCBkZSBTaGFwaXJvLVdpbGsgc3VyIGxlcyByw6lzaWR1cyBkdSBtb2TDqGxlIGRvbm5lIHVuIFcgPSAwLDk1MiBldCB1biBwLXZhbHVlIGRlIDAsMDI5LiBDb21tZSBsZSBwLXZhbHVlIGVzdCBpbmbDqXJpZXVyIMOgIDAsMDUsIG9uICoqcmVqZXR0ZSBs4oCZaHlwb3Row6hzZSBudWxsZSoqIGRlIG5vcm1hbGl0w6kgOiBsZXMgcsOpc2lkdXMgbmUgc3VpdmVudCBwYXMgcGFyZmFpdGVtZW50IHVuZSBkaXN0cmlidXRpb24gbm9ybWFsZS4gQ2VsYSBpbmRpcXVlIHF1ZSBjZXJ0YWluZXMgcHLDqWNhdXRpb25zIGRvaXZlbnQgw6p0cmUgcHJpc2VzIHBvdXIgbOKAmWludGVycHLDqXRhdGlvbiBkZXMgaW50ZXJ2YWxsZXMgZGUgY29uZmlhbmNlIGV0IGRlcyB0ZXN0cyBzdGF0aXN0aXF1ZXMgY2xhc3NpcXVlcy4KCmBgYHtyfQphY2YoZG9ubmVlc19maW5sYW5kZV9yZXNpZHVzJHJlc2lkdWFscywgbWFpbiA9ICJBQ0YgZGVzIHLDqXNpZHVzIEZpbmxhbmRlIikKYGBgCgpMYSBwcsOpc2VuY2UgZOKAmXVuZSBhdXRvY29ycsOpbGF0aW9uIHNpZ25pZmljYXRpdmUgYXUgbGFnIDEgaW5kaXF1ZSBxdWUgbGVzIHLDqXNpZHVzIHByw6lzZW50ZW50IGVuY29yZSB1biBwZXUgZGUgZMOpcGVuZGFuY2UgdGVtcG9yZWxsZQoKYGBge3J9CkJveC50ZXN0KGRvbm5lZXNfZmlubGFuZGVfcmVzaWR1cyRyZXNpZHVhbHMsIGxhZyA9IDEwLCB0eXBlID0gIkxqdW5nLUJveCIpCgpgYGAKCkxlIHRlc3QgZGUgTGp1bmctQm94IGFwcGxpcXXDqSBhdXggcsOpc2lkdXMgZG9ubmUgdW4gWMKyID0gNiwyOSBhdmVjIHVuIHAtdmFsdWUgZGUgMCw3OS4gQ29tbWUgbGUgcC12YWx1ZSBlc3QgbGFyZ2VtZW50IHN1cMOpcmlldXIgw6AgMCwwNSwgb24gKipuZSByZWpldHRlIHBhcyBs4oCZaHlwb3Row6hzZSBudWxsZSoqIGTigJlhYnNlbmNlIGTigJlhdXRvY29ycsOpbGF0aW9uIGRlcyByw6lzaWR1cy4gQ2VsYSBpbmRpcXVlIHF1ZSBsZXMgZXJyZXVycyBkdSBtb2TDqGxlIG5lIHByw6lzZW50ZW50IHBhcyBkZSBkw6lwZW5kYW5jZSB0ZW1wb3JlbGxlIHNpZ25pZmljYXRpdmUgZXQgcXVlIGzigJlhdXRvY29ycsOpbGF0aW9uIGVzdCBjb3JyZWN0ZW1lbnQgcHJpc2UgZW4gY29tcHRlLgoKYGBge3J9CnJlcXVpcmUoZm9yZWNhc3QpCgpgYGAKCkxlIHBhY2thZ2UgYGZvcmVjYXN0YCBlc3QgY2hhcmfDqSwgY2UgcXVpIHBlcm1ldCBk4oCZYWNjw6lkZXIgYXV4IGZvbmN0aW9ucyBwb3VyIGzigJllc3RpbWF0aW9uIGV0IGxhIHByw6l2aXNpb24gZGUgbW9kw6hsZXMgZGUgc8OpcmllcyB0ZW1wb3JlbGxlcywgbm90YW1tZW50IEFSSU1BLCBFVFMgZXQgYXV0cmVzIG91dGlscyBkZSBwcsOpdmlzaW9uLgoKYGBge3J9CmNoZWNrcmVzaWR1YWxzKG1vZGVsZV9jb250cm9sZXMpCgpgYGAKCkxlIGdyYXBoaXF1ZSBtb250cmUgcXVlIGxlcyByw6lzaWR1cyBzb250IGdsb2JhbGVtZW50IGNlbnRyw6lzIGF1dG91ciBkZSB6w6lybyBzYW5zIHRlbmRhbmNlIHBhcnRpY3VsacOocmUgZGFucyBsZSB0ZW1wcy4gTOKAmUFDRiBuZSBwcsOpc2VudGUgcGFzIGTigJlhdXRvY29ycsOpbGF0aW9ucyBzaWduaWZpY2F0aXZlcywgY2UgcXVpIGluZGlxdWUgdW5lIGFic2VuY2UgZGUgZMOpcGVuZGFuY2Ugc8OpcmlldXNlIGVudHJlIGxlcyByw6lzaWR1cy4gTOKAmWhpc3RvZ3JhbW1lIHN1Z2fDqHJlIHVuZSBkaXN0cmlidXRpb24gw6AgcGV1IHByw6hzIG5vcm1hbGUsIG3Dqm1lIHNpIGzigJlvbiBvYnNlcnZlIHF1ZWxxdWVzIHZhbGV1cnMgZXh0csOqbWVzLgoKIyBQYXJ0aWUgMiBQcsOpdmlzaW9uIGF2ZWMgQVJJTUEKCmBgYHtyfQoKCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHJlYWR4bCkKbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeSh0c2VyaWVzKQpsaWJyYXJ5KGxtdGVzdCkKbGlicmFyeSh1cmNhKQpsaWJyYXJ5KHpvbykKCgp2b3RyZV9wYXlzIDwtICJGaW5sYW5kIgoKCgpkb25uZWVzX2NwaSA8LSBkYXRhX3NjaHVsYXJpY2sgJT4lCmZpbHRlcihjb3VudHJ5ID09IHZvdHJlX3BheXMpICU+JQphcnJhbmdlKHllYXIpICU+JQpmaWx0ZXIoeWVhciA+IDE5NjApICU+JQpzZWxlY3QoeWVhciwgY3BpKSAlPiUKbXV0YXRlKApjcGlfZ3Jvd3RoID0gKGxvZyhjcGkpIC0gbGFnKGxvZyhjcGkpKSkgKiAxMDAgICMgaW5mbGF0aW9uIGVuICUKKSAlPiUKbmEub21pdCgpCgoKCmdsaW1wc2UoZG9ubmVlc19jcGkpCnByaW50KHJhbmdlKGRvbm5lZXNfY3BpJHllYXIpKQoKCgpzdGFydF95ZWFyIDwtIG1pbihkb25uZWVzX2NwaSR5ZWFyKQppbmZsX3RzIDwtIHRzKGRvbm5lZXNfY3BpJGNwaV9ncm93dGgsIHN0YXJ0ID0gc3RhcnRfeWVhciwgZnJlcXVlbmN5ID0gMSkKCgoKYXV0b3Bsb3QoaW5mbF90cykgKyBnZ3RpdGxlKHBhc3RlKCJJbmZsYXRpb24gKHRhdXggZGUgY3JvaXNzYW5jZSBDUEkgJSkgIiwgdm90cmVfcGF5cykpICsgeWxhYigiSW5mbGF0aW9uICglKSIpICsgeGxhYigiQW5uw6llIikKCgoKYWRmX3JlcyA8LSB1ci5kZihhcy5udW1lcmljKGluZmxfdHMpLCB0eXBlID0gImRyaWZ0Iiwgc2VsZWN0bGFncyA9ICJBSUMiKQpzdW1tYXJ5KGFkZl9yZXMpCgoKCmtwc3NfcmVzIDwtIHRzZXJpZXM6Omtwc3MudGVzdChhcy5udW1lcmljKGluZmxfdHMpKQprcHNzX3JlcwoKCgoKYmVzdF9hcmltYSA8LSBmb3JlY2FzdDo6YXV0by5hcmltYShpbmZsX3RzLApzZWFzb25hbCA9IEZBTFNFLApzdGVwd2lzZSA9IEZBTFNFLAphcHByb3hpbWF0aW9uID0gRkFMU0UsCnRyYWNlID0gVFJVRSwKaWMgPSAiYWljYyIpCgpiZXN0X2FyaW1hCmNoZWNrcmVzaWR1YWxzKGJlc3RfYXJpbWEpICAjIGRpYWdub3N0aWMgOiBBQ0YsIGhpc3RvZ3JhbW1lLCB0ZXN0IExqdW5nLUJveAoKCgpsYiA8LSBCb3gudGVzdChyZXNpZHVhbHMoYmVzdF9hcmltYSksIGxhZyA9IDEwLCB0eXBlID0gIkxqdW5nLUJveCIsIGZpdGRmID0gbGVuZ3RoKGJlc3RfYXJpbWEkY29lZikpCmxpYnJhcnkoRmluVFMpCgphcmNoX3Rlc3QgPC0gQXJjaFRlc3QocmVzaWR1YWxzKGJlc3RfYXJpbWEpLCBsYWcgPSAxKQphcmNoX3Rlc3QKCgoKaCA8LSA1ICAjIDUgYW5uw6llcwpmYyA8LSBmb3JlY2FzdChiZXN0X2FyaW1hLCBoID0gaCwgbGV2ZWwgPSBjKDgwLCA5NSkpCgoKZmNfZGYgPC0gZGF0YS5mcmFtZSgKWWVhciA9IChtYXgoZG9ubmVlc19jcGkkeWVhcikgKyAxKToobWF4KGRvbm5lZXNfY3BpJHllYXIpICsgaCksCk1lYW5fRkMgPSByb3VuZChmYyRtZWFuLCAyKSwKTG9fODAgPSByb3VuZChmYyRsb3dlclssMV0sIDIpLApIaV84MCA9IHJvdW5kKGZjJHVwcGVyWywxXSwgMiksCkxvXzk1ID0gcm91bmQoZmMkbG93ZXJbLDJdLCAyKSwKSGlfOTUgPSByb3VuZChmYyR1cHBlclssMl0sIDIpCikKZmNfZGYgJT4lIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJBbm7DqWUiLCAiUHLDqXZpc2lvbiBtb3llbm5lICglKSIsICJCb3JuZSA4MCUgaW5mIiwgIkJvcm5lIDgwJSBzdXAiLCAiQm9ybmUgOTUlIGluZiIsICJCb3JuZSA5NSUgc3VwIikpCgoKCmF1dG9wbG90KGZjKSArCmF1dG9sYXllcihpbmZsX3RzLCBzZXJpZXMgPSAiSGlzdG9yaXF1ZSIpICsKZ2d0aXRsZShwYXN0ZSgiUHLDqXZpc2lvbiBkZSBsJ2luZmxhdGlvbiAiLCB2b3RyZV9wYXlzLCAiKGggPSIsIGgsICJhbnMpIikpICsKeWxhYigiSW5mbGF0aW9uICglKSIpICsgeGxhYigiQW5uw6llIikKCgoKZmNfYm9vdCA8LSBmb3JlY2FzdDo6Zm9yZWNhc3QoYmVzdF9hcmltYSwgaCA9IGgsIGJvb3QgPSBUUlVFLCBsZXZlbCA9IGMoODAsOTUpLCBucGF0aHMgPSAyMDAwKQoKCgpwbG90KGZjX2Jvb3QsIG1haW4gPSBwYXN0ZSgiUHLDqXZpc2lvbnMgKGJvb3RzdHJhcCkgIiwgdm90cmVfcGF5cykpCgoKCmluX3NhbXBsZV9hY2N1cmFjeSA8LSBhY2N1cmFjeShiZXN0X2FyaW1hKQppbl9zYW1wbGVfYWNjdXJhY3kKCgoKYGBgCgpMZXMgZG9ubsOpZXMgZOKAmWluZmxhdGlvbiBwb3VyIGxhIEZpbmxhbmRlIGFwcsOocyAxOTYwIHNvbnQgZXh0cmFpdGVzIGV0IHRyYW5zZm9ybcOpZXMgZW4gdGF1eCBkZSBjcm9pc3NhbmNlIGFubnVlbCBkdSBDUEkuIExhIHPDqXJpZSB0ZW1wb3JlbGxlIGVzdCBjb252ZXJ0aWUgZW4gb2JqZXQgYHRzYCBldCB2aXN1YWxpc8OpZSBwb3VyIG9ic2VydmVyIHNvbiDDqXZvbHV0aW9uIGRhbnMgbGUgdGVtcHMuCgpEZXMgdGVzdHMgZGUgc3RhdGlvbm5hcml0w6kgc29udCByw6lhbGlzw6lzIDogbGUgdGVzdCBBREYgYXZlYyBjb25zdGFudGUgKGBkcmlmdGApIGV0IGxlIHRlc3QgS1BTUyBwZXJtZXR0ZW50IGRlIHbDqXJpZmllciBzaSBsYSBzw6lyaWUgcGV1dCDDqnRyZSBtb2TDqWxpc8OpZSBkaXJlY3RlbWVudCBvdSBzaSB1bmUgZGlmZsOpcmVuY2lhdGlvbiBlc3QgbsOpY2Vzc2FpcmUuCgpMYSBmb25jdGlvbiBgYXV0by5hcmltYWAgaWRlbnRpZmllIGxlIG1laWxsZXVyIG1vZMOobGUgQVJJTUEgcG91ciBsYSBzw6lyaWUgbm9uIHNhaXNvbm5pw6hyZSBzZWxvbiBsZSBjcml0w6hyZSBBSUNjLiBMZXMgcsOpc2lkdXMgZHUgbW9kw6hsZSBzb250IGNvbnRyw7Rsw6lzIHZpYSBgY2hlY2tyZXNpZHVhbHNgLCBsZSB0ZXN0IGRlIExqdW5nLUJveCBldCB1biB0ZXN0IEFSQ0gsIGFmaW4gZGUgdsOpcmlmaWVyIGzigJlhYnNlbmNlIGTigJlhdXRvY29ycsOpbGF0aW9uIGV0IGTigJlow6l0w6lyb3Njw6lkYXN0aWNpdMOpLgoKRGVzIHByw6l2aXNpb25zIHN1ciA1IGFucyBzb250IHByb2R1aXRlcyBhdmVjIGludGVydmFsbGVzIGRlIGNvbmZpYW5jZSDDoCA4MCAlIGV0IDk1ICUsIHByw6lzZW50w6llcyBzb3VzIGZvcm1lIGRlIHRhYmxlYXUgZXQgZGUgZ3JhcGhpcXVlLiBVbmUgcHLDqXZpc2lvbiBib290c3RyYXAgZXN0IMOpZ2FsZW1lbnQgcsOpYWxpc8OpZSBwb3VyIHZpc3VhbGlzZXIgbOKAmWluY2VydGl0dWRlIGRlIG1hbmnDqHJlIHBsdXMgcm9idXN0ZS4gRW5maW4sIGxhIHByw6ljaXNpb24gZHUgbW9kw6hsZSBzdXIgbOKAmcOpY2hhbnRpbGxvbiBoaXN0b3JpcXVlIGVzdCDDqXZhbHXDqWUgYXZlYyBsYSBmb25jdGlvbiBgYWNjdXJhY3lgLgoKQ2V0dGUgYXBwcm9jaGUgcGVybWV0IGRlIGp1c3RpZmllciBsZSBjaG9peCBk4oCZQVJJTUEsIGRlIHByb2R1aXJlIGRlcyBwcsOpdmlzaW9ucyBmaWFibGVzIGV0IGRlIGTDqXRlY3RlciBsZXMgbGltaXRlcyBsacOpZXMgYXV4IHLDqXNpZHVzIG91IMOgIGxhIHZhcmlhYmlsaXTDqSBmdXR1cmUgZGUgbOKAmWluZmxhdGlvbi4KCiMgUGFydGllIDMgLSBNb2TDqGxlIMOgIENvcnJlY3Rpb24gZOKAmUVycmV1cnMKCmBgYHtyfQoKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KHVyY2EpICAgICAgICMgdXIuZGYsIGNhLmpvCmxpYnJhcnkodHNlcmllcykgICAgIyBrcHNzLnRlc3QsIGphcnF1ZS5iZXJhLnRlc3QKbGlicmFyeShmb3JlY2FzdCkgICAjIGF1dG8uYXJpbWEgKGRpYWdub3N0aWMpCmxpYnJhcnkobG10ZXN0KSAgICAgIyBiZ3Rlc3QsIGJwdGVzdApsaWJyYXJ5KHNhbmR3aWNoKSAgICMgTmV3ZXlXZXN0IC8gdmNvdkhBQwpsaWJyYXJ5KHpvbykKCiMgUGFyYW3DqHRyZXMKCnZvdHJlX3BheXMgPC0gIkZpbmxhbmQiICAgIAogICAgICAgICAgICAgICAKCgoKZGF0YV9zY2h1bGFyaWNrIDwtIHJlYWRfZXhjZWwoImRhdGFfc2NodWxhcmljay54bHN4IikKCmRvbm5lZXNfZWNtIDwtIGRhdGFfc2NodWxhcmljayAlPiUKZmlsdGVyKGNvdW50cnkgPT0gdm90cmVfcGF5cykgJT4lCmFycmFuZ2UoeWVhcikgJT4lCmZpbHRlcih5ZWFyID4gMTk2MCkgJT4lCnNlbGVjdCh5ZWFyLCB3YWdlLCBnZHAsIHJldmVudWUsIGV4cGVuZGl0dXJlLCB1bmVtcCkgJT4lCm11dGF0ZSgKIyBsb2dzIG5pdmVhdXggKHBvdXIgdGVzdCBkZSBJKDEpIGV0IHJlbGF0aW9uIGxvbmcgdGVybWUpCmxvZ193YWdlID0gaWZfZWxzZSghaXMubmEod2FnZSksIGxvZyh3YWdlKSwgTkFfcmVhbF8pLApsb2dfZ2RwICA9IGlmX2Vsc2UoIWlzLm5hKGdkcCksICBsb2coZ2RwKSwgIE5BX3JlYWxfKSwKbG9nX3JldmVudWUgPSBpZl9lbHNlKCFpcy5uYShyZXZlbnVlKSwgbG9nKHJldmVudWUpLCBOQV9yZWFsXyksCmxvZ19leHBlbmRpdHVyZSA9IGlmX2Vsc2UoIWlzLm5hKGV4cGVuZGl0dXJlKSwgbG9nKGV4cGVuZGl0dXJlKSwgTkFfcmVhbF8pCikgJT4lCgojIHRhdXggZGUgY3JvaXNzYW5jZSAoIFZhciBsb2cgKjEwMCkKCm11dGF0ZSgKd2FnZV9ncm93dGggPSBpZl9lbHNlKCFpcy5uYShsb2dfd2FnZSksIChsb2dfd2FnZSAtIGxhZyhsb2dfd2FnZSkpICogMTAwLCBOQV9yZWFsXyksCmdkcF9ncm93dGggID0gaWZfZWxzZSghaXMubmEobG9nX2dkcCksICAobG9nX2dkcCAgLSBsYWcobG9nX2dkcCkpICAqIDEwMCwgTkFfcmVhbF8pLApyZXZlbnVlX2dyb3d0aCA9IGlmX2Vsc2UoIWlzLm5hKGxvZ19yZXZlbnVlKSwgICAgKGxvZ19yZXZlbnVlIC0gbGFnKGxvZ19yZXZlbnVlKSkgKiAxMDAsIE5BX3JlYWxfKSwKZXhwZW5kaXR1cmVfZ3Jvd3RoID0gaWZfZWxzZSghaXMubmEobG9nX2V4cGVuZGl0dXJlKSwgKGxvZ19leHBlbmRpdHVyZSAtIGxhZyhsb2dfZXhwZW5kaXR1cmUpKSAqIDEwMCwgTkFfcmVhbF8pCikgJT4lCm5hLm9taXQoKQoKZ2xpbXBzZShkb25uZWVzX2VjbSkKcHJpbnQocmFuZ2UoZG9ubmVlc19lY20keWVhcikpCgpgYGAKCkxlcyBkb25uw6llcyBwb3VyIGxhIEZpbmxhbmRlIGFwcsOocyAxOTYwIHNvbnQgcHLDqXBhcsOpZXMgcG91ciB1biBtb2TDqGxlIMOgIGNvcnJlY3Rpb24gZOKAmWVycmV1cnMgKEVDTSkuIExlcyB2YXJpYWJsZXMgZGUgc2FsYWlyZSwgUElCLCByZWNldHRlcyBldCBkw6lwZW5zZXMgcHVibGlxdWVzIHNvbnQgdHJhbnNmb3Jtw6llcyBlbiBsb2dhcml0aG1lcyBwb3VyIHRlc3RlciBsYSBjb2ludMOpZ3JhdGlvbiBldCBsZXMgcmVsYXRpb25zIGRlIGxvbmcgdGVybWUuIExlcyB0YXV4IGRlIGNyb2lzc2FuY2UgY29ycmVzcG9uZGFudHMgc29udCBjYWxjdWzDqXMgw6AgcGFydGlyIGRlcyBkaWZmw6lyZW5jZXMgbG9nYXJpdGhtaXF1ZXMsIGV4cHJpbcOpcyBlbiBwb3VyY2VudGFnZS4gTGVzIG9ic2VydmF0aW9ucyBtYW5xdWFudGVzIHNvbnQgc3VwcHJpbcOpZXMgZXQgbGEgc3RydWN0dXJlIGZpbmFsZSBkdSBqZXUgZGUgZG9ubsOpZXMgZXN0IGFmZmljaMOpZSwgcGVybWV0dGFudCBkZSB2w6lyaWZpZXIgbGEgY29ow6lyZW5jZSBldCBsYSBjb250aW51aXTDqSBkZXMgc8OpcmllcyBwb3VyIGzigJllc3RpbWF0aW9uIGTigJl1biBFQ00uCgpgYGB7cn0KWV9sdmwgPC0gImxvZyByZXZlbnVlIgpYX2x2bCA8LSAibG9nIGV4cGVuZGl0dXJlIgpkWSAgICA8LSAicmV2ZW51ZSBncm93dGgiCmRYICAgIDwtICJleHBlbmRpdHVyZSBncm93dGgiCgpjYXQoIlJlbGF0aW9uIHRlc3TDqWUgOiIsIFlfbHZsLCAifiIsIFhfbHZsLCAiXG4iKQpgYGAKCkxhIHJlbGF0aW9uIHRlc3TDqWUgcG9ydGUgc3VyIGxhIGNvaW50w6lncmF0aW9uIGVudHJlIGxlcyBuaXZlYXV4IGRlIGxvZ2FyaXRobWVzIGRlcyByZWNldHRlcyBwdWJsaXF1ZXMgKGBsb2cgcmV2ZW51ZWApIGV0IGRlcyBkw6lwZW5zZXMgcHVibGlxdWVzIChgbG9nIGV4cGVuZGl0dXJlYCkuIExlcyB2YXJpYWJsZXMgY29ycmVzcG9uZGFudGVzIGVuIGRpZmbDqXJlbmNlcywgYHJldmVudWUgZ3Jvd3RoYCBldCBgZXhwZW5kaXR1cmUgZ3Jvd3RoYCwgc2Vyb250IHV0aWxpc8OpZXMgcG91ciBlc3RpbWVyIGxlIG1vZMOobGUgw6AgY29ycmVjdGlvbiBk4oCZZXJyZXVycy4KCmBgYHtyfQpZX2x2bCA8LSAibG9nX3JldmVudWUiClhfbHZsIDwtICJsb2dfZXhwZW5kaXR1cmUiCgojIFbDqXJpZmljYXRpb24Kc3VtbWFyeShkb25uZWVzX2VjbVtbWV9sdmxdXSkKCmBgYAoKTGVzIHN0YXRpc3RpcXVlcyByw6lzdW3DqWVzIGluZGlxdWVudCBxdWUgbGUgbG9nYXJpdGhtZSBkZXMgcmVjZXR0ZXMgcHVibGlxdWVzIChgbG9nIHJldmVudWVgKSB2YXJpZSBkZSA4LDE2IMOgIDEyLDc3IHN1ciBsYSBww6lyaW9kZSDDqXR1ZGnDqWUuIExhIG3DqWRpYW5lIGVzdCBkZSAxMSw4MSBldCBsYSBtb3llbm5lIGRlIDExLDI0LCBtb250cmFudCB1bmUgbMOpZ8OocmUgYXN5bcOpdHJpZSBhdmVjIGRlcyB2YWxldXJzIG1heGltYWxlcyBwbHVzIMOpbGV2w6llcyBxdWUgbGEgbW95ZW5uZS4gQ2VzIGNoaWZmcmVzIGZvdXJuaXNzZW50IHVuZSB2dWUgZOKAmWVuc2VtYmxlIGRlcyBuaXZlYXV4IGRlIHJlY2V0dGVzIHBvdXIgbGEgRmlubGFuZGUgZW50cmUgMTk2MCBldCBsYSBmaW4gZGUgbGEgcMOpcmlvZGUgw6l0dWRpw6llLgoKYGBge3J9CiMgLS0tIFbDqXJpZmljYXRpb24gZGUgbCdpbnTDqWdyYXRpb24gKEFERiArIEtQU1MpIHPDqWN1cmlzw6llIC0tLQoKbGlicmFyeSh1cmNhKQpsaWJyYXJ5KHRzZXJpZXMpCgojIEZvbmN0aW9uIHBvdXIgbGFuY2VyIHVyLmRmKCkgc2V1bGVtZW50IHNpIGxhIHPDqXJpZSBlc3Qgc3VmZmlzYW50ZQoKc2FmZV91cl9kZiA8LSBmdW5jdGlvbih4LCB0eXBlID0gInRyZW5kIikgewp4X251bSA8LSBhcy5udW1lcmljKHgpCnhfbnVtIDwtIHhfbnVtWyFpcy5uYSh4X251bSldCgppZihsZW5ndGgoeF9udW0pIDwgMykgewp3YXJuaW5nKCJTw6lyaWUgdHJvcCBjb3VydGUgcG91ciB1ci5kZigpIDogIiwgZGVwYXJzZShzdWJzdGl0dXRlKHgpKSkKcmV0dXJuKE5VTEwpCn0KCm1heF9sYWdzIDwtIGZsb29yKGxlbmd0aCh4X251bSkgLyAyKSAtIDEKaWYobWF4X2xhZ3MgPCAwKSBtYXhfbGFncyA8LSAwCgp1ci5kZih4X251bSwgdHlwZSA9IHR5cGUsIGxhZ3MgPSBtYXhfbGFncykKfQoKIyBGb25jdGlvbiBwb3VyIEtQU1Mgc8OpY3VyaXPDqWUKCnNhZmVfa3BzcyA8LSBmdW5jdGlvbih4KSB7CnhfbnVtIDwtIGFzLm51bWVyaWMoeCkKeF9udW0gPC0geF9udW1bIWlzLm5hKHhfbnVtKV0KaWYobGVuZ3RoKHhfbnVtKSA8IDMpIHsKd2FybmluZygiU8OpcmllIHRyb3AgY291cnRlIHBvdXIgS1BTUyA6ICIsIGRlcGFyc2Uoc3Vic3RpdHV0ZSh4KSkpCnJldHVybihOVUxMKQp9CnRzZXJpZXM6Omtwc3MudGVzdCh4X251bSkKfQoKIyBWw6lyaWZpY2F0aW9uIEFERiBwb3VyIG5pdmVhdXggKGxvZ3MpCgphZGZfWV9sdmwgPC0gc2FmZV91cl9kZihkb25uZWVzX2VjbVtbWV9sdmxdXSwgdHlwZSA9ICJ0cmVuZCIpCmFkZl9YX2x2bCA8LSBzYWZlX3VyX2RmKGRvbm5lZXNfZWNtW1tYX2x2bF1dLCB0eXBlID0gInRyZW5kIikKCmlmKCFpcy5udWxsKGFkZl9ZX2x2bCkpIHN1bW1hcnkoYWRmX1lfbHZsKQppZighaXMubnVsbChhZGZfWF9sdmwpKSBzdW1tYXJ5KGFkZl9YX2x2bCkKCiMgVsOpcmlmaWNhdGlvbiBBREYgcG91ciBkaWZmw6lyZW5jZXMKCmFkZl9kWSA8LSBzYWZlX3VyX2RmKGRvbm5lZXNfZWNtW1tkWV1dLCB0eXBlID0gImRyaWZ0IikKYWRmX2RYIDwtIHNhZmVfdXJfZGYoZG9ubmVlc19lY21bW2RYXV0sIHR5cGUgPSAiZHJpZnQiKQoKaWYoIWlzLm51bGwoYWRmX2RZKSkgc3VtbWFyeShhZGZfZFkpCmlmKCFpcy5udWxsKGFkZl9kWCkpIHN1bW1hcnkoYWRmX2RYKQoKIyBLUFNTIHBvdXIgdG91dGVzIGxlcyBzw6lyaWVzCgprcHNzX1kgPC0gc2FmZV9rcHNzKGRvbm5lZXNfZWNtW1tZX2x2bF1dKQprcHNzX1ggPC0gc2FmZV9rcHNzKGRvbm5lZXNfZWNtW1tYX2x2bF1dKQprcHNzX2RZIDwtIHNhZmVfa3Bzcyhkb25uZWVzX2VjbVtbZFldXSkKa3Bzc19kWCA8LSBzYWZlX2twc3MoZG9ubmVlc19lY21bW2RYXV0pCgprcHNzX1kKa3Bzc19YCmtwc3NfZFkKa3Bzc19kWAoKYGBgCgpMZXMgdGVzdHMgQURGIGV0IEtQU1Mgc29udCB1dGlsaXPDqXMgcG91ciB2w6lyaWZpZXIgbOKAmWludMOpZ3JhdGlvbiBkZXMgc8OpcmllcyBhdmFudCBlc3RpbWF0aW9uIGTigJl1biBFQ00uCgpMZXMgKipuaXZlYXV4KiogKGBsb2cgcmV2ZW51ZWAgZXQgYGxvZyBleHBlbmRpdHVyZWApIHNvbnQgdGVzdMOpcyBhdmVjIEFERiBpbmNsdWFudCB1bmUgdGVuZGFuY2UgZXQgS1BTUyBhdXRvdXIgZGUgbGEgdGVuZGFuY2UuIFNpIGxhIHPDqXJpZSBu4oCZZXN0IHBhcyBzdGF0aW9ubmFpcmUgZW4gbml2ZWF1eCBtYWlzIHN0YXRpb25uYWlyZSBlbiBkaWZmw6lyZW5jZXMsIGNlbGEgaW5kaXF1ZSBxdeKAmWVsbGUgZXN0IGludMOpZ3LDqWUgZOKAmW9yZHJlIDEgKEkoMSkpIGV0IHF14oCZdW4gbW9kw6hsZSBkZSBjb2ludMOpZ3JhdGlvbiBwZXV0IMOqdHJlIGFwcHJvcHJpw6kuCgpMZXMgKipkaWZmw6lyZW5jZXMgcHJlbWnDqHJlcyoqIChgcmV2ZW51ZSBncm93dGhgIGV0IGBleHBlbmRpdHVyZSBncm93dGhgKSBzb250IHRlc3TDqWVzIGF2ZWMgQURGIGluY2x1YW50IHVuZSBjb25zdGFudGUgZXQgS1BTUyBhdXRvdXIgZGUgbGEgbW95ZW5uZS4gQ2VzIHRlc3RzIGNvbmZpcm1lbnQgZ8OpbsOpcmFsZW1lbnQgcXVlIGxlcyBzw6lyaWVzIGRlIGNyb2lzc2FuY2Ugc29udCBzdGF0aW9ubmFpcmVzIChJKDApKSwgY29uZGl0aW9uIG7DqWNlc3NhaXJlIHBvdXIgc3DDqWNpZmllciBjb3JyZWN0ZW1lbnQgbOKAmUVDTS4KCkNldHRlIHByb2PDqWR1cmUgc8OpY3VyaXPDqWUgcGVybWV0IGRlIHPigJlhc3N1cmVyIHF1ZSBsZXMgc8OpcmllcyBzb250IHN1ZmZpc2FtbWVudCBsb25ndWVzIGV0IGFkYXB0w6llcyBhdXggdGVzdHMsIMOpdml0YW50IGxlcyBlcnJldXJzIGR1ZXMgw6AgZGVzIGRvbm7DqWVzIHRyb3AgY291cnRlcyBvdSBtYW5xdWFudGVzLgoKTGVzIHLDqXN1bHRhdHMgbW9udHJlbnQgcXVlIGxlcyB0ZXN0cyBkZSByYWNpbmUgdW5pdGFpcmUgc3VyIGxlcyBuaXZlYXV4IChgbG9nIHJldmVudWVgIGV0IGBsb2cgZXhwZW5kaXR1cmVgKSBuZSBwZXV2ZW50IHBhcyDDqnRyZSBjYWxjdWzDqXMgY29ycmVjdGVtZW50IGF2ZWMgQURGIGVuIHJhaXNvbiBkZSBsYSAqKnRhaWxsZSB0cm9wIGZhaWJsZSBkZSBsYSBzw6lyaWUqKiBldCBkZSBwcm9ibMOobWVzIGRlIGNvbGluw6lhcml0w6ksIGNlIHF1aSBwcm9kdWl0IGRlcyBjb2VmZmljaWVudHMgZXQgZGVzIHN0YXRpc3RpcXVlcyBgTmFOYC4KCkNlcGVuZGFudCwgbGVzIHRlc3RzICoqS1BTUyoqIGluZGlxdWVudCB1bmUgZm9ydGUgc2lnbmlmaWNhdGl2aXTDqSAocC12YWx1ZSDiiYggMCwwMSksIGNlIHF1aSAqKnJlamV0dGUgbOKAmWh5cG90aMOoc2UgZGUgc3RhdGlvbm5hcml0w6kgZW4gbml2ZWF1eCoqLiBBdXRyZW1lbnQgZGl0LCBsZXMgc8OpcmllcyBkZSByZXZlbnVzIGV0IGRlIGTDqXBlbnNlcyBwdWJsaXF1ZXMgbmUgc29udCBwYXMgc3RhdGlvbm5haXJlcyBldCBzb250IGRvbmMgdnJhaXNlbWJsYWJsZW1lbnQgaW50w6lncsOpZXMgZOKAmW9yZHJlIDEgKEkoMSkpLgoKTGVzIHRlc3RzIHN1ciBsZXMgZGlmZsOpcmVuY2VzIHByZW1pw6hyZXMgKGByZXZlbnVlIGdyb3d0aGAgZXQgYGV4cGVuZGl0dXJlIGdyb3d0aGApIG7igJlvbnQgcGFzIMOpdMOpIHLDqWFsaXPDqXMgY2FyIGxhIHPDqXJpZSBlc3QgdHJvcCBjb3VydGUsIG1haXMgZW4gcHJhdGlxdWUsIGNlcyBzw6lyaWVzIGRlIGNyb2lzc2FuY2Ugc29udCBnw6luw6lyYWxlbWVudCBzdGF0aW9ubmFpcmVzLCBjZSBxdWkgZXN0IG7DqWNlc3NhaXJlIHBvdXIgc3DDqWNpZmllciB1biAqKkVDTSoqLgoKRW4gcsOpc3Vtw6kgOiBsZXMgc8OpcmllcyBkZSBuaXZlYXUgc29udCBJKDEpIGV0IGxlcyBzw6lyaWVzIGRlIGNyb2lzc2FuY2UgcGV1dmVudCDDqnRyZSB1dGlsaXPDqWVzIGNvbW1lIHZhcmlhYmxlcyBzdGF0aW9ubmFpcmVzIHBvdXIgbGUgbW9kw6hsZSDDoCBjb3JyZWN0aW9uIGTigJllcnJldXJzLgoKYGBge3J9CiNTdGVwIDEgRW5nbGUgJiBHcmFuZ2VyIDogZXN0aW1hdGlvbiByZWxhdGlvbiBsb25nLXRlcm1lIChuaXZlYXV4KSAKCiMgT24gZXN0aW1lIFkgPSBhbHBoYSArIGJldGEgKiBYIGVuIG5pdmVhdXggKGxvZ3MpCgpmb3JtdWxhX2x2bCA8LSBhcy5mb3JtdWxhKHBhc3RlKFlfbHZsLCAifiIsIFhfbHZsKSkKZWdfbHZsIDwtIGxtKGZvcm11bGFfbHZsLCBkYXRhID0gZG9ubmVlc19lY20pCnN1bW1hcnkoZWdfbHZsKQoKIyBFeHRyYWlyZSByw6lzaWR1cyBkZSBsYSByw6lncmVzc2lvbiBlbiBuaXZlYXV4ICh1LXQpCgpkb25uZWVzX2VjbSA8LSBkb25uZWVzX2VjbSAlPiUKbXV0YXRlKGVnX3Jlc2lkID0gcmVzaWR1YWxzKGVnX2x2bCkpCgpgYGAKCkxhIHLDqWdyZXNzaW9uIGVuIG5pdmVhdXggbW9udHJlIHVuZSByZWxhdGlvbiAqKnRyw6hzIGZvcnRlIGV0IHBvc2l0aXZlKiogZW50cmUgbGVzIHJlY2V0dGVzIGV0IGxlcyBkw6lwZW5zZXMgcHVibGlxdWVzIDoKCkxlIGNvZWZmaWNpZW50IGRlIGBsb2dfZXhwZW5kaXR1cmVgIGVzdCAqKjEsMDI0KiosIGhhdXRlbWVudCBzaWduaWZpY2F0aWYgKHAgXDwgMCwwMDEpLCBpbmRpcXVhbnQgcXVlLCDDoCBsb25nIHRlcm1lLCB1bmUgYXVnbWVudGF0aW9uIGRlIDEgJSBkZXMgZMOpcGVuc2VzIHB1YmxpcXVlcyBlc3QgYXNzb2Npw6llIMOgIHVuZSBhdWdtZW50YXRpb24gZOKAmWVudmlyb24gMSwwMiAlIGRlcyByZWNldHRlcy4KCkzigJlvcmRvbm7DqWUgw6AgbOKAmW9yaWdpbmUgZXN0IG7DqWdhdGl2ZSAoLTAsMzYyKSBldCBzaWduaWZpY2F0aXZlLCBtYWlzIHNhIHZhbGV1ciBlc3QgZmFpYmxlIHBhciByYXBwb3J0IMOgIGzigJnDqWNoZWxsZSBkZXMgbG9ncy4KCkxlIFLCsiBlc3QgZXh0csOqbWVtZW50IMOpbGV2w6kgKCoqMCw5OTIqKiksIGNlIHF1aSByZWZsw6h0ZSBxdWUgbGEgdmFyaWF0aW9uIGRlcyBkw6lwZW5zZXMgZXhwbGlxdWUgcHJlc3F1ZSB0b3RhbGVtZW50IGNlbGxlIGRlcyByZWNldHRlcyBzdXIgbGEgcMOpcmlvZGUuCgpMZXMgcsOpc2lkdXMgZGUgY2V0dGUgcsOpZ3Jlc3Npb24gKGBlZ19yZXNpZGApIHJlcHLDqXNlbnRlbnQgbGVzIMOpY2FydHMgw6AgbOKAmcOpcXVpbGlicmUgZGUgbG9uZyB0ZXJtZSBldCBzZXJ2aXJvbnQgw6AgZXN0aW1lciBsZSAqKm1vZMOobGUgw6AgY29ycmVjdGlvbiBk4oCZZXJyZXVycyoqLgoKYGBge3J9CiNUZXN0IGRlIHN0YXRpb25uYXJpdMOpIGRlcyByw6lzaWR1cyAoQURGIHN1ciB1LXQpIDogRW5nbGUtR3JhbmdlciB0ZXN0CgphZGZfcmVzaWQgPC0gdXIuZGYoZG9ubmVlc19lY20kZWdfcmVzaWQsIHR5cGUgPSAibm9uZSIsIHNlbGVjdGxhZ3MgPSAiQUlDIikgCnN1bW1hcnkoYWRmX3Jlc2lkKQoKIyBJbnRlcnByw6l0YXRpb24gOgoKIyAtIFNpIGxlIHRlc3QgcmVqZXR0ZSBsYSByYWNpbmUgdW5pdGFpcmUgKHN0YXQgPCBjcml0LiA1JSksIGFsb3JzIHUtdCBlc3QgSSgwKSAtPiBjb2ludMOpZ3JhdGlvbi4KCmBgYAoKTGUgdGVzdCBBREYgc3VyIGxlcyByw6lzaWR1cyBkZSBsYSByw6lncmVzc2lvbiBlbiBuaXZlYXV4IGluZGlxdWUgcXVlIGNlcyByw6lzaWR1cyBzb250ICoqc3RhdGlvbm5haXJlcyoqIDoKCkxhIHN0YXRpc3RpcXVlIGRlIHRlc3QgZXN0ICoqLTMsMDI3KiosIGNlIHF1aSBlc3QgKippbmbDqXJpZXVyIMOgIGxhIHZhbGV1ciBjcml0aXF1ZSDDoCA1ICUgKC0xLDk1KSoqLgoKTOKAmWh5cG90aMOoc2UgbnVsbGUgZGUgcmFjaW5lIHVuaXRhaXJlIGVzdCBkb25jICoqcmVqZXTDqWUqKiwgY2UgcXVpIHNpZ25pZmllIHF1ZSBsZXMgcsOpc2lkdXMgc29udCBJKDApLgoKKipJbnRlcnByw6l0YXRpb24qKiA6IGxlcyBzw6lyaWVzIGBsb2cgcmV2ZW51ZWAgZXQgYGxvZyBleHBlbmRpdHVyZWAgc29udCAqKmNvaW50w6lncsOpZXMqKiwgY29uZmlybWFudCBs4oCZZXhpc3RlbmNlIGTigJl1biDDqXF1aWxpYnJlIGRlIGxvbmcgdGVybWUgZW50cmUgcmVjZXR0ZXMgZXQgZMOpcGVuc2VzIHB1YmxpcXVlcy4gQ2V0dGUgdmFsaWRhdGlvbiBqdXN0aWZpZSBs4oCZdXRpbGlzYXRpb24gZOKAmXVuICoqbW9kw6hsZSDDoCBjb3JyZWN0aW9uIGTigJllcnJldXJzIChFQ00pKiogcG91ciBhbmFseXNlciBsYSBkeW5hbWlxdWUgZGUgY291cnQgdGVybWUgYXV0b3VyIGRlIGNldCDDqXF1aWxpYnJlLgoKYGBge3J9CiMgT3B0aW9ubmVsIHBvdXIgcm9idXN0ZXNzZSA6IHRlc3QgZGUgSm9oYW5zZW4gKG11bHRpdmFyacOpKQoKClltYXQgPC0gY2JpbmQoZG9ubmVlc19lY21bW1lfbHZsXV0sIGRvbm5lZXNfZWNtW1tYX2x2bF1dKQpjb2xuYW1lcyhZbWF0KSA8LSBjKCJZIiwgIlgiKQoKIyBDaG9peCBkdSBsYWcgSyBpY2kgaz0yCgpqbyA8LSBjYS5qbyhZbWF0LCB0eXBlID0gInRyYWNlIiwgZWNkZXQgPSAiY29uc3QiLCBLID0gMikKc3VtbWFyeShqbykKCiMgSW50ZXJwcsOpdGF0aW9uIDogc2kgdHJhY2UgdGVzdCBpbmRpcXVlIHIgPSAxID0+IDEgdmVjdGV1ciBkZSBjb2ludMOpZ3JhdGlvbi4KCmBgYAoKTGUgdGVzdCBkZSBKb2hhbnNlbiBjb25maXJtZSBsYSAqKnByw6lzZW5jZSBk4oCZdW4gdmVjdGV1ciBkZSBjb2ludMOpZ3JhdGlvbiB1bmlxdWUqKiBlbnRyZSBgbG9nIHJldmVudWVgIGV0IGBsb2cgZXhwZW5kaXR1cmVgIDoKClBvdXIgKipyIOKJpCAxKiosIGxhIHN0YXRpc3RpcXVlIGRlIHRyYWNlIGVzdCAqKjksNjIqKiwgc3Vww6lyaWV1cmUgw6AgbGEgdmFsZXVyIGNyaXRpcXVlIMOgIDEwICUgKDcsNTIpIG1haXMgaW5mw6lyaWV1cmUgw6AgY2VsbGUgw6AgNSAlICg5LDI0KS4gQ2VsYSBzdWdnw6hyZSAqKnVuIHZlY3RldXIgZGUgY29pbnTDqWdyYXRpb24qKiDDoCB1biBuaXZlYXUgZGUgY29uZmlhbmNlIGRlIDkwIGEgOTUgJS4KClBvdXIgKipyID0gMCoqLCBsYSBzdGF0aXN0aXF1ZSBlc3QgdHLDqHMgw6lsZXbDqWUgKDQ2LDg4KSwgYmllbiBhdS1kZXNzdXMgZGUgbGEgdmFsZXVyIGNyaXRpcXVlLCBjZSBxdWkgcmVqZXR0ZSBs4oCZaHlwb3Row6hzZSBk4oCZYWJzZW5jZSBkZSBjb2ludMOpZ3JhdGlvbi4KCioqSW50ZXJwcsOpdGF0aW9uKiogOiBsZXMgcmVjZXR0ZXMgZXQgbGVzIGTDqXBlbnNlcyBwdWJsaXF1ZXMgcGFydGFnZW50IHVuICoqw6lxdWlsaWJyZSBkZSBsb25nIHRlcm1lKiouIExlcyAqKnZlY3RldXJzIHByb3ByZXMgbm9ybWFsaXPDqXMqKiBtb250cmVudCBsYSByZWxhdGlvbiBlbnRyZSBsZXMgdmFyaWFibGVzIGV0IGxlICoqbWF0cmljZSBkZSBjaGFyZ2VzIChsb2FkaW5nIG1hdHJpeCkqKiBpbmRpcXVlIGxhIHZpdGVzc2Ugw6AgbGFxdWVsbGUgY2hhcXVlIHZhcmlhYmxlIHPigJlhanVzdGUgcG91ciByZXZlbmlyIMOgIGzigJnDqXF1aWxpYnJlIGFwcsOocyB1biBjaG9jLgoKQ2VsYSB2YWxpZGUgbGEgbWlzZSBlbiBwbGFjZSBk4oCZdW4gKiptb2TDqGxlIMOgIGNvcnJlY3Rpb24gZOKAmWVycmV1cnMgKEVDTSkqKiBwb3VyIGFuYWx5c2VyIGxlcyBhanVzdGVtZW50cyBkZSBjb3VydCB0ZXJtZSBhdXRvdXIgZGUgY2V0IMOpcXVpbGlicmUuCgpgYGB7cn0KIyBTdGVwIDIgRW5nbGUgZXQgR3JhbmdlciA6IEVzdGltYXRpb24gRUNNIChzaSByw6lzaWR1cyBzdGF0aW9ubmFpcmVzKQoKIyBEw6lmaW5pciBsZXMgbm9tcyBkZXMgY29sb25uZXMKWV9sdmwgPC0gImxvZ19yZXZlbnVlIgpYX2x2bCA8LSAibG9nX2V4cGVuZGl0dXJlIgpkWSAgICA8LSAicmV2ZW51ZV9ncm93dGgiCmRYICAgIDwtICJleHBlbmRpdHVyZV9ncm93dGgiCgojIFbDqXJpZmllciBxdWUgbGVzIGNvbG9ubmVzIGRlIG5pdmVhdXggZXhpc3RlbnQKc3RvcGlmbm90KGFsbChjKFlfbHZsLCBYX2x2bCkgJWluJSBuYW1lcyhkb25uZWVzX2VjbSkpKQoKIyBWw6lyaWZpZXIgcXVlIGxlcyBjb2xvbm5lcyBkZSBkaWZmw6lyZW5jZXMgZXhpc3RlbnQsIHNpbm9uIGxlcyBjcsOpZXIKaWYoIWFsbChjKGRZLCBkWCkgJWluJSBuYW1lcyhkb25uZWVzX2VjbSkpKSB7CiAgZG9ubmVlc19lY20gPC0gZG9ubmVlc19lY20gJT4lCiAgICBtdXRhdGUoCiAgICAgICEhZFkgOj0gMTAwICogKCAuZGF0YVtbWV9sdmxdXSAtIGxhZyguZGF0YVtbWV9sdmxdXSkgKSwKICAgICAgISFkWCA6PSAxMDAgKiAoIC5kYXRhW1tYX2x2bF1dIC0gbGFnKC5kYXRhW1tYX2x2bF1dKSApCiAgICApCn0KCiMgVsOpcmlmaWVyIHF1ZSBlZyByZXNpZCBleGlzdGUsIHNpbm9uIGfDqW7DqXJlciB1bmUgZXJyZXVyCnN0b3BpZm5vdCgiZWdfcmVzaWQiICVpbiUgbmFtZXMoZG9ubmVlc19lY20pKQoKIyBDb25zdHJ1aXJlIGRlbGF0WSwgZGVsdGFYIGV0IGxhZ2dlZCByZXNpZHVhbCAodSB0LTEpCmRvbm5lZXNfZWNtIDwtIGRvbm5lZXNfZWNtICU+JQogIG11dGF0ZSgKICAgIGRZX3YgPSAuZGF0YVtbZFldXSwKICAgIGRYX3YgPSAuZGF0YVtbZFhdXSwKICAgIGxhZ19lZ19yZXNpZCA9IGxhZyhlZ19yZXNpZCkKICApICU+JQogIG5hLm9taXQoKSAgIyBTdXBwcmltZSBsZXMgbGlnbmVzIE5BIGludHJvZHVpdGVzIHBhciBsZXMgbGFncwoKIyBFQ00gYmFzZWxpbmUgOiBkZWx0YSBZIHQgPSBrICsgYWxwaGEgKiBkZWx0YSB4dCArIGdhbW1hICogdSB0LTEgKyBlcnJldXIKZWNtX2Zvcm11bGEgPC0gYXMuZm9ybXVsYSgiZFlfdiB+IGRYX3YgKyBsYWdfZWdfcmVzaWQiKQplY21fbW9kIDwtIGxtKGVjbV9mb3JtdWxhLCBkYXRhID0gZG9ubmVlc19lY20pCgojIFLDqXN1bcOpIGNsYXNzaXF1ZQpzdW1tYXJ5KGVjbV9tb2QpCgojIENvZWZmaWNpZW50cyByb2J1c3RlcyBOZXdleSBXZXN0IChjb3JyaWdlIGF1dG9jb3JyL2jDqXTDqXJvc2PDqWRhc3RpY2l0w6kpCmNvZWZ0ZXN0KGVjbV9tb2QsIHZjb3YgPSBOZXdleVdlc3QoZWNtX21vZCwgcHJld2hpdGUgPSBGQUxTRSkpCgpgYGAKCioqQ29uc3RhbnRlIChJbnRlcmNlcHQpKiogOiBsw6lnw6hyZW1lbnQgcG9zaXRpdmUgZXQgc2lnbmlmaWNhdGl2ZSBhdSBzZXVpbCA14oCvJSBhdmVjIGVycmV1cnMgcm9idXN0ZXMsIGVsbGUgcmVwcsOpc2VudGUgbGUgY2hhbmdlbWVudCBtb3llbiBkZXMgcmVjZXR0ZXMgbG9yc3F1ZSBsZXMgYXV0cmVzIHZhcmlhYmxlcyBzb250IG51bGxlcy4KCioqZFhfdiAodmFyaWF0aW9uIGRlcyBkw6lwZW5zZXMpKiogOiBjb2VmZmljaWVudCBwb3NpdGlmIGV0IHRyw6hzIHNpZ25pZmljYXRpZiAoKirigK8wLDcwKiopLCBjZSBxdWkgaW5kaXF1ZSBxdeKAmXVuZSBhdWdtZW50YXRpb24gZGVzIGTDqXBlbnNlcyBkZSAx4oCvJSBlbnRyYcOubmUgdW5lIGhhdXNzZSBpbW3DqWRpYXRlIGTigJllbnZpcm9uIDAsN+KAryUgZGVzIHJlY2V0dGVzIGRhbnMgbGUgY291cnQgdGVybWUuCgoqKmxhZ19lZ19yZXNpZCAocsOpc2lkdSBkdSBsb25nIHRlcm1lKSoqIDogY29lZmZpY2llbnQgbsOpZ2F0aWYgKCoq4oCvLTExLDMqKikgZXQgcHJvY2hlIGR1IHNldWlsIGRlIHNpZ25pZmljYXRpdml0w6kgKHAg4omIIDAsMDUgYXZlYyBlcnJldXJzIHJvYnVzdGVzKS4gQ2VsYSBzaWduaWZpZSBxdWUgbG9yc3F1ZSBsZXMgcmVjZXR0ZXMgc29udCBzdXDDqXJpZXVyZXMgw6AgbGV1ciBuaXZlYXUgZOKAmcOpcXVpbGlicmUsIGVsbGVzIHRlbmRlbnQgw6Agc2UgY29ycmlnZXIgw6AgbGEgYmFpc3NlLCBldCBpbnZlcnNlbWVudC4gQ+KAmWVzdCBsZSAqKm3DqWNhbmlzbWUgZOKAmWFqdXN0ZW1lbnQgdmVycyBs4oCZw6lxdWlsaWJyZSBkZSBsb25nIHRlcm1lKiouCgpgYGB7cn0KIyBEaWFnbm9zdGljcyBFQ00KCiMgMSkgQXV0b2NvcnIgcsOpc2lkdXMgKEJyZXVzY2ggR29kZnJleSkKCnByaW50KGJndGVzdChlY21fbW9kLCBvcmRlciA9IDQpKQoKIyAyKSBIw6l0w6lyb3Njw6lkYXN0aWNpdMOpIChCcmV1c2NoIFBhZ2FuKQoKcHJpbnQoYnB0ZXN0KGVjbV9tb2QpKQoKIyAzKSBOb3JtYWxpdMOpIChKYXJxdWUgQmVyYSkKCnByaW50KHRzZXJpZXM6OmphcnF1ZS5iZXJhLnRlc3QocmVzaWR1YWxzKGVjbV9tb2QpKSkKCiMgNCkgQUNGIHLDqXNpZHVzIHZpc3VlbAoKYWNmKHJlc2lkdWFscyhlY21fbW9kKSwgbWFpbiA9ICJBQ0YgZGVzIHLDqXNpZHVzIEVDTSIpCgpgYGAKCkEgQ09NUExFVEVSCgpgYGB7cn0KIyAtLS0gRXh0cmFjdGlvbiBkZXMgY29lZmZpY2llbnRzIGNsw6lzIEVDTSAtLS0KCiMgTG9uZy1ydW4gYmV0YSA6IHBlbnRlIGRlIGxhIHJlbGF0aW9uIGVuIG5pdmVhdXggKEVuZ2xlLUdyYW5nZXIpCmxvbmdfcnVuX2JldGEgPC0gY29lZihlZ19sdmwpWzJdCgojIFNob3J0LXJ1biBhbHBoYSA6IGVmZmV0IGRlIGxhIHZhcmlhdGlvbiBkZSBYIHN1ciBkZWx0YSBZCnNob3J0X3J1bl9hbHBoYSA8LSBjb2VmKGVjbV9tb2QpWyJkWF92Il0KCiMgRUNNIGdhbW1hIDogY29lZmZpY2llbnQgZGUgY29ycmVjdGlvbiBkJ2VycmV1ciAobGFnIGRlcyByw6lzaWR1cyBFbmdsZS1HcmFuZ2VyKQplY21fZ2FtbWEgPC0gY29lZihlY21fbW9kKVsibGFnX2VnX3Jlc2lkIl0KCiMgLS0tIEFmZmljaGFnZSBjbGFpciAtLS0KY2F0KCJSw6lzdWx0YXRzIGNsw6lzIGRlIGwnRUNNIDpcbiIpCmNhdCgiTG9uZy1ydW4gYmV0YSAgPSIsIHJvdW5kKGxvbmdfcnVuX2JldGEsIDMpLCAiXG4iKQpjYXQoIlNob3J0LXJ1biBhbHBoYSA9Iiwgcm91bmQoc2hvcnRfcnVuX2FscGhhLCAzKSwgIlxuIikKY2F0KCJFQ00gZ2FtbWEgICAgID0iLCByb3VuZChlY21fZ2FtbWEsIDMpLCAiXG4iKQoKYGBgCgotICAgKipMb25nLXJ1biBiZXRhID0gMS4wMjQqKgoKICAgIExhIHJlbGF0aW9uIGRlIGxvbmcgdGVybWUgZW50cmUgYGxvZ19yZXZlbnVlYCBldCBgbG9nX2V4cGVuZGl0dXJlYCBlc3QgcHJlc3F1ZSBwcm9wb3J0aW9ubmVsbGUuCgogICAgQXV0cmVtZW50IGRpdCwgdW5lIGF1Z21lbnRhdGlvbiBkZSAx4oCvJSBkZXMgZMOpcGVuc2VzIHB1YmxpcXVlcyBlc3QgYXNzb2Npw6llIMOgIHVuZSBhdWdtZW50YXRpb24gZOKAmWVudmlyb24gMSwwMuKAryUgZGVzIHJlY2V0dGVzIMOgIGxvbmcgdGVybWUuCgogICAgKipTaG9ydC1ydW4gYWxwaGEgPSAwLjcqKgoKTOKAmWVmZmV0IGltbcOpZGlhdCBk4oCZdW5lIHZhcmlhdGlvbiBkZSBgZXhwZW5kaXR1cmVgIHN1ciBsYSB2YXJpYXRpb24gZGUgYHJldmVudWVgIGVzdCBwb3NpdGlmIGV0IHNpZ25pZmljYXRpZi4KClVuZSBhdWdtZW50YXRpb24gZGUgMeKAryUgZGVzIGTDqXBlbnNlcyBlbnRyYcOubmUgZW52aXJvbiAwLDfigK8lIGTigJlhdWdtZW50YXRpb24gZGVzIHJlY2V0dGVzIHN1ciBs4oCZYW5uw6llIGVuIGNvdXJzLgoKKipFQ00gZ2FtbWEgPSAtMTEuMzIzKioKCkxlIGNvZWZmaWNpZW50IGRlIGNvcnJlY3Rpb24gZOKAmWVycmV1ciBlc3QgbsOpZ2F0aWYgZXQgYXNzZXogw6lsZXbDqSBlbiB2YWxldXIgYWJzb2x1ZS4KCkNlbGEgaW5kaXF1ZSBxdWUgc2kgbGUgc3lzdMOobWUgZXN0IGF1LWRlc3N1cyBkZSBs4oCZw6lxdWlsaWJyZSBkZSBsb25nIHRlcm1lLCBpbCBzZSBjb3JyaWdlIHJhcGlkZW1lbnQgdmVycyBjZXQgw6lxdWlsaWJyZSBs4oCZYW5uw6llIHN1aXZhbnRlLgoKYGBge3J9CiMgU2kgcGFzIGRlIGNvaW50w6lncmF0aW9uIDogbW9kw6hsZSBlbiBkaWZmw6lyZW5jZXMgc2ltcGxlIChyb2J1c3QgYWx0ZXJuYXRpdmUpIAojIEljaSBvbiBlc3QgIFZhclJldmVudWUgIFZhckV4cGVuZGl0dXJlCiMgT24gc2Ugc2VydCBkaXJlY3RlbWVudCBkZXMgdmFyaWFibGVzIGTDqWrDoCBwcsOpcGFyw6llcyBkYW5zICdkb25uZWVzX2VjbScKCiMgVsOpcmlmaWVyIHF1ZSBsZXMgY29sb25uZXMgZXhpc3RlbnQKc3RvcGlmbm90KGFsbChjKCJyZXZlbnVlX2dyb3d0aCIsICJleHBlbmRpdHVyZV9ncm93dGgiKSAlaW4lIG5hbWVzKGRvbm5lZXNfZWNtKSkpCgojIEVzdGltYXRpb24gT0xTIGVuIGRpZmbDqXJlbmNlcwpvbHNfZGlmZnMgPC0gbG0ocmV2ZW51ZV9ncm93dGggfiBleHBlbmRpdHVyZV9ncm93dGgsIGRhdGEgPSBkb25uZWVzX2VjbSkKc3VtbWFyeShvbHNfZGlmZnMpCgojIFJvYnVzdGVzc2UgOiBlcnJldXJzIHN0YW5kYXJkcyBOZXdleS1XZXN0CmxpYnJhcnkoc2FuZHdpY2gpOyBsaWJyYXJ5KGxtdGVzdCkKY29lZnRlc3Qob2xzX2RpZmZzLCB2Y292ID0gTmV3ZXlXZXN0KG9sc19kaWZmcywgcHJld2hpdGUgPSBGQUxTRSkpCgpgYGAKCkxlIG1vZMOobGUgbW9udHJlIHVuIGxpZW4gKipwb3NpdGlmIGV0IHNpZ25pZmljYXRpZioqIGVudHJlIHZhcmlhdGlvbiBkZXMgZMOpcGVuc2VzIGV0IHZhcmlhdGlvbiBkZXMgcmVjZXR0ZXMsIGNvaMOpcmVudCBhdmVjIHVuIGVmZmV0IGF1dG9tYXRpcXVlIG91IHJlZGlzdHJpYnV0aWYgZGVzIGTDqXBlbnNlcyBwdWJsaXF1ZXMgc3VyIGxlcyByZWNldHRlcyBmaXNjYWxlCgojIENvbmNsdXNpb24KCkzigJlvYmplY3RpZiBwcmluY2lwYWwgZGUgY2V0dGUgYW5hbHlzZSDDqXRhaXQgZOKAmcOpdHVkaWVyIGxlcyBkeW5hbWlxdWVzIG1hY3Jvw6ljb25vbWlxdWVzIGRlIGxhIEZpbmxhbmRlIGVudHJlIDE5NjAgZXQgMjAyMCwgZW4gc2UgY29uY2VudHJhbnQgc3VyIHRyb2lzIGF4ZXMgOiBsYSBjcm9pc3NhbmNlIGRlIGxhIHBvcHVsYXRpb24sIGxhIGNyb2lzc2FuY2UgZHUgUElCIGV0IGxlcyByZWxhdGlvbnMgZW50cmUgcmVjZXR0ZXMgZXQgZMOpcGVuc2VzIHB1YmxpcXVlcy4gTGEgRmlubGFuZGUgYSBjb25udSBkZXMgdmFyaWF0aW9ucyBtb2TDqXLDqWVzIGR1IHRhdXggZGUgY3JvaXNzYW5jZSBkw6ltb2dyYXBoaXF1ZS4gTOKAmWFuYWx5c2Ugc3RhdGlzdGlxdWUgZGVzY3JpcHRpdmUgYSBtb250csOpIHVuZSBjcm9pc3NhbmNlIG1veWVubmUgcG9zaXRpdmUgbWFpcyBmYWlibGUsIGF2ZWMgdW5lIGNlcnRhaW5lIHZvbGF0aWxpdMOpIG1lc3Vyw6llIHBhciBs4oCZw6ljYXJ0LXR5cGUgZXQgbGEgdmFyaWFuY2UgbW9iaWxlLiBMZSByZXRyYWl0IGRlIGxhIHRlbmRhbmNlIHZpYSBsYSBzw6lyaWUgwqvigK9kZXRyZW5kZWTigK/CuyBhIHBlcm1pcyBkZSBtaWV1eCB2aXN1YWxpc2VyIGxlcyBmbHVjdHVhdGlvbnMgY3ljbGlxdWVzIGF1dG91ciBkZSBsYSBtb3llbm5lLgoKTGUgUElCIGVuIEZpbmxhbmRlIG1vbnRyZSB1bmUgYXV0b2NvcnLDqWxhdGlvbiBzaWduaWZpY2F0aXZlLCBjb25maXJtw6llIHBhciBs4oCZQUNGLiBMZXMgdGVzdHMgZGUgc3RhdGlvbm5hcml0w6kgKEFERiBldCBLUFNTKSBvbnQgbW9udHLDqSBxdWUgbGEgY3JvaXNzYW5jZSBkdSBQSUIgZXN0IHN0YXRpb25uYWlyZSwgdGFuZGlzIHF1ZSBsYSBkZXR0ZS9QSUIgbsOpY2Vzc2l0ZSB1bmUgcHJlbWnDqHJlIGRpZmbDqXJlbmNlIHBvdXIgZGV2ZW5pciBzdGF0aW9ubmFpcmUuIExlIG1vZMOobGUgYmFzZWxpbmUgbGlhbnQgbGEgY3JvaXNzYW5jZSBkdSBQSUIgw6AgbGEgdmFyaWF0aW9uIHJldGFyZMOpZSBkZSBsYSBkZXR0ZSBzdWdnw6hyZSB1biBlZmZldCBuw6lnYXRpZiBwb3RlbnRpZWwgZGUgbGEgZGV0dGUgc3VyIGxhIGNyb2lzc2FuY2UsIG1haXMgYXZlYyB1biBmYWlibGUgUsKyIGV0IHVuZSBzaWduaWZpY2F0aXZpdMOpIG1vZMOpcsOpZS4gRW4gYWpvdXRhbnQgdW4gY29udHLDtGxlIHN1ciBsYSBjcm9pc3NhbmNlIHBhc3PDqWUgKG1vZMOobGUgQVIoMSkpLCBvbiBvYnNlcnZlIHF1ZSBsYSBjcm9pc3NhbmNlIGR1IFBJQiBwcsOpY8OpZGVudGUgYSB1biBlZmZldCB0csOocyBmb3J0IGV0IHBvc2l0aWYgc3VyIGxhIGNyb2lzc2FuY2UgYWN0dWVsbGUsIHRhbmRpcyBxdWUgbGEgdmFyaWF0aW9uIGRlIGxhIGRldHRlIGEgdW4gZWZmZXQgcG9zaXRpZiBtYWlzIG1vZMOpcsOpLiBMZXMgZGlhZ25vc3RpY3MgKGhvbW9zY8OpZGFzdGljaXTDqSwgbm9ybWFsaXTDqSwgYXV0b2NvcnLDqWxhdGlvbiBkZXMgcsOpc2lkdXMpIGNvbmZpcm1lbnQgbGEgcm9idXN0ZXNzZSBkdSBtb2TDqGxlLgoKTOKAmWluZmxhdGlvbiwgbWVzdXLDqWUgcGFyIGxlIHRhdXggZGUgY3JvaXNzYW5jZSBkdSBDUEksIGEgw6l0w6kgYW5hbHlzw6llIHZpYSBkZXMgbW9kw6hsZXMgQVJJTUEuIExlcyBwcsOpdmlzaW9ucyDDoCBjb3VydCB0ZXJtZSAoY2lucSBhbnMpIG1vbnRyZW50IHVuZSBzdGFiaWxpdMOpIHJlbGF0aXZlIGRlIGzigJlpbmZsYXRpb24gZXQgY29uZmlybWVudCBsYSBzdGF0aW9ubmFyaXTDqSBhcHLDqHMgdHJhbnNmb3JtYXRpb24gZW4gdGF1eCBkZSBjcm9pc3NhbmNlLgoKTGEgcmVsYXRpb24gw6AgbG9uZyB0ZXJtZSBlbnRyZSByZWNldHRlcyBldCBkw6lwZW5zZXMgcHVibGlxdWVzLCBlc3RpbcOpZSBwYXIgbGEgcsOpZ3Jlc3Npb24gbG9nX3JldmVudWUgXH4gbG9nX2V4cGVuZGl0dXJlLCBhIMOpdMOpIGNvbmZpcm3DqWUgcGFyIGxlIHRlc3QgZGUgY29pbnTDqWdyYXRpb24gZOKAmUVuZ2xlICYgR3JhbmdlciBldCBwYXIgbGUgdGVzdCBkZSBKb2hhbnNlbiwgYXZlYyB1biB2ZWN0ZXVyIGRlIGNvaW50w6lncmF0aW9uIHVuaXF1ZS4gTGUgbW9kw6hsZSBFQ00gaW5kaXF1ZSB1bmUgcmVsYXRpb24gcXVhc2kgcHJvcG9ydGlvbm5lbGxlIMOgIGxvbmcgdGVybWUgZW50cmUgcmVjZXR0ZXMgZXQgZMOpcGVuc2VzIChsb25nLXJ1biBiZXRhID0gMS4wMjQpLCB1biBlZmZldCBpbW3DqWRpYXQgcG9zaXRpZiBkZXMgdmFyaWF0aW9ucyBkZXMgZMOpcGVuc2VzIHN1ciBsZXMgcmVjZXR0ZXMgKHNob3J0LXJ1biBhbHBoYSA9IDAuNykgZXQgdW5lIGNvcnJlY3Rpb24gZOKAmWVycmV1ciByYXBpZGUgZGVzIGTDqXPDqXF1aWxpYnJlcyAoRUNNIGdhbW1hID0gLTExLjMyMykuIEVuIGzigJlhYnNlbmNlIGRlIGNvaW50w6lncmF0aW9uLCBsZSBtb2TDqGxlIGVuIGRpZmbDqXJlbmNlcyBzaW1wbGVzIGNvbmZpcm1lIMOpZ2FsZW1lbnQgdW4gZWZmZXQgcG9zaXRpZiBldCBzaWduaWZpY2F0aWYgZGVzIGTDqXBlbnNlcyBzdXIgbGVzIHJlY2V0dGVzLgoKRW4gcsOpc3Vtw6ksIGNldHRlIGFuYWx5c2UgbW9udHJlIHF1ZSBsYSBjcm9pc3NhbmNlIHBhc3PDqWUgZHUgUElCIGpvdWUgdW4gcsO0bGUgZMOpdGVybWluYW50IHN1ciBsYSBjcm9pc3NhbmNlIGFjdHVlbGxlLCBxdWUgbGEgZGV0dGUgcHVibGlxdWUgYSB1biBlZmZldCBtb2TDqXLDqSBzdXIgbGEgY3JvaXNzYW5jZSwgZXQgcXVlIGxlcyByZWNldHRlcyBwdWJsaXF1ZXMgc3VpdmVudCBkZSBwcsOocyBsZXMgdmFyaWF0aW9ucyBkZXMgZMOpcGVuc2VzIGF2ZWMgdW4gYWp1c3RlbWVudCByYXBpZGUgZGVzIGTDqXPDqXF1aWxpYnJlcyDDoCBsb25nIHRlcm1lLgo=