Este documento tem como objetivo contribuir para o entendimento básico de programação em R sobre os seguintes temas:
- Aritmética
- Variáveis
- Vetores
- Fatores
- Matrizes
- Data frames
- Listas
Basicamente, é um resumo do curso Introduction to R do DataCamp (2017). Recomendo que você faça o curso para um entendimento mais detalhado dos temas estudados.
ARITMÉTICA
O R pode ser usado como uma calculadora. Todas operações aritméticas e funções matemáticas principais estão disponíveis. Note que a notação básica de operações algébricas, como a aplicação hierárquica de parênteses, também pode ser utilizada como mostra o código abaixo.
# Adição
5 + 5
# Subtração
5 - 5
# Multiplicação
3 * 5
# Divisão
(5 + 5)/2
# Exponencial
2^5
# Exponencial na base e
exp(1)
# Módulo ou valor absoluto
abs(-10)
# Aplica a notação hierárquica de parênteses. Primeiro o que está em parênteses.
(4 + 5 ) * 7 - (36/18)^3
# Raiz Quadrada
sqrt(9)
# Logaritmo natural ou neperiano
log(10)
# Logaritmo base 10
log(10, base = 10)
# Também logaritmo de base 10
log10(10)
# Seno
sin(0.5*pi)
# Coseno
cos(2*pi)
# Tangente
tan(pi)
VARIÁVEIS
Nem sempre você tem o interesse de usar o R apenas como uma calculadora para executar operações artiméticas. Há situações onde você tem como objetivo criar variáveis para uso posteriormente ou variáveis que recebem valores de alguma tarefa executada pelo R. Assim, temos abaixo algumas opções de como gerar variáveis e atribuir valores para elas.
################################
#### ATRIBUIR UMA VARIÁVEL #####
################################
# Atribuir o valor 42 para x
x <- 42
# Visualizar o valor da variável x
x
# Atribuir valores para duas variáveis: my_apples e my_oranges
my_apples <- 5
my_oranges <- 6
# Definir uma nova variável como a soma das duas variáveis anteriores
my_fruit <- my_apples + my_oranges
# Visualizar o valor da variável my_fruit
my_fruit
VETORES
Um vetor é uma sequência de elementos do mesmo tipo (caracteres, números, lógico, …). Os membros em um vetor são oficialmente chamados de componentes. Nesta seção você entenderá como criar vetores no R, nomeá-los e executar operações matemáticas com eles como mostra os códigos abaixo.
################################
#### CRIANDO VETORES #####
################################
# Definindo tipos de vetores usando os tipos de dados estudados anteriormente
numeric_vector <- c(1, 10, 49)
character_vector <- c("a", "b", "c")
boolean_vector <- c(T,F,T)
# Visualizando os vetores criados
numeric_vector
character_vector
boolean_vector
# Verificando o tipo de cada vetor
class(numeric_vector)
class(character_vector)
class(boolean_vector)
# Vetor de ganhos com Poker de Segunda-feira a Sexta-feira
poker_vector <- c(140, -50, 20, -120, 240)
poker_vector
# Vetor de ganhos na roleta de Segunda-feira a Sexta-feira
roulette_vector <- c(-24, -50, 100, -350, 10)
roulette_vector
################################
#### NOMEANDO VETORES #####
################################
# Criando a variável days_vector com os dias da semana
days_vector <- c("Mon","Tues","Wed","Thur","Fri")
# Atribuindo os nomes dos dias aos vetores usando a variável days_fator
names(poker_vector) <- days_vector
poker_vector
names(roulette_vector) <- days_vector
roulette_vector
################################
#### OPERAÇÕES COM VETORES #####
################################
# Calculando o ganho total por dia nos dois jogos
total_daily <- poker_vector + roulette_vector
total_daily
# Calculando o ganho total na semana por tipo de jogo
total_poker <- sum(poker_vector)
total_roulette <- sum(roulette_vector)
# Calculando o ganho total na semama nos dois jogos
total_week <- sum(roulette_vector) + sum(poker_vector)
total_week
# Verificando se você ganhou mais no poker do que com a roleta
answer <- total_poker > total_roulette
answer
# Criar uma nova variável a partir da seleção de um valor do vetor
poker_wednesday <- poker_vector["Wed"]
poker_wednesday
poker_midweek <- poker_vector[c("Tues","Wed","Thur")]
poker_midweek
# Outra opção de selecionar valores de um vetor e atribuí-los a outra variável
roulette_selection_vector <- roulette_vector[2:5]
roulette_selection_vector
# Calculando o ganho médio no meio da semana a partir da seleção de valores do vetor
average_midweek_gain <- mean(poker_vector[c("Mon","Tues","Wed")])
average_midweek_gain
# Verificando que dia da semana você ganhou no poker
selection_vector <- poker_vector > 0
selection_vector
# Selecionando os valores para os dias que você ganhou no poker
poker_winning_days <- poker_vector[selection_vector]
poker_winning_days
# Outra opção de fazer o mesmo, mas agora para a roleta
roulette_winning_days <- roulette_vector[roulette_vector > 0]
roulette_winning_days
FATORES
Os fatores são uma classe especial de vetores, que definem variáveis categóricas. Nesta seção você entenderá como executar operações com fatores e declará-los como mostra os códigos abaixo.
################################
#### CRIANDO UM VETOR #####
################################
# Criar um vetor de gênero
gender_vector <- c("Male","Female","Female","Male","Male")
# Criar um vetor de animais
animals_vector <- c("Elephant", "Giraffe", "Donkey", "Horse")
# Criar um vetor de temperatura
temperature_vector <- c("High", "Low", "High", "Low", "Medium")
################################
#### DECLARAR UM FATOR #####
################################
# Declarar o vetor de gênero como um fator
factor_gender_vector <- factor(gender_vector)
factor_gender_vector
# Declarar o vetor de animais como um fator
factor_animals_vector <- factor(animals_vector)
factor_animals_vector
# Atribuir levels para o fator e label. O level define a ordem (baixa, média e alta) enquanto o label pode
# ser entendido como um nome para cada level do fator
factor_temperature_vector <- factor(temperature_vector, order = TRUE,
levels = c("Low", "Medium", "High"), labels = c("L","M","H"))
factor_temperature_vector
################################
#### OPERAÇÕES COM FATOR #####
################################
# quantidade de homens e mulheres
table(factor_gender_vector)
# quantidade de animais por tipo
table(factor_animals_vector)
# quantidade de temperaturas por tipo
table(factor_temperature_vector)
################################
#### FATOR ORDENADO #####
################################
# Note que fatores têm um atributo que especifica seu níveis ou categorias (levels), que seguem ordem alfanumérica crescente, por default. Como essa ordem é importante para muitas análises, pode-se alterá-la com o argumento levels, por exemplo para colocar a ordem desejada.
speed_vector <- c('Fast','Slow','Slow','Fast','Ultra-fast')
# Transformar o vetor em um fator e definir a ordem das velocidades
factor_speed_vector <- factor(speed_vector, ordered = T, levels = c('Slow','Fast','Ultra-fast'))
factor_speed_vector
# Quantidade por tipo de velocidade
table(factor_speed_vector)
MATRIZES
Matrizes, são tabelas retangulares de números, expressões matemáticas ou símbolos, cujos elementos são arranjados em \(n\) linhas e \(p\) colunas. A matrix \(M\) abaixo, por exemplo, organiza cada elemento \(a_{ij}\) em 2 linhas e 3 colunas.
\[
M\quad =\left(\begin{matrix}{a}_{11}&{a}_{12}&{a}_{13} \\ {a}_{21}&{a}_{22}&{a}_{23} \end{matrix}\right)
\] Em R, a matriz é uma estrutura de dados homogênea (deve conter mesmo tipo de dados, isto é. numérico, caracteres, lógico) de duas dimensões. Sua sintaxe básica é realizada por meio da função matrix(), tendo como argumentos os elementos que compõem a matriz, na forma de um vetor, e o número de linhas e colunas.
################################
#### CRIANDO MATRIZES #####
################################
# Gerar uma matriz com 3 linhas, preenchida por linha com os números de 1 a 9.
# Por default os elementos são organizados por coluna na matriz, caso se deseje
# que estes sejam organizados por linha usa-se o argumento byrow = TRUE.
M <- matrix(data = 1:9, nrow = 3, ncol = 3, byrow = TRUE)
# Bilheteria Star Wars: em milhões! O primeiro elemento: US e o segundo No-US
new_hope <- c(461, 314.4)
empire_strikes <- c(290.5, 247.9)
return_jedi <- c(309.3,165.8)
# Construir a matriz usando os dados acima
star_wars_matrix <- matrix(c(new_hope, empire_strikes, return_jedi), byrow=T, nrow=3)
star_wars_matrix
################################
#### NOMEAR MATRIZES #####
################################
# Nomeando as linhas e colunas da matriz anterior
rownames(star_wars_matrix) <- c('A New Hope','The Empire Strikes Back','Return of the Jedi')
colnames(star_wars_matrix) <- c('US','non-US')
star_wars_matrix
################################
### OPERAÇÕES COM MATRIZES ####
################################
# Dados de bilheteria da segunda trilogia
box_office_all <- c(474.5, 552.5, 310.7, 338.7, 380.3, 468.5)
movie_names <- c("The Phantom Menace","Attack of the Clones","Revenge of the Sixth")
col_titles <- c("US","non-US")
# Matriz com os dados da segunda trilogia
star_wars_matrix2 <- matrix(box_office_all, nrow=3, byrow=TRUE, dimnames=list(movie_names,col_titles))
star_wars_matrix2
# Combinar as linhas das duas trilogias
all_wars_matrix <- rbind(star_wars_matrix, star_wars_matrix2)
all_wars_matrix
# A bilheteria total para a saga
total_revenue_vector <- colSums(all_wars_matrix)
total_revenue_vector
# Somar para cada linha (ou filme) a bilheteria total (US e non-US)
worldwide_vector <- rowSums(all_wars_matrix)
worldwide_vector
# Calculando a média da segunda coluna
mean_non_us_all <- mean(star_wars_matrix[,2])
mean_non_us_all
# Calculando a média das duas primeiras linhas da segunda coluna
mean_non_us_some <- mean(star_wars_matrix[1:2,2])
mean_non_us_some
ÁLBEGRA MATRICIAL
Para ilustar as operações entre matrizes usaremos as seguintes matrizes para fins de cálculo.
\[
{M}_{1}=\left(\begin{matrix} 2 & 5 \\ 3 & 6 \end{matrix} \right) \quad \quad{M}{2}=\left(\begin{matrix} 5 & 8 \\ 3 & 2 \end{matrix} \right) \\ {M}_{3}=\left(\begin{matrix} 2 & 6 & 0 \\ 4 & 2 & 1 \end{matrix} \right) \quad {M}_{4}=\left(\begin{matrix} 1 & 0.5 & 0.3 \\ 0.5 & 1 & 0.9 \\ 0.3 & 0.9 & 1 \end{matrix} \right)
\]
Dada duas matrizes de mesma dimensionalidade, a matriz resultante da soma/substração destas matrizes corresponde à matriz cujos elementos são a soma/subtração dos elementos das matrizes originais:
\[
\left(\begin{matrix}a&b \\c&d \end{matrix} \right) +\left(\begin{matrix}e&f \\ g & h \end{matrix} \right) =\left(\begin{matrix} a+e & b+f \\ c+g & d+h \end{matrix} \right)
\]
- MULTIPLICAÇÃO POR ESCALAR:
Uma matriz de dimensionalidade qualquer quando multiplicada por um escalar \(k\), tal que \(k \in \mathbb{R}\) que resulta em uma matriz de mesmas dimensões cujos elementos são o produto do escalar \(k\) por cada um dos elementos da matriz original.
\[
k\cdot \left( \begin{matrix} a & b \\ c & d \end{matrix} \right) =\left( \begin{matrix} k\cdot a & k\cdot b \\ k\cdot c & k\cdot d \end{matrix} \right)
\]
A multiplicação entre uma matriz \((n \times m)\) por uma matriz \((m \times p)\), em que \(m,n,p \in \mathbb{N}_{+}\), resulta em uma matriz de dimensões \((n \times p)\), cujos elementos são a somatória do produto entre os elementos em linha da matriz que pré-multiplica pelos elementos em coluna da matriz que pós-multiplica.
Em R, a multiplicação matricial clássica é desenvolvida pelo uso do operador %*%, respeitando a equidade entre o número de colunas da matriz que pré-multiplica e o número de linhas da matriz que pós-multiplica.
- TRANSPOSTA DE UMA MATRIZ:
A transposta de uma matriz \(A_{nxm}\) é uma matriz \(M=A_{mxn}^{T}\), em que os elementos em coluna correspondem aos elementos em linha da matriz original. Em R, a transposta de uma matriz é determinada pela pela função t().
- DETERMINANTE DE UMA MATRIZ:
O determinante de uma matriz é uma função matricial que converte uma matriz quadrada em um escalar. Para uma matriz quadrada de ordem 2, o determinante é definido como:
\[
det\left(\begin{matrix} a & b \\ c & d \end{matrix}\right)=a\cdot d-c\cdot b
\] Para uma matriz de ordem 3 ou superior, o determinante pode ser estimado pela seguinte equação:
\[
det\left(A \right)=\sum_{j=1}^{n}{{\left(-1 \right)}^{i+j}} \cdot {a}_{ij}\cdot det\left({A}_{-i-j} \right)
\] Em que \(A_{−i−j}\) corresponde à matriz A excluindo-se a linha \(i\) e a coluna \(j\). Por esta equação uma matriz de ordem \(n > 2\) tem seu cálculo simplificado à soma de \(n^{2}\) determinantes originados da matriz A. Em R, o determinante de uma matriz é calculado pela função det().
A inversa de uma matriz quadrada qualquer cujo determinante seja não nulo, \(A_{n,n}\), é uma matriz de mesmas dimensões que atenda a seguinte condição:
\[
{A}^{-1}\cdot A=I
\] Onde, \(I\) é a matriz identidade de mesma dimensão que a matriz \(A\). A inversa de uma matriz é estimada pela função solve(), mesma função utilizada para resolução de sistemas de equações em R.
Abaixo, códigos que mostram como executar no R as operações com matrizes citadas anteriormente.
################################
#### CRIANDO MATRIZES #####
################################
M1 <- matrix(c(2, 3, 5, 6), nrow = 2)
M2 <- matrix(c(5, 3, 8, 2), nrow = 2)
M3 <- matrix(c(2, 4, 6, 2, 0,1), nrow = 2, ncol = 3)
M4 <- matrix(c(1, 0.5, 0.3, 0.5, 1, 0.9, 0.3, 0.9, 1), nrow = 3, ncol = 3)
################################
#### SOMA E SUBTRAÇÃO #####
################################
soma <- M2 + M1
subtracao <- M2 - M1
################################
### MULTIPLICAR ESCALAR ####
################################
prod_escalar <- 42*M4
################################
### MULTIPLICAR MATRICIAL ####
################################
prod_matricial <- M1 %*% M3
################################
### TRANSPOSTA MATRIZ ######
################################
transposta <- t(M3)
################################
#### DETERMINANTE MATRIZ #####
################################
determinante <- det(M2)
################################
#### INVERSA MATRIZ #######
################################
inversa <- solve(M1)
DATA FRAMES
Até agora temos utilizado apenas dados de uma mesma classe, armazenados ou em um vetor ou em uma matriz. Mas uma base de dados, em geral, é feita de dados de diversas classes. Por exemplo, podemos querer ter uma coluna com os nomes dos funcionários, outra com o sexo dos funcionários, outra com valores… note que essas colunas são de classes diferentes, como textos e números. Como guardar essas informações?
A solução para isso é o data frame que, talvez, é o formato de dados mais importante do R. No data frame cada coluna representa uma variável e cada linha uma observação. Essa é a estrutura ideal para quando você tem várias variáveis de classes diferentes em um banco de dados.
Abaixo, código em R que mostra como usar a função data.frame() para definir um data frame bem como operações com este formato de armazenar dados no R.
################################
### CRIANDO UM DATA FRAME ####
################################
# stringsAsFactors diz se quero (TRUE) ou não (FALSE) transformar as variáveis com texto em um fator
funcionarios <- data.frame(nome = c("João", "Maria", "José"),
sexo = c("M", "F", "M"),
salario = c(1000, 1200, 1300),
stringsAsFactors = FALSE)
# verificando a classe de cada coluna do data frame
str(funcionarios)
# uma matriz com os mesmos dados obrigatoriamente terá uma única classe (character)
# a função as.matrix obriga que o dado recebido seja transformado em uma matriz
as.matrix(funcionarios)
################################
### OPERAÇÕES COM DATA FRAME ###
################################
# Tudo menos a linha 1
funcionarios[-1, ]
# Apenas a primeira linha da primeira coluna
funcionarios[1, 1]
# Terceira linha das colunas "nome" e "salario"
funcionarios[3 , c("nome", "salario")]
LISTAS
Uma lista em R é similar à uma lista de atividades. Os diferentes itens da lista em sua grande maioria diferem em tamanho, tipo de atividade que deve ser feita, entre outras coisas.
A lista no R nos permite armazenar uma variedade de objetos (matrizes, vetores, data frames ou até mesmo outra lista) e tais objetos podem não estar relacionados uns com os outros. Desta forma, uma lista tem grande utilidade quando queremos armazenar qualquer tipo de dado em um único objeto sem nos preocupar com o tamanho dos objetos envolvidos.
Abaixo, códigos em R que mostram como criar uma lista com diferentes tipos de dados e como fazer operações com uma lista.
################################
### CRIANDO UM LISTA ####
################################
# Vetor com números de 1 a 10
my_vector <- 1:10
my_vector
# Matriz com números de 1 até 9
my_matrix <- matrix(1:9, ncol = 3)
my_matrix
# Primeiras 10 linhas do data frame mtcars
my_df <- mtcars[1:10,]
my_df
# Construindo uma lista com os três diferentes objetos
my_list <- list(my_vector, my_matrix, my_df)
my_list
# Nomear cada elemento da lista
names(my_list) <- c("vetor","matriz","dataframe")
################################
### OPERAÇÕES COM UM LISTA ####
################################
# Selecionar a primeira linha da primeira coluna da matriz que está na lista
my_list$matriz[1,1]
# Selecionar o primeiro valor do vetor
my_list$vetor[1]
# Selecionar 3 primeiras linhas do data frame
my_list$dataframe[1:3,]
REFERÊNCIAS
Fieller, Nick. 2015. Basics of Matrix Algebra for Statistics with R. CRC Press.
LS0tCnRpdGxlOiA8Y2VudGVyPiA8aDI+IDxiPlByb2dyYW1hw6fDo28gZW0gUiAtIEludHJvZHXDp8OjbyA8L2I+IDwvaDI+IDwvY2VudGVyPiAKYXV0aG9yOiA8Y2VudGVyPiBGcmFuayBNYWdhbGjDo2VzIGRlIFBpbmhvIC0gSUJNRUMvTUcgPC9jZW50ZXI+CmhlYWRlci1pbmNsdWRlczoKICAgLSBcdXNlcGFja2FnZXthbXNtYXRofQpncmFwaGljczogeWVzCmxpbmtjb2xvcjogYmx1ZQpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICB0aGVtZTogY2VydWxlYW4KICAgIGZpZ19jYXB0aW9uOiB5ZXMKcmVmZXJlbmNlczoKLSBpZDogZmllbGxlcjIwMTViYXNpY3MKICB0aXRsZTogQmFzaWNzIG9mIG1hdHJpeCBhbGdlYnJhIGZvciBzdGF0aXN0aWNzIHdpdGggUgogIGF1dGhvcjoKICAtIGZhbWlseTogRmllbGxlcgogICAgZ2l2ZW46IE5pY2sKICBwdWJsaXNoZXI6IENSQyBQcmVzcwogIHR5cGU6IGJvb2sKICBpc3N1ZWQ6CiAgICB5ZWFyOiAyMDE1Ci0gaWQ6IGRhdGFjYW1wCiAgdGl0bGU6IEludHJvZHVjdGlvbiB0byBSCiAgYXV0aG9yOiAKICAtIGZhbWlseTogRGF0YUNhbXAKICAgIGdpdmVuOiBJbmMKICBVUkw6IGh0dHBzOi8vd3d3LmRhdGFjYW1wLmNvbS9jb3Vyc2VzL2ZyZWUtaW50cm9kdWN0aW9uLXRvLXIKICBpc3N1ZWQ6CiAgICB5ZWFyOiAyMDE3Cm5vY2l0ZTogfCAKICBAZmllbGxlcjIwMTViYXNpY3MsIEBkYXRhY2FtcAotLS0KCkVzdGUgZG9jdW1lbnRvIHRlbSBjb21vIG9iamV0aXZvIGNvbnRyaWJ1aXIgcGFyYSBvIGVudGVuZGltZW50byBiw6FzaWNvIGRlIHByb2dyYW1hw6fDo28gZW0gW1JdKGh0dHBzOi8vd3d3LnItcHJvamVjdC5vcmcvKSBzb2JyZSBvcyBzZWd1aW50ZXMgdGVtYXM6CgoqIEFyaXRtw6l0aWNhCiogVmFyacOhdmVpcwoqIFZldG9yZXMKKiBGYXRvcmVzCiogTWF0cml6ZXMKKiBEYXRhIGZyYW1lcwoqIExpc3RhcwoKQmFzaWNhbWVudGUsIMOpIHVtIHJlc3VtbyBkbyBjdXJzbyBbSW50cm9kdWN0aW9uIHRvIFJdKGh0dHBzOi8vd3d3LmRhdGFjYW1wLmNvbS9jb3Vyc2VzL2ZyZWUtaW50cm9kdWN0aW9uLXRvLXIpIGRvIEBkYXRhY2FtcC4gUmVjb21lbmRvIHF1ZSB2b2PDqiBmYcOnYSBvIGN1cnNvIHBhcmEgdW0gZW50ZW5kaW1lbnRvIG1haXMgZGV0YWxoYWRvIGRvcyB0ZW1hcyBlc3R1ZGFkb3MuCgojIyMjICoqQVJJVE3DiVRJQ0EqKgoKTyBSIHBvZGUgc2VyIHVzYWRvIGNvbW8gdW1hIGNhbGN1bGFkb3JhLiBUb2RhcyBvcGVyYcOnw7VlcyBhcml0bcOpdGljYXMgZSBmdW7Dp8O1ZXMgbWF0ZW3DoXRpY2FzIHByaW5jaXBhaXMgZXN0w6NvIGRpc3BvbsOtdmVpcy4gTm90ZSBxdWUgYSBub3Rhw6fDo28gYsOhc2ljYSBkZSBvcGVyYcOnw7VlcyBhbGfDqWJyaWNhcywgY29tbyBhIGFwbGljYcOnw6NvIGhpZXLDoXJxdWljYSBkZSBwYXLDqm50ZXNlcywgdGFtYsOpbSBwb2RlIHNlciB1dGlsaXphZGEgY29tbyBtb3N0cmEgbyBjw7NkaWdvIGFiYWl4by4KCmBgYHtyfQojIEFkacOnw6NvCjUgKyA1CgojIFN1YnRyYcOnw6NvCjUgLSA1CgojIE11bHRpcGxpY2HDp8OjbwozICogNQoKIyBEaXZpc8OjbwooNSArIDUpLzIKCiMgRXhwb25lbmNpYWwKMl41CgojIEV4cG9uZW5jaWFsIG5hIGJhc2UgZQpleHAoMSkgICAgICAgCgojIE3Ds2R1bG8gb3UgdmFsb3IgYWJzb2x1dG8KYWJzKC0xMCkKCiMgQXBsaWNhIGEgbm90YcOnw6NvIGhpZXLDoXJxdWljYSBkZSBwYXLDqm50ZXNlcy4gUHJpbWVpcm8gbyBxdWUgZXN0w6EgZW0gcGFyw6pudGVzZXMuCig0ICsgNSApICogNyAtICgzNi8xOCleMwoKIyBSYWl6IFF1YWRyYWRhCnNxcnQoOSkgICAKCiMgTG9nYXJpdG1vIG5hdHVyYWwgb3UgbmVwZXJpYW5vCmxvZygxMCkgICAKCiMgTG9nYXJpdG1vIGJhc2UgMTAKbG9nKDEwLCBiYXNlID0gMTApIAoKIyBUYW1iw6ltIGxvZ2FyaXRtbyBkZSBiYXNlIDEwCmxvZzEwKDEwKSAgIAoKIyBTZW5vCnNpbigwLjUqcGkpICAgIAoKIyBDb3Nlbm8KY29zKDIqcGkpICAgICAgCgojIFRhbmdlbnRlCnRhbihwaSkgICAgICAKYGBgCgojIyMjICoqVkFSScOBVkVJUyoqCgpOZW0gc2VtcHJlIHZvY8OqIHRlbSBvIGludGVyZXNzZSBkZSB1c2FyIG8gUiBhcGVuYXMgY29tbyB1bWEgY2FsY3VsYWRvcmEgcGFyYSBleGVjdXRhciBvcGVyYcOnw7VlcyBhcnRpbcOpdGljYXMuIEjDoSBzaXR1YcOnw7VlcyBvbmRlIHZvY8OqIHRlbSBjb21vIG9iamV0aXZvIGNyaWFyIHZhcmnDoXZlaXMgcGFyYSB1c28gcG9zdGVyaW9ybWVudGUgb3UgdmFyacOhdmVpcyBxdWUgcmVjZWJlbSB2YWxvcmVzIGRlIGFsZ3VtYSB0YXJlZmEgZXhlY3V0YWRhIHBlbG8gUi4gQXNzaW0sIHRlbW9zIGFiYWl4byBhbGd1bWFzIG9ww6fDtWVzIGRlIGNvbW8gZ2VyYXIgdmFyacOhdmVpcyBlIGF0cmlidWlyIHZhbG9yZXMgcGFyYSBlbGFzLgoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgQVRSSUJVSVIgVU1BIFZBUknDgVZFTCAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBBdHJpYnVpciBvIHZhbG9yIDQyIHBhcmEgeAp4IDwtIDQyCgojIFZpc3VhbGl6YXIgbyB2YWxvciBkYSB2YXJpw6F2ZWwgeCAKeAoKIyBBdHJpYnVpciB2YWxvcmVzIHBhcmEgZHVhcyB2YXJpw6F2ZWlzOiBteV9hcHBsZXMgZSBteV9vcmFuZ2VzCm15X2FwcGxlcyA8LSA1Cm15X29yYW5nZXMgPC0gNgoKIyBEZWZpbmlyIHVtYSBub3ZhIHZhcmnDoXZlbCBjb21vIGEgc29tYSBkYXMgZHVhcyB2YXJpw6F2ZWlzIGFudGVyaW9yZXMKbXlfZnJ1aXQgPC0gbXlfYXBwbGVzICsgbXlfb3JhbmdlcwoKIyBWaXN1YWxpemFyIG8gdmFsb3IgZGEgdmFyacOhdmVsIG15X2ZydWl0Cm15X2ZydWl0CmBgYAoKIyMjIyAqKlZFVE9SRVMqKgoKVW0gdmV0b3Igw6kgdW1hIHNlcXXDqm5jaWEgZGUgZWxlbWVudG9zIGRvIG1lc21vIHRpcG8gKGNhcmFjdGVyZXMsIG7Dum1lcm9zLCBsw7NnaWNvLCAuLi4pLiBPcyBtZW1icm9zIGVtIHVtIHZldG9yIHPDo28gb2ZpY2lhbG1lbnRlIGNoYW1hZG9zIGRlIGNvbXBvbmVudGVzLiBOZXN0YSBzZcOnw6NvIHZvY8OqIGVudGVuZGVyw6EgY29tbyBjcmlhciB2ZXRvcmVzIG5vIFIsIG5vbWXDoS1sb3MgZSBleGVjdXRhciBvcGVyYcOnw7VlcyBtYXRlbcOhdGljYXMgY29tIGVsZXMgY29tbyBtb3N0cmEgb3MgY8OzZGlnb3MgYWJhaXhvLgoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgQ1JJQU5ETyBWRVRPUkVTICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIERlZmluaW5kbyB0aXBvcyBkZSB2ZXRvcmVzIHVzYW5kbyBvcyB0aXBvcyBkZSBkYWRvcyBlc3R1ZGFkb3MgYW50ZXJpb3JtZW50ZQpudW1lcmljX3ZlY3RvciA8LSBjKDEsIDEwLCA0OSkKY2hhcmFjdGVyX3ZlY3RvciA8LSBjKCJhIiwgImIiLCAiYyIpCmJvb2xlYW5fdmVjdG9yIDwtIGMoVCxGLFQpCgojIFZpc3VhbGl6YW5kbyBvcyB2ZXRvcmVzIGNyaWFkb3MKbnVtZXJpY192ZWN0b3IKY2hhcmFjdGVyX3ZlY3Rvcgpib29sZWFuX3ZlY3RvcgoKIyBWZXJpZmljYW5kbyBvIHRpcG8gZGUgY2FkYSB2ZXRvcgpjbGFzcyhudW1lcmljX3ZlY3RvcikKY2xhc3MoY2hhcmFjdGVyX3ZlY3RvcikKY2xhc3MoYm9vbGVhbl92ZWN0b3IpCgojIFZldG9yIGRlIGdhbmhvcyBjb20gUG9rZXIgZGUgU2VndW5kYS1mZWlyYSBhIFNleHRhLWZlaXJhCnBva2VyX3ZlY3RvciA8LSBjKDE0MCwgLTUwLCAyMCwgLTEyMCwgMjQwKQpwb2tlcl92ZWN0b3IKCiMgVmV0b3IgZGUgZ2FuaG9zIG5hIHJvbGV0YSBkZSBTZWd1bmRhLWZlaXJhIGEgU2V4dGEtZmVpcmEKcm91bGV0dGVfdmVjdG9yIDwtIGMoLTI0LCAtNTAsIDEwMCwgLTM1MCwgMTApCnJvdWxldHRlX3ZlY3RvcgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyAgIE5PTUVBTkRPIFZFVE9SRVMgICAgIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgQ3JpYW5kbyBhIHZhcmnDoXZlbCBkYXlzX3ZlY3RvciBjb20gb3MgZGlhcyBkYSBzZW1hbmEKZGF5c192ZWN0b3IgPC0gYygiTW9uIiwiVHVlcyIsIldlZCIsIlRodXIiLCJGcmkiKQoKIyBBdHJpYnVpbmRvIG9zIG5vbWVzIGRvcyBkaWFzIGFvcyB2ZXRvcmVzIHVzYW5kbyBhIHZhcmnDoXZlbCBkYXlzX2ZhdG9yCm5hbWVzKHBva2VyX3ZlY3RvcikgPC0gZGF5c192ZWN0b3IKcG9rZXJfdmVjdG9yCgpuYW1lcyhyb3VsZXR0ZV92ZWN0b3IpIDwtIGRheXNfdmVjdG9yCnJvdWxldHRlX3ZlY3RvcgoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyBPUEVSQcOHw5VFUyBDT00gVkVUT1JFUyAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBDYWxjdWxhbmRvIG8gZ2FuaG8gdG90YWwgcG9yIGRpYSBub3MgZG9pcyBqb2dvcwp0b3RhbF9kYWlseSA8LSBwb2tlcl92ZWN0b3IgKyByb3VsZXR0ZV92ZWN0b3IKdG90YWxfZGFpbHkKCiMgQ2FsY3VsYW5kbyBvIGdhbmhvIHRvdGFsIG5hIHNlbWFuYSBwb3IgdGlwbyBkZSBqb2dvCnRvdGFsX3Bva2VyIDwtIHN1bShwb2tlcl92ZWN0b3IpCnRvdGFsX3JvdWxldHRlIDwtIHN1bShyb3VsZXR0ZV92ZWN0b3IpCgojIENhbGN1bGFuZG8gbyBnYW5obyB0b3RhbCBuYSBzZW1hbWEgbm9zIGRvaXMgam9nb3MKdG90YWxfd2VlayA8LSBzdW0ocm91bGV0dGVfdmVjdG9yKSArIHN1bShwb2tlcl92ZWN0b3IpCnRvdGFsX3dlZWsKCiMgVmVyaWZpY2FuZG8gc2Ugdm9jw6ogZ2FuaG91IG1haXMgbm8gcG9rZXIgZG8gcXVlIGNvbSBhIHJvbGV0YQphbnN3ZXIgPC0gdG90YWxfcG9rZXIgPiB0b3RhbF9yb3VsZXR0ZQphbnN3ZXIKCiMgQ3JpYXIgdW1hIG5vdmEgdmFyacOhdmVsIGEgcGFydGlyIGRhIHNlbGXDp8OjbyBkZSB1bSB2YWxvciBkbyB2ZXRvcgpwb2tlcl93ZWRuZXNkYXkgPC0gcG9rZXJfdmVjdG9yWyJXZWQiXQpwb2tlcl93ZWRuZXNkYXkKCnBva2VyX21pZHdlZWsgPC0gcG9rZXJfdmVjdG9yW2MoIlR1ZXMiLCJXZWQiLCJUaHVyIildICAgICAgIApwb2tlcl9taWR3ZWVrIAoKIyBPdXRyYSBvcMOnw6NvIGRlIHNlbGVjaW9uYXIgdmFsb3JlcyBkZSB1bSB2ZXRvciBlIGF0cmlidcOtLWxvcyBhIG91dHJhIHZhcmnDoXZlbApyb3VsZXR0ZV9zZWxlY3Rpb25fdmVjdG9yIDwtIHJvdWxldHRlX3ZlY3RvclsyOjVdCnJvdWxldHRlX3NlbGVjdGlvbl92ZWN0b3IgCgojIENhbGN1bGFuZG8gbyBnYW5obyBtw6lkaW8gbm8gbWVpbyBkYSBzZW1hbmEgYSBwYXJ0aXIgZGEgc2VsZcOnw6NvIGRlIHZhbG9yZXMgZG8gdmV0b3IKYXZlcmFnZV9taWR3ZWVrX2dhaW4gPC0gbWVhbihwb2tlcl92ZWN0b3JbYygiTW9uIiwiVHVlcyIsIldlZCIpXSkKYXZlcmFnZV9taWR3ZWVrX2dhaW4KCiMgVmVyaWZpY2FuZG8gcXVlIGRpYSBkYSBzZW1hbmEgdm9jw6ogZ2FuaG91IG5vIHBva2VyCnNlbGVjdGlvbl92ZWN0b3IgPC0gcG9rZXJfdmVjdG9yID4gMApzZWxlY3Rpb25fdmVjdG9yCgojIFNlbGVjaW9uYW5kbyBvcyB2YWxvcmVzIHBhcmEgb3MgZGlhcyBxdWUgdm9jw6ogZ2FuaG91IG5vIHBva2VyCnBva2VyX3dpbm5pbmdfZGF5cyA8LSBwb2tlcl92ZWN0b3Jbc2VsZWN0aW9uX3ZlY3Rvcl0KcG9rZXJfd2lubmluZ19kYXlzCgojIE91dHJhIG9ww6fDo28gZGUgZmF6ZXIgbyBtZXNtbywgbWFzIGFnb3JhIHBhcmEgYSByb2xldGEKcm91bGV0dGVfd2lubmluZ19kYXlzIDwtIHJvdWxldHRlX3ZlY3Rvcltyb3VsZXR0ZV92ZWN0b3IgPiAwXQpyb3VsZXR0ZV93aW5uaW5nX2RheXMKYGBgCgojIyMjICoqRkFUT1JFUyoqCgpPcyBmYXRvcmVzIHPDo28gdW1hIGNsYXNzZSBlc3BlY2lhbCBkZSB2ZXRvcmVzLCBxdWUgZGVmaW5lbSB2YXJpw6F2ZWlzIGNhdGVnw7NyaWNhcy4gTmVzdGEgc2XDp8OjbyB2b2PDqiBlbnRlbmRlcsOhIGNvbW8gZXhlY3V0YXIgb3BlcmHDp8O1ZXMgY29tIGZhdG9yZXMgZSBkZWNsYXLDoS1sb3MgY29tbyBtb3N0cmEgb3MgY8OzZGlnb3MgYWJhaXhvLgoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICBDUklBTkRPIFVNIFZFVE9SICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIENyaWFyIHVtIHZldG9yIGRlIGfDqm5lcm8KZ2VuZGVyX3ZlY3RvciA8LSBjKCJNYWxlIiwiRmVtYWxlIiwiRmVtYWxlIiwiTWFsZSIsIk1hbGUiKQoKIyBDcmlhciB1bSB2ZXRvciBkZSBhbmltYWlzCmFuaW1hbHNfdmVjdG9yIDwtIGMoIkVsZXBoYW50IiwgIkdpcmFmZmUiLCAiRG9ua2V5IiwgIkhvcnNlIikKCiMgQ3JpYXIgdW0gdmV0b3IgZGUgdGVtcGVyYXR1cmEgCnRlbXBlcmF0dXJlX3ZlY3RvciA8LSBjKCJIaWdoIiwgIkxvdyIsICJIaWdoIiwgIkxvdyIsICJNZWRpdW0iKQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyAgIERFQ0xBUkFSIFVNIEZBVE9SICAgIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgRGVjbGFyYXIgbyB2ZXRvciBkZSBnw6puZXJvIGNvbW8gdW0gZmF0b3IKZmFjdG9yX2dlbmRlcl92ZWN0b3IgPC0gZmFjdG9yKGdlbmRlcl92ZWN0b3IpCmZhY3Rvcl9nZW5kZXJfdmVjdG9yCgojIERlY2xhcmFyIG8gdmV0b3IgZGUgYW5pbWFpcyBjb21vIHVtIGZhdG9yCmZhY3Rvcl9hbmltYWxzX3ZlY3RvciA8LSBmYWN0b3IoYW5pbWFsc192ZWN0b3IpCmZhY3Rvcl9hbmltYWxzX3ZlY3RvcgoKIyBBdHJpYnVpciBsZXZlbHMgcGFyYSBvIGZhdG9yIGUgbGFiZWwuIE8gbGV2ZWwgZGVmaW5lIGEgb3JkZW0gKGJhaXhhLCBtw6lkaWEgZSBhbHRhKSBlbnF1YW50byBvIGxhYmVsIHBvZGUgCiMgc2VyIGVudGVuZGlkbyBjb21vIHVtIG5vbWUgcGFyYSBjYWRhIGxldmVsIGRvIGZhdG9yCmZhY3Rvcl90ZW1wZXJhdHVyZV92ZWN0b3IgPC0gZmFjdG9yKHRlbXBlcmF0dXJlX3ZlY3Rvciwgb3JkZXIgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJMb3ciLCAiTWVkaXVtIiwgIkhpZ2giKSwgbGFiZWxzID0gYygiTCIsIk0iLCJIIikpCmZhY3Rvcl90ZW1wZXJhdHVyZV92ZWN0b3IKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgIE9QRVJBw4fDlUVTIENPTSBGQVRPUiAgIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgcXVhbnRpZGFkZSBkZSBob21lbnMgZSBtdWxoZXJlcwp0YWJsZShmYWN0b3JfZ2VuZGVyX3ZlY3RvcikKCiMgcXVhbnRpZGFkZSBkZSBhbmltYWlzIHBvciB0aXBvCnRhYmxlKGZhY3Rvcl9hbmltYWxzX3ZlY3RvcikKCiMgcXVhbnRpZGFkZSBkZSB0ZW1wZXJhdHVyYXMgcG9yIHRpcG8KdGFibGUoZmFjdG9yX3RlbXBlcmF0dXJlX3ZlY3RvcikKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgIEZBVE9SIE9SREVOQURPICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIE5vdGUgcXVlIGZhdG9yZXMgdMOqbSB1bSBhdHJpYnV0byBxdWUgZXNwZWNpZmljYSBzZXUgbsOtdmVpcyBvdSBjYXRlZ29yaWFzIChsZXZlbHMpLCBxdWUgc2VndWVtIG9yZGVtIGFsZmFudW3DqXJpY2EgY3Jlc2NlbnRlLCBwb3IgZGVmYXVsdC4gQ29tbyBlc3NhIG9yZGVtIMOpIGltcG9ydGFudGUgcGFyYSBtdWl0YXMgYW7DoWxpc2VzLCBwb2RlLXNlIGFsdGVyw6EtbGEgY29tIG8gYXJndW1lbnRvIGxldmVscywgcG9yIGV4ZW1wbG8gcGFyYSBjb2xvY2FyIGEgb3JkZW0gZGVzZWphZGEuCgpzcGVlZF92ZWN0b3IgPC0gYygnRmFzdCcsJ1Nsb3cnLCdTbG93JywnRmFzdCcsJ1VsdHJhLWZhc3QnKQoKIyBUcmFuc2Zvcm1hciBvIHZldG9yIGVtIHVtIGZhdG9yIGUgZGVmaW5pciBhIG9yZGVtIGRhcyB2ZWxvY2lkYWRlcwpmYWN0b3Jfc3BlZWRfdmVjdG9yIDwtIGZhY3RvcihzcGVlZF92ZWN0b3IsIG9yZGVyZWQgPSBULCBsZXZlbHMgPSBjKCdTbG93JywnRmFzdCcsJ1VsdHJhLWZhc3QnKSkKZmFjdG9yX3NwZWVkX3ZlY3RvcgoKIyBRdWFudGlkYWRlIHBvciB0aXBvIGRlIHZlbG9jaWRhZGUKdGFibGUoZmFjdG9yX3NwZWVkX3ZlY3RvcikKCmBgYAoKIyMjIyAqKk1BVFJJWkVTKioKCk1hdHJpemVzLCBzw6NvIHRhYmVsYXMgcmV0YW5ndWxhcmVzIGRlIG7Dum1lcm9zLCBleHByZXNzw7VlcyBtYXRlbcOhdGljYXMgb3Ugc8OtbWJvbG9zLCBjdWpvcyBlbGVtZW50b3Mgc8OjbyBhcnJhbmphZG9zIGVtICRuJCBsaW5oYXMgZSAkcCQgY29sdW5hcy4gQSBtYXRyaXggJE0kIGFiYWl4bywgcG9yIGV4ZW1wbG8sIG9yZ2FuaXphIGNhZGEgZWxlbWVudG8gJGFfe2lqfSQgZW0gMiBsaW5oYXMgZSAzIGNvbHVuYXMuCgokJApNXHF1YWQgPVxsZWZ0KFxiZWdpbnttYXRyaXh9e2F9X3sxMX0me2F9X3sxMn0me2F9X3sxM30gXFwge2F9X3syMX0me2F9X3syMn0me2F9X3syM30gXGVuZHttYXRyaXh9XHJpZ2h0KQokJApFbSBSLCBhIG1hdHJpeiDDqSB1bWEgZXN0cnV0dXJhIGRlIGRhZG9zIGhvbW9nw6puZWEgKGRldmUgY29udGVyIG1lc21vIHRpcG8gZGUgZGFkb3MsIGlzdG8gw6kuIG51bcOpcmljbywgY2FyYWN0ZXJlcywgbMOzZ2ljbykgZGUgZHVhcyBkaW1lbnPDtWVzLiBTdWEgc2ludGF4ZSBiw6FzaWNhIMOpIHJlYWxpemFkYSBwb3IgbWVpbyBkYSBmdW7Dp8OjbyBgbWF0cml4KClgLCB0ZW5kbyBjb21vIGFyZ3VtZW50b3Mgb3MgZWxlbWVudG9zIHF1ZSBjb21ww7VlbSBhIG1hdHJpeiwgbmEgZm9ybWEgZGUgdW0gdmV0b3IsIGUgbyBuw7ptZXJvIGRlIGxpbmhhcyBlIGNvbHVuYXMuCgpgYGB7ciB3YXJuaW5nPXRydWV9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICBDUklBTkRPIE1BVFJJWkVTICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIEdlcmFyIHVtYSBtYXRyaXogY29tIDMgbGluaGFzLCBwcmVlbmNoaWRhIHBvciBsaW5oYSBjb20gb3MgbsO6bWVyb3MgZGUgMSBhIDkuIAojIFBvciBkZWZhdWx0IG9zIGVsZW1lbnRvcyBzw6NvIG9yZ2FuaXphZG9zIHBvciBjb2x1bmEgbmEgbWF0cml6LCBjYXNvIHNlIGRlc2VqZQojIHF1ZSBlc3RlcyBzZWphbSBvcmdhbml6YWRvcyBwb3IgbGluaGEgdXNhLXNlIG8gYXJndW1lbnRvIGJ5cm93ID0gVFJVRS4KTSA8LSBtYXRyaXgoZGF0YSA9IDE6OSwgbnJvdyA9IDMsIG5jb2wgPSAzLCBieXJvdyA9IFRSVUUpCgoKIyBCaWxoZXRlcmlhIFN0YXIgV2FyczogZW0gbWlsaMO1ZXMhIE8gcHJpbWVpcm8gZWxlbWVudG86IFVTIGUgbyBzZWd1bmRvIE5vLVVTCm5ld19ob3BlIDwtIGMoNDYxLCAzMTQuNCkKZW1waXJlX3N0cmlrZXMgPC0gYygyOTAuNSwgMjQ3LjkpCnJldHVybl9qZWRpIDwtIGMoMzA5LjMsMTY1LjgpCgojIENvbnN0cnVpciBhIG1hdHJpeiB1c2FuZG8gb3MgZGFkb3MgYWNpbWEKc3Rhcl93YXJzX21hdHJpeCA8LSBtYXRyaXgoYyhuZXdfaG9wZSwgZW1waXJlX3N0cmlrZXMsIHJldHVybl9qZWRpKSwgYnlyb3c9VCwgbnJvdz0zKQpzdGFyX3dhcnNfbWF0cml4CgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjICAgTk9NRUFSIE1BVFJJWkVTICAgICAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyBOb21lYW5kbyBhcyBsaW5oYXMgZSBjb2x1bmFzIGRhIG1hdHJpeiBhbnRlcmlvcgpyb3duYW1lcyhzdGFyX3dhcnNfbWF0cml4KSA8LSBjKCdBIE5ldyBIb3BlJywnVGhlIEVtcGlyZSBTdHJpa2VzIEJhY2snLCdSZXR1cm4gb2YgdGhlIEplZGknKQpjb2xuYW1lcyhzdGFyX3dhcnNfbWF0cml4KSA8LSBjKCdVUycsJ25vbi1VUycpCnN0YXJfd2Fyc19tYXRyaXgKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyBPUEVSQcOHw5VFUyBDT00gTUFUUklaRVMgICMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgRGFkb3MgZGUgYmlsaGV0ZXJpYSBkYSBzZWd1bmRhIHRyaWxvZ2lhIApib3hfb2ZmaWNlX2FsbCA8LSBjKDQ3NC41LCA1NTIuNSwgMzEwLjcsIDMzOC43LCAzODAuMywgNDY4LjUpCm1vdmllX25hbWVzIDwtIGMoIlRoZSBQaGFudG9tIE1lbmFjZSIsIkF0dGFjayBvZiB0aGUgQ2xvbmVzIiwiUmV2ZW5nZSBvZiB0aGUgU2l4dGgiKQpjb2xfdGl0bGVzIDwtIGMoIlVTIiwibm9uLVVTIikKCiMgTWF0cml6IGNvbSBvcyBkYWRvcyBkYSBzZWd1bmRhIHRyaWxvZ2lhCnN0YXJfd2Fyc19tYXRyaXgyIDwtIG1hdHJpeChib3hfb2ZmaWNlX2FsbCwgbnJvdz0zLCBieXJvdz1UUlVFLCBkaW1uYW1lcz1saXN0KG1vdmllX25hbWVzLGNvbF90aXRsZXMpKQpzdGFyX3dhcnNfbWF0cml4MgoKIyBDb21iaW5hciBhcyBsaW5oYXMgZGFzIGR1YXMgdHJpbG9naWFzCmFsbF93YXJzX21hdHJpeCA8LSByYmluZChzdGFyX3dhcnNfbWF0cml4LCBzdGFyX3dhcnNfbWF0cml4MikKYWxsX3dhcnNfbWF0cml4CgojIEEgYmlsaGV0ZXJpYSB0b3RhbCBwYXJhIGEgc2FnYSAKdG90YWxfcmV2ZW51ZV92ZWN0b3IgPC0gY29sU3VtcyhhbGxfd2Fyc19tYXRyaXgpCnRvdGFsX3JldmVudWVfdmVjdG9yCgojIFNvbWFyIHBhcmEgY2FkYSBsaW5oYSAob3UgZmlsbWUpIGEgYmlsaGV0ZXJpYSB0b3RhbCAoVVMgZSBub24tVVMpCndvcmxkd2lkZV92ZWN0b3IgPC0gcm93U3VtcyhhbGxfd2Fyc19tYXRyaXgpCndvcmxkd2lkZV92ZWN0b3IKCiMgQ2FsY3VsYW5kbyBhIG3DqWRpYSBkYSBzZWd1bmRhIGNvbHVuYQptZWFuX25vbl91c19hbGwgIDwtICBtZWFuKHN0YXJfd2Fyc19tYXRyaXhbLDJdKQptZWFuX25vbl91c19hbGwKCiMgQ2FsY3VsYW5kbyBhIG3DqWRpYSBkYXMgZHVhcyBwcmltZWlyYXMgbGluaGFzIGRhIHNlZ3VuZGEgY29sdW5hCm1lYW5fbm9uX3VzX3NvbWUgPC0gbWVhbihzdGFyX3dhcnNfbWF0cml4WzE6MiwyXSkKbWVhbl9ub25fdXNfc29tZQpgYGAKCiMjIyMjICoqw4FMQkVHUkEgTUFUUklDSUFMKioKClBhcmEgaWx1c3RhciBhcyBvcGVyYcOnw7VlcyBlbnRyZSBtYXRyaXplcyB1c2FyZW1vcyBhcyBzZWd1aW50ZXMgbWF0cml6ZXMgcGFyYSBmaW5zIGRlIGPDoWxjdWxvLgoKJCQKe019X3sxfT1cbGVmdChcYmVnaW57bWF0cml4fSAyICYgNSBcXCAzICYgNiBcZW5ke21hdHJpeH0gXHJpZ2h0KSBccXVhZCBccXVhZHtNfXsyfT1cbGVmdChcYmVnaW57bWF0cml4fSA1ICYgOCBcXCAzICYgMiBcZW5ke21hdHJpeH0gXHJpZ2h0KSBcXCB7TX1fezN9PVxsZWZ0KFxiZWdpbnttYXRyaXh9IDIgJiA2ICYgMCBcXCA0ICYgMiAmIDEgXGVuZHttYXRyaXh9IFxyaWdodCkgXHF1YWQge019X3s0fT1cbGVmdChcYmVnaW57bWF0cml4fSAxICYgMC41ICYgMC4zIFxcIDAuNSAmIDEgJiAwLjkgXFwgMC4zICYgMC45ICYgMSBcZW5ke21hdHJpeH0gXHJpZ2h0KSAgCiQkCgoqICoqU09NQSBFIFNVQlRSQcOHw4NPOioqCgpEYWRhIGR1YXMgbWF0cml6ZXMgZGUgbWVzbWEgZGltZW5zaW9uYWxpZGFkZSwgYSBtYXRyaXogcmVzdWx0YW50ZSBkYSBzb21hL3N1YnN0cmHDp8OjbyBkZXN0YXMgbWF0cml6ZXMgY29ycmVzcG9uZGUgw6AgbWF0cml6IGN1am9zIGVsZW1lbnRvcyBzw6NvIGEgc29tYS9zdWJ0cmHDp8OjbyBkb3MgZWxlbWVudG9zIGRhcyBtYXRyaXplcyBvcmlnaW5haXM6CgokJApcbGVmdChcYmVnaW57bWF0cml4fWEmYiBcXGMmZCBcZW5ke21hdHJpeH0gXHJpZ2h0KSArXGxlZnQoXGJlZ2lue21hdHJpeH1lJmYgXFwgZyAmIGggXGVuZHttYXRyaXh9IFxyaWdodCkgPVxsZWZ0KFxiZWdpbnttYXRyaXh9IGErZSAmIGIrZiBcXCBjK2cgJiBkK2ggXGVuZHttYXRyaXh9IFxyaWdodCkKJCQKCiogKipNVUxUSVBMSUNBw4fDg08gUE9SIEVTQ0FMQVI6KioKClVtYSBtYXRyaXogZGUgZGltZW5zaW9uYWxpZGFkZSBxdWFscXVlciBxdWFuZG8gbXVsdGlwbGljYWRhIHBvciB1bSBlc2NhbGFyICRrJCwgdGFsIHF1ZSAkayBcaW4gXG1hdGhiYntSfSQgcXVlIHJlc3VsdGEgZW0gdW1hIG1hdHJpeiBkZSBtZXNtYXMgZGltZW5zw7VlcyBjdWpvcyBlbGVtZW50b3Mgc8OjbyBvIHByb2R1dG8gZG8gZXNjYWxhciAkayQgcG9yIGNhZGEgdW0gZG9zIGVsZW1lbnRvcyBkYSBtYXRyaXogb3JpZ2luYWwuCgokJAprXGNkb3QgXGxlZnQoIFxiZWdpbnttYXRyaXh9IGEgJiBiIFxcIGMgJiBkIFxlbmR7bWF0cml4fSBccmlnaHQpID1cbGVmdCggXGJlZ2lue21hdHJpeH0ga1xjZG90IGEgJiBrXGNkb3QgYiBcXCBrXGNkb3QgYyAmIGtcY2RvdCBkIFxlbmR7bWF0cml4fSBccmlnaHQpCiQkCgoqICoqTVVMVElQTElDQcOHw4NPIE1BVFJJQ0lBTDoqKgoKQSBtdWx0aXBsaWNhw6fDo28gZW50cmUgdW1hIG1hdHJpeiAkKG4gXHRpbWVzIG0pJCBwb3IgdW1hIG1hdHJpeiAkKG0gXHRpbWVzIHApJCwgZW0gcXVlICRtLG4scCBcaW4gXG1hdGhiYntOfV97K30kLCByZXN1bHRhIGVtIHVtYSBtYXRyaXogZGUgZGltZW5zw7VlcyAkKG4gXHRpbWVzIHApJCwgY3Vqb3MgZWxlbWVudG9zIHPDo28gYSBzb21hdMOzcmlhIGRvIHByb2R1dG8gZW50cmUgb3MgZWxlbWVudG9zIGVtIGxpbmhhIGRhIG1hdHJpeiBxdWUgcHLDqS1tdWx0aXBsaWNhIHBlbG9zIGVsZW1lbnRvcyBlbSBjb2x1bmEgZGEgbWF0cml6IHF1ZSBww7NzLW11bHRpcGxpY2EuCgpFbSBSLCBhIG11bHRpcGxpY2HDp8OjbyBtYXRyaWNpYWwgY2zDoXNzaWNhIMOpIGRlc2Vudm9sdmlkYSBwZWxvIHVzbyBkbyBvcGVyYWRvciBgJSolYCwgcmVzcGVpdGFuZG8gYSBlcXVpZGFkZSBlbnRyZSBvIG7Dum1lcm8gZGUgY29sdW5hcyBkYSBtYXRyaXogcXVlIHByw6ktbXVsdGlwbGljYSBlIG8gbsO6bWVybyBkZSBsaW5oYXMgZGEgbWF0cml6IHF1ZSBww7NzLW11bHRpcGxpY2EuCgoqICoqVFJBTlNQT1NUQSBERSBVTUEgTUFUUklaOioqCgpBIHRyYW5zcG9zdGEgZGUgdW1hIG1hdHJpeiAkQV97bnhtfSQgw6kgdW1hIG1hdHJpeiAkTT1BX3tteG59XntUfSQsIGVtIHF1ZSBvcyBlbGVtZW50b3MgZW0gY29sdW5hIGNvcnJlc3BvbmRlbSBhb3MgZWxlbWVudG9zIGVtIGxpbmhhIGRhIG1hdHJpeiBvcmlnaW5hbC4gRW0gUiwgYSB0cmFuc3Bvc3RhIGRlIHVtYSBtYXRyaXogw6kgZGV0ZXJtaW5hZGEgcGVsYSBwZWxhIGZ1bsOnw6NvIGB0KClgLgoKKiAqKkRFVEVSTUlOQU5URSBERSBVTUEgTUFUUklaOioqCgpPIGRldGVybWluYW50ZSBkZSB1bWEgbWF0cml6IMOpIHVtYSBmdW7Dp8OjbyBtYXRyaWNpYWwgcXVlIGNvbnZlcnRlIHVtYSBtYXRyaXogcXVhZHJhZGEgZW0gdW0gZXNjYWxhci4gUGFyYSB1bWEgbWF0cml6IHF1YWRyYWRhIGRlIG9yZGVtIDIsIG8gZGV0ZXJtaW5hbnRlIMOpIGRlZmluaWRvIGNvbW86CgokJApkZXRcbGVmdChcYmVnaW57bWF0cml4fSBhICYgYiBcXCBjICYgZCBcZW5ke21hdHJpeH1ccmlnaHQpPWFcY2RvdCBkLWNcY2RvdCBiCiQkClBhcmEgdW1hIG1hdHJpeiBkZSBvcmRlbSAzIG91IHN1cGVyaW9yLCBvIGRldGVybWluYW50ZSBwb2RlIHNlciBlc3RpbWFkbyBwZWxhIHNlZ3VpbnRlIGVxdWHDp8OjbzoKCiQkCmRldFxsZWZ0KEEgXHJpZ2h0KT1cc3VtX3tqPTF9XntufXt7XGxlZnQoLTEgXHJpZ2h0KX1ee2kran19IFxjZG90IHthfV97aWp9XGNkb3QgZGV0XGxlZnQoe0F9X3staS1qfSBccmlnaHQpIAokJApFbSBxdWUgJEFfe+KIkmniiJJqfSQgY29ycmVzcG9uZGUgw6AgbWF0cml6IEEgZXhjbHVpbmRvLXNlIGEgbGluaGEgJGkkIGUgYSBjb2x1bmEgJGokLiBQb3IgZXN0YSBlcXVhw6fDo28gdW1hIG1hdHJpeiBkZSBvcmRlbSAkbiA+IDIkIHRlbSBzZXUgY8OhbGN1bG8gc2ltcGxpZmljYWRvIMOgIHNvbWEgZGUgJG5eezJ9JCBkZXRlcm1pbmFudGVzIG9yaWdpbmFkb3MgZGEgbWF0cml6IEEuIEVtIFIsIG8gZGV0ZXJtaW5hbnRlIGRlIHVtYSBtYXRyaXogw6kgY2FsY3VsYWRvIHBlbGEgZnVuw6fDo28gYGRldCgpYC4KCiogKipJTlZFUlNBIERFIFVNQSBNQVRSSVo6KioKCkEgaW52ZXJzYSBkZSB1bWEgbWF0cml6IHF1YWRyYWRhIHF1YWxxdWVyIGN1am8gZGV0ZXJtaW5hbnRlIHNlamEgbsOjbyBudWxvLCAkQV97bixufSQsIMOpIHVtYSBtYXRyaXogZGUgbWVzbWFzIGRpbWVuc8O1ZXMgcXVlIGF0ZW5kYSBhIHNlZ3VpbnRlIGNvbmRpw6fDo286CgokJAp7QX1eey0xfVxjZG90IEE9SQokJApPbmRlLCAkSSQgw6kgYSBtYXRyaXogaWRlbnRpZGFkZSBkZSBtZXNtYSBkaW1lbnPDo28gcXVlIGEgbWF0cml6ICRBJC4gQSBpbnZlcnNhIGRlIHVtYSBtYXRyaXogw6kgZXN0aW1hZGEgcGVsYSBmdW7Dp8OjbyBgc29sdmUoKWAsIG1lc21hIGZ1bsOnw6NvIHV0aWxpemFkYSBwYXJhIHJlc29sdcOnw6NvIGRlIHNpc3RlbWFzIGRlIGVxdWHDp8O1ZXMgZW0gUi4KCkFiYWl4bywgY8OzZGlnb3MgcXVlIG1vc3RyYW0gY29tbyBleGVjdXRhciBubyBSIGFzIG9wZXJhw6fDtWVzIGNvbSBtYXRyaXplcyBjaXRhZGFzIGFudGVyaW9ybWVudGUuCgpgYGB7cn0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjIyAgIENSSUFORE8gTUFUUklaRVMgICAgIyMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCk0xIDwtIG1hdHJpeChjKDIsIDMsIDUsIDYpLCBucm93ID0gMikKTTIgPC0gbWF0cml4KGMoNSwgMywgOCwgMiksIG5yb3cgPSAyKQpNMyA8LSBtYXRyaXgoYygyLCA0LCA2LCAyLCAwLDEpLCBucm93ID0gMiwgbmNvbCA9IDMpCk00IDwtIG1hdHJpeChjKDEsIDAuNSwgMC4zLCAwLjUsIDEsIDAuOSwgMC4zLCAwLjksIDEpLCBucm93ID0gMywgbmNvbCA9IDMpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjICAgU09NQSBFIFNVQlRSQcOHw4NPICAgICMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpzb21hIDwtIE0yICsgTTEKc3VidHJhY2FvIDwtIE0yIC0gTTEKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyAgTVVMVElQTElDQVIgRVNDQUxBUiAgICAjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpwcm9kX2VzY2FsYXIgPC0gNDIqTTQKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyAgTVVMVElQTElDQVIgTUFUUklDSUFMICAjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgpwcm9kX21hdHJpY2lhbCA8LSBNMSAlKiUgTTMKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyAgICBUUkFOU1BPU1RBIE1BVFJJWiAgIyMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgp0cmFuc3Bvc3RhIDwtIHQoTTMpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMjICBERVRFUk1JTkFOVEUgTUFUUklaICAjIyMjIwojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKZGV0ZXJtaW5hbnRlIDwtIGRldChNMikKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyMgICAgIElOVkVSU0EgTUFUUklaICAjIyMjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgppbnZlcnNhIDwtIHNvbHZlKE0xKQoKYGBgCgojIyMjICoqREFUQSBGUkFNRVMqKgoKQXTDqSBhZ29yYSB0ZW1vcyB1dGlsaXphZG8gYXBlbmFzIGRhZG9zIGRlIHVtYSBtZXNtYSBjbGFzc2UsIGFybWF6ZW5hZG9zIG91IGVtIHVtIHZldG9yIG91IGVtIHVtYSBtYXRyaXouIE1hcyB1bWEgYmFzZSBkZSBkYWRvcywgZW0gZ2VyYWwsIMOpIGZlaXRhIGRlIGRhZG9zIGRlIGRpdmVyc2FzIGNsYXNzZXMuIFBvciBleGVtcGxvLCBwb2RlbW9zIHF1ZXJlciB0ZXIgdW1hIGNvbHVuYSBjb20gb3Mgbm9tZXMgZG9zIGZ1bmNpb27DoXJpb3MsIG91dHJhIGNvbSBvIHNleG8gZG9zIGZ1bmNpb27DoXJpb3MsIG91dHJhIGNvbSB2YWxvcmVz4oCmIG5vdGUgcXVlIGVzc2FzIGNvbHVuYXMgc8OjbyBkZSBjbGFzc2VzIGRpZmVyZW50ZXMsIGNvbW8gdGV4dG9zIGUgbsO6bWVyb3MuIENvbW8gZ3VhcmRhciBlc3NhcyBpbmZvcm1hw6fDtWVzPwoKQSBzb2x1w6fDo28gcGFyYSBpc3NvIMOpIG8gZGF0YSBmcmFtZSBxdWUsIHRhbHZleiwgw6kgbyBmb3JtYXRvIGRlIGRhZG9zIG1haXMgaW1wb3J0YW50ZSBkbyBSLiBObyBkYXRhIGZyYW1lIGNhZGEgY29sdW5hIHJlcHJlc2VudGEgdW1hIHZhcmnDoXZlbCBlIGNhZGEgbGluaGEgdW1hIG9ic2VydmHDp8Ojby4gRXNzYSDDqSBhIGVzdHJ1dHVyYSBpZGVhbCBwYXJhIHF1YW5kbyB2b2PDqiB0ZW0gdsOhcmlhcyB2YXJpw6F2ZWlzIGRlIGNsYXNzZXMgZGlmZXJlbnRlcyBlbSB1bSBiYW5jbyBkZSBkYWRvcy4KCkFiYWl4bywgY8OzZGlnbyBlbSBSIHF1ZSBtb3N0cmEgY29tbyB1c2FyIGEgZnVuw6fDo28gYGRhdGEuZnJhbWUoKWAgcGFyYSBkZWZpbmlyIHVtIGRhdGEgZnJhbWUgYmVtIGNvbW8gb3BlcmHDp8O1ZXMgY29tIGVzdGUgZm9ybWF0byBkZSBhcm1hemVuYXIgZGFkb3Mgbm8gUi4KCgpgYGB7cn0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKIyMjICBDUklBTkRPIFVNIERBVEEgRlJBTUUgICMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgc3RyaW5nc0FzRmFjdG9ycyBkaXogc2UgcXVlcm8gKFRSVUUpIG91IG7Do28gKEZBTFNFKSB0cmFuc2Zvcm1hciBhcyB2YXJpw6F2ZWlzIGNvbSB0ZXh0byBlbSB1bSBmYXRvcgpmdW5jaW9uYXJpb3MgPC0gZGF0YS5mcmFtZShub21lID0gYygiSm/Do28iLCAiTWFyaWEiLCAiSm9zw6kiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgc2V4byA9IGMoIk0iLCAiRiIsICJNIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbGFyaW8gPSBjKDEwMDAsIDEyMDAsIDEzMDApLAogICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgojIHZlcmlmaWNhbmRvIGEgY2xhc3NlIGRlIGNhZGEgY29sdW5hIGRvIGRhdGEgZnJhbWUKc3RyKGZ1bmNpb25hcmlvcykKCiMgdW1hIG1hdHJpeiBjb20gb3MgbWVzbW9zIGRhZG9zIG9icmlnYXRvcmlhbWVudGUgdGVyw6EgdW1hIMO6bmljYSBjbGFzc2UgKGNoYXJhY3RlcikKIyBhIGZ1bsOnw6NvIGFzLm1hdHJpeCBvYnJpZ2EgcXVlIG8gZGFkbyByZWNlYmlkbyBzZWphIHRyYW5zZm9ybWFkbyBlbSB1bWEgbWF0cml6CmFzLm1hdHJpeChmdW5jaW9uYXJpb3MpCgojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwojIyMgT1BFUkHDh8OVRVMgQ09NIERBVEEgRlJBTUUgIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFR1ZG8gbWVub3MgYSBsaW5oYSAxCmZ1bmNpb25hcmlvc1stMSwgXQoKIyBBcGVuYXMgYSBwcmltZWlyYSBsaW5oYSBkYSBwcmltZWlyYSBjb2x1bmEKZnVuY2lvbmFyaW9zWzEsIDFdCgojIFRlcmNlaXJhIGxpbmhhIGRhcyBjb2x1bmFzICJub21lIiBlICJzYWxhcmlvIgpmdW5jaW9uYXJpb3NbMyAsIGMoIm5vbWUiLCAic2FsYXJpbyIpXQoKYGBgCgojIyMjICoqTElTVEFTKioKClVtYSBsaXN0YSBlbSBSIMOpIHNpbWlsYXIgw6AgdW1hIGxpc3RhIGRlIGF0aXZpZGFkZXMuIE9zIGRpZmVyZW50ZXMgaXRlbnMgZGEgbGlzdGEgZW0gc3VhIGdyYW5kZSBtYWlvcmlhIGRpZmVyZW0gZW0gdGFtYW5obywgdGlwbyBkZSBhdGl2aWRhZGUgcXVlIGRldmUgc2VyIGZlaXRhLCBlbnRyZSBvdXRyYXMgY29pc2FzLgoKQSBsaXN0YSBubyBSIG5vcyBwZXJtaXRlIGFybWF6ZW5hciB1bWEgdmFyaWVkYWRlIGRlIG9iamV0b3MgKG1hdHJpemVzLCB2ZXRvcmVzLCBkYXRhIGZyYW1lcyBvdSBhdMOpIG1lc21vIG91dHJhIGxpc3RhKSBlIHRhaXMgb2JqZXRvcyBwb2RlbSBuw6NvIGVzdGFyIHJlbGFjaW9uYWRvcyB1bnMgY29tIG9zIG91dHJvcy4gRGVzdGEgZm9ybWEsIHVtYSBsaXN0YSB0ZW0gZ3JhbmRlIHV0aWxpZGFkZSBxdWFuZG8gcXVlcmVtb3MgYXJtYXplbmFyIHF1YWxxdWVyIHRpcG8gZGUgZGFkbyBlbSB1bSDDum5pY28gb2JqZXRvIHNlbSBub3MgcHJlb2N1cGFyIGNvbSBvIHRhbWFuaG8gZG9zIG9iamV0b3MgZW52b2x2aWRvcy4gCgpBYmFpeG8sIGPDs2RpZ29zIGVtIFIgcXVlIG1vc3RyYW0gY29tbyBjcmlhciB1bWEgbGlzdGEgY29tIGRpZmVyZW50ZXMgdGlwb3MgZGUgZGFkb3MgZSBjb21vIGZhemVyIG9wZXJhw6fDtWVzIGNvbSB1bWEgbGlzdGEuIAoKYGBge3J9CiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyAgICBDUklBTkRPIFVNIExJU1RBICAgICAjIyMjCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIFZldG9yIGNvbSBuw7ptZXJvcyBkZSAxIGEgMTAKbXlfdmVjdG9yIDwtIDE6MTAgCm15X3ZlY3RvcgoKIyBNYXRyaXogY29tIG7Dum1lcm9zIGRlIDEgYXTDqSA5Cm15X21hdHJpeCA8LSBtYXRyaXgoMTo5LCBuY29sID0gMykKbXlfbWF0cml4CgojIFByaW1laXJhcyAxMCBsaW5oYXMgZG8gZGF0YSBmcmFtZSBtdGNhcnMKbXlfZGYgPC0gbXRjYXJzWzE6MTAsXQpteV9kZgoKIyBDb25zdHJ1aW5kbyB1bWEgbGlzdGEgY29tIG9zIHRyw6pzIGRpZmVyZW50ZXMgb2JqZXRvcwpteV9saXN0IDwtIGxpc3QobXlfdmVjdG9yLCBteV9tYXRyaXgsIG15X2RmKQpteV9saXN0CgojIE5vbWVhciBjYWRhIGVsZW1lbnRvIGRhIGxpc3RhCm5hbWVzKG15X2xpc3QpIDwtIGMoInZldG9yIiwibWF0cml6IiwiZGF0YWZyYW1lIikKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCiMjIyAgT1BFUkHDh8OVRVMgQ09NIFVNIExJU1RBICMjIyMKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKCiMgU2VsZWNpb25hciBhIHByaW1laXJhIGxpbmhhIGRhIHByaW1laXJhIGNvbHVuYSBkYSBtYXRyaXogcXVlIGVzdMOhIG5hIGxpc3RhCm15X2xpc3QkbWF0cml6WzEsMV0KCiMgU2VsZWNpb25hciBvIHByaW1laXJvIHZhbG9yIGRvIHZldG9yCm15X2xpc3QkdmV0b3JbMV0KCiMgU2VsZWNpb25hciAzIHByaW1laXJhcyBsaW5oYXMgZG8gZGF0YSBmcmFtZQpteV9saXN0JGRhdGFmcmFtZVsxOjMsXQpgYGAKCiMjIyMgKipSRUZFUsOKTkNJQVMqKg==