To construct the incidence matrix, N say, we could use
N <- crossprod(Xb,Xv)
However a simpler direct way of producing this matrix is to use table()
N <- table(blocks, varieties)
Index matrices must be numerical: any other form of matrix (e.g. a logical or character matrix) supplied as a matrix is treated as an indexing vector.
5.4 The array() function
As well as giving a vector structure a dim attribute, arrays can be constructed from vectors by the array function, which has the form
Z <- array(data_vector,dim_vector)
For example, if the vector h contains 24 or fewer, numbers then the command
Z <- array(h, dim=(3,4,2))
would use h to set up 3 by 4 by 2 array in Z. If the size of h is exactly 24 the result is the same as
Z <- h; dim(Z) <- c(3,4,2)
However if h is shorter than 24, its values are reycled from the beginning again to make it up to size 24 but dim(h) <- c(3,4,2) would signal an error about mismatching length. As an extreme but common example
Z <- array(0, c(3,4,2))
Z
, , 1
[,1] [,2] [,3] [,4]
[1,] 0 0 0 0
[2,] 0 0 0 0
[3,] 0 0 0 0
, , 2
[,1] [,2] [,3] [,4]
[1,] 0 0 0 0
[2,] 0 0 0 0
[3,] 0 0 0 0
makes Z an array of all zeroes
At this point dim(Z) stands for the dimension vector c(3,4,2), and Z[1:24] stands for the data vector as it was in h, and Z[] with an empty subscript or Z with no subscript stands for the entire array as an array.
Arrays may be used in arithmetic expressions and the result is an array formed by element-by-element operations on the data vector. The dim attributes of operands generally need to be the same, and this becomes the dimension vector of the result. So if A, B and C are all similar arrays, then
D <- 2 * A * B + C + 1
makes D a similar array with its data vector being the result of the given element-by-element operations. However the precise rule concerning mixed array and vector calculations has to be considered a little more carefully.
5.4.1 Mixed vector and array arithmetic. The recycling rule
The precise rule affecting element by element mixed calculations with vectors and arrays is somewhat quirky and hard to find in the references. From experience we have found the following to be a reliable guide.
- The expression is scanned from left to right.
- Any short vector operands are extended by recycling their values until they match the size of any other operands.
- As long as short vectors and arrays only are encountered, the arrays must all have the same dim attribute or an error results.
- Any vector operand longer than a matrix or array operand generates an error.
- If array structures are present and no error or coercion to vector has been precipitated, the result is an array structure with the common dim attribute of its array operands.
5.5 The outer product of two arrays
An important operation on arrays is the outer product. If a and b are two numeric arrays, their outer product is an array whose dimension vector is obtained by concatenating their two dimension vectors (order is important), and whose data vector is got by forming all possible products of elements of the data vector of a with those of b. The outer product is formed by the special operator %o%:
ab <- a %o% b
An alternative is
ab <- outer(a,b,"*")
The multiplication function can be replaced by an arbitrary function of two variables. For example if we wished to evaluate the function f(x;y) = cos(y)/(1+x2) over a regular grid of values with x- and y- coordinates defined by the R vectors x and y respectively, we could proceed as follows:
f <- fuction(x,y) cos(y)/(1+x2)
z <- outer(x,y,f)
In particular the outer product of two ordinary vectors is a doubly subscripted array(that is a matrix, of rank at most 1). Notice that the outer product operator is of course non-commutative. Defining R functions will be considered further in Chapter 10.
An example: Determinants of 2 by 2 single-digit matrices
As an artificial but cute example, consider the determinants of 2 by 2 matrices [a,b;c,d] where each entry is a non-negative integer in the rang 0, 1, …, 9, that is a digit.
The problem is to find the determinants, ad - bc, of all possible matrices of this form and represent the frequency with which each value occurs as a high density plot. This amounts to finding the probability distribution of the determinant if each digit is chosen independently and uniformly at random.
A neat way of doing this uses the outer() function twice:
d <- outer(0:9, 0:9)
fr <- table(outer(d,d,"-"))
plot(fr,xlab="Determinant",ylab="Frequency")

Plot() here uses a histogram like plot method, because it “sees” that fr is of class “table”.
5.6 Generalized transpose of an array
The function aperm(a,perm) may be used to permute an array, a. The argument perm must be a permutation of the integers {1, …, k}, where k is the number of subscripts in a. The result of the function is an array of the same size as a but with old dimension given by perm[j] becoming the new j-th dimension. The easiest way to think of this operation is as a generalization of transposition for matrices. Indeed if A is a matrix, (that is, a doubly subscripted array) then B given by
B <- aperm(a, c(2,1))
is just the transpose of A. For this special case a simpler function t() is available, so we coud have used B <- t(A).
5.7 Matrix facilities
As noted above, a matrix is just an array with two subscripts. However it is such an important special case it needs a separate discussion. R contains many operators and functions that are available only for matrices. For example t(X) is the matrix transpose function, as noted above. The functions nrow(A) and ncol(A) give the number of rows and columns in the matrix A respectively.
5.7.1 Matrix multiplication
The operator __%%__ is used for matrix multiplication. An n* by 1 or 1 by n matrix may of course be used as an n-vector if in the context such is appropriate. Conversely, vectors which occur in matrix multiplication expressions are automatically promoted either to row or column vectors, whichever is multiplicatively coherent, if possible, (although this is not always unambiguously possible, as we see later).
If, for example, A and B are square matrices of the same size, then
A * B
is the matrix of element by element products and
A %*% B
is the matrix product. If x is a vector, then
x %*% A %*% x
is the quadratic form.
The function crossprod() forms “crossproducts”, meaning that crossprod(X,y) is the same as t(X)%*%y but the operation is more efficient. If the second argument to crossprod() is omitted it is taken to be the same as the first.
The meaning of diag() depends on its argument. diag(v) where v is a vector, gives a diagonal matrix with elements of the vector as the diagonal entries. On the other hand diag(M), where M is a matrix, gives the vector of main diagonal entries of M. This is the same convention as that used for diag() in MATLAB. Also, somewhat confusingly, if k is a single numeric value then diag(k) is the k by k identity matrix!
5.7.2 Linear equations and inversion
Solving linear equations is the inverse of matrix multiplication. When after
b <- A %*% x
only A and b are given, the vector x is the solution of that linear equation system. In R,
solve(A,b)
solves the system, returning x (up to some accuracy loss). Note that in linear algebra, formally x = A-1b where A-1 denotes the inverse of A, which can be computed by
solve(A) but rarely is needed. Numerically, it is both inefficient and potentially unstable to compute x <- solve(A)%%b instead of solve(A,b).
The quadratic form xTA-1x which is used in multivariate computations, should be computed by something like x %*% solve(A,x), rather than computing the inverse of A.
5.7.3 Eigenvalues and eigenvectors
The function eigen(Sm) caluclates the eigenvalues and eigenvectors of a symetric matrix SM. The result of this function is a list of two components named values and vectors. The assignment
ev <- eigen(Sm)
will asign this list to ev. Then ev\(val__ is the vector of eigenvalues of __Sm__ and __ev\)vec is the matrix of corresponding eigenvectors. Had we only needed the eigenvalues we could have used the assignment:
evals <- eigen(Sm)$values
evals now holds the vector of eigenvalues and the second component is discarded. If the expression
eigen(Sm)
is used by itself as a command the two components are printed, with their names. For large matrices it is better to avoid computing the eigenvectors if they are not needed by using the expression
evals <- eigen(Sm, only.values = TRUE)$values
5.7.4 Singular value decomposition and determinants
The function svd(M) takes an arbitrary matrix argument, M, and calculates the singular value decomposition of M. This consists of a matrix of orthonormal columns U with the same column space as M, a second matrix of orthonormal columns V whose column space is the row space of M and a diagonal matrix of positive entries D such that M = U %*% D %*% t(V). D is actually returned as a vector of the diagonal elements. The result of svd(M) is actually a list of three components named d, u, and v, with evident meanings.
If M is in fact square, then, it is not hard to see that
absdetM <- prod(svd(M)$d(
calculates the absolute value of the determinant of M. If this calculation were needed often with a variety of matrices it could be defined as an R function
absdet <- function(M) prod(svd(M)$d)
after which we could use absdet() as just another R function. As a further trivial but potentially useful example, you might like to consider writing a function, say tr() to calculate the trace of a square matrix.
R has a builtin function det to calculate a determinant, including the sign, and another, determinant, to give the sign and modulus (optionally on log scale),
5.7.5 Least squares fitting and the QR decomposition
The function lsfit() returns a list giving results of a least squares fitting procedure. An assignment such as
ans <- lsfit(X,y)
gives the results of a least squares fit where y is the vector of observations and X is the design matrix. ls.diag() gives the follow-up for the function and among other things, regression diagnostics. Note that a grand mean term is automatically included and need not be included explicitly as a column of X. Further note that you almost always will prefer using lm(.) to lsfit() for regression modelling. Another closely related function is qr() and its allies. Consider the following assignments
Xplus <- qr(X) b <- qr.coef(Xplus,y) fit <- qr.fitted(Xplus,y) res <- qr.resid(Xplus,y)
These compute the orthogonal projection of y onto the range of X in fit, the projection onto the orthogonal complement in res and the coefficient vector for the projection in b, that is, b is essentially the result of the MATLAB ‘backslash’ operator.
It is not assumed that X has full column rank. Redundancies will be discovered and removed as they are found.
This alternative is the older, low-level way to perform least squares calculations. Although still useful in some contexts, it would now generally be replaced by the statistical models features.
5.9 The concatenation function, c(), with arrays
It should be noted that whereas cbind() and rbind() are concatenation functions that respect dim attributes, the basic c() function does not, but rather clears numeric objects of all dim and dimnames attributes. This is occasionally useful in its own right.
The official way to coerce an array back to a simple vector object is to use as.vector()
vec <- as.vector(X)
However a similar result can be achieved by using c() with just one argument, simply for thise side-effect:
vec <- c(X)
There are slight differences between the two, but ultimately the choice between them is largely a matter of style (with the former being preferable).
5.10 Frequency tables from factors
Recall that a factor defines a partition into groups. Similarly a pair of factors defines a two way cross classification, and so on. The function table() allows frequency tables to be calculated from equal length factors. If there are k factor arguments, the result is a k0way array of frequencies.
Suppose, for example, that statef is a factor giving the state code for each entry in a data vector. The assignment
statefr <- table(statef)
gives in statefr a table of frequencies of each state in the sample. The frequencies are ordered and labelled by the levels attribute of the factor. This simple case is equivalent to, but more convenient than,
statefr <- tapply(statef, statef, length)
Further suppose that incomef is a factor giving a suitably defined “income class” for each entry in the data vector, for example with the cut() function:
factor(cut(incomes, breaks = 35+10*(0:7))) -> incomef
Then to calculate a two-way table of frequencies:
table(incomef, statef)
Extension to higher-way frequency tables is immediate.
LS0tCnRpdGxlOiAiQ2hhcHRlciA1IC0gQXJyYXlzIGFuZCBNYXRyaWNlcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyMgNS4xIEFycmF5cyAjIwoKQW4gYXJyYXkgY2FuIGJlIGNvbnNpZGVyZWQgYXMgYSBtdWx0aXBseSBzdWJzY3JpcHRlZCBjb2xsZWN0aW9uIG9mIGRhdGEgZW50cmllcywgZm9yIGV4YW1wbGUgbnVtZXJpYy4gUiBhbGxvd3Mgc2ltcGxlIGZhY2lsaXRpZXMgZm9yIGNyZWF0aW5nIGFuZCBoYW5kbGluZyBhcnJheXMsIGFuZCBpbiBwYXJ0aWN1bGFyIHRoZSBzcGVjaWFsIGNhc2Ugb2YgbWF0cmljZXMuCgpBIGRpbWVuc2lvbiB2ZWN0b3IgaXMgYSB2ZWN0b3Igb2Ygbm9uLW5lZ2F0aXZlIGludGVnZXJzLiBJZiBpdHMgbGVuZ3RoIGlzICprKiB0aGVuIHRoZSBhcnJheSBpcyAqayotZGltZW5zaW9uYWwsIGUuZy4gYSBtYXRyaXggaXMgYSAyLWRpbWVuc2lvbmFsIGFycmF5LiBUaGUgZGltZW5zaW9ucyBhcmUgaW5kZXhlZCBmcm9tIG9uZSB1cCB0byB0aGUgdmFsdWVzIGdpdmVuIGluIHRoZSBkaW1lbnNpb24gdmVjdG9yLiAKCkEgdmVjdG9yIGNhbiBiZSB1c2VkIGJ5IFIgYXMgYW4gYXJyYXkgb25seSBpZiBpdCBoYXMgYSBkaW1lbnNpb24gdmVjdG9yIGFzIGl0cyAqZGltKiBhdHRyaWJ1dGUuIFN1cHBvc2UsIGZvciBleGFtcGxlLCBfX3pfXyBpcyBhIHZlY3RvciBvZiAxNTAwIGVsZW1lbnRzLiBUaGUgYXNzaWdubWVudAoKZGltKHopIDwtIGMoMyw1LDEwMCkKCmBgYHtyfQp6IDwtIGMoMDoxNDk5KQpsZW5ndGgoeikKZGltKHopIDwtIGMoMyw1LDEwMCkKZGltKHopCmBgYAoKZ2l2ZXMgaXQgdGhlICpkaW0qIGF0dHJpYnV0ZSB0aGF0IGFsbG93cyBpdCB0byBiZSB0cmVhdGVkIGFzIGEgMyBieSA1IGJ5IDEwMCBhcnJheS4gCgpPdGhlciBmdW5jdGlvbnMgc3VjaCBhcyBfX21hdHJpeCgpX18gYW5kIF9fYXJyYXkoKV9fIGFyZSBhdmFpbGFibGUgZm9yIHNpbXBsZXIgYW5kIG1vcmUgbmF0dXJhbCBsb29raW5nIGFzc2lnbm1lbnRzLgoKVGhlIHZhbHVlcyBpbiB0aGUgZGF0YSB2ZWN0b3IgZ2l2ZSB0aGUgdmFsdWVzIGluIHRoZSBhcnJheSBpbiB0aGUgc2FtZSBvcmRlciBhcyB0aGV5IHdvdWxkIG9jY3VyIGluIF9fRk9SVFJBTl9fLCB0aGF0IGlzICJjb2x1bW4gbWFqb3Igb3JkZXIiLCB3aXRoIHRoZSBmaXJzdCBzdWJzY3JpcHQgbW92aW5nIGZhc3Rlc3QgYW5kIHRoZSBsYXN0IHN1YnNjcmlwdCBzbG93ZXN0LgoKRm9yIGV4YW1wbGUgaWYgdGhlIGRpbWVuc2lvbiB2ZWN0b3IgZm9yIGFuIGFycmF5LCBzYXkgX19hX18sIGlzIGEgYygzLDQsMikgdGhlbiB0aGVyZSBhcmUgMyB4IDQgeCAyID0gMjQgZW50cmllcyBpbiBfX2FfXyBhbmQgdGhlIGRhdGEgdmVjdG9yIGhvbGRzIHRoZW0gaW4gdGhlIG9yZGVyIGFbMSwxLDFdLCBhWzIsMSwxXSwgLi4uLCBhWzIsNCwyXSwgYVszLDQsMl0uCgpBcnJheXMgY2FuIGJlIG9uZS1kaW1lbnNpb25hbDogc3VjaCBhcnJheXMgYXJlIHVzdWFsbHkgdHJlYXRlZCBpbiB0aGUgc2FtZSB3YXkgYXMgdmVjdG9ycyAoaW5jbHVkaW5nIHdoZW4gcHJpbnRpbmcpLCBidXQgdGhlIGV4Y2VwdGlvbnMgY2FuIGNhdXNlIGNvbmZ1c2lvbi4KCiMjIDUuMiBBcnJheSBpbmRleGluZy4gU3Vic2VjdGlvbnMgb2YgYW4gYXJyYXkgIyMKCkluZGl2aWR1YWwgZWxlbWVudHMgb2YgYW4gYXJyYXkgbWF5IGJlIHJlZmVyZW5jZWQgYnkgZ2l2aW5nIHRoZSBuYW1lIG9mIHRoZSBhcnJheSBmb2xsb3dlZCBieSB0aGUgc3Vic2NyaXB0cyBpbiBzcXVhcmUgYnJhY2tldHMsIHNlcGFyYXRlZCBieSBjb21tYXMuIAoKTW9yZSBnZW5lcmFsbHksIHN1YnNlY3Rpb25zIG9mIGFuIGFycmF5IG1heSBiZSBzcGVjaWZpZWQgYnkgZ2l2aW5nIGEgc2VxdWVuY2Ugb2YgKmluZGV4IHZlY3RvcnMqIGluIHBsYWNlIG9mIHN1YnNjcmlwdHM7IGhvd2V2ZXIgKmlmIGFueSBpbmRleCBwb3NpdGlvbiBpcyBnaXZlbiBhbiBlbXB0eSBpbmRleCB2ZWN0b3IsIHRoZW4gdGhlIGZ1bGwgcmFuZ2Ugb2YgdGhhdCBzdWJzY3JpcHQgaXMgdGFrZW4qLiAKCkNvbnRpbnVpbmcgdGhlIHByZXZpb3VzIGV4YW1wbGUsIF9fYVsyLCxdX18gaXMgYSA0IHggMiBhcnJheSB3aXRoIGRpbWVuc2lvbiB2ZWN0b3IgYyg0LDIpIGFuZCBkYXRhIHZlY3RvciBjb250YWluaW5nIHRoZSB2YWx1ZXMKCiRjKGFbMiwxLDFdLCBhWzIsMiwxXSwgYVsyLDMsMV0sIGFbMiw0LDFdLCBhWzIsMSwyXSxhWzIsMiwyXSxhWzIsMywyXSxhWzIsNCwyXSkkCgppbiB0aGF0IG9yZGVyLiBfX2FbLCxdX18gc3RhbmRzIGZvciB0aGUgZW50aXJlIGFycmF5LCB3aGljaCBpcyB0aGUgc2FtZSBhcyBvbWl0dGluZyB0aGUgc3Vic2NyaXB0cyBlbnRpcmVseSBhbmQgdXNpbmcgX19hX18gYWxvbmUuCgpGb3IgYW55IGFycmF5LCBzYXkgX19aX18sIHRoZSBkaW1lbnNpb24gdmVjdG9yIG1heSBiZSByZWZlcmVuY2VkIGV4cGxpY2l0bHkgYXMgX19kaW0oWilfXyAob24gZWl0aGVyIHNpZGUgb2YgYW4gYXNzaWdubWVudCkuCgpBbHNvLCBpZiBhbiBhcnJheSBuYW1lIGlzIGdpdmVuIHdpdGgganVzdCAqb25lIHN1YnNjcmlwdCBvciBpbmRleCB2ZWN0b3IqLCB0aGVuIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcyBvZiB0aGUgZGF0YSB2ZWN0b3Igb25seSBhcmUgdXNlZDsgaW4gdGhpcyBjYXNlIHRoZSBkaW1lbnNpb24gdmVjdG9yIGlzIGlnbm9yZWQuIAoKQWxzbywgaWYgYW4gYXJyYXkgbmFtZSBpcyBnaXZlbiB3aXRoIGp1c3QgKm9uZSBzdWJzY3JpcHQgb3IgaW5kZXggdmVjdG9yKiwgdGhlbiB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMgb2YgdGhlIGRhdGEgdmVjdG9yIG9ubHkgYXJlIHVzZWQ7IGluIHRoaXMgY2FzZSB0aGUgZGltZW5zaW9uIHZlY3RvciBpcyBpZ25vcmVkLiBUaGlzIGlzIG5vdCB0aGUgY2FzZSwgaG93ZXZlciwgaWYgdGhlIHNpbmdsZSBpbmRleCBpcyBub3QgYSB2ZWN0b3IgYnV0IGl0c2VsZiBhbiBhcnJheSwgYXMgd2UgbmV4dCBkaXNjdXNzLiAKCiMjIDUuMyBJbmRleCBtYXRyaWNlcyAjIwoKQXMgd2VsbCBhcyBhbiBpbmRleCB2ZWN0b3IgaW4gYW55IHN1YnNjcmlwdCBwb3NpdGlvbiwgYSBtYXRyaXggbWF5IGJlIHVzZWQgd2l0aCBhIHNpbmdsZSAqaW5kZXggbWF0cml4KiBpbiBvcmRlciBlaXRoZXIgdG8gYXNzaWduIGEgdmVjdG9yIG9mIHF1YW50aXRpZXMgdG8gYW4gaXJyZWd1bGFyIGNvbGxlY3Rpb24gb2YgZWxlbWVudHMgaW4gdGhlIGFycmF5LCBvciB0byBleHRyYWN0IGFuIGlycmVndWxhciBjb2xsZWN0aW9uIGFzIGEgdmVjdG9yLgoKQSBtYXRyaXggZXhhbXBsZSBtYWtlcyB0aGUgcHJvY2VzcyBjbGVhci4gSW4gdGhlIGNhc2Ugb2YgYSBkb3VibHkgaW5kZXhlZCBhcnJheSwgYW4gaW5kZXggbWF0cml4IG1heSBiZSBnaXZlbiBjb25zaXN0aW5nIG9mIHR3byBjb2x1bW5zIGFuZCBhcyBtYW55IHJvd3MgYXMgZGVzaXJlZC4gVGhlIGVudHJpZXMgaW4gdGhlIGluZGV4IG1hdHJpeCBhcmUgdGhlIHJvdyBhbmQgY29sdW1uIGluZGljZXMgZm9yIHRoZSBkb3VibHkgaW5kZXhlZCBhcnJheS4gU3VwcG9zZSBmb3IgZXhhbXBsZSB3ZSBoYXZlIGEgNCBieSA1IGFycmF5IF9fWF9fIGFuZCB3ZSB3aXNoIHRvIGRvIHRoZSBmb2xsb3dpbmc6CgoqIEV4dHJhY3QgZWxlbWVudHMgWFsxLDNdLCBYWzIsMl0gYW5kIFhbMywxXSBhcyBhIHZlY3RvciBzdHJ1Y3R1cmUsIGFuZAoqIFJlcGxhY2UgdGhlc2UgZW50cmllcyBpbiB0aGUgYXJyYXkgWCBieSB6ZXJvZXMuCgpJbiB0aGlzIGNhc2Ugd2UgbmVlZCBhIDMgYnkgMiBzdWJzY3JpcHQgYXJyYXksIGFzIGluIHRoZSBmb2xsb3dpbmcgZXhhbXBsZS4KCmBgYHtyfQp4IDwtIGFycmF5KDE6MjAsIGRpbT1jKDQsNSkpICMgR2VuZXJhdGUgYSA0IGJ5IDUgYXJyYXkuCngKYGBgCgpgYGB7cn0KaSA8LSBhcnJheShjKDE6MywzOjEpLCBkaW09YygzLDIpKSAjIEdlbmVyYXRlIGEgMyB4IDIgaW5kZXggYXJyYXkuCmkKYGBgCgpgYGB7cn0KeFtpXSAjIEV4dHJhY3QgdGhvc2UgZWxlbWVudHMKYGBgCgpgYGB7cn0KeFtpXSA8LSAwICNSZXBsYWNlIHRob3NlIGVsZW1lbnRzIGJ5IHplcm9zLgp4CmBgYAoKTmVnYXRpdmUgaW5kaWNlcyBhcmUgbm90IGFsbG93ZWQgaW4gaW5kZXggbWF0cmljZXMuIE5BIGFuZCB6ZXJvIHZhbHVlcyBhcmUgYWxsb3dlZDogcm93cyBpbiB0aGUgaW5kZXggbWF0cml4IGNvbnRhaW5pbmcgYSB6ZXJvIGFyZSBpZ25vcmVkLCBhbmQgcm93cyBjb250YWluaW5nIGFuIE5BIHByb2R1Y2UgYW4gTkEgaW4gdGhlIHJlc3VsdC4KCkFzIGEgbGVzcyB0cml2aWFsIGV4YW1wbGUsIHN1cHBvc2Ugd2Ugd2lzaCB0byBnZW5lcmF0ZSBhbiAodW5yZWR1Y2VkKSBkZXNpZ24gbWF0cml4IGZvciBhIGJsb2NrIGRlc2lnbiBkZWZpbmVkIGJ5IGZhY3RvcnMgX19ibG9ja3NfXyAoYiBsZXZlbHMpIGFuZCBfX3ZhcmlldGllc19fICh2IGxldmVscykuIEZ1cnRoZXIgc3VwcG9zZSB0aGVyZSBhcmUgX19uX18gcGxvdHMgaW4gdGhlIGV4cGVyaW1lbnQuIFdlIGNvdWxkIHByb2NlZWQgYXMgZm9sbG93czoKCjxkaXYgYWxpZ249ImNlbnRlciI+CgpYYiA8LSBtYXRyaXgoMCxuLGIpICAKWHYgPC0gbWF0cml4KDAsbix2KSAgCmliIDwtIGNiaW5kKDE6biwgYmxvY2tzKSAgCml2IDwtIGNiaW5kKDE6biwgdmFyaWV0aWVzKSAgClhiW2liXSA8LTEgIApYdltpdl0gPC0gMSAgClggPC0gY2JpbmQoWGIsWHYpCgo8ZGl2IGFsaWduPSJsZWZ0Ij4KClRvIGNvbnN0cnVjdCB0aGUgaW5jaWRlbmNlIG1hdHJpeCwgTiBzYXksIHdlIGNvdWxkIHVzZQoKPiBOIDwtIGNyb3NzcHJvZChYYixYdikKCkhvd2V2ZXIgYSBzaW1wbGVyIGRpcmVjdCB3YXkgb2YgcHJvZHVjaW5nIHRoaXMgbWF0cml4IGlzIHRvIHVzZSBfX3RhYmxlKClfXwoKPiBOIDwtIHRhYmxlKGJsb2NrcywgdmFyaWV0aWVzKQoKSW5kZXggbWF0cmljZXMgbXVzdCBiZSBudW1lcmljYWw6IGFueSBvdGhlciBmb3JtIG9mIG1hdHJpeCAoZS5nLiBhIGxvZ2ljYWwgb3IgY2hhcmFjdGVyIG1hdHJpeCkgc3VwcGxpZWQgYXMgYSBtYXRyaXggaXMgdHJlYXRlZCBhcyBhbiBpbmRleGluZyB2ZWN0b3IuCgo8ZGl2IGFsaWduPSJsZWZ0Ij4KCiMjIDUuNCBUaGUgYXJyYXkoKSBmdW5jdGlvbiAjIwoKQXMgd2VsbCBhcyBnaXZpbmcgYSB2ZWN0b3Igc3RydWN0dXJlIGEgX19kaW1fXyBhdHRyaWJ1dGUsIGFycmF5cyBjYW4gYmUgY29uc3RydWN0ZWQgZnJvbSB2ZWN0b3JzIGJ5IHRoZSBfX2FycmF5X18gZnVuY3Rpb24sIHdoaWNoIGhhcyB0aGUgZm9ybQoKPiBaIDwtIGFycmF5KCpkYXRhX3ZlY3RvciosKmRpbV92ZWN0b3IqKQoKRm9yIGV4YW1wbGUsIGlmIHRoZSB2ZWN0b3IgX19oX18gY29udGFpbnMgMjQgb3IgZmV3ZXIsIG51bWJlcnMgdGhlbiB0aGUgY29tbWFuZAoKPiBaIDwtIGFycmF5KGgsIGRpbT0oMyw0LDIpKSAKCndvdWxkIHVzZSBfX2hfXyB0byBzZXQgdXAgMyBieSA0IGJ5IDIgYXJyYXkgaW4gX19aX18uIElmIHRoZSBzaXplIG9mIF9faF9fIGlzIGV4YWN0bHkgMjQgdGhlIHJlc3VsdCBpcyB0aGUgc2FtZSBhcwoKPiBaIDwtIGg7IGRpbShaKSA8LSBjKDMsNCwyKQoKSG93ZXZlciBpZiBfX2hfXyBpcyBzaG9ydGVyIHRoYW4gMjQsIGl0cyB2YWx1ZXMgYXJlIHJleWNsZWQgZnJvbSB0aGUgYmVnaW5uaW5nIGFnYWluIHRvIG1ha2UgaXQgdXAgdG8gc2l6ZSAyNCBidXQgZGltKGgpIDwtIGMoMyw0LDIpIHdvdWxkIHNpZ25hbCBhbiBlcnJvciBhYm91dCBtaXNtYXRjaGluZyBsZW5ndGguIEFzIGFuIGV4dHJlbWUgYnV0IGNvbW1vbiBleGFtcGxlCgpgYGB7cn0KWiA8LSBhcnJheSgwLCBjKDMsNCwyKSkKWgpgYGAKCm1ha2VzIF9fWl9fIGFuIGFycmF5IG9mIGFsbCB6ZXJvZXMKCkF0IHRoaXMgcG9pbnQgX19kaW0oWilfXyBzdGFuZHMgZm9yIHRoZSBkaW1lbnNpb24gdmVjdG9yIGMoMyw0LDIpLCBhbmQgWlsxOjI0XSBzdGFuZHMgZm9yIHRoZSBkYXRhIHZlY3RvciBhcyBpdCB3YXMgaW4gX19oX18sIGFuZCBfX1pbXV9fIHdpdGggYW4gZW1wdHkgc3Vic2NyaXB0IG9yIF9fWl9fIHdpdGggbm8gc3Vic2NyaXB0IHN0YW5kcyBmb3IgdGhlIGVudGlyZSBhcnJheSBhcyBhbiBhcnJheS4KCkFycmF5cyBtYXkgYmUgdXNlZCBpbiBhcml0aG1ldGljIGV4cHJlc3Npb25zIGFuZCB0aGUgcmVzdWx0IGlzIGFuIGFycmF5IGZvcm1lZCBieSBlbGVtZW50LWJ5LWVsZW1lbnQgb3BlcmF0aW9ucyBvbiB0aGUgZGF0YSB2ZWN0b3IuIFRoZSBfX2RpbV9fIGF0dHJpYnV0ZXMgb2Ygb3BlcmFuZHMgZ2VuZXJhbGx5IG5lZWQgdG8gYmUgdGhlIHNhbWUsIGFuZCB0aGlzIGJlY29tZXMgdGhlIGRpbWVuc2lvbiB2ZWN0b3Igb2YgdGhlIHJlc3VsdC4gU28gaWYgX19BX18sIF9fQl9fIGFuZCBfX0NfXyBhcmUgYWxsIHNpbWlsYXIgYXJyYXlzLCB0aGVuCgo+IEQgPC0gMiAqIEEgKiBCICsgQyArIDEKCm1ha2VzIF9fRF9fIGEgc2ltaWxhciBhcnJheSB3aXRoIGl0cyBkYXRhIHZlY3RvciBiZWluZyB0aGUgcmVzdWx0IG9mIHRoZSBnaXZlbiBlbGVtZW50LWJ5LWVsZW1lbnQgb3BlcmF0aW9ucy4gSG93ZXZlciB0aGUgcHJlY2lzZSBydWxlIGNvbmNlcm5pbmcgbWl4ZWQgYXJyYXkgYW5kIHZlY3RvciBjYWxjdWxhdGlvbnMgaGFzIHRvIGJlIGNvbnNpZGVyZWQgYSBsaXR0bGUgbW9yZSBjYXJlZnVsbHkuIAoKIyMgNS40LjEgTWl4ZWQgdmVjdG9yIGFuZCBhcnJheSBhcml0aG1ldGljLiBUaGUgcmVjeWNsaW5nIHJ1bGUgIyMKClRoZSBwcmVjaXNlIHJ1bGUgYWZmZWN0aW5nIGVsZW1lbnQgYnkgZWxlbWVudCBtaXhlZCBjYWxjdWxhdGlvbnMgd2l0aCB2ZWN0b3JzIGFuZCBhcnJheXMgaXMgc29tZXdoYXQgcXVpcmt5IGFuZCBoYXJkIHRvIGZpbmQgaW4gdGhlIHJlZmVyZW5jZXMuIEZyb20gZXhwZXJpZW5jZSB3ZSBoYXZlIGZvdW5kIHRoZSBmb2xsb3dpbmcgdG8gYmUgYSByZWxpYWJsZSBndWlkZS4KCiogVGhlIGV4cHJlc3Npb24gaXMgc2Nhbm5lZCBmcm9tIGxlZnQgdG8gcmlnaHQuCiogQW55IHNob3J0IHZlY3RvciBvcGVyYW5kcyBhcmUgZXh0ZW5kZWQgYnkgcmVjeWNsaW5nIHRoZWlyIHZhbHVlcyB1bnRpbCB0aGV5IG1hdGNoIHRoZSBzaXplIG9mIGFueSBvdGhlciBvcGVyYW5kcy4KKiBBcyBsb25nIGFzIHNob3J0IHZlY3RvcnMgYW5kIGFycmF5cyAqb25seSogYXJlIGVuY291bnRlcmVkLCB0aGUgYXJyYXlzIG11c3QgYWxsIGhhdmUgdGhlIHNhbWUgX19kaW1fXyBhdHRyaWJ1dGUgb3IgYW4gZXJyb3IgcmVzdWx0cy4KKiBBbnkgdmVjdG9yIG9wZXJhbmQgbG9uZ2VyIHRoYW4gYSBtYXRyaXggb3IgYXJyYXkgb3BlcmFuZCBnZW5lcmF0ZXMgYW4gZXJyb3IuCiogSWYgYXJyYXkgc3RydWN0dXJlcyBhcmUgcHJlc2VudCBhbmQgbm8gZXJyb3Igb3IgY29lcmNpb24gdG8gdmVjdG9yIGhhcyBiZWVuIHByZWNpcGl0YXRlZCwgdGhlIHJlc3VsdCBpcyBhbiBhcnJheSBzdHJ1Y3R1cmUgd2l0aCB0aGUgY29tbW9uIF9fZGltX18gYXR0cmlidXRlIG9mIGl0cyBhcnJheSBvcGVyYW5kcy4KCiMjIDUuNSBUaGUgb3V0ZXIgcHJvZHVjdCBvZiB0d28gYXJyYXlzICMjCgpBbiBpbXBvcnRhbnQgb3BlcmF0aW9uIG9uIGFycmF5cyBpcyB0aGUgKm91dGVyIHByb2R1Y3QqLiBJZiBfX2FfXyBhbmQgX19iX18gYXJlIHR3byBudW1lcmljIGFycmF5cywgdGhlaXIgb3V0ZXIgcHJvZHVjdCBpcyBhbiBhcnJheSB3aG9zZSBkaW1lbnNpb24gdmVjdG9yIGlzIG9idGFpbmVkIGJ5IGNvbmNhdGVuYXRpbmcgdGhlaXIgdHdvIGRpbWVuc2lvbiB2ZWN0b3JzIChvcmRlciBpcyBpbXBvcnRhbnQpLCBhbmQgd2hvc2UgZGF0YSB2ZWN0b3IgaXMgZ290IGJ5IGZvcm1pbmcgYWxsIHBvc3NpYmxlIHByb2R1Y3RzIG9mIGVsZW1lbnRzIG9mIHRoZSBkYXRhIHZlY3RvciBvZiBfX2FfXyB3aXRoIHRob3NlIG9mIF9fYl9fLiBUaGUgb3V0ZXIgcHJvZHVjdCBpcyBmb3JtZWQgYnkgdGhlIHNwZWNpYWwgb3BlcmF0b3IgJW8lOgoKPiBhYiA8LSBhICVvJSBiCgpBbiBhbHRlcm5hdGl2ZSBpcwoKPiBhYiA8LSBvdXRlcihhLGIsIioiKQoKVGhlIG11bHRpcGxpY2F0aW9uIGZ1bmN0aW9uIGNhbiBiZSByZXBsYWNlZCBieSBhbiBhcmJpdHJhcnkgZnVuY3Rpb24gb2YgdHdvIHZhcmlhYmxlcy4gRm9yIGV4YW1wbGUgaWYgd2Ugd2lzaGVkIHRvIGV2YWx1YXRlIHRoZSBmdW5jdGlvbiAqZih4O3kpID0gY29zKHkpLygxK3heMl4pKiBvdmVyIGEgcmVndWxhciBncmlkIG9mIHZhbHVlcyB3aXRoICp4LSogYW5kICp5LSogY29vcmRpbmF0ZXMgZGVmaW5lZCBieSB0aGUgUiB2ZWN0b3JzIF9feF9fIGFuZCBfX3lfXyByZXNwZWN0aXZlbHksIHdlIGNvdWxkIHByb2NlZWQgYXMgZm9sbG93czoKCj4gZiA8LSBmdWN0aW9uKHgseSkgY29zKHkpLygxK3heMl4pICAKPiB6IDwtIG91dGVyKHgseSxmKQoKSW4gcGFydGljdWxhciB0aGUgb3V0ZXIgcHJvZHVjdCBvZiB0d28gb3JkaW5hcnkgdmVjdG9ycyBpcyBhIGRvdWJseSBzdWJzY3JpcHRlZCBhcnJheSh0aGF0IGlzIGEgbWF0cml4LCBvZiByYW5rIGF0IG1vc3QgMSkuIE5vdGljZSB0aGF0IHRoZSBvdXRlciBwcm9kdWN0IG9wZXJhdG9yIGlzIG9mIGNvdXJzZSBub24tY29tbXV0YXRpdmUuIERlZmluaW5nIFIgZnVuY3Rpb25zIHdpbGwgYmUgY29uc2lkZXJlZCBmdXJ0aGVyIGluIENoYXB0ZXIgMTAuCgpfX0FuIGV4YW1wbGU6IERldGVybWluYW50cyBvZiAyIGJ5IDIgc2luZ2xlLWRpZ2l0IG1hdHJpY2VzX18KCkFzIGFuIGFydGlmaWNpYWwgYnV0IGN1dGUgZXhhbXBsZSwgY29uc2lkZXIgdGhlIGRldGVybWluYW50cyBvZiAyIGJ5IDIgbWF0cmljZXMgW2EsYjtjLGRdIHdoZXJlIGVhY2ggZW50cnkgaXMgYSBub24tbmVnYXRpdmUgaW50ZWdlciBpbiB0aGUgcmFuZyAwLCAxLCAuLi4sIDksIHRoYXQgaXMgYSBkaWdpdC4KClRoZSBwcm9ibGVtIGlzIHRvIGZpbmQgdGhlIGRldGVybWluYW50cywgKmFkKiAtICpiYyosIG9mIGFsbCBwb3NzaWJsZSBtYXRyaWNlcyBvZiB0aGlzIGZvcm0gYW5kIHJlcHJlc2VudCB0aGUgZnJlcXVlbmN5IHdpdGggd2hpY2ggZWFjaCB2YWx1ZSBvY2N1cnMgYXMgYSAqaGlnaCBkZW5zaXR5KiBwbG90LiBUaGlzIGFtb3VudHMgdG8gZmluZGluZyB0aGUgcHJvYmFiaWxpdHkgZGlzdHJpYnV0aW9uIG9mIHRoZSBkZXRlcm1pbmFudCBpZiBlYWNoIGRpZ2l0IGlzIGNob3NlbiBpbmRlcGVuZGVudGx5IGFuZCB1bmlmb3JtbHkgYXQgcmFuZG9tLgoKQSBuZWF0IHdheSBvZiBkb2luZyB0aGlzIHVzZXMgdGhlIF9fb3V0ZXIoKV9fIGZ1bmN0aW9uIHR3aWNlOgoKYGBge3J9CmQgPC0gb3V0ZXIoMDo5LCAwOjkpCmZyIDwtIHRhYmxlKG91dGVyKGQsZCwiLSIpKQpwbG90KGZyLHhsYWI9IkRldGVybWluYW50Iix5bGFiPSJGcmVxdWVuY3kiKQpgYGAKCl9fUGxvdCgpX18gaGVyZSB1c2VzIGEgaGlzdG9ncmFtIGxpa2UgcGxvdCBtZXRob2QsIGJlY2F1c2UgaXQgInNlZXMiIHRoYXQgX19mcl9fIGlzIG9mIGNsYXNzIF9fInRhYmxlIl9fLgoKIyMgNS42IEdlbmVyYWxpemVkIHRyYW5zcG9zZSBvZiBhbiBhcnJheSAjIwoKVGhlIGZ1bmN0aW9uIF9fYXBlcm0oYSxwZXJtKV9fIG1heSBiZSB1c2VkIHRvIHBlcm11dGUgYW4gYXJyYXksIF9fYV9fLiBUaGUgYXJndW1lbnQgX19wZXJtX18gbXVzdCBiZSBhIHBlcm11dGF0aW9uIG9mIHRoZSBpbnRlZ2VycyB7MSwgLi4uLCAqayp9LCB3aGVyZSAqayogaXMgdGhlIG51bWJlciBvZiBzdWJzY3JpcHRzIGluIF9fYV9fLiBUaGUgcmVzdWx0IG9mIHRoZSBmdW5jdGlvbiBpcyBhbiBhcnJheSBvZiB0aGUgc2FtZSBzaXplIGFzIF9fYV9fIGJ1dCB3aXRoIG9sZCBkaW1lbnNpb24gZ2l2ZW4gYnkgX19wZXJtW2pdX18gYmVjb21pbmcgdGhlIG5ldyBfX2otdGhfXyBkaW1lbnNpb24uIFRoZSBlYXNpZXN0IHdheSB0byB0aGluayBvZiB0aGlzIG9wZXJhdGlvbiBpcyBhcyBhIGdlbmVyYWxpemF0aW9uIG9mIHRyYW5zcG9zaXRpb24gZm9yIG1hdHJpY2VzLiBJbmRlZWQgaWYgX19BX18gaXMgYSBtYXRyaXgsICh0aGF0IGlzLCBhIGRvdWJseSBzdWJzY3JpcHRlZCBhcnJheSkgdGhlbiBfX0JfXyBnaXZlbiBieSAKCj5CIDwtIGFwZXJtKGEsIGMoMiwxKSkKCmlzIGp1c3QgdGhlIHRyYW5zcG9zZSBvZiBBLiBGb3IgdGhpcyBzcGVjaWFsIGNhc2UgYSBzaW1wbGVyIGZ1bmN0aW9uIF9fdCgpX18gaXMgYXZhaWxhYmxlLCBzbyB3ZSBjb3VkIGhhdmUgdXNlZCBCIDwtIHQoQSkuCgojIyA1LjcgTWF0cml4IGZhY2lsaXRpZXMgIyMKCkFzIG5vdGVkIGFib3ZlLCBhIG1hdHJpeCBpcyBqdXN0IGFuIGFycmF5IHdpdGggdHdvIHN1YnNjcmlwdHMuIEhvd2V2ZXIgaXQgaXMgc3VjaCBhbiBpbXBvcnRhbnQgc3BlY2lhbCBjYXNlIGl0IG5lZWRzIGEgc2VwYXJhdGUgZGlzY3Vzc2lvbi4gUiBjb250YWlucyBtYW55IG9wZXJhdG9ycyBhbmQgZnVuY3Rpb25zIHRoYXQgYXJlIGF2YWlsYWJsZSBvbmx5IGZvciBtYXRyaWNlcy4gRm9yIGV4YW1wbGUgX190KFgpX18gaXMgdGhlIG1hdHJpeCB0cmFuc3Bvc2UgZnVuY3Rpb24sIGFzIG5vdGVkIGFib3ZlLiBUaGUgZnVuY3Rpb25zIF9fbnJvdyhBKV9fIGFuZCBfX25jb2woQSlfXyBnaXZlIHRoZSBudW1iZXIgb2Ygcm93cyBhbmQgY29sdW1ucyBpbiB0aGUgbWF0cml4IF9fQV9fIHJlc3BlY3RpdmVseS4KCiMjIDUuNy4xIE1hdHJpeCBtdWx0aXBsaWNhdGlvbiAjIwoKVGhlIG9wZXJhdG9yIF9fJSolX18gaXMgdXNlZCBmb3IgbWF0cml4IG11bHRpcGxpY2F0aW9uLiBBbiAqbiogYnkgMSBvciAxIGJ5ICpuKiBtYXRyaXggbWF5IG9mIGNvdXJzZSBiZSB1c2VkIGFzIGFuICpuKi12ZWN0b3IgaWYgaW4gdGhlIGNvbnRleHQgc3VjaCBpcyBhcHByb3ByaWF0ZS4gQ29udmVyc2VseSwgdmVjdG9ycyB3aGljaCBvY2N1ciBpbiBtYXRyaXggbXVsdGlwbGljYXRpb24gZXhwcmVzc2lvbnMgYXJlIGF1dG9tYXRpY2FsbHkgcHJvbW90ZWQgZWl0aGVyIHRvIHJvdyBvciBjb2x1bW4gdmVjdG9ycywgd2hpY2hldmVyIGlzIG11bHRpcGxpY2F0aXZlbHkgY29oZXJlbnQsIGlmIHBvc3NpYmxlLCAoYWx0aG91Z2ggdGhpcyBpcyBub3QgYWx3YXlzIHVuYW1iaWd1b3VzbHkgcG9zc2libGUsIGFzIHdlIHNlZSBsYXRlcikuCgpJZiwgZm9yIGV4YW1wbGUsIF9fQV9fIGFuZCBfX0JfXyBhcmUgc3F1YXJlIG1hdHJpY2VzIG9mIHRoZSBzYW1lIHNpemUsIHRoZW4KCj4gQSAqIEIKCmlzIHRoZSBtYXRyaXggb2YgZWxlbWVudCBieSBlbGVtZW50IHByb2R1Y3RzIGFuZCAKCj4gQSAlKiUgQgoKaXMgdGhlIG1hdHJpeCBwcm9kdWN0LiBJZiAqeCogaXMgYSB2ZWN0b3IsIHRoZW4KCj4geCAlXColIEEgJVwqJSB4CgppcyB0aGUgcXVhZHJhdGljIGZvcm0uCgpUaGUgZnVuY3Rpb24gX19jcm9zc3Byb2QoKV9fIGZvcm1zICJjcm9zc3Byb2R1Y3RzIiwgbWVhbmluZyB0aGF0IF9fY3Jvc3Nwcm9kKFgseSlfXyBpcyB0aGUgc2FtZSBhcyB0KFgpJSoleSBidXQgdGhlIG9wZXJhdGlvbiBpcyBtb3JlIGVmZmljaWVudC4gSWYgdGhlIHNlY29uZCBhcmd1bWVudCB0byBfX2Nyb3NzcHJvZCgpX18gaXMgb21pdHRlZCBpdCBpcyB0YWtlbiB0byBiZSB0aGUgc2FtZSBhcyB0aGUgZmlyc3QuCgpUaGUgbWVhbmluZyBvZiBfX2RpYWcoKV9fIGRlcGVuZHMgb24gaXRzIGFyZ3VtZW50LiBfX2RpYWcodilfXyB3aGVyZSAqdiogaXMgYSB2ZWN0b3IsIGdpdmVzIGEgZGlhZ29uYWwgbWF0cml4IHdpdGggZWxlbWVudHMgb2YgdGhlIHZlY3RvciBhcyB0aGUgZGlhZ29uYWwgZW50cmllcy4gT24gdGhlIG90aGVyIGhhbmQgX19kaWFnKE0pX18sIHdoZXJlIF9fTV9fIGlzIGEgbWF0cml4LCBnaXZlcyB0aGUgdmVjdG9yIG9mIG1haW4gZGlhZ29uYWwgZW50cmllcyBvZiBfX01fXy4gVGhpcyBpcyB0aGUgc2FtZSBjb252ZW50aW9uIGFzIHRoYXQgdXNlZCBmb3IgX19kaWFnKClfXyBpbiBNQVRMQUIuIEFsc28sIHNvbWV3aGF0IGNvbmZ1c2luZ2x5LCBpZiAqayogaXMgYSBzaW5nbGUgbnVtZXJpYyB2YWx1ZSB0aGVuIF9fZGlhZyhrKV9fIGlzIHRoZSAqayogYnkgKmsqIGlkZW50aXR5IG1hdHJpeCEKCiMjIDUuNy4yIExpbmVhciBlcXVhdGlvbnMgYW5kIGludmVyc2lvbiAjIwoKU29sdmluZyBsaW5lYXIgZXF1YXRpb25zIGlzIHRoZSBpbnZlcnNlIG9mIG1hdHJpeCBtdWx0aXBsaWNhdGlvbi4gV2hlbiBhZnRlcgoKPiBiIDwtIEEgJSolIHgKCm9ubHkgX19BX18gYW5kIF9fYl9fIGFyZSBnaXZlbiwgdGhlIHZlY3RvciBfX3hfXyBpcyB0aGUgc29sdXRpb24gb2YgdGhhdCBsaW5lYXIgZXF1YXRpb24gc3lzdGVtLiBJbiBSLAoKPiBzb2x2ZShBLGIpCgpzb2x2ZXMgdGhlIHN5c3RlbSwgcmV0dXJuaW5nIF9feF9fICh1cCB0byBzb21lIGFjY3VyYWN5IGxvc3MpLiBOb3RlIHRoYXQgaW4gbGluZWFyIGFsZ2VicmEsIGZvcm1hbGx5IF9feCA9IEFeLTFeYl9fIHdoZXJlIF9fQV4tMV5fXyBkZW5vdGVzIHRoZSAqaW52ZXJzZSogb2YgX19BX18sIHdoaWNoIGNhbiBiZSBjb21wdXRlZCBieSAKCnNvbHZlKEEpCioKYnV0IHJhcmVseSBpcyBuZWVkZWQuIE51bWVyaWNhbGx5LCBpdCBpcyBib3RoIGluZWZmaWNpZW50IGFuZCBwb3RlbnRpYWxseSB1bnN0YWJsZSB0byBjb21wdXRlIHggPC0gc29sdmUoQSklKiViIGluc3RlYWQgb2Ygc29sdmUoQSxiKS4KClRoZSBxdWFkcmF0aWMgZm9ybSBfX3heVF5BXi0xXnhfXyB3aGljaCBpcyB1c2VkIGluIG11bHRpdmFyaWF0ZSBjb21wdXRhdGlvbnMsIHNob3VsZCBiZSBjb21wdXRlZCBieSBzb21ldGhpbmcgbGlrZSB4ICUqJSBzb2x2ZShBLHgpLCByYXRoZXIgdGhhbiBjb21wdXRpbmcgdGhlIGludmVyc2Ugb2YgX19BX18uCgojIyA1LjcuMyBFaWdlbnZhbHVlcyBhbmQgZWlnZW52ZWN0b3JzICMjCgpUaGUgZnVuY3Rpb24gX19laWdlbihTbSlfXyBjYWx1Y2xhdGVzIHRoZSBlaWdlbnZhbHVlcyBhbmQgZWlnZW52ZWN0b3JzIG9mIGEgc3ltZXRyaWMgbWF0cml4IF9fU01fXy4gVGhlIHJlc3VsdCBvZiB0aGlzIGZ1bmN0aW9uIGlzIGEgbGlzdCBvZiB0d28gY29tcG9uZW50cyBuYW1lZCBfX3ZhbHVlc19fIGFuZCBfX3ZlY3RvcnNfXy4gVGhlIGFzc2lnbm1lbnQKCj4gZXYgPC0gZWlnZW4oU20pCgp3aWxsIGFzaWduIHRoaXMgbGlzdCB0byBfX2V2X18uIFRoZW4gX19ldiR2YWxfXyBpcyB0aGUgdmVjdG9yIG9mIGVpZ2VudmFsdWVzIG9mIF9fU21fXyBhbmQgX19ldiR2ZWNfXyBpcyB0aGUgbWF0cml4IG9mIGNvcnJlc3BvbmRpbmcgZWlnZW52ZWN0b3JzLiBIYWQgd2Ugb25seSBuZWVkZWQgdGhlIGVpZ2VudmFsdWVzIHdlIGNvdWxkIGhhdmUgdXNlZCB0aGUgYXNzaWdubWVudDoKCj4gZXZhbHMgPC0gZWlnZW4oU20pJHZhbHVlcwoKX19ldmFsc19fIG5vdyBob2xkcyB0aGUgdmVjdG9yIG9mIGVpZ2VudmFsdWVzIGFuZCB0aGUgc2Vjb25kIGNvbXBvbmVudCBpcyBkaXNjYXJkZWQuIElmIHRoZSBleHByZXNzaW9uCgo+IGVpZ2VuKFNtKQoKaXMgdXNlZCBieSBpdHNlbGYgYXMgYSBjb21tYW5kIHRoZSB0d28gY29tcG9uZW50cyBhcmUgcHJpbnRlZCwgd2l0aCB0aGVpciBuYW1lcy4gRm9yIGxhcmdlIG1hdHJpY2VzIGl0IGlzIGJldHRlciB0byBhdm9pZCBjb21wdXRpbmcgdGhlIGVpZ2VudmVjdG9ycyBpZiB0aGV5IGFyZSBub3QgbmVlZGVkIGJ5IHVzaW5nIHRoZSBleHByZXNzaW9uCgo+IGV2YWxzIDwtIGVpZ2VuKFNtLCBvbmx5LnZhbHVlcyA9IFRSVUUpJHZhbHVlcwoKIyMgNS43LjQgU2luZ3VsYXIgdmFsdWUgZGVjb21wb3NpdGlvbiBhbmQgZGV0ZXJtaW5hbnRzICMjCgpUaGUgZnVuY3Rpb24gX19zdmQoTSlfXyB0YWtlcyBhbiBhcmJpdHJhcnkgbWF0cml4IGFyZ3VtZW50LCBfX01fXywgYW5kIGNhbGN1bGF0ZXMgdGhlIHNpbmd1bGFyIHZhbHVlIGRlY29tcG9zaXRpb24gb2YgX19NX18uIFRoaXMgY29uc2lzdHMgb2YgYSBtYXRyaXggb2Ygb3J0aG9ub3JtYWwgY29sdW1ucyBVIHdpdGggdGhlIHNhbWUgY29sdW1uIHNwYWNlIGFzIF9fTV9fLCBhIHNlY29uZCBtYXRyaXggb2Ygb3J0aG9ub3JtYWwgY29sdW1ucyBfX1ZfXyB3aG9zZSBjb2x1bW4gc3BhY2UgaXMgdGhlIHJvdyBzcGFjZSBvZiBfX01fXyBhbmQgYSBkaWFnb25hbCBtYXRyaXggb2YgcG9zaXRpdmUgZW50cmllcyBfX0RfXyBzdWNoIHRoYXQgX19NID0gVSAlXColIEQgJVwqJSB0KFYpX18uIF9fRF9fIGlzIGFjdHVhbGx5IHJldHVybmVkIGFzIGEgdmVjdG9yIG9mIHRoZSBkaWFnb25hbCBlbGVtZW50cy4gVGhlIHJlc3VsdCBvZiBfX3N2ZChNKV9fIGlzIGFjdHVhbGx5IGEgbGlzdCBvZiB0aHJlZSBjb21wb25lbnRzIG5hbWVkIF9fZF9fLCBfX3VfXywgYW5kIF9fdl9fLCB3aXRoIGV2aWRlbnQgbWVhbmluZ3MuCgpJZiBfX01fXyBpcyBpbiBmYWN0IHNxdWFyZSwgdGhlbiwgaXQgaXMgbm90IGhhcmQgdG8gc2VlIHRoYXQKCj4gYWJzZGV0TSA8LSBwcm9kKHN2ZChNKSRkKAoKY2FsY3VsYXRlcyB0aGUgYWJzb2x1dGUgdmFsdWUgb2YgdGhlIGRldGVybWluYW50IG9mIE0uIElmIHRoaXMgY2FsY3VsYXRpb24gd2VyZSBuZWVkZWQgb2Z0ZW4gd2l0aCBhIHZhcmlldHkgb2YgbWF0cmljZXMgaXQgY291bGQgYmUgZGVmaW5lZCBhcyBhbiBSIGZ1bmN0aW9uCgo+IGFic2RldCA8LSBmdW5jdGlvbihNKSBwcm9kKHN2ZChNKSRkKQoKYWZ0ZXIgd2hpY2ggd2UgY291bGQgdXNlIF9fYWJzZGV0KClfXyBhcyBqdXN0IGFub3RoZXIgUiBmdW5jdGlvbi4gQXMgYSBmdXJ0aGVyIHRyaXZpYWwgYnV0IHBvdGVudGlhbGx5IHVzZWZ1bCBleGFtcGxlLCB5b3UgbWlnaHQgbGlrZSB0byBjb25zaWRlciB3cml0aW5nIGEgZnVuY3Rpb24sIHNheSBfX3RyKClfXyB0byBjYWxjdWxhdGUgdGhlIHRyYWNlIG9mIGEgc3F1YXJlIG1hdHJpeC4KClIgaGFzIGEgYnVpbHRpbiBmdW5jdGlvbiBfX2RldF9fIHRvIGNhbGN1bGF0ZSBhIGRldGVybWluYW50LCBpbmNsdWRpbmcgdGhlIHNpZ24sIGFuZCBhbm90aGVyLCBfX2RldGVybWluYW50X18sIHRvIGdpdmUgdGhlIHNpZ24gYW5kIG1vZHVsdXMgKG9wdGlvbmFsbHkgb24gbG9nIHNjYWxlKSwKCiMjIDUuNy41IExlYXN0IHNxdWFyZXMgZml0dGluZyBhbmQgdGhlIFFSIGRlY29tcG9zaXRpb24gIyMKClRoZSBmdW5jdGlvbiBfX2xzZml0KClfXyByZXR1cm5zIGEgbGlzdCBnaXZpbmcgcmVzdWx0cyBvZiBhIGxlYXN0IHNxdWFyZXMgZml0dGluZyBwcm9jZWR1cmUuIEFuIGFzc2lnbm1lbnQgc3VjaCBhcwoKPiBhbnMgPC0gbHNmaXQoWCx5KQoKZ2l2ZXMgdGhlIHJlc3VsdHMgb2YgYSBsZWFzdCBzcXVhcmVzIGZpdCB3aGVyZSBfX3lfXyBpcyB0aGUgdmVjdG9yIG9mIG9ic2VydmF0aW9ucyBhbmQgX19YX18gaXMgdGhlIGRlc2lnbiBtYXRyaXguIF9fbHMuZGlhZygpX18gZ2l2ZXMgdGhlIGZvbGxvdy11cCBmb3IgdGhlIGZ1bmN0aW9uIGFuZCBhbW9uZyBvdGhlciB0aGluZ3MsIHJlZ3Jlc3Npb24gZGlhZ25vc3RpY3MuIE5vdGUgdGhhdCBhIGdyYW5kIG1lYW4gdGVybSBpcyBhdXRvbWF0aWNhbGx5IGluY2x1ZGVkIGFuZCBuZWVkIG5vdCBiZSBpbmNsdWRlZCBleHBsaWNpdGx5IGFzIGEgY29sdW1uIG9mIF9fWF9fLiBGdXJ0aGVyIG5vdGUgdGhhdCB5b3UgYWxtb3N0IGFsd2F5cyB3aWxsIHByZWZlciB1c2luZyBfX2xtKC4pX18gdG8gX19sc2ZpdCgpX18gZm9yIHJlZ3Jlc3Npb24gbW9kZWxsaW5nLgpBbm90aGVyIGNsb3NlbHkgcmVsYXRlZCBmdW5jdGlvbiBpcyBfX3FyKClfXyBhbmQgaXRzIGFsbGllcy4gQ29uc2lkZXIgdGhlIGZvbGxvd2luZyBhc3NpZ25tZW50cwoKPiBYcGx1cyA8LSBxcihYKQo+IGIgPC0gcXIuY29lZihYcGx1cyx5KQo+IGZpdCA8LSBxci5maXR0ZWQoWHBsdXMseSkKPiByZXMgPC0gcXIucmVzaWQoWHBsdXMseSkKClRoZXNlIGNvbXB1dGUgdGhlIG9ydGhvZ29uYWwgcHJvamVjdGlvbiBvZiBfX3lfXyBvbnRvIHRoZSByYW5nZSBvZiBfX1hfXyBpbiBfX2ZpdF9fLCB0aGUgcHJvamVjdGlvbiBvbnRvIHRoZSBvcnRob2dvbmFsIGNvbXBsZW1lbnQgaW4gX19yZXNfXyBhbmQgdGhlIGNvZWZmaWNpZW50IHZlY3RvciBmb3IgdGhlIHByb2plY3Rpb24gaW4gX19iX18sIHRoYXQgaXMsIF9fYl9fIGlzIGVzc2VudGlhbGx5IHRoZSByZXN1bHQgb2YgdGhlIE1BVExBQiAnYmFja3NsYXNoJyBvcGVyYXRvci4KCkl0IGlzIG5vdCBhc3N1bWVkIHRoYXQgX19YX18gaGFzIGZ1bGwgY29sdW1uIHJhbmsuIFJlZHVuZGFuY2llcyB3aWxsIGJlIGRpc2NvdmVyZWQgYW5kIHJlbW92ZWQgYXMgdGhleSBhcmUgZm91bmQuCgpUaGlzIGFsdGVybmF0aXZlIGlzIHRoZSBvbGRlciwgbG93LWxldmVsIHdheSB0byBwZXJmb3JtIGxlYXN0IHNxdWFyZXMgY2FsY3VsYXRpb25zLiBBbHRob3VnaCBzdGlsbCB1c2VmdWwgaW4gc29tZSBjb250ZXh0cywgaXQgd291bGQgbm93IGdlbmVyYWxseSBiZSByZXBsYWNlZCBieSB0aGUgc3RhdGlzdGljYWwgbW9kZWxzIGZlYXR1cmVzLiAKCiMjIDUuOCBGb3JtaW5nIHBhcnRpdGlvbmVkIG1hdHJpY2VzLCAqY2JpbmQoKSogYW5kICpyYmluZCgpKgoKQXMgd2UgaGF2ZSBhbHJlYWR5IHNlZW4gaW5mb3JtYWxseSwgbWF0cmljZXMgY2FuIGJlIGJ1aWx0IHVwIGZyb20gb3RoZXIgdmVjdG9ycyBhbmQgbWF0cmljZXMgYnkgdGhlIGZpbmN0aW9ucyBfX2NiaW5kKClfXyBhbmQgX19yYmluZCgpX18uIFJvdWdobHkgX19jYmluZCgpX18gZm9ybXMgbWF0cmljZXMgYnkgYmluZGluZyB0b2dldGhlciBtYXRyaWNlcyBob3Jpem9udGFsbHksIG9yIGNvbHVtbi13aXNlLCBhbmQgX19yYmluZCgpX18gdmVydGljYWxseSwgb3Igcm93LXdpc2UuCgpJbiB0aGUgYXNzaWdubWVudAoKPiBYIDwtIGNiaW5kKGFyZ18xLCBhcmdfMiwgYXJnXzMsLi4uKQoKdGhlIGFyZ3VtZW50cyB0byBfX2NiaW5kKClfXyBtdXN0IGJlIGVpdGhlciB2ZWN0b3JzIG9mIGFueSBsZW5ndGgsIG9yIG1hdHJpY2VzIHdpdGggdGhlIHNhbWUgY29sdW0gc2l6ZSwgdGhhdCBpcyB0aGUgc2FtZSBudW1iZXIgb2Ygcm93cy4gVGhlIHJlc3VsdCBpcyBhIG1hdHJpeCB3aXRoIHRoZSBjb25jYXRlbmF0ZWQgYXJndW1lbnRzICphcmdfMSosICphcmdfMiosIC4uLiBmb3JtaW5nIHRoZSBjb2x1bW5zLgoKSWYgc29tZSBvZiB0aGUgYXJndW1lbnRzIHRvIF9fY2JpbmQoKV9fIGFyZSB2ZWN0b3JzIHRoZXkgbWF5IGJlIHNob3J0ZXIgdGhhbiB0aGUgY29sdW1uIHNpemUgb2YgYW55IG1hdHJpY2VzIHByZXNlbnQsIGluIHdoaWNoIGNhc2UgdGhleSBhcmUgY3ljbGljYWxseSBleHRlbmRlZCB0byBtYXRjaCB0aGUgbWF0cml4IGNvbHVtbiBzaXplIChvciB0aGUgbGVuZ3RoIG9mIHRoZSBsb25nZXN0IHZlY3RvciBpZiBubyBtYXRyaWNlcyBhcmUgZ2l2ZW4pLgoKVGhlIGZ1bmN0aW9uIF9fcmJpbmQoKV9fIGRvZXMgdGhlIGNvcnJlc3BvbmRpbmcgb3BlcmF0aW9uIGZvciByb3dzLiBJbiB0aGlzIGNhc2UgYW55IHZlY3RvciBhcmd1bWVudCwgcG9zc2libHkgY3ljbGljYWxseSBleHRlbmRlZCwgYXJlIG9mIGNvdXJzZSB0YWtlbiBhcyByb3cgdmVjdG9ycy4KClN1cHBvc2UgX19YMV9fIGFuZCBfX1gyX18gaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2Ygcm93cy4gVG8gY29tYmluZSB0aGVzZSBieSBjb2x1bW5zIGludG8gYSBtYXRyaXggX19YX18sIHRvZ2V0aGVyIHdpdGggYW4gaW5pdGlhbCBjb2x1bW4gb2YgMXMgd2UgY2FuIHVzZQoKPiBYIDwtIGNiaW5kKDEsWDEsWDIpCgpUaGUgcmVzdWx0IG9mIF9fcmJpbmQoKV9fIG9yIF9fY2JpbmQoKV9fIGFsd2F5cyBoYXMgbWF0cml4IHN0YXR1cy4gSGVuY2UgX19jYmluZCh4KV9fIGFuZCBfX3JiaW5kKHgpX18gYXJlIHBvc3NpYmx5IHRoZSBzaW1wbGVzdCB3YXlzIGV4cGxpY2l0bHkgdG8gYWxsb3cgdGhlIHZlY3RvciB4IHRvIGJlIHRyZWF0ZWQgYXMgYSBjb2x1bW4gb3Igcm93IG1hdHJpeCByZXNwZWN0aXZlbHkuCgojIyA1LjkgVGhlIGNvbmNhdGVuYXRpb24gZnVuY3Rpb24sICpjKCkqLCB3aXRoIGFycmF5cyAjIwoKSXQgc2hvdWxkIGJlIG5vdGVkIHRoYXQgd2hlcmVhcyBfX2NiaW5kKClfXyBhbmQgX19yYmluZCgpX18gYXJlIGNvbmNhdGVuYXRpb24gZnVuY3Rpb25zIHRoYXQgcmVzcGVjdCBkaW0gYXR0cmlidXRlcywgdGhlIGJhc2ljIF9fYygpX18gZnVuY3Rpb24gZG9lcyBub3QsIGJ1dCByYXRoZXIgY2xlYXJzIG51bWVyaWMgb2JqZWN0cyBvZiBhbGwgX19kaW1fXyBhbmQgX19kaW1uYW1lc19fIGF0dHJpYnV0ZXMuIFRoaXMgaXMgb2NjYXNpb25hbGx5IHVzZWZ1bCBpbiBpdHMgb3duIHJpZ2h0LgoKVGhlIG9mZmljaWFsIHdheSB0byBjb2VyY2UgYW4gYXJyYXkgYmFjayB0byBhIHNpbXBsZSB2ZWN0b3Igb2JqZWN0IGlzIHRvIHVzZSBfX2FzLnZlY3RvcigpX18KCj4gdmVjIDwtIGFzLnZlY3RvcihYKQoKSG93ZXZlciBhIHNpbWlsYXIgcmVzdWx0IGNhbiBiZSBhY2hpZXZlZCBieSB1c2luZyBfX2MoKV9fIHdpdGgganVzdCBvbmUgYXJndW1lbnQsIHNpbXBseSBmb3IgdGhpc2Ugc2lkZS1lZmZlY3Q6Cgo+IHZlYyA8LSBjKFgpCgpUaGVyZSBhcmUgc2xpZ2h0IGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHR3bywgYnV0IHVsdGltYXRlbHkgdGhlIGNob2ljZSBiZXR3ZWVuIHRoZW0gaXMgbGFyZ2VseSBhIG1hdHRlciBvZiBzdHlsZSAod2l0aCB0aGUgZm9ybWVyIGJlaW5nIHByZWZlcmFibGUpLgoKIyMgNS4xMCBGcmVxdWVuY3kgdGFibGVzIGZyb20gZmFjdG9ycyAjIwoKUmVjYWxsIHRoYXQgYSBmYWN0b3IgZGVmaW5lcyBhIHBhcnRpdGlvbiBpbnRvIGdyb3Vwcy4gU2ltaWxhcmx5IGEgcGFpciBvZiBmYWN0b3JzIGRlZmluZXMgYSB0d28gd2F5IGNyb3NzIGNsYXNzaWZpY2F0aW9uLCBhbmQgc28gb24uIFRoZSBmdW5jdGlvbiBfX3RhYmxlKClfXyBhbGxvd3MgZnJlcXVlbmN5IHRhYmxlcyB0byBiZSBjYWxjdWxhdGVkIGZyb20gZXF1YWwgbGVuZ3RoIGZhY3RvcnMuIElmIHRoZXJlIGFyZSAqayogZmFjdG9yIGFyZ3VtZW50cywgdGhlIHJlc3VsdCBpcyBhICprKjB3YXkgYXJyYXkgb2YgZnJlcXVlbmNpZXMuCgpTdXBwb3NlLCBmb3IgZXhhbXBsZSwgdGhhdCBfX3N0YXRlZl9fIGlzIGEgZmFjdG9yIGdpdmluZyB0aGUgc3RhdGUgY29kZSBmb3IgZWFjaCBlbnRyeSBpbiBhIGRhdGEgdmVjdG9yLiBUaGUgYXNzaWdubWVudAoKPiBzdGF0ZWZyIDwtIHRhYmxlKHN0YXRlZikKCmdpdmVzIGluIF9fc3RhdGVmcl9fIGEgdGFibGUgb2YgZnJlcXVlbmNpZXMgb2YgZWFjaCBzdGF0ZSBpbiB0aGUgc2FtcGxlLiBUaGUgZnJlcXVlbmNpZXMgYXJlIG9yZGVyZWQgYW5kIGxhYmVsbGVkIGJ5IHRoZSBfX2xldmVsc19fIGF0dHJpYnV0ZSBvZiB0aGUgZmFjdG9yLiBUaGlzIHNpbXBsZSBjYXNlIGlzIGVxdWl2YWxlbnQgdG8sIGJ1dCBtb3JlIGNvbnZlbmllbnQgdGhhbiwKCj4gc3RhdGVmciA8LSB0YXBwbHkoc3RhdGVmLCBzdGF0ZWYsIGxlbmd0aCkKCkZ1cnRoZXIgc3VwcG9zZSB0aGF0IF9faW5jb21lZl9fIGlzIGEgZmFjdG9yIGdpdmluZyBhIHN1aXRhYmx5IGRlZmluZWQgImluY29tZSBjbGFzcyIgZm9yIGVhY2ggZW50cnkgaW4gdGhlIGRhdGEgdmVjdG9yLCBmb3IgZXhhbXBsZSB3aXRoIHRoZSBfX2N1dCgpX18gZnVuY3Rpb246Cgo+IGZhY3RvcihjdXQoaW5jb21lcywgYnJlYWtzID0gMzUrMTAqKDA6NykpKSAtPiBpbmNvbWVmCgpUaGVuIHRvIGNhbGN1bGF0ZSBhIHR3by13YXkgdGFibGUgb2YgZnJlcXVlbmNpZXM6Cgo+IHRhYmxlKGluY29tZWYsIHN0YXRlZikKCkV4dGVuc2lvbiB0byBoaWdoZXItd2F5IGZyZXF1ZW5jeSB0YWJsZXMgaXMgaW1tZWRpYXRlLgoKCgoKCgoK