Jared Cohen 5/7/2019

Introduction

Diversification is a cornerstone of Modern Portfolio Theory. Essentially, by diversifying financial assets into different categories, one can minimize risk while optimizing returns at a certain risk level. One layer of diversification involves the usage of separate assets classes, such as equities, bonds, and precious metals. Beyond asset class diversification, it is important to diversify within an asset class. The global equities market, for example, has myriad types of investments varying based on sector, industry, geography, size, and other factors. By spreading money across a greater variety of investment types, risk can be reduced, and investors can gain exposure to specific domains of the economy without taking on undue risk.

As a result of this desire to access returns of specifc areas of the economy while limiting risk, exchange-traded funds (ETFs) have massively grown in popularity. The fund invests in many different securities, and investors can trade shares of the fund. This allows investors to gain exposure to certain types of investments that would otherwise be too risky to invest in.

A popular trend within the realm of funds is the low-cost fund, or index fund. These ETFs track broad indices or follow broad strategies and are passively managed. Because there is no active management, fees are lower, which allows investors to keep more of their returns.

An important element about diversification is the correlation between different assets. In a perfectly diversified portfolio, losses in some positions would be offset by gains in others. For this to work effectively, different securities should have low or negative correlations. This paper will analyze a selection of low-cost ETFs with different strategies in order to gain an understanding of the patterns of correlation between them.

Data

The following dataset contains historical daily closing prices from 4/1/2014 until 3/31/2019 for 13 different ETFs. This data was retrieved from Yahoo Finance. A separate CSV file was downloaded for each ETF. The column of closing prices from each file was copied into a new CSV file. This CSV file was uploaded as “ETF_prices.csv”

An additional CSV file “ETF_edges.csv” was created. This file contains an edge list, where nodes are the ETFs. Edges represent a correlation in closing price, and all nodes are connected. The CSV file has a column containing the correlation coefficients, and the edge weights are equal to the correlation coeficients multiplied by 100 and then rounded to the nearest integer.

The 13 ETFs are the following:

  1. SPDR S&P 500 ETF (SPY) This fund tracks the performance of the S&P 500 index
  2. Vanguard S&P 500 ETF (VOO) This fund also tracks the performance of the S&P 500 index
  3. Invesco QQQ Trust (QQQ) This fund tracks the performance of the NASDAQ index
  4. Vanguard Total Stock Market Index Fund ETF (VTI) This fund tracks the performance of the entirety of the US stock market
  5. Vanguard Total International Stock Index Fund ETF (VXUS) This fund tracks the overall performance of stock markets around the world
  6. Vanguard FTSE Developed Markets Index Fund ETF (VEA) This fund tracks the performance of the stock markets of developed economies outside North America, such as Japan and Western European nations
  7. Vanguard FTSE Emerging Markets Index Fund ETF (VWO) This fund tracks the overall performance of the stock markets in many
    developing economies
  8. Vanguard High Dividend Yield Index Fund ETF (VYM) This fund focuses on US large-cap stocks that pay dividends
  9. Vanguard Dividend Appreciation Index Fund ETF (VIG) This fund tracks the performance of the NASDAQ US Dividend Achievers Select Index, which is comprised of US large-cap dividend-paying stocks that exhibit characteristics of growth
  10. Vanguard Value Index Fund ETF (VTV) This fund tracks the performance of the MSCI US Prime Market Value Index, focusing on US stocks that adhere to the value style of investing
  11. Vanguard Growth Index Fund ETF (VUG) This fund tracks the MSCI US Prime Market Growth Index, focusing on large-cap US stocks that adgere to the growth style of investing
  12. Vanguard Mid-Cap Value Index Fund ETF (VOE) This fund tracks the performance of mid-cap US stocks, following a value investing style
  13. Vanguard Small-Cap Growth Index Fund ETF (VBK) This fund tracks the performance of small-cap US stocks, following a growth investing style

All of these ETFs are low-cost, passively managed funds that hold hundreds of positions. The purpose of these types of funds is to provide investors with wide-exposure to a specific area of the market while diversifying between differnet equities within that area. Some of these funds simply track major indices like the S&P 500 or the NASDAQ, while others don’t track a specific index but rather employ a broad strategy in order to generate returns that are representative of that segment of the market. For example, the strategy of VWO is to invest in foreign, emerging markets that are capable of growly more quickly than more established markets. VTV, however, focuson on large US value companies. A value company may or may not have very high growth rates; the core of the value investing style is to buy stocks at a discount to their intrinsic value. In fact, long-term stock market analyses have revealed the merits of value investing. One study at Yale University demonstrated that buying a stock above a fair valuation materially decreased total returns for up to 30 years into the future (refernece to Yale article).

(ETF data from ETFdb.com)

The last row was removed from ETF_prices because an empty row was automatically added to the CSV file after saving it. ETF_prices was also trimmed to contain only the first 14 columns for the same reason. This was needed to ensure that all values contained in the CSV file were numeric, which was needed for the following calculations.

library(readr)
library(igraph)

Attaching package: ‘igraph’

The following objects are masked from ‘package:stats’:

    decompose, spectrum

The following object is masked from ‘package:base’:

    union
ETF_prices <- read_csv("ETF_prices.csv")
Missing column names filled in: 'X15' [15], 'X16' [16]Parsed with column specification:
cols(
  Date = col_character(),
  SPY = col_double(),
  VOO = col_double(),
  QQQ = col_double(),
  VTI = col_double(),
  VXUS = col_double(),
  VEA = col_double(),
  VWO = col_double(),
  VYM = col_double(),
  VIG = col_double(),
  VTV = col_double(),
  VUG = col_double(),
  VOE = col_double(),
  VBK = col_double(),
  X15 = col_logical(),
  X16 = col_logical()
)
ETF_prices <- ETF_prices[-nrow(ETF_prices),1:14]

Methods

Correlations were calculated between the vectors of historical closing price data for each pair of ETFs. The correlations were used to give proportional edge weights in a complete network. The edge weight was set to the nearest integer to 100 times the correlation coefficient.

A heat map was created to visualize the correlation coefficients betweren each pair of ETFs. A histogram was also plotted to visulaize the distribution of correlation coefficents bewtween ETFs. The graph of the ETFs was plotted using a force directed layout, so that nodes with heavier edges between them were closer together. Edge thickness was also set proportionally to edge weight in order to visualize the relative correlary strengths,

The network was then run through community detection algorithm, focusing on modularity. These algorithms were also run on an unweighted version if the graph to establish a baseline. Another plot was then generated to visualize the differnet communities in the ETF network.

These methods were then redone with price data from each individual year within the five year sample in order to compare the different results.

Results

summary(ETF_prices[,-1])
      SPY             VOO             QQQ              VTI              VXUS            VEA       
 Min.   :181.5   Min.   :166.3   Min.   : 84.11   Min.   : 92.56   Min.   :39.73   Min.   :32.23  
 1st Qu.:205.0   1st Qu.:188.1   1st Qu.:105.86   1st Qu.:105.16   1st Qu.:47.09   1st Qu.:37.44  
 Median :216.6   Median :198.8   Median :117.11   Median :111.21   Median :50.70   Median :40.15  
 Mean   :229.8   Mean   :211.0   Mean   :128.77   Mean   :118.28   Mean   :50.58   Mean   :40.05  
 3rd Qu.:259.8   3rd Qu.:238.6   3rd Qu.:155.85   3rd Qu.:133.71   3rd Qu.:53.82   3rd Qu.:42.39  
 Max.   :293.6   Max.   :269.8   Max.   :186.74   Max.   :151.31   Max.   :61.17   Max.   :47.88  
      VWO             VYM             VIG              VTV              VUG              VOE        
 Min.   :28.55   Min.   :60.85   Min.   : 72.10   Min.   : 73.67   Min.   : 89.98   Min.   : 75.33  
 1st Qu.:37.36   1st Qu.:68.00   1st Qu.: 79.61   1st Qu.: 82.91   1st Qu.:105.43   1st Qu.: 87.95  
 Median :40.80   Median :72.93   Median : 84.77   Median : 87.50   Median :111.52   Median : 93.25  
 Mean   :40.18   Mean   :74.61   Mean   : 88.60   Mean   : 91.87   Mean   :120.53   Mean   : 96.75  
 3rd Qu.:43.33   3rd Qu.:82.46   3rd Qu.: 99.55   3rd Qu.:102.13   3rd Qu.:139.24   3rd Qu.:106.14  
 Max.   :50.98   Max.   :90.91   Max.   :112.45   Max.   :113.26   Max.   :161.48   Max.   :117.78  
      VBK       
 Min.   :100.6  
 1st Qu.:124.5  
 Median :134.5  
 Mean   :141.0  
 3rd Qu.:158.6  
 Max.   :190.0  

Calculate correlation matrix

ETF_Cor_matrix <- cor(ETF_prices[,-1])
ETF_Cor_matrix
           SPY       VOO       QQQ       VTI      VXUS       VEA       VWO       VYM       VIG
SPY  1.0000000 0.9999616 0.9917854 0.9992553 0.5787891 0.6075434 0.4949917 0.9863730 0.9934929
VOO  0.9999616 1.0000000 0.9917455 0.9992486 0.5782746 0.6069869 0.4946115 0.9866153 0.9935335
QQQ  0.9917854 0.9917455 1.0000000 0.9893916 0.5211175 0.5546232 0.4288681 0.9633972 0.9822217
VTI  0.9992553 0.9992486 0.9893916 1.0000000 0.5966961 0.6249407 0.5129306 0.9848334 0.9918898
VXUS 0.5787891 0.5782746 0.5211175 0.5966961 1.0000000 0.9929997 0.9573807 0.5804221 0.5673828
VEA  0.6075434 0.6069869 0.5546232 0.6249407 0.9929997 1.0000000 0.9188415 0.6021841 0.5911180
VWO  0.4949917 0.4946115 0.4288681 0.5129306 0.9573807 0.9188415 1.0000000 0.5146943 0.4933169
VYM  0.9863730 0.9866153 0.9633972 0.9848334 0.5804221 0.6021841 0.5146943 1.0000000 0.9818726
VIG  0.9934929 0.9935335 0.9822217 0.9918898 0.5673828 0.5911180 0.4933169 0.9818726 1.0000000
VTV  0.9932698 0.9933849 0.9729177 0.9934355 0.6021431 0.6248710 0.5310698 0.9951071 0.9884243
VUG  0.9953226 0.9952348 0.9965622 0.9947169 0.5664017 0.5992106 0.4738464 0.9679061 0.9873790
VOE  0.9709235 0.9710278 0.9434570 0.9751733 0.6573828 0.6827102 0.5823031 0.9792913 0.9528102
VBK  0.9721199 0.9719318 0.9639486 0.9787801 0.6414844 0.6682942 0.5549126 0.9376058 0.9669227
           VTV       VUG       VOE       VBK
SPY  0.9932698 0.9953226 0.9709235 0.9721199
VOO  0.9933849 0.9952348 0.9710278 0.9719318
QQQ  0.9729177 0.9965622 0.9434570 0.9639486
VTI  0.9934355 0.9947169 0.9751733 0.9787801
VXUS 0.6021431 0.5664017 0.6573828 0.6414844
VEA  0.6248710 0.5992106 0.6827102 0.6682942
VWO  0.5310698 0.4738464 0.5823031 0.5549126
VYM  0.9951071 0.9679061 0.9792913 0.9376058
VIG  0.9884243 0.9873790 0.9528102 0.9669227
VTV  1.0000000 0.9779297 0.9810755 0.9593473
VUG  0.9779297 1.0000000 0.9544401 0.9773931
VOE  0.9810755 0.9544401 1.0000000 0.9458348
VBK  0.9593473 0.9773931 0.9458348 1.0000000

Create a heat map to visualize the relative strengths of correlation between ETFs.

library(ggplot2)
library(reshape2)
cormat <- ETF_Cor_matrix2
# Get lower triangle of the correlation matrix
  get_lower_tri<-function(cormat){
    cormat[upper.tri(cormat)] <- NA
    return(cormat)
  }
  # Get upper triangle of the correlation matrix
  get_upper_tri <- function(cormat){
    cormat[lower.tri(cormat)]<- NA
    return(cormat)
  }
  upper_tri <- get_upper_tri(cormat)
melted_cormat <- melt(upper_tri, na.rm = TRUE)
ggplot(data = melted_cormat, aes(Var2, Var1, fill = value))+
 geom_tile(color = "white")+
 scale_fill_gradient2(low = "blue", high = "red", mid = "white", 
   midpoint = 0, limit = c(-1,1), space = "Lab", 
   name="Pearson\nCorrelation") +
  theme_minimal()+ 
 theme(axis.text.x = element_text(angle = 45, vjust = 1, 
    size = 12, hjust = 1))+
 coord_fixed()

These values and this histogram illustrate the distribution of correlation coefficients between ETFs. The majority of the ETFs have an r value above 0.9, which is a strong correlation. However, there is a group of some pairs of ETFs with r values between 0.4 and 0.7, which is a moderately strong, positive correlation. This does not include self-edges. Additionally, it would be possible to look remove the less correlatated pairs in order to gain insight into the differences in correlations of the pairs in the 0.9 to 1.0 range; however, any differences on that small a scale would likely be practically insignificant due to random market fluctuations. The primary insight from this is that the majority of ETFs are extremely highly correlated with each other while a few ETFs had only a moderate correlation, meaning there was a greater divergence in price patterns, which may reflect differences in overall performance.

summary(ETF_edges$Correlation)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
 0.4289  0.5999  0.9637  0.8217  0.9872  1.0000 
hist(ETF_edges$Correlation, main="Frequency Of Correlation Coefficients between Edges",xlab="Correlation Coefficient")

#Create an unweighted, complete iGraph object and a weighted, complete iGraph object with each ETF as a node
ETFgraph <- graph.data.frame(ETF_edges, directed = FALSE)
ETFgraph.weighted <- ETFgraph
E(ETFgraph.weighted)$weight <- E(ETFgraph.weighted)$Weight

This plot illustrates the relationships between these ETFs (nodes). Thicker edges indicate a stronger correlation. The use of a force layout causes the nodes to be placed such that the nodes connected with greater weight (more highly correlated) are closer together. This plot gives the impression that VXUS, VWO, and VEA are loosely connected to all other nodes while the remaining nodes are tightly interconnected.

set.seed(50)
E(ETFgraph.weighted)$width <- E(ETFgraph.weighted)$weight/42
plot(ETFgraph.weighted, layout=layout_with_fr)

These calculations detect communities in the unweighted version of the graph in order to provide a baseline for comparison to the weighted graph. The unweighted graph is basically one large group, with only VBK occupying a separate community. The modularity of close to zero indicates that overall, the unweighted graph lacks much of a sense of communities anywhere,

ETFcommunity <- fastgreedy.community(ETFgraph)
length(ETFcommunity)
[1] 2
sizes(ETFcommunity)
Community sizes
 1  2 
12  1 
membership(ETFcommunity)
 SPY  VOO  QQQ  VTI VXUS  VEA  VWO  VYM  VIG  VTV  VUG  VOE  VBK 
   1    1    1    1    1    1    1    1    1    1    1    1    2 
modularity(ETFcommunity)
[1] -1.908196e-17

These calculations detect communites in the weighted graph. The graph is split into two groups. One group has VXUS, VEA, and VWO, and the other group has the other 10 nodes. The modularity of 0.026, while still small, is orders of magnitide greater than the baseline modularity, indicating that the relative edge weights based on correlation coefficeints did have a material impact in the community structure of the ETFs.

ETFcommunity.weighted <- fastgreedy.community(ETFgraph.weighted)
length(ETFcommunity.weighted)
[1] 2
sizes(ETFcommunity.weighted)
Community sizes
 1  2 
10  3 
membership(ETFcommunity.weighted)
 SPY  VOO  QQQ  VTI VXUS  VEA  VWO  VYM  VIG  VTV  VUG  VOE  VBK 
   1    1    1    1    2    2    2    1    1    1    1    1    1 
modularity(ETFcommunity.weighted)
[1] 0.02603699

This plot illustrates the separation of the two communites. VEA, VXUS, and VWO occupy their own small communinty aside form the majority of nodes. In the earlier plot, these three ETFs appeared to be more peripheral, and the community detection algorithm confirms that idea.

set.seed(50)
plot(ETFcommunity.weighted,ETFgraph.weighted)

Looking at just April 1, 2014 until March 31 2015, the majority of the correlation coefficients between ETFs are above 0.8; however, instead of a there being a group of moderately, positively correlatated ETFs, there is a group of weakly-moderately, negatively correlated ETFs. The presence of these negative correlations is indicative of higher amounts of variation between ETFs in shorter time periods while they tend to converge more over longer time periods.

ETF_edges_Y1 <- read_csv("/Users/jaredmacbook/Documents/R/MATH 190 data/MATH 190 Final Project/ETF_edges_Y1.csv")
Parsed with column specification:
cols(
  ETF1 = col_character(),
  ETF2 = col_character(),
  Weight = col_double(),
  Correlation = col_double()
)
summary(ETF_edges_Y1$Correlation)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
-0.5276 -0.2285  0.8733  0.4601  0.9704  0.9998 
hist(ETF_edges_Y1$Correlation, main="Frequency Of Correlation Coefficients between Edges",xlab="Correlation Coefficient")

#Create an unweighted, complete iGraph object and a weighted, complete iGraph object with each ETF as a node
#Add 100 to each edge weight to turn negative edge weights positive while maintaining the same relative weighting
ETFgraph.Y1 <- graph.data.frame(ETF_edges_Y1, directed = FALSE)
E(ETFgraph.Y1)$weight <- (E(ETFgraph.Y1)$Weight + 100)
E(ETFgraph.weighted)$width <- E(ETFgraph.weighted)$weight/42
set.seed(50)
plot(ETFgraph.weighted, layout=layout_with_fr)

The correlation network from just the first year of the five year sample splits into the exact same two communities as the network that includes all five years. The modularity for this network is also about double that of the five year period network, indicating that these same communities are more tightly connected over this single year. This could mean that: 1) VXUS, VEA, and VWO were more correlated with each other during this period than overall 2) The other seven ETFs were more correlated with each other during this time period than overall 3) VXUS, VEA, and VWO were less correlated with the other seven ETFs during this period than overall The third seems most likely as it explains the meaningful number of negative correlations.

ETFcommunity.Y1 <- fastgreedy.community(ETFgraph.Y1)
length(ETFcommunity.Y1)
[1] 2
sizes(ETFcommunity.Y1)
Community sizes
 1  2 
10  3 
membership(ETFcommunity.Y1)
 SPY  VOO  QQQ  VTI VXUS  VEA  VWO  VYM  VIG  VTV  VUG  VOE  VBK 
   1    1    1    1    2    2    2    1    1    1    1    1    1 
modularity(ETFcommunity.Y1)
[1] 0.05622614
set.seed(50)
plot(ETFcommunity.Y1,ETFgraph.Y1)

Discussion

VXUS, VEA, and VWO emerged as a community both over the entire five year span and over the course of the first year within that. These funds are Vanguard Total International Stock Index Fund ETF (VXUS), Vanguard FTSE Developed Markets Index Fund ETF (VEA), and Vanguard FTSE Emerging Markets Index Fund ETF (VWO). It makes sense that these are highly correlated because they all focus on equities outside of North America while the other seven ETFs focus on American equities. One possible conclusion is that there is not much of a difference between the three internation ETFs despite one being focused on developed economies with another being focused on emerging economies. The correlation coefficient for those two ETFs over all five years was 0.92, indicating a very strong, positve correlation. Additionally, the fact that the other seven ETFs formed a community, combined with the fact that the majority of correlation coefficients were greater than 0.9, indicates that the overall performance of these funds was quite similar despite the funds varying in their approaches, whether that be growth, value, high-yield, dividend growth, large-cap, mid-cap, or small-cap. This high correlation implies that investment performance would not differ much between these seven funds, which means that attempting to diversify by investing in several of these funds would not be effective. It’s important to note, however, that the five year period being analyzed is entirely encompassed by a bull market. It is thus difficult to determine if these conclusions would hold true in a bear market, which is perhaps more important because a bear market is when reducing risk becomes most prudent.

Future Analysis

This analysis can be taken further in two sets of ways. First, the parameters of this analysis could be altered. For example, including more ETFs, including different time periods, covering a longer time period, using opening prices, or using daily average prices could possibly provide more insight. Additionally, analyzing a greater number of funds would allow for community detection at a higher resolution. Also, instead of creating a complete graph with varying edge weights corresponding to correlation strength, it may be interesting to only set the edge if the r value is above 0.5 or even 0.8. This would likely have a material affect of the nature and community structure of the graph. Secondly, the ETFs could be compared in other ways besides price correlations. For example, correlations in yearly total returns over time or similarity of holdings could also be analyzed. It would also be interesting to determine how accurate price correlation is for predicting relative capial appreciation.

Sources

ETFdb.com

Yahoo Finance

LS0tCnRpdGxlOiAiQ29tbXVuaXR5IERldGVjdGlvbiBpbiBFVEYgQ29ycmVsYXRpb24gTmV0d29ya3MsIDIwMTQtMjAxOSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQpKYXJlZCBDb2hlbgo1LzcvMjAxOQoKI0ludHJvZHVjdGlvbgpEaXZlcnNpZmljYXRpb24gaXMgYSBjb3JuZXJzdG9uZSBvZiBNb2Rlcm4gUG9ydGZvbGlvIFRoZW9yeS4gRXNzZW50aWFsbHksIGJ5IGRpdmVyc2lmeWluZyBmaW5hbmNpYWwgYXNzZXRzIGludG8gZGlmZmVyZW50IGNhdGVnb3JpZXMsIG9uZSBjYW4gbWluaW1pemUgcmlzayB3aGlsZSBvcHRpbWl6aW5nIHJldHVybnMgYXQgYSBjZXJ0YWluIHJpc2sgbGV2ZWwuIE9uZSBsYXllciBvZiBkaXZlcnNpZmljYXRpb24gaW52b2x2ZXMgdGhlIHVzYWdlIG9mIHNlcGFyYXRlIGFzc2V0cyBjbGFzc2VzLCBzdWNoIGFzIGVxdWl0aWVzLCBib25kLCBhbmQgcHJlY2lvdXMgbWV0YWxzLiBCZXlvbmQgYXNzc2V0IGNsYXNzIGRpdmVyc2lmaWNhdGlvbiwgaXQgaXMgaW1wb3J0YW50IHRvIGRpdmVyc2lmeSB3aXRoaW4gYW4gYXNzZXQgY2xhc3MuIFRoZSBnbG9iYWwgZXF1aXRpZXMgbWFya2V0LCBmb3IgZXhhbXBsZSwgaGFzIG15cmlhZCB0eXBlcyBvZiBpbnZlc3RtZW50cyB2YXJ5aW5nIGJhc2VkIG9uIHNlY3RvciwgaW5kdXN0cnksIGdlb2dyYXBnaHksIHNpemUsIGFuZCBvdGhlciBmYWN0b3JzLiBCeSBzcHJlYWRpbmcgbW9uZXkgYWNyb3NzIGEgZ3JlYXRlciB2YXJpZXR5IG9mIGludmVzdG1lbnQgdHlwZXMsIHJpc2sgY2FuIGJlIHJlZHVjZWQsIGFuZCBpbnZlc3RvcnMgY2FuIGdhaW4gZXhwb3N1cmUgdG8gc3BlY2lmaWMgZG9tYWlucyBvZiB0aGUgZWNvbm9teSB3aXRob3V0IHRha2luZyBvbiB1bmR1ZSByaXNrLgoKQXMgYSByZXN1bHQgb2YgdGhpcyBkZXNpcmUgdG8gYWNjZXNzIHJldHVybnMgb2Ygc3BlY2lmYyBhcmVhcyBvZiB0aGUgZWNvbm9teSB3aGlsZSBsaW1pdGluZyByaXNrLCBleGNoYW5nZS10cmFkZWQgZnVuZHMgKEVURnMpIGhhdmUgbWFzc2l2ZWx5IGdyb3duIGluIHBvcHVsYXJpdHkuIFRoZSBmdW5kIGludmVzdHMgaW4gbWFueSBkaWZmZXJlbnQgc2VjdXJpdGllcywgYW5kIGludmVzdG9ycyBjYW4gdHJhZGUgc2hhcmVzIG9mIHRoZSBmdW5kLiBUaGlzIGFsbG93cyBpbnZlc3RvcnMgdG8gZ2FpbiBleHBvc3VyZSB0byBjZXJ0YWluIHR5cGVzIG9mIGludmVzdG1lbnRzIHRoYXQgd291bGQgb3RoZXJ3aXNlIGJlIHRvbyByaXNreSB0byBpbnZlc3QgaW4uCgpBIHBvcHVsYXIgdHJlbmQgd2l0aGluIHRoZSByZWFsbSBvZiBmdW5kcyBpcyB0aGUgbG93LWNvc3QgZnVuZCwgb3IgaW5kZXggZnVuZC4gVGhlc2UgRVRGcyB0cmFjayBicm9hZCBpbmRpY2VzIG9yIGZvbGxvdyBicm9hZCBzdHJhdGVnaWVzIGFuZCBhcmUgcGFzc2l2ZWx5IG1hbmFnZWQuIEJlY2F1c2UgdGhlcmUgaXMgbm8gYWN0aXZlIG1hbmFnZW1lbnQsIGZlZXMgYXJlIGxvd2VyLCB3aGljaCBhbGxvd3MgaW52ZXN0b3JzIHRvIGtlZXAgbW9yZSBvZiB0aGVpciByZXR1cm5zLgoKQW4gaW1wb3J0YW50IGVsZW1lbnQgYWJvdXQgZGl2ZXJzaWZpY2F0aW9uIGlzIHRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIGRpZmZlcmVudCBhc3NldHMuIEluIGEgcGVyZmVjdGx5IGRpdmVyc2lmaWVkIHBvcnRmb2xpbywgbG9zc2VzIGluIHNvbWUgcG9zaXRpb25zIHdvdWxkIGJlIG9mZnNldCBieSBnYWlucyBpbiBvdGhlcnMuIEZvciB0aGlzIHRvIHdvcmsgZWZmZWN0aXZlbHksIGRpZmZlcmVudCBzZWN1cml0aWVzIHNob3VsZCBoYXZlIGxvdyBvciBuZWdhdGl2ZSBjb3JyZWxhdGlvbnMuIFRoaXMgcGFwZXIgd2lsbCBhbmFseXplIGEgc2VsZWN0aW9uIG9mIGxvdy1jb3N0IEVURnMgd2l0aCBkaWZmZXJlbnQgc3RyYXRlZ2llcyBpbiBvcmRlciB0byBnYWluIGFuIHVuZGVyc3RhbmRpbmcgb2YgdGhlIHBhdHRlcm5zIG9mIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlbS4KCiNEYXRhClRoZSBmb2xsb3dpbmcgZGF0YXNldCBjb250YWlucyBoaXN0b3JpY2FsIGRhaWx5IGNsb3NpbmcgcHJpY2VzIGZyb20gNC8xLzIwMTQgdW50aWwgMy8zMS8yMDE5IGZvciAxMyBkaWZmZXJlbnQgRVRGcy4gVGhpcyBkYXRhIHdhcyByZXRyaWV2ZWQgZnJvbSBZYWhvbyBGaW5hbmNlLiBBIHNlcGFyYXRlIENTViBmaWxlIHdhcyBkb3dubG9hZGVkIGZvciBlYWNoIEVURi4gVGhlIGNvbHVtbiBvZiBjbG9zaW5nIHByaWNlcyBmcm9tIGVhY2ggZmlsZSB3YXMgY29waWVkIGludG8gYSBuZXcgQ1NWIGZpbGUuIFRoaXMgQ1NWIGZpbGUgd2FzIHVwbG9hZGVkIGFzICJFVEZfcHJpY2VzLmNzdiIKCkFuIGFkZGl0aW9uYWwgQ1NWIGZpbGUgIkVURl9lZGdlcy5jc3YiIHdhcyBjcmVhdGVkLiBUaGlzIGZpbGUgY29udGFpbnMgYW4gZWRnZSBsaXN0LCB3aGVyZSBub2RlcyBhcmUgdGhlIEVURnMuIEVkZ2VzIHJlcHJlc2VudCBhIGNvcnJlbGF0aW9uIGluIGNsb3NpbmcgcHJpY2UsIGFuZCBhbGwgbm9kZXMgYXJlIGNvbm5lY3RlZC4gVGhlIENTViBmaWxlIGhhcyBhIGNvbHVtbiBjb250YWluaW5nIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMsIGFuZCB0aGUgZWRnZSB3ZWlnaHRzIGFyZSBlcXVhbCB0byB0aGUgY29ycmVsYXRpb24gY29lZmljaWVudHMgbXVsdGlwbGllZCBieSAxMDAgYW5kIHRoZW4gcm91bmRlZCB0byB0aGUgbmVhcmVzdCBpbnRlZ2VyLgoKVGhlIDEzIEVURnMgYXJlIHRoZSBmb2xsb3dpbmc6CgoxKSBTUERSIFMmUCA1MDAgRVRGIChTUFkpCiAgICAgIFRoaXMgZnVuZCB0cmFja3MgdGhlIHBlcmZvcm1hbmNlIG9mIHRoZSBTJlAgNTAwIGluZGV4CjIpIFZhbmd1YXJkIFMmUCA1MDAgRVRGIChWT08pCiAgICAgIFRoaXMgZnVuZCBhbHNvIHRyYWNrcyB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIFMmUCA1MDAgaW5kZXgKMykgSW52ZXNjbyBRUVEgVHJ1c3QgKFFRUSkKICAgICAgVGhpcyBmdW5kIHRyYWNrcyB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIE5BU0RBUSBpbmRleAo0KSBWYW5ndWFyZCBUb3RhbCBTdG9jayBNYXJrZXQgSW5kZXggRnVuZCBFVEYgKFZUSSkKICAgICAgVGhpcyBmdW5kIHRyYWNrcyB0aGUgcGVyZm9ybWFuY2Ugb2YgdGhlIGVudGlyZXR5IG9mIHRoZSBVUyBzdG9jayBtYXJrZXQKNSkgVmFuZ3VhcmQgVG90YWwgSW50ZXJuYXRpb25hbCBTdG9jayBJbmRleCBGdW5kIEVURiAoVlhVUykKICAgICAgVGhpcyBmdW5kIHRyYWNrcyB0aGUgb3ZlcmFsbCBwZXJmb3JtYW5jZSBvZiBzdG9jayBtYXJrZXRzIGFyb3VuZCB0aGUgd29ybGQKNikgVmFuZ3VhcmQgRlRTRSBEZXZlbG9wZWQgTWFya2V0cyBJbmRleCBGdW5kIEVURiAoVkVBKQogICAgICBUaGlzIGZ1bmQgdHJhY2tzIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgc3RvY2sgbWFya2V0cyBvZiBkZXZlbG9wZWQgZWNvbm9taWVzIAogICAgICBvdXRzaWRlIE5vcnRoIEFtZXJpY2EsIHN1Y2ggYXMgSmFwYW4gYW5kIFdlc3Rlcm4gRXVyb3BlYW4gbmF0aW9ucwo3KSBWYW5ndWFyZCBGVFNFIEVtZXJnaW5nIE1hcmtldHMgSW5kZXggRnVuZCBFVEYgKFZXTykKICAgICAgVGhpcyBmdW5kIHRyYWNrcyB0aGUgb3ZlcmFsbCBwZXJmb3JtYW5jZSBvZiB0aGUgc3RvY2sgbWFya2V0cyBpbiBtYW55ICAgICAKICAgICAgZGV2ZWxvcGluZyBlY29ub21pZXMKOCkgVmFuZ3VhcmQgSGlnaCBEaXZpZGVuZCBZaWVsZCBJbmRleCBGdW5kIEVURiAoVllNKQogICAgVGhpcyBmdW5kIGZvY3VzZXMgb24gVVMgbGFyZ2UtY2FwIHN0b2NrcyB0aGF0IHBheSBkaXZpZGVuZHMKOSkgVmFuZ3VhcmQgRGl2aWRlbmQgQXBwcmVjaWF0aW9uIEluZGV4IEZ1bmQgRVRGIChWSUcpCiAgICBUaGlzIGZ1bmQgdHJhY2tzIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgTkFTREFRIFVTIERpdmlkZW5kIEFjaGlldmVycyBTZWxlY3QgCiAgICBJbmRleCwgd2hpY2ggaXMgY29tcHJpc2VkIG9mIFVTIGxhcmdlLWNhcCBkaXZpZGVuZC1wYXlpbmcgc3RvY2tzIHRoYXQgZXhoaWJpdCAKICAgIGNoYXJhY3RlcmlzdGljcyBvZiBncm93dGgKMTApIFZhbmd1YXJkIFZhbHVlIEluZGV4IEZ1bmQgRVRGIChWVFYpCiAgICBUaGlzIGZ1bmQgdHJhY2tzIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgTVNDSSBVUyBQcmltZSBNYXJrZXQgVmFsdWUgSW5kZXgsIAogICAgZm9jdXNpbmcgb24gVVMgc3RvY2tzIHRoYXQgYWRoZXJlIHRvIHRoZSB2YWx1ZSBzdHlsZSBvZiBpbnZlc3RpbmcgICAKMTEpIFZhbmd1YXJkIEdyb3d0aCBJbmRleCBGdW5kIEVURiAoVlVHKQogICAgVGhpcyBmdW5kIHRyYWNrcyB0aGUgTVNDSSBVUyBQcmltZSBNYXJrZXQgR3Jvd3RoIEluZGV4LCBmb2N1c2luZyBvbiBsYXJnZS1jYXAgCiAgICBVUyBzdG9ja3MgdGhhdCBhZGdlcmUgdG8gdGhlIGdyb3d0aCBzdHlsZSBvZiBpbnZlc3RpbmcKMTIpIFZhbmd1YXJkIE1pZC1DYXAgVmFsdWUgSW5kZXggRnVuZCBFVEYgKFZPRSkKICAgIFRoaXMgZnVuZCB0cmFja3MgdGhlIHBlcmZvcm1hbmNlIG9mIG1pZC1jYXAgVVMgc3RvY2tzLCBmb2xsb3dpbmcgYSB2YWx1ZSAKICAgIGludmVzdGluZyBzdHlsZQoxMykgVmFuZ3VhcmQgU21hbGwtQ2FwIEdyb3d0aCBJbmRleCBGdW5kIEVURiAoVkJLKQogICAgVGhpcyBmdW5kIHRyYWNrcyB0aGUgcGVyZm9ybWFuY2Ugb2Ygc21hbGwtY2FwIFVTIHN0b2NrcywgZm9sbG93aW5nIGEgZ3Jvd3RoIAogICAgaW52ZXN0aW5nIHN0eWxlCiAgICAKQWxsIG9mIHRoZXNlIEVURnMgYXJlIGxvdy1jb3N0LCBwYXNzaXZlbHkgbWFuYWdlZCBmdW5kcyB0aGF0IGhvbGQgaHVuZHJlZHMgb2YgcG9zaXRpb25zLiBUaGUgcHVycG9zZSBvZiB0aGVzZSB0eXBlcyBvZiBmdW5kcyBpcyB0byBwcm92aWRlIGludmVzdG9ycyB3aXRoIHdpZGUtZXhwb3N1cmUgdG8gYSBzcGVjaWZpYyBhcmVhIG9mIHRoZSBtYXJrZXQgd2hpbGUgZGl2ZXJzaWZ5aW5nIGJldHdlZW4gZGlmZmVybmV0IGVxdWl0aWVzIHdpdGhpbiB0aGF0IGFyZWEuIFNvbWUgb2YgdGhlc2UgZnVuZHMgc2ltcGx5IHRyYWNrIG1ham9yIGluZGljZXMgbGlrZSB0aGUgUyZQIDUwMCBvciB0aGUgTkFTREFRLCB3aGlsZSBvdGhlcnMgZG9uJ3QgdHJhY2sgYSBzcGVjaWZpYyBpbmRleCBidXQgcmF0aGVyIGVtcGxveSBhIGJyb2FkIHN0cmF0ZWd5IGluIG9yZGVyIHRvIGdlbmVyYXRlIHJldHVybnMgdGhhdCBhcmUgcmVwcmVzZW50YXRpdmUgb2YgdGhhdCBzZWdtZW50IG9mIHRoZSBtYXJrZXQuIEZvciBleGFtcGxlLCB0aGUgc3RyYXRlZ3kgb2YgVldPIGlzIHRvIGludmVzdCBpbiBmb3JlaWduLCBlbWVyZ2luZyBtYXJrZXRzIHRoYXQgYXJlIGNhcGFibGUgb2YgZ3Jvd2x5IG1vcmUgcXVpY2tseSB0aGFuIG1vcmUgZXN0YWJsaXNoZWQgbWFya2V0cy4gVlRWLCBob3dldmVyLCBmb2N1c29uIG9uIGxhcmdlIFVTIHZhbHVlIGNvbXBhbmllcy4gQSB2YWx1ZSBjb21wYW55IG1heSBvciBtYXkgbm90IGhhdmUgdmVyeSBoaWdoIGdyb3d0aCByYXRlczsgdGhlIGNvcmUgb2YgdGhlIHZhbHVlIGludmVzdGluZyBzdHlsZSBpcyB0byBidXkgc3RvY2tzIGF0IGEgZGlzY291bnQgdG8gdGhlaXIgaW50cmluc2ljIHZhbHVlLiBJbiBmYWN0LCBsb25nLXRlcm0gc3RvY2sgbWFya2V0IGFuYWx5c2VzIGhhdmUgcmV2ZWFsZWQgdGhlIG1lcml0cyBvZiB2YWx1ZSBpbnZlc3RpbmcuIE9uZSBzdHVkeSBhdCBZYWxlIFVuaXZlcnNpdHkgZGVtb25zdHJhdGVkIHRoYXQgYnV5aW5nIGEgc3RvY2sgYWJvdmUgYSBmYWlyIHZhbHVhdGlvbiBtYXRlcmlhbGx5IGRlY3JlYXNlZCB0b3RhbCByZXR1cm5zIGZvciB1cCB0byAzMCB5ZWFycyBpbnRvIHRoZSBmdXR1cmUgKHJlZmVybmVjZSB0byBZYWxlIGFydGljbGUpLgoKKEVURiBkYXRhIGZyb20gRVRGZGIuY29tKQoKVGhlIGxhc3Qgcm93IHdhcyByZW1vdmVkIGZyb20gRVRGX3ByaWNlcyBiZWNhdXNlIGFuIGVtcHR5IHJvdyB3YXMgYXV0b21hdGljYWxseSBhZGRlZCB0byB0aGUgQ1NWIGZpbGUgYWZ0ZXIgc2F2aW5nIGl0LiBFVEZfcHJpY2VzIHdhcyBhbHNvIHRyaW1tZWQgdG8gY29udGFpbiBvbmx5IHRoZSBmaXJzdCAxNCBjb2x1bW5zIGZvciB0aGUgc2FtZSByZWFzb24uIFRoaXMgd2FzIG5lZWRlZCB0byBlbnN1cmUgdGhhdCBhbGwgdmFsdWVzIGNvbnRhaW5lZCBpbiB0aGUgQ1NWIGZpbGUgd2VyZSBudW1lcmljLCB3aGljaCB3YXMgbmVlZGVkIGZvciB0aGUgZm9sbG93aW5nIGNhbGN1bGF0aW9ucy4KYGBge3J9CmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoaWdyYXBoKQpFVEZfcHJpY2VzIDwtIHJlYWRfY3N2KCJFVEZfcHJpY2VzLmNzdiIpCkVURl9wcmljZXMgPC0gRVRGX3ByaWNlc1stbnJvdyhFVEZfcHJpY2VzKSwxOjE0XQpgYGAKCiNNZXRob2RzCkNvcnJlbGF0aW9ucyB3ZXJlIGNhbGN1bGF0ZWQgYmV0d2VlbiB0aGUgdmVjdG9ycyBvZiBoaXN0b3JpY2FsIGNsb3NpbmcgcHJpY2UgZGF0YSBmb3IgZWFjaCBwYWlyIG9mIEVURnMuIFRoZSBjb3JyZWxhdGlvbnMgd2VyZSB1c2VkIHRvIGdpdmUgcHJvcG9ydGlvbmFsIGVkZ2Ugd2VpZ2h0cyBpbiBhIGNvbXBsZXRlIG5ldHdvcmsuIFRoZSBlZGdlIHdlaWdodCB3YXMgc2V0IHRvIHRoZSBuZWFyZXN0IGludGVnZXIgdG8gMTAwIHRpbWVzIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudC4KCkEgaGVhdCBtYXAgd2FzIGNyZWF0ZWQgdG8gdmlzdWFsaXplIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgYmV0d2VyZW4gZWFjaCBwYWlyIG9mIEVURnMuIEEgaGlzdG9ncmFtIHdhcyBhbHNvIHBsb3R0ZWQgdG8gdmlzdWxhaXplIHRoZSBkaXN0cmlidXRpb24gb2YgY29ycmVsYXRpb24gY29lZmZpY2VudHMgYmV3dHdlZW4gRVRGcy4gVGhlIGdyYXBoIG9mIHRoZSBFVEZzIHdhcyBwbG90dGVkIHVzaW5nIGEgZm9yY2UgZGlyZWN0ZWQgbGF5b3V0LCBzbyB0aGF0IG5vZGVzIHdpdGggaGVhdmllciBlZGdlcyBiZXR3ZWVuIHRoZW0gd2VyZSBjbG9zZXIgdG9nZXRoZXIuIEVkZ2UgdGhpY2tuZXNzIHdhcyBhbHNvIHNldCBwcm9wb3J0aW9uYWxseSB0byBlZGdlIHdlaWdodCBpbiBvcmRlciB0byB2aXN1YWxpemUgdGhlIHJlbGF0aXZlIGNvcnJlbGFyeSBzdHJlbmd0aHMsIAoKVGhlIG5ldHdvcmsgd2FzIHRoZW4gcnVuIHRocm91Z2ggY29tbXVuaXR5IGRldGVjdGlvbiBhbGdvcml0aG0sIGZvY3VzaW5nIG9uIG1vZHVsYXJpdHkuIFRoZXNlIGFsZ29yaXRobXMgd2VyZSBhbHNvIHJ1biBvbiBhbiB1bndlaWdodGVkIHZlcnNpb24gaWYgdGhlIGdyYXBoIHRvIGVzdGFibGlzaCBhIGJhc2VsaW5lLiBBbm90aGVyIHBsb3Qgd2FzIHRoZW4gZ2VuZXJhdGVkIHRvIHZpc3VhbGl6ZSB0aGUgZGlmZmVybmV0IGNvbW11bml0aWVzIGluIHRoZSBFVEYgbmV0d29yay4KClRoZXNlIG1ldGhvZHMgd2VyZSB0aGVuIHJlZG9uZSB3aXRoIHByaWNlIGRhdGEgZnJvbSBlYWNoIGluZGl2aWR1YWwgeWVhciB3aXRoaW4gdGhlIGZpdmUgeWVhciBzYW1wbGUgaW4gb3JkZXIgdG8gY29tcGFyZSB0aGUgZGlmZmVyZW50IHJlc3VsdHMuCgojUmVzdWx0cwoKYGBge3J9CnN1bW1hcnkoRVRGX3ByaWNlc1ssLTFdKQpgYGAKCkNhbGN1bGF0ZSBjb3JyZWxhdGlvbiBtYXRyaXgKYGBge3J9CkVURl9Db3JfbWF0cml4IDwtIGNvcihFVEZfcHJpY2VzWywtMV0pCkVURl9Db3JfbWF0cml4CmBgYAoKQ3JlYXRlIGEgaGVhdCBtYXAgdG8gdmlzdWFsaXplIHRoZSByZWxhdGl2ZSBzdHJlbmd0aHMgb2YgY29ycmVsYXRpb24gYmV0d2VlbiBFVEZzLgpgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQoKY29ybWF0IDwtIEVURl9Db3JfbWF0cml4CiMgR2V0IGxvd2VyIHRyaWFuZ2xlIG9mIHRoZSBjb3JyZWxhdGlvbiBtYXRyaXgKICBnZXRfbG93ZXJfdHJpPC1mdW5jdGlvbihjb3JtYXQpewogICAgY29ybWF0W3VwcGVyLnRyaShjb3JtYXQpXSA8LSBOQQogICAgcmV0dXJuKGNvcm1hdCkKICB9CiAgIyBHZXQgdXBwZXIgdHJpYW5nbGUgb2YgdGhlIGNvcnJlbGF0aW9uIG1hdHJpeAogIGdldF91cHBlcl90cmkgPC0gZnVuY3Rpb24oY29ybWF0KXsKICAgIGNvcm1hdFtsb3dlci50cmkoY29ybWF0KV08LSBOQQogICAgcmV0dXJuKGNvcm1hdCkKICB9CiAgdXBwZXJfdHJpIDwtIGdldF91cHBlcl90cmkoY29ybWF0KQptZWx0ZWRfY29ybWF0IDwtIG1lbHQodXBwZXJfdHJpLCBuYS5ybSA9IFRSVUUpCgpnZ3Bsb3QoZGF0YSA9IG1lbHRlZF9jb3JtYXQsIGFlcyhWYXIyLCBWYXIxLCBmaWxsID0gdmFsdWUpKSsKIGdlb21fdGlsZShjb2xvciA9ICJ3aGl0ZSIpKwogc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBoaWdoID0gInJlZCIsIG1pZCA9ICJ3aGl0ZSIsIAogICBtaWRwb2ludCA9IDAsIGxpbWl0ID0gYygtMSwxKSwgc3BhY2UgPSAiTGFiIiwgCiAgIG5hbWU9IlBlYXJzb25cbkNvcnJlbGF0aW9uIikgKwogIHRoZW1lX21pbmltYWwoKSsgCiB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDEsIAogICAgc2l6ZSA9IDEyLCBoanVzdCA9IDEpKSsKIGNvb3JkX2ZpeGVkKCkKCmBgYAoKVGhlc2UgdmFsdWVzIGFuZCB0aGlzIGhpc3RvZ3JhbSBpbGx1c3RyYXRlIHRoZSBkaXN0cmlidXRpb24gb2YgY29ycmVsYXRpb24gY29lZmZpY2llbnRzIGJldHdlZW4gRVRGcy4gVGhlIG1ham9yaXR5IG9mIHRoZSBFVEZzIGhhdmUgYW4gciB2YWx1ZSBhYm92ZSAwLjksIHdoaWNoIGlzIGEgc3Ryb25nIGNvcnJlbGF0aW9uLiBIb3dldmVyLCB0aGVyZSBpcyBhIGdyb3VwIG9mIHNvbWUgcGFpcnMgb2YgRVRGcyB3aXRoIHIgdmFsdWVzIGJldHdlZW4gMC40IGFuZCAwLjcsIHdoaWNoIGlzIGEgbW9kZXJhdGVseSBzdHJvbmcsIHBvc2l0aXZlIGNvcnJlbGF0aW9uLiBUaGlzIGRvZXMgbm90IGluY2x1ZGUgc2VsZi1lZGdlcy4gQWRkaXRpb25hbGx5LCBpdCB3b3VsZCBiZSBwb3NzaWJsZSB0byBsb29rIHJlbW92ZSB0aGUgbGVzcyBjb3JyZWxhdGF0ZWQgcGFpcnMgaW4gb3JkZXIgdG8gZ2FpbiBpbnNpZ2h0IGludG8gdGhlIGRpZmZlcmVuY2VzIGluIGNvcnJlbGF0aW9ucyBvZiB0aGUgcGFpcnMgaW4gdGhlIDAuOSB0byAxLjAgcmFuZ2U7IGhvd2V2ZXIsIGFueSBkaWZmZXJlbmNlcyBvbiB0aGF0IHNtYWxsIGEgc2NhbGUgd291bGQgbGlrZWx5IGJlIHByYWN0aWNhbGx5IGluc2lnbmlmaWNhbnQgZHVlIHRvIHJhbmRvbSBtYXJrZXQgZmx1Y3R1YXRpb25zLiBUaGUgcHJpbWFyeSBpbnNpZ2h0IGZyb20gdGhpcyBpcyB0aGF0IHRoZSBtYWpvcml0eSBvZiBFVEZzIGFyZSBleHRyZW1lbHkgaGlnaGx5IGNvcnJlbGF0ZWQgd2l0aCBlYWNoIG90aGVyIHdoaWxlIGEgZmV3IEVURnMgaGFkIG9ubHkgYSBtb2RlcmF0ZSBjb3JyZWxhdGlvbiwgbWVhbmluZyB0aGVyZSB3YXMgYSBncmVhdGVyIGRpdmVyZ2VuY2UgaW4gcHJpY2UgcGF0dGVybnMsIHdoaWNoIG1heSByZWZsZWN0IGRpZmZlcmVuY2VzIGluIG92ZXJhbGwgcGVyZm9ybWFuY2UuIApgYGB7cn0Kc3VtbWFyeShFVEZfZWRnZXMkQ29ycmVsYXRpb24pCmBgYAoKYGBge3J9Cmhpc3QoRVRGX2VkZ2VzJENvcnJlbGF0aW9uLCBtYWluPSJGcmVxdWVuY3kgT2YgQ29ycmVsYXRpb24gQ29lZmZpY2llbnRzIGJldHdlZW4gRWRnZXMiLHhsYWI9IkNvcnJlbGF0aW9uIENvZWZmaWNpZW50IikKYGBgCgpgYGB7cn0KI0NyZWF0ZSBhbiB1bndlaWdodGVkLCBjb21wbGV0ZSBpR3JhcGggb2JqZWN0IGFuZCBhIHdlaWdodGVkLCBjb21wbGV0ZSBpR3JhcGggb2JqZWN0IHdpdGggZWFjaCBFVEYgYXMgYSBub2RlCkVURmdyYXBoIDwtIGdyYXBoLmRhdGEuZnJhbWUoRVRGX2VkZ2VzLCBkaXJlY3RlZCA9IEZBTFNFKQpFVEZncmFwaC53ZWlnaHRlZCA8LSBFVEZncmFwaApFKEVURmdyYXBoLndlaWdodGVkKSR3ZWlnaHQgPC0gRShFVEZncmFwaC53ZWlnaHRlZCkkV2VpZ2h0CmBgYAoKClRoaXMgcGxvdCBpbGx1c3RyYXRlcyB0aGUgcmVsYXRpb25zaGlwcyBiZXR3ZWVuIHRoZXNlIEVURnMgKG5vZGVzKS4gVGhpY2tlciBlZGdlcyBpbmRpY2F0ZSBhIHN0cm9uZ2VyIGNvcnJlbGF0aW9uLiBUaGUgdXNlIG9mIGEgZm9yY2UgbGF5b3V0IGNhdXNlcyB0aGUgbm9kZXMgdG8gYmUgcGxhY2VkIHN1Y2ggdGhhdCB0aGUgbm9kZXMgY29ubmVjdGVkIHdpdGggZ3JlYXRlciB3ZWlnaHQgKG1vcmUgaGlnaGx5IGNvcnJlbGF0ZWQpIGFyZSBjbG9zZXIgdG9nZXRoZXIuIFRoaXMgcGxvdCBnaXZlcyB0aGUgaW1wcmVzc2lvbiB0aGF0IFZYVVMsIFZXTywgYW5kIFZFQSBhcmUgbG9vc2VseSBjb25uZWN0ZWQgdG8gYWxsIG90aGVyIG5vZGVzIHdoaWxlIHRoZSByZW1haW5pbmcgbm9kZXMgYXJlIHRpZ2h0bHkgaW50ZXJjb25uZWN0ZWQuCmBgYHtyfQpzZXQuc2VlZCg1MCkKRShFVEZncmFwaC53ZWlnaHRlZCkkd2lkdGggPC0gRShFVEZncmFwaC53ZWlnaHRlZCkkd2VpZ2h0LzQyCnBsb3QoRVRGZ3JhcGgud2VpZ2h0ZWQsIGxheW91dD1sYXlvdXRfd2l0aF9mcikKYGBgCgpUaGVzZSBjYWxjdWxhdGlvbnMgZGV0ZWN0IGNvbW11bml0aWVzIGluIHRoZSB1bndlaWdodGVkIHZlcnNpb24gb2YgdGhlIGdyYXBoIGluIG9yZGVyIHRvIHByb3ZpZGUgYSBiYXNlbGluZSBmb3IgY29tcGFyaXNvbiB0byB0aGUgd2VpZ2h0ZWQgZ3JhcGguIFRoZSB1bndlaWdodGVkIGdyYXBoIGlzIGJhc2ljYWxseSBvbmUgbGFyZ2UgZ3JvdXAsIHdpdGggb25seSBWQksgb2NjdXB5aW5nIGEgc2VwYXJhdGUgY29tbXVuaXR5LiBUaGUgbW9kdWxhcml0eSBvZiBjbG9zZSB0byB6ZXJvIGluZGljYXRlcyB0aGF0IG92ZXJhbGwsIHRoZSB1bndlaWdodGVkIGdyYXBoIGxhY2tzIG11Y2ggb2YgYSBzZW5zZSBvZiBjb21tdW5pdGllcyBhbnl3aGVyZSwKYGBge3J9CkVURmNvbW11bml0eSA8LSBmYXN0Z3JlZWR5LmNvbW11bml0eShFVEZncmFwaCkKbGVuZ3RoKEVURmNvbW11bml0eSkKc2l6ZXMoRVRGY29tbXVuaXR5KQptZW1iZXJzaGlwKEVURmNvbW11bml0eSkKbW9kdWxhcml0eShFVEZjb21tdW5pdHkpCmBgYAoKVGhlc2UgY2FsY3VsYXRpb25zIGRldGVjdCBjb21tdW5pdGVzIGluIHRoZSB3ZWlnaHRlZCBncmFwaC4gVGhlIGdyYXBoIGlzIHNwbGl0IGludG8gdHdvIGdyb3Vwcy4gT25lIGdyb3VwIGhhcyBWWFVTLCBWRUEsIGFuZCBWV08sIGFuZCB0aGUgb3RoZXIgZ3JvdXAgaGFzIHRoZSBvdGhlciAxMCBub2Rlcy4gVGhlIG1vZHVsYXJpdHkgb2YgMC4wMjYsIHdoaWxlIHN0aWxsIHNtYWxsLCBpcyBvcmRlcnMgb2YgbWFnbml0aWRlIGdyZWF0ZXIgdGhhbiB0aGUgYmFzZWxpbmUgbW9kdWxhcml0eSwgaW5kaWNhdGluZyB0aGF0IHRoZSByZWxhdGl2ZSBlZGdlIHdlaWdodHMgYmFzZWQgb24gY29ycmVsYXRpb24gY29lZmZpY2VpbnRzIGRpZCBoYXZlIGEgbWF0ZXJpYWwgaW1wYWN0IGluIHRoZSBjb21tdW5pdHkgc3RydWN0dXJlIG9mIHRoZSBFVEZzLgpgYGB7cn0KRVRGY29tbXVuaXR5LndlaWdodGVkIDwtIGZhc3RncmVlZHkuY29tbXVuaXR5KEVURmdyYXBoLndlaWdodGVkKQpsZW5ndGgoRVRGY29tbXVuaXR5LndlaWdodGVkKQpzaXplcyhFVEZjb21tdW5pdHkud2VpZ2h0ZWQpCm1lbWJlcnNoaXAoRVRGY29tbXVuaXR5LndlaWdodGVkKQptb2R1bGFyaXR5KEVURmNvbW11bml0eS53ZWlnaHRlZCkKYGBgCgpUaGlzIHBsb3QgaWxsdXN0cmF0ZXMgdGhlIHNlcGFyYXRpb24gb2YgdGhlIHR3byBjb21tdW5pdGVzLiBWRUEsIFZYVVMsIGFuZCBWV08gb2NjdXB5IHRoZWlyIG93biBzbWFsbCBjb21tdW5pbnR5IGFzaWRlIGZvcm0gdGhlIG1ham9yaXR5IG9mIG5vZGVzLiBJbiB0aGUgZWFybGllciBwbG90LCB0aGVzZSB0aHJlZSBFVEZzIGFwcGVhcmVkIHRvIGJlIG1vcmUgcGVyaXBoZXJhbCwgYW5kIHRoZSBjb21tdW5pdHkgZGV0ZWN0aW9uIGFsZ29yaXRobSBjb25maXJtcyB0aGF0IGlkZWEuCmBgYHtyfQpzZXQuc2VlZCg1MCkKcGxvdChFVEZjb21tdW5pdHkud2VpZ2h0ZWQsRVRGZ3JhcGgud2VpZ2h0ZWQpCmBgYAoKTG9va2luZyBhdCBqdXN0IEFwcmlsIDEsIDIwMTQgdW50aWwgTWFyY2ggMzEgMjAxNSwgdGhlIG1ham9yaXR5IG9mIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgYmV0d2VlbiBFVEZzIGFyZSBhYm92ZSAwLjg7IGhvd2V2ZXIsIGluc3RlYWQgb2YgYSB0aGVyZSBiZWluZyBhIGdyb3VwIG9mIG1vZGVyYXRlbHksIHBvc2l0aXZlbHkgY29ycmVsYXRhdGVkIEVURnMsIHRoZXJlIGlzIGEgZ3JvdXAgb2Ygd2Vha2x5LW1vZGVyYXRlbHksIG5lZ2F0aXZlbHkgY29ycmVsYXRlZCBFVEZzLiBUaGUgcHJlc2VuY2Ugb2YgdGhlc2UgbmVnYXRpdmUgY29ycmVsYXRpb25zIGlzIGluZGljYXRpdmUgb2YgaGlnaGVyIGFtb3VudHMgb2YgdmFyaWF0aW9uIGJldHdlZW4gRVRGcyBpbiBzaG9ydGVyIHRpbWUgcGVyaW9kcyB3aGlsZSB0aGV5IHRlbmQgdG8gY29udmVyZ2UgbW9yZSBvdmVyIGxvbmdlciB0aW1lIHBlcmlvZHMuCmBgYHtyfQpFVEZfZWRnZXNfWTEgPC0gcmVhZF9jc3YoIi9Vc2Vycy9qYXJlZG1hY2Jvb2svRG9jdW1lbnRzL1IvTUFUSCAxOTAgZGF0YS9NQVRIIDE5MCBGaW5hbCBQcm9qZWN0L0VURl9lZGdlc19ZMS5jc3YiKQpzdW1tYXJ5KEVURl9lZGdlc19ZMSRDb3JyZWxhdGlvbikKaGlzdChFVEZfZWRnZXNfWTEkQ29ycmVsYXRpb24sIG1haW49IkZyZXF1ZW5jeSBPZiBDb3JyZWxhdGlvbiBDb2VmZmljaWVudHMgYmV0d2VlbiBFZGdlcyIseGxhYj0iQ29ycmVsYXRpb24gQ29lZmZpY2llbnQiKQpgYGAKCmBgYHtyfQojQ3JlYXRlIGFuIHVud2VpZ2h0ZWQsIGNvbXBsZXRlIGlHcmFwaCBvYmplY3QgYW5kIGEgd2VpZ2h0ZWQsIGNvbXBsZXRlIGlHcmFwaCBvYmplY3Qgd2l0aCBlYWNoIEVURiBhcyBhIG5vZGUKI0FkZCAxMDAgdG8gZWFjaCBlZGdlIHdlaWdodCB0byB0dXJuIG5lZ2F0aXZlIGVkZ2Ugd2VpZ2h0cyBwb3NpdGl2ZSB3aGlsZSBtYWludGFpbmluZyB0aGUgc2FtZSByZWxhdGl2ZSB3ZWlnaHRpbmcKRVRGZ3JhcGguWTEgPC0gZ3JhcGguZGF0YS5mcmFtZShFVEZfZWRnZXNfWTEsIGRpcmVjdGVkID0gRkFMU0UpCkUoRVRGZ3JhcGguWTEpJHdlaWdodCA8LSAoRShFVEZncmFwaC5ZMSkkV2VpZ2h0ICsgMTAwKQoKRShFVEZncmFwaC53ZWlnaHRlZCkkd2lkdGggPC0gRShFVEZncmFwaC53ZWlnaHRlZCkkd2VpZ2h0LzQyCnNldC5zZWVkKDUwKQpwbG90KEVURmdyYXBoLndlaWdodGVkLCBsYXlvdXQ9bGF5b3V0X3dpdGhfZnIpCmBgYAoKVGhlIGNvcnJlbGF0aW9uIG5ldHdvcmsgZnJvbSBqdXN0IHRoZSBmaXJzdCB5ZWFyIG9mIHRoZSBmaXZlIHllYXIgc2FtcGxlIHNwbGl0cyBpbnRvIHRoZSBleGFjdCBzYW1lIHR3byBjb21tdW5pdGllcyBhcyB0aGUgbmV0d29yayB0aGF0IGluY2x1ZGVzIGFsbCBmaXZlIHllYXJzLiBUaGUgbW9kdWxhcml0eSBmb3IgdGhpcyBuZXR3b3JrIGlzIGFsc28gYWJvdXQgZG91YmxlIHRoYXQgb2YgdGhlIGZpdmUgeWVhciBwZXJpb2QgbmV0d29yaywgaW5kaWNhdGluZyB0aGF0IHRoZXNlIHNhbWUgY29tbXVuaXRpZXMgYXJlIG1vcmUgdGlnaHRseSBjb25uZWN0ZWQgb3ZlciB0aGlzIHNpbmdsZSB5ZWFyLgpUaGlzIGNvdWxkIG1lYW4gdGhhdDogCjEpIFZYVVMsIFZFQSwgYW5kIFZXTyB3ZXJlIG1vcmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIgZHVyaW5nIHRoaXMgcGVyaW9kIHRoYW4gb3ZlcmFsbAoyKSBUaGUgb3RoZXIgc2V2ZW4gRVRGcyB3ZXJlIG1vcmUgY29ycmVsYXRlZCB3aXRoIGVhY2ggb3RoZXIgZHVyaW5nIHRoaXMgdGltZSBwZXJpb2QgdGhhbiBvdmVyYWxsCjMpIFZYVVMsIFZFQSwgYW5kIFZXTyB3ZXJlIGxlc3MgY29ycmVsYXRlZCB3aXRoIHRoZSBvdGhlciBzZXZlbiBFVEZzIGR1cmluZyB0aGlzIHBlcmlvZCB0aGFuIG92ZXJhbGwKVGhlIHRoaXJkIHNlZW1zIG1vc3QgbGlrZWx5IGFzIGl0IGV4cGxhaW5zIHRoZSBtZWFuaW5nZnVsIG51bWJlciBvZiBuZWdhdGl2ZSBjb3JyZWxhdGlvbnMuCmBgYHtyfQpFVEZjb21tdW5pdHkuWTEgPC0gZmFzdGdyZWVkeS5jb21tdW5pdHkoRVRGZ3JhcGguWTEpCmxlbmd0aChFVEZjb21tdW5pdHkuWTEpCnNpemVzKEVURmNvbW11bml0eS5ZMSkKbWVtYmVyc2hpcChFVEZjb21tdW5pdHkuWTEpCm1vZHVsYXJpdHkoRVRGY29tbXVuaXR5LlkxKQpgYGAKCmBgYHtyfQpzZXQuc2VlZCg1MCkKcGxvdChFVEZjb21tdW5pdHkuWTEsRVRGZ3JhcGguWTEpCmBgYAoKI0Rpc2N1c3Npb24KVlhVUywgVkVBLCBhbmQgVldPIGVtZXJnZWQgYXMgYSBjb21tdW5pdHkgYm90aCBvdmVyIHRoZSBlbnRpcmUgZml2ZSB5ZWFyIHNwYW4gYW5kIG92ZXIgdGhlIGNvdXJzZSBvZiB0aGUgZmlyc3QgeWVhciB3aXRoaW4gdGhhdC4gVGhlc2UgZnVuZHMgYXJlIFZhbmd1YXJkIFRvdGFsIEludGVybmF0aW9uYWwgU3RvY2sgSW5kZXggRnVuZCBFVEYgKFZYVVMpLCBWYW5ndWFyZCBGVFNFIERldmVsb3BlZCBNYXJrZXRzIEluZGV4IEZ1bmQgRVRGIChWRUEpLCBhbmQgVmFuZ3VhcmQgRlRTRSBFbWVyZ2luZyBNYXJrZXRzIEluZGV4IEZ1bmQgRVRGIChWV08pLiBJdCBtYWtlcyBzZW5zZSB0aGF0IHRoZXNlIGFyZSBoaWdobHkgY29ycmVsYXRlZCBiZWNhdXNlIHRoZXkgYWxsIGZvY3VzIG9uIGVxdWl0aWVzIG91dHNpZGUgb2YgTm9ydGggQW1lcmljYSB3aGlsZSB0aGUgb3RoZXIgc2V2ZW4gRVRGcyBmb2N1cyBvbiBBbWVyaWNhbiBlcXVpdGllcy4gT25lIHBvc3NpYmxlIGNvbmNsdXNpb24gaXMgdGhhdCB0aGVyZSBpcyBub3QgbXVjaCBvZiBhIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdGhyZWUgaW50ZXJuYXRpb24gRVRGcyBkZXNwaXRlIG9uZSBiZWluZyBmb2N1c2VkIG9uIGRldmVsb3BlZCBlY29ub21pZXMgd2l0aCBhbm90aGVyIGJlaW5nIGZvY3VzZWQgb24gZW1lcmdpbmcgZWNvbm9taWVzLiBUaGUgY29ycmVsYXRpb24gY29lZmZpY2llbnQgZm9yIHRob3NlIHR3byBFVEZzIG92ZXIgYWxsIGZpdmUgeWVhcnMgd2FzIDAuOTIsIGluZGljYXRpbmcgYSB2ZXJ5IHN0cm9uZywgcG9zaXR2ZSBjb3JyZWxhdGlvbi4gQWRkaXRpb25hbGx5LCB0aGUgZmFjdCB0aGF0IHRoZSBvdGhlciBzZXZlbiBFVEZzIGZvcm1lZCBhIGNvbW11bml0eSwgY29tYmluZWQgd2l0aCB0aGUgZmFjdCB0aGF0IHRoZSBtYWpvcml0eSBvZiBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgd2VyZSBncmVhdGVyIHRoYW4gMC45LCBpbmRpY2F0ZXMgdGhhdCB0aGUgb3ZlcmFsbCBwZXJmb3JtYW5jZSBvZiB0aGVzZSBmdW5kcyB3YXMgcXVpdGUgc2ltaWxhciBkZXNwaXRlIHRoZSBmdW5kcyB2YXJ5aW5nIGluIHRoZWlyIGFwcHJvYWNoZXMsIHdoZXRoZXIgdGhhdCBiZSBncm93dGgsIHZhbHVlLCBoaWdoLXlpZWxkLCBkaXZpZGVuZCBncm93dGgsIGxhcmdlLWNhcCwgbWlkLWNhcCwgb3Igc21hbGwtY2FwLiBUaGlzIGhpZ2ggY29ycmVsYXRpb24gaW1wbGllcyB0aGF0IGludmVzdG1lbnQgcGVyZm9ybWFuY2Ugd291bGQgbm90IGRpZmZlciBtdWNoIGJldHdlZW4gdGhlc2Ugc2V2ZW4gZnVuZHMsIHdoaWNoIG1lYW5zIHRoYXQgYXR0ZW1wdGluZyB0byBkaXZlcnNpZnkgYnkgaW52ZXN0aW5nIGluIHNldmVyYWwgb2YgdGhlc2UgZnVuZHMgd291bGQgbm90IGJlIGVmZmVjdGl2ZS4gSXQncyBpbXBvcnRhbnQgdG8gbm90ZSwgaG93ZXZlciwgdGhhdCB0aGUgZml2ZSB5ZWFyIHBlcmlvZCBiZWluZyBhbmFseXplZCBpcyBlbnRpcmVseSBlbmNvbXBhc3NlZCBieSBhIGJ1bGwgbWFya2V0LiBJdCBpcyB0aHVzIGRpZmZpY3VsdCB0byBkZXRlcm1pbmUgaWYgdGhlc2UgY29uY2x1c2lvbnMgd291bGQgaG9sZCB0cnVlIGluIGEgYmVhciBtYXJrZXQsIHdoaWNoIGlzIHBlcmhhcHMgbW9yZSBpbXBvcnRhbnQgYmVjYXVzZSBhIGJlYXIgbWFya2V0IGlzIHdoZW4gcmVkdWNpbmcgcmlzayBiZWNvbWVzIG1vc3QgcHJ1ZGVudC4KCiNGdXR1cmUgQW5hbHlzaXMKVGhpcyBhbmFseXNpcyBjYW4gYmUgdGFrZW4gZnVydGhlciBpbiB0d28gc2V0cyBvZiB3YXlzLiBGaXJzdCwgdGhlIHBhcmFtZXRlcnMgb2YgdGhpcyBhbmFseXNpcyBjb3VsZCBiZSBhbHRlcmVkLiBGb3IgZXhhbXBsZSwgaW5jbHVkaW5nIG1vcmUgRVRGcywgaW5jbHVkaW5nIGRpZmZlcmVudCB0aW1lIHBlcmlvZHMsIGNvdmVyaW5nIGEgbG9uZ2VyIHRpbWUgcGVyaW9kLCAgdXNpbmcgb3BlbmluZyBwcmljZXMsIG9yIHVzaW5nIGRhaWx5IGF2ZXJhZ2UgcHJpY2VzIGNvdWxkIHBvc3NpYmx5IHByb3ZpZGUgbW9yZSBpbnNpZ2h0LiBBZGRpdGlvbmFsbHksIGFuYWx5emluZyBhIGdyZWF0ZXIgbnVtYmVyIG9mIGZ1bmRzIHdvdWxkIGFsbG93IGZvciBjb21tdW5pdHkgZGV0ZWN0aW9uIGF0IGEgaGlnaGVyIHJlc29sdXRpb24uIEFsc28sIGluc3RlYWQgb2YgY3JlYXRpbmcgYSBjb21wbGV0ZSBncmFwaCB3aXRoIHZhcnlpbmcgZWRnZSB3ZWlnaHRzIGNvcnJlc3BvbmRpbmcgdG8gY29ycmVsYXRpb24gc3RyZW5ndGgsIGl0IG1heSBiZSBpbnRlcmVzdGluZyB0byBvbmx5IHNldCB0aGUgZWRnZSBpZiB0aGUgciB2YWx1ZSBpcyBhYm92ZSAwLjUgb3IgZXZlbiAwLjguIFRoaXMgd291bGQgbGlrZWx5IGhhdmUgYSBtYXRlcmlhbCBhZmZlY3Qgb2YgdGhlIG5hdHVyZSBhbmQgY29tbXVuaXR5IHN0cnVjdHVyZSBvZiB0aGUgZ3JhcGguIFNlY29uZGx5LCB0aGUgRVRGcyBjb3VsZCBiZSBjb21wYXJlZCBpbiBvdGhlciB3YXlzIGJlc2lkZXMgcHJpY2UgY29ycmVsYXRpb25zLiBGb3IgZXhhbXBsZSwgY29ycmVsYXRpb25zIGluIHllYXJseSB0b3RhbCByZXR1cm5zIG92ZXIgdGltZSBvciBzaW1pbGFyaXR5IG9mIGhvbGRpbmdzIGNvdWxkIGFsc28gYmUgYW5hbHl6ZWQuIEl0IHdvdWxkIGFsc28gYmUgaW50ZXJlc3RpbmcgdG8gZGV0ZXJtaW5lIGhvdyBhY2N1cmF0ZSBwcmljZSBjb3JyZWxhdGlvbiBpcyBmb3IgcHJlZGljdGluZyByZWxhdGl2ZSBjYXBpYWwgYXBwcmVjaWF0aW9uLgoKCiNTb3VyY2VzCkVURmRiLmNvbQoKWWFob28gRmluYW5jZQo=