About the examples

The following examples



Note: If you wish to replicate the R code below, then you will need to copy and paste the following commands in R first (to make sure you have all the packages and their dependencies):

install.packages("install.load")
# install the install.load package

install.load::install_load("ramify")
# install and/or load the packages and their dependencies


install.packages("import")
# install the import package

import::from(pracma, mldivide)
# import mldivide from the pracma package



1) Balance the following equation


sodium hydrogen carbonate + hydrochloric acid yields sodium chloride + carbon dioxide + water

NaHCO3 + HCl —> NaCl + CO2 + H2O


Written in a form to create the matrix using ramify as found in the Chemistry Fundamentals Program (UNC-Chapel Hill):

Na: 1a + 0b - 1c - 0d = 0e
H: 1a + 1b - 0c - 0d = 2e
C: 1a + 0b - 0c - 1d = 0e
O: 3a + 0b - 0c - 2d = 1e
Cl: 0a + 1b - 1c - 0d = 0e


Set up the matrix in R and then solve


library(ramify)

A <- mat("1, 0, -1, 0, 1; 1, 1, 0, 0, 1; 1, 0, 0, -1, 1; 3, 0, 0, -2, 1; 0, 1, -1, 0, 1")
# The ones are added to the last column of A to make it square.

A
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    0   -1    0    1
## [2,]    1    1    0    0    1
## [3,]    1    0    0   -1    1
## [4,]    3    0    0   -2    1
## [5,]    0    1   -1    0    1
b <- mat("0; 2; 0; 1; 0")

b
##      [,1]
## [1,]    0
## [2,]    2
## [3,]    0
## [4,]    1
## [5,]    0
coeffs1 <- inv(A) %*% b * det(A)
# determines the values of the other coefficients

coeffs1
##      [,1]
## [1,]   -3
## [2,]   -3
## [3,]   -3
## [4,]   -3
## [5,]    0
deta1 <- det(A)
# determines the value of the last coefficient

deta1
## [1] -3

a = 3
b = 3
c = 3
d = 3
e = 3

Thus, the final solution is 3NaHCO3 + 3HCl —> 3NaCl + 3CO2 + 3H2O



2) Balance the following equation (UNC-Chapel Hill)


iron (II) chloride + sodium phosphate yields iron (II) phosphate + sodium chloride

FeCl2 + Na3(PO4) —> Fe3(PO4)2 + NaCl


Written in a form to create the matrix using ramify as found in the Chemistry Fundamentals Program (UNC-Chapel Hill):

Fe: 1a + 0b - 3c = 0d
Cl: 2a + 0b - 0c = 1d
Na: 0a + 3b - 0c = 1d
(PO4): 0a + 1b - 2c = 0d


Set up the matrix in R and then solve


library(ramify)

A <- mat("1, 0, -3, 1; 2, 0, 0, 1; 0, 3, 0, 1; 0, 1, -2, 1")
# The ones are added to the last column of A to make it square.

A
##      [,1] [,2] [,3] [,4]
## [1,]    1    0   -3    1
## [2,]    2    0    0    1
## [3,]    0    3    0    1
## [4,]    0    1   -2    1
b <- mat("0; 1; 1; 0")

b
##      [,1]
## [1,]    0
## [2,]    1
## [3,]    1
## [4,]    0
coeffs2 <- inv(A) %*% b * det(A)
# determines the values of the other coefficients

coeffs2
##      [,1]
## [1,]   -3
## [2,]   -2
## [3,]   -1
## [4,]    0
deta2 <- det(A)
# determines the value of the last coefficient

deta2
## [1] -6

a = 3
b = 2
c = 1

Thus, the final solution is 3FeCl2 + 2Na3(PO4) —> 1Fe3(PO4)2 + 6NaCl



3) Balance the following equation (Andersen)


methane + oxygen yields carbon dioxide + water

CH4 + O2 —> CO2 + H2O


Written in a form to create the matrix using ramify as found in Andersen:

C: 1a + 0b = 1c + 0d
H: 4a + 0b = 0c + 2d
O: 0a + 2b = 2c + 1d


Set d = 1 to complete the system of equations

Set up the matrix in R and then solve


library(ramify)

A <- mat("1, 0, -1, 0; 4, 0, 0, -2; 0, 2, -2, -1; 0, 0, 0, 1")

A
##      [,1] [,2] [,3] [,4]
## [1,]    1    0   -1    0
## [2,]    4    0    0   -2
## [3,]    0    2   -2   -1
## [4,]    0    0    0    1
b <- mat("0; 0; 0; 1")

b
##      [,1]
## [1,]    0
## [2,]    0
## [3,]    0
## [4,]    1
coeffs3 <- inv(A) %*% b
# determines the values of the coefficients

coeffs3
##      [,1]
## [1,]  0.5
## [2,]  1.0
## [3,]  0.5
## [4,]  1.0
coeffs3 <- coeffs3/min(coeffs3)
# obtains the coefficients as whole integers

coeffs3
##      [,1]
## [1,]    1
## [2,]    2
## [3,]    1
## [4,]    2

a = 1
b = 2
c = 1
d = 2

Thus, the final solution is 1CH4 + 2O2 —> 1CO2 + 2H2O



4) Balance the following equation (Andersen)


dichromate ion + iron (II) ion + hydrogen ion yields chromium (III) ion + iron (III) ion + water (Purdue University)

Cr2O7-2 + Fe2 + H1 —> Cr3 + Fe3 + H2O


Written in a form to create the matrix using ramify as found in Andersen:

Cr: 2a + 0b + 0c - 1d - 0e - 0f = 0
O: 7a + 0b + 0c - 0d - 0e - 1f = 0
Fe: 0a + 1b + 0c + 0d - 1e - 0f = 0
H: 0a + 0b + 1c + 0d - 0e - 2f = 0
Charge: -2a + 2b + 1c - 3d - 3e - 0f = 0


Set f = 1 to complete the system of equations

Set up the matrix in R and then solve


library(ramify)


import::from(pracma, mldivide)
# import mldivide from the pracma package


A <- mat("2, 0, 0, -1, 0, 0; 7, 0, 0, 0, 0, -1; 0, 1, 0, 0, -1, 0; 0, 0, 1, 0, 0, -2; -2, 2, 1, -3, -3, 0; 0, 0, 0, 0, 0, 1")

A
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    2    0    0   -1    0    0
## [2,]    7    0    0    0    0   -1
## [3,]    0    1    0    0   -1    0
## [4,]    0    0    1    0    0   -2
## [5,]   -2    2    1   -3   -3    0
## [6,]    0    0    0    0    0    1
b <- mat("0; 0; 0; 0; 0; 1")

b
##      [,1]
## [1,]    0
## [2,]    0
## [3,]    0
## [4,]    0
## [5,]    0
## [6,]    1
coeffs4 <- mldivide(A, b)  # solve using pracma mldivide (left division or \)
# determines the values of the coefficients

coeffs4
##           [,1]
## [1,] 0.1428571
## [2,] 0.8571429
## [3,] 2.0000000
## [4,] 0.2857143
## [5,] 0.8571429
## [6,] 1.0000000
coeffs4 <- coeffs4/min(coeffs4)
# obtains the coefficients as whole integers

coeffs4
##      [,1]
## [1,]    1
## [2,]    6
## [3,]   14
## [4,]    2
## [5,]    6
## [6,]    7

a = 1
b = 6
c = 14
d = 2
e = 6
f = 7

Thus, the final solution is 1Cr2O7-2 + 6Fe2 + 14H1 —> 2Cr3 + 6Fe3 + 7H2O



5) Balance the following equation (Andersen)


diphosphorus tetraiodide + white phosphorus + water yields phosphonium iodide + phosphoric acid (Purdue University & Wikipedia)

P2I4 + P4 + H2O —> PH4I + H3PO4


Written in a form to create the matrix using ramify as found in Andersen:

P: 2a + 4b + 0c - 1d - 1e = 0
I: 4a + 0b + 0c - 1d - 0e = 0
H: 0a + 0b + 2c + 4d - 3e = 0
O: 0a + 0b + 1c + 0d - 4e = 0


Set e = 1 to complete the system of equations

Set up the matrix in R and then solve


library(ramify)


import::from(pracma, mldivide)
# import mldivide from the pracma package


A <- mat("2, 4, 0, -1, -1; 4, 0, 0, -1, 0; 0, 0, 2, -4, -3; 0, 0, 1, 0, -4; 0, 0, 0, 0, 1")

A
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    2    4    0   -1   -1
## [2,]    4    0    0   -1    0
## [3,]    0    0    2   -4   -3
## [4,]    0    0    1    0   -4
## [5,]    0    0    0    0    1
b <- mat("0; 0; 0; 0; 1")

b
##      [,1]
## [1,]    0
## [2,]    0
## [3,]    0
## [4,]    0
## [5,]    1
coeffs5 <- mldivide(A, b)  # solve using pracma mldivide (left division or \)
# determines the values of the coefficients

coeffs5
##         [,1]
## [1,] 0.31250
## [2,] 0.40625
## [3,] 4.00000
## [4,] 1.25000
## [5,] 1.00000
coeffs5 <- coeffs5/min(coeffs5)
# attempt to obtain the coefficients as whole integers

coeffs5
##      [,1]
## [1,]  1.0
## [2,]  1.3
## [3,] 12.8
## [4,]  4.0
## [5,]  3.2
coeffs5 <- coeffs5 * 10
# obtains the coefficients as whole integers

coeffs5
##      [,1]
## [1,]   10
## [2,]   13
## [3,]  128
## [4,]   40
## [5,]   32

a = 10
b = 13
c = 128
d = 40
e = 32

Thus, the final solution is 10P2I4 + 13P4 + 128H2O —> 40PH4I + 32H3PO4



6) Balance the following equation (Sen)


potassium nitrate + carbon yields potassium carbonate + carbon monoxide + nitrogen

KNO3 + C —> K2CO3 + CO + N2


Written in a form to create the matrix using ramify as found in Sen:

K: 1a + 0b - 2c - 0d - 0e
N: 1a + 0b - 0c - 0d - 2e
O: 3a + 0b - 3c - 1d - 0e
C: 0a + 1b - 1c - 1d - 0e


Set up the matrix in R and then solve to obtain similar results to the MATLAB cheminpsolver from Sen


library(ramify)


import::from(pracma, mldivide)
# import mldivide from the pracma package


A <- mat("1, 0, -2, 0, 0; 1, 0, 0, 0, -2; 3, 0, -3, -1, 0; 0, 1, -1, -1, 0")

b <- mat("0; 0; 0; 0")


m <- dim(A)[1]

m
## [1] 4
n <- dim(A)[2]

n
## [1] 5
P <- rbind(cbind(A, zeros(m, n)), cbind(eye(n), -eye(n)))
# non-homogeneous system element

P
##       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
##  [1,]    1    0   -2    0    0    0    0    0    0     0
##  [2,]    1    0    0    0   -2    0    0    0    0     0
##  [3,]    3    0   -3   -1    0    0    0    0    0     0
##  [4,]    0    1   -1   -1    0    0    0    0    0     0
##  [5,]    1    0    0    0    0   -1    0    0    0     0
##  [6,]    0    1    0    0    0    0   -1    0    0     0
##  [7,]    0    0    1    0    0    0    0   -1    0     0
##  [8,]    0    0    0    1    0    0    0    0   -1     0
##  [9,]    0    0    0    0    1    0    0    0    0    -1
l <- rbind(zeros(m, 1), ones(n, 1))
# non-homogeneous system element

l
##       [,1]
##  [1,]    0
##  [2,]    0
##  [3,]    0
##  [4,]    0
##  [5,]    1
##  [6,]    1
##  [7,]    1
##  [8,]    1
##  [9,]    1
# Py = l

coeffs6 <- mldivide(P, l, pinv = FALSE)

coeffs6
##                [,1]
##  [1,]  2.000000e+00
##  [2,]  4.000000e+00
##  [3,]  1.000000e+00
##  [4,]  3.000000e+00
##  [5,]  1.000000e+00
##  [6,]  1.000000e+00
##  [7,]  3.000000e+00
##  [8,] -1.845734e-15
##  [9,]  2.000000e+00
## [10,]  0.000000e+00
coeffs6 <- coeffs6[1:5]

coeffs6
## [1] 2 4 1 3 1
coeffs6 <- coeffs6/min(coeffs6)
# obtains the coefficients as whole integers

coeffs6
## [1] 2 4 1 3 1

a = 2
b = 4
c = 1
d = 3
e = 1

Thus, the final solution is 2KNO3 + 4C —> 1K2CO3 + 3CO + 1N2



Works Cited

P. K. Andersen and G. Bjedov, Department of Freshman Engineering, Purdue University, “Chemical Stoichiometry Using MATLAB” by https://bloqm.files.wordpress.com/2015/03/estequiometria-com-matlab.pdf

Purdue University College of Science Chemical Education Division Groups Division of Chemical Education, “Nomenclature”, http://chemed.chem.purdue.edu/genchem/topicreview/bp/ch2/names.html

S. K. Sen, Hans Agarwal, Sagar Sen, “Chemical equation balancing: An integer programming approach”, Mathematical and Computer Modelling 44 (2006) 678-691, http://www.irisa.fr/triskell/members/sagarsen/papers/folder.2009-12-15.3064396439/ploneexfile.2009-12-15.5737828636/attachment_download/file

UNC-Chapel Hill Department of Chemistry – Chemistry Fundamentals Program, “Balancing Equations Using Matrices”, https://www.shodor.org/unchem/math/matrix/ and https://www.shodor.org/unchem/math/matrix/balance3.html.

Wikimedia Foundation, Inc. Wikipedia, 27 May 2016, “Phosphine”, https://en.wikipedia.org/wiki/Phosphine.



LS0tCnRpdGxlOiAiVXNpbmcgUiB0byBCYWxhbmNlIENoZW1pY2FsIFJlYWN0aW9ucyAoU3RvaWNoaW9tZXRyeSkiCmF1dGhvcjogIklydWNrYSBFbWJyeSwgRS5JLlQuIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKaHRtbF9kb2N1bWVudDoKbWF0aGpheDogZGVmYXVsdAotLS0KCjxiciAvPgo8YnIgLz4KCiMgQWJvdXQgdGhlIGV4YW1wbGVzCgpUaGUgZm9sbG93aW5nIGV4YW1wbGVzCgo8YnIgLz4KPGJyIC8+CgpOb3RlOiBJZiB5b3Ugd2lzaCB0byByZXBsaWNhdGUgdGhlIFIgY29kZSBiZWxvdywgdGhlbiB5b3Ugd2lsbCBuZWVkIHRvIGNvcHkgYW5kIHBhc3RlIHRoZSBmb2xsb3dpbmcgY29tbWFuZHMgaW4gUiBmaXJzdCAodG8gbWFrZSBzdXJlIHlvdSBoYXZlIGFsbCB0aGUgcGFja2FnZXMgYW5kIHRoZWlyIGRlcGVuZGVuY2llcyk6CgpgYGB7ciBldmFsID0gRkFMU0V9Cmluc3RhbGwucGFja2FnZXMoImluc3RhbGwubG9hZCIpCiMgaW5zdGFsbCB0aGUgaW5zdGFsbC5sb2FkIHBhY2thZ2UKCmluc3RhbGwubG9hZDo6aW5zdGFsbF9sb2FkKCJyYW1pZnkiKQojIGluc3RhbGwgYW5kL29yIGxvYWQgdGhlIHBhY2thZ2VzIGFuZCB0aGVpciBkZXBlbmRlbmNpZXMKCgppbnN0YWxsLnBhY2thZ2VzKCJpbXBvcnQiKQojIGluc3RhbGwgdGhlIGltcG9ydCBwYWNrYWdlCgppbXBvcnQ6OmZyb20ocHJhY21hLCBtbGRpdmlkZSkKIyBpbXBvcnQgbWxkaXZpZGUgZnJvbSB0aGUgcHJhY21hIHBhY2thZ2UKYGBgCgo8YnIgLz4KPGJyIC8+CgojIDEpIEJhbGFuY2UgdGhlIGZvbGxvd2luZyBlcXVhdGlvbgoKPGJyIC8+Cgpzb2RpdW0gaHlkcm9nZW4gY2FyYm9uYXRlICsgaHlkcm9jaGxvcmljIGFjaWQgeWllbGRzIHNvZGl1bSBjaGxvcmlkZSArIGNhcmJvbiBkaW94aWRlICsgd2F0ZXIKCk5hSENPfjN+ICsgSENsIC0tLT4gTmFDbCArIENPfjJ+ICsgSH4yfk8KCjxiciAvPgoKV3JpdHRlbiBpbiBhIGZvcm0gdG8gY3JlYXRlIHRoZSBtYXRyaXggdXNpbmcgYHJhbWlmeWAgYXMgZm91bmQgaW4gdGhlIENoZW1pc3RyeSBGdW5kYW1lbnRhbHMgUHJvZ3JhbSAoVU5DLUNoYXBlbCBIaWxsKToKCk5hOiAxYSArIDBiIC0gMWMgLSAwZCA9IDBlCjxiciAvPgpIOiAxYSArIDFiIC0gMGMgLSAwZCA9IDJlCjxiciAvPgpDOiAxYSArIDBiIC0gMGMgLSAxZCA9IDBlCjxiciAvPgpPOiAzYSArIDBiIC0gMGMgLSAyZCA9IDFlCjxiciAvPgpDbDogMGEgKyAxYiAtIDFjIC0gMGQgPSAwZQo8YnIgLz4KCjxiciAvPgoKU2V0IHVwIHRoZSBtYXRyaXggaW4gUiBhbmQgdGhlbiBzb2x2ZQoKPGJyIC8+CgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHRpZHkgPSBUUlVFfQpsaWJyYXJ5KHJhbWlmeSkKCkEgPC0gbWF0KCIxLCAwLCAtMSwgMCwgMTsgMSwgMSwgMCwgMCwgMTsgMSwgMCwgMCwgLTEsIDE7IDMsIDAsIDAsIC0yLCAxOyAwLCAxLCAtMSwgMCwgMSIpCiMgVGhlIG9uZXMgYXJlIGFkZGVkIHRvIHRoZSBsYXN0IGNvbHVtbiBvZiBBIHRvIG1ha2UgaXQgc3F1YXJlLgoKQQoKCmIgPC0gbWF0KCIwOyAyOyAwOyAxOyAwIikKCmIKCgpjb2VmZnMxIDwtIGludihBKSAlKiUgYiAqIGRldChBKQojIGRldGVybWluZXMgdGhlIHZhbHVlcyBvZiB0aGUgb3RoZXIgY29lZmZpY2llbnRzCgpjb2VmZnMxCgoKZGV0YTEgPC0gZGV0KEEpCiMgZGV0ZXJtaW5lcyB0aGUgdmFsdWUgb2YgdGhlIGxhc3QgY29lZmZpY2llbnQKCmRldGExCmBgYAoKYSA9IGByIGFicyhjb2VmZnMxWzFdKWAKPGJyIC8+CmIgPSBgciBhYnMoY29lZmZzMVsyXSlgCjxiciAvPgpjID0gYHIgYWJzKGNvZWZmczFbM10pYAo8YnIgLz4KZCA9IGByIGFicyhjb2VmZnMxWzRdKWAKPGJyIC8+CmUgPSBgciBhYnMoZGV0YTFbMV0pYAoKIyMjIFRodXMsIHRoZSBmaW5hbCBzb2x1dGlvbiBpcyBgciBhYnMoY29lZmZzMVsxXSlgTmFIQ09+M34gKyBgciBhYnMoY29lZmZzMVsyXSlgSENsIC0tLT4gYHIgYWJzKGNvZWZmczFbM10pYE5hQ2wgKyBgciBhYnMoY29lZmZzMVs0XSlgQ09+Mn4gKyBgciBhYnMoZGV0YTFbMV0pYEh+Mn5PCgo8YnIgLz4KPGJyIC8+CgojIDIpIEJhbGFuY2UgdGhlIGZvbGxvd2luZyBlcXVhdGlvbiAoVU5DLUNoYXBlbCBIaWxsKQoKPGJyIC8+Cgppcm9uIChJSSkgY2hsb3JpZGUgKyBzb2RpdW0gcGhvc3BoYXRlIHlpZWxkcyBpcm9uIChJSSkgcGhvc3BoYXRlICsgc29kaXVtIGNobG9yaWRlCgpGZUNsfjJ+ICsgTmF+M34oUE9+NH4pIC0tLT4gRmV+M34oUE9+NH4pfjJ+ICsgTmFDbAoKPGJyIC8+CgpXcml0dGVuIGluIGEgZm9ybSB0byBjcmVhdGUgdGhlIG1hdHJpeCB1c2luZyBgcmFtaWZ5YCBhcyBmb3VuZCBpbiB0aGUgQ2hlbWlzdHJ5IEZ1bmRhbWVudGFscyBQcm9ncmFtIChVTkMtQ2hhcGVsIEhpbGwpOgoKRmU6IDFhICsgMGIgLSAzYyA9IDBkCjxiciAvPgpDbDogMmEgKyAwYiAtIDBjID0gMWQKPGJyIC8+Ck5hOiAwYSArIDNiIC0gMGMgPSAxZAo8YnIgLz4KKFBPfjR+KTogMGEgKyAxYiAtIDJjID0gMGQKPGJyIC8+Cgo8YnIgLz4KClNldCB1cCB0aGUgbWF0cml4IGluIFIgYW5kIHRoZW4gc29sdmUKCjxiciAvPgoKYGBge3IsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB0aWR5ID0gVFJVRX0KbGlicmFyeShyYW1pZnkpCgpBIDwtIG1hdCgiMSwgMCwgLTMsIDE7IDIsIDAsIDAsIDE7IDAsIDMsIDAsIDE7IDAsIDEsIC0yLCAxIikKIyBUaGUgb25lcyBhcmUgYWRkZWQgdG8gdGhlIGxhc3QgY29sdW1uIG9mIEEgdG8gbWFrZSBpdCBzcXVhcmUuCgpBCgoKYiA8LSBtYXQoIjA7IDE7IDE7IDAiKQoKYgoKCmNvZWZmczIgPC0gaW52KEEpICUqJSBiICogZGV0KEEpCiMgZGV0ZXJtaW5lcyB0aGUgdmFsdWVzIG9mIHRoZSBvdGhlciBjb2VmZmljaWVudHMKCmNvZWZmczIKCgpkZXRhMiA8LSBkZXQoQSkKIyBkZXRlcm1pbmVzIHRoZSB2YWx1ZSBvZiB0aGUgbGFzdCBjb2VmZmljaWVudAoKZGV0YTIKYGBgCgphID0gYHIgYWJzKGNvZWZmczJbMV0pYAo8YnIgLz4KYiA9IGByIGFicyhjb2VmZnMyWzJdKWAKPGJyIC8+CmMgPSBgciBhYnMoY29lZmZzMlszXSlgCgojIyMgVGh1cywgdGhlIGZpbmFsIHNvbHV0aW9uIGlzIGByIGFicyhjb2VmZnMyWzFdKWBGZUNsfjJ+ICsgYHIgYWJzKGNvZWZmczJbMl0pYE5hfjN+KFBPfjR+KSAtLS0+IGByIGFicyhjb2VmZnMyWzNdKWBGZX4zfihQT340fil+Mn4gKyBgciBhYnMoZGV0YTJbMV0pYE5hQ2wKCjxiciAvPgo8YnIgLz4KCiMgMykgQmFsYW5jZSB0aGUgZm9sbG93aW5nIGVxdWF0aW9uIChBbmRlcnNlbikKCjxiciAvPgoKbWV0aGFuZSArIG94eWdlbiB5aWVsZHMgY2FyYm9uIGRpb3hpZGUgKyB3YXRlcgoKQ0h+NH4gKyBPfjJ+IC0tLT4gQ09+Mn4gKyBIfjJ+TwoKPGJyIC8+CgpXcml0dGVuIGluIGEgZm9ybSB0byBjcmVhdGUgdGhlIG1hdHJpeCB1c2luZyBgcmFtaWZ5YCBhcyBmb3VuZCBpbiBBbmRlcnNlbjoKCkM6IDFhICsgMGIgPSAxYyArIDBkCjxiciAvPgpIOiA0YSArIDBiID0gMGMgKyAyZAo8YnIgLz4KTzogMGEgKyAyYiA9IDJjICsgMWQKPGJyIC8+Cgo8YnIgLz4KClNldCBkID0gMSB0byBjb21wbGV0ZSB0aGUgc3lzdGVtIG9mIGVxdWF0aW9ucwoKU2V0IHVwIHRoZSBtYXRyaXggaW4gUiBhbmQgdGhlbiBzb2x2ZQoKPGJyIC8+CgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHRpZHkgPSBUUlVFfQpsaWJyYXJ5KHJhbWlmeSkKCkEgPC0gbWF0KCIxLCAwLCAtMSwgMDsgNCwgMCwgMCwgLTI7IDAsIDIsIC0yLCAtMTsgMCwgMCwgMCwgMSIpCgpBCgoKYiA8LSBtYXQoIjA7IDA7IDA7IDEiKQoKYgoKCmNvZWZmczMgPC0gaW52KEEpICUqJSBiCiMgZGV0ZXJtaW5lcyB0aGUgdmFsdWVzIG9mIHRoZSBjb2VmZmljaWVudHMKCmNvZWZmczMKCmNvZWZmczMgPC0gY29lZmZzMyAvIG1pbihjb2VmZnMzKQojIG9idGFpbnMgdGhlIGNvZWZmaWNpZW50cyBhcyB3aG9sZSBpbnRlZ2VycwoKY29lZmZzMwpgYGAKCmEgPSBgciBhYnMoY29lZmZzM1sxXSlgCjxiciAvPgpiID0gYHIgYWJzKGNvZWZmczNbMl0pYAo8YnIgLz4KYyA9IGByIGFicyhjb2VmZnMzWzNdKWAKPGJyIC8+CmQgPSBgciBhYnMoY29lZmZzM1s0XSlgCgojIyMgVGh1cywgdGhlIGZpbmFsIHNvbHV0aW9uIGlzIGByIGFicyhjb2VmZnMzWzFdKWBDSH40fiArIGByIGFicyhjb2VmZnMzWzJdKWBPfjJ+IC0tLT4gYHIgYWJzKGNvZWZmczNbM10pYENPfjJ+ICsgYHIgYWJzKGNvZWZmczNbNF0pYEh+Mn5PCgo8YnIgLz4KPGJyIC8+CgojIDQpIEJhbGFuY2UgdGhlIGZvbGxvd2luZyBlcXVhdGlvbiAoQW5kZXJzZW4pCgo8YnIgLz4KCmRpY2hyb21hdGUgaW9uICsgaXJvbiAoSUkpIGlvbiArIGh5ZHJvZ2VuIGlvbiB5aWVsZHMgY2hyb21pdW0gKElJSSkgaW9uICsgaXJvbiAoSUlJKSBpb24gKyB3YXRlciAoUHVyZHVlIFVuaXZlcnNpdHkpCgpDcn4yfk9+N35eLTJeICsgRmVeMl4gKyBIXjFeIC0tLT4gQ3JeM14gKyBGZV4zXiArIEh+Mn5PCgo8YnIgLz4KCldyaXR0ZW4gaW4gYSBmb3JtIHRvIGNyZWF0ZSB0aGUgbWF0cml4IHVzaW5nIGByYW1pZnlgIGFzIGZvdW5kIGluIEFuZGVyc2VuOgoKQ3I6IDJhICsgMGIgKyAwYyAtIDFkIC0gMGUgLSAwZiA9IDAKPGJyIC8+Ck86IDdhICsgMGIgKyAwYyAtIDBkIC0gMGUgLSAxZiA9IDAKPGJyIC8+CkZlOiAwYSArIDFiICsgMGMgKyAwZCAtIDFlIC0gMGYgPSAwCjxiciAvPgpIOiAwYSArIDBiICsgMWMgKyAwZCAtIDBlIC0gMmYgPSAwCjxiciAvPgpDaGFyZ2U6IC0yYSArIDJiICsgMWMgLSAzZCAtIDNlIC0gMGYgPSAwCjxiciAvPgoKPGJyIC8+CgpTZXQgZiA9IDEgdG8gY29tcGxldGUgdGhlIHN5c3RlbSBvZiBlcXVhdGlvbnMKClNldCB1cCB0aGUgbWF0cml4IGluIFIgYW5kIHRoZW4gc29sdmUKCjxiciAvPgoKYGBge3IsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB0aWR5ID0gVFJVRX0KbGlicmFyeShyYW1pZnkpCgoKaW1wb3J0Ojpmcm9tKHByYWNtYSwgbWxkaXZpZGUpCiMgaW1wb3J0IG1sZGl2aWRlIGZyb20gdGhlIHByYWNtYSBwYWNrYWdlCgoKQSA8LSBtYXQoIjIsIDAsIDAsIC0xLCAwLCAwOyA3LCAwLCAwLCAwLCAwLCAtMTsgMCwgMSwgMCwgMCwgLTEsIDA7IDAsIDAsIDEsIDAsIDAsIC0yOyAtMiwgMiwgMSwgLTMsIC0zLCAwOyAwLCAwLCAwLCAwLCAwLCAxIikKCkEKCgpiIDwtIG1hdCgiMDsgMDsgMDsgMDsgMDsgMSIpCgpiCgoKY29lZmZzNCA8LSBtbGRpdmlkZShBLCBiKSAjIHNvbHZlIHVzaW5nIHByYWNtYSBtbGRpdmlkZSAobGVmdCBkaXZpc2lvbiBvciBcKQojIGRldGVybWluZXMgdGhlIHZhbHVlcyBvZiB0aGUgY29lZmZpY2llbnRzCgpjb2VmZnM0Cgpjb2VmZnM0IDwtIGNvZWZmczQgLyBtaW4oY29lZmZzNCkKIyBvYnRhaW5zIHRoZSBjb2VmZmljaWVudHMgYXMgd2hvbGUgaW50ZWdlcnMKCmNvZWZmczQKYGBgCgphID0gYHIgYWJzKGNvZWZmczRbMV0pYAo8YnIgLz4KYiA9IGByIGFicyhjb2VmZnM0WzJdKWAKPGJyIC8+CmMgPSBgciBhYnMoY29lZmZzNFszXSlgCjxiciAvPgpkID0gYHIgYWJzKGNvZWZmczRbNF0pYAo8YnIgLz4KZSA9IGByIGFicyhjb2VmZnM0WzVdKWAKPGJyIC8+CmYgPSBgciBhYnMoY29lZmZzNFs2XSlgCgojIyMgVGh1cywgdGhlIGZpbmFsIHNvbHV0aW9uIGlzIGByIGFicyhjb2VmZnM0WzFdKWBDcn4yfk9+N35eLTJeICsgYHIgYWJzKGNvZWZmczRbMl0pYEZlXjJeICsgYHIgYWJzKGNvZWZmczRbM10pYEheMV4gLS0tPiBgciBhYnMoY29lZmZzNFs0XSlgQ3JeM14gKyBgciBhYnMoY29lZmZzNFs1XSlgRmVeM14gKyBgciBhYnMoY29lZmZzNFs2XSlgSH4yfk8KCjxiciAvPgo8YnIgLz4KCiMgNSkgQmFsYW5jZSB0aGUgZm9sbG93aW5nIGVxdWF0aW9uIChBbmRlcnNlbikKCjxiciAvPgoKZGlwaG9zcGhvcnVzIHRldHJhaW9kaWRlICsgd2hpdGUgcGhvc3Bob3J1cyArIHdhdGVyIHlpZWxkcyBwaG9zcGhvbml1bSBpb2RpZGUgKyBwaG9zcGhvcmljIGFjaWQgKFB1cmR1ZSBVbml2ZXJzaXR5ICYgV2lraXBlZGlhKQoKUH4yfkl+NH4gKyBQfjR+ICsgSH4yfk8gLS0tPiBQSH40fkkgKyBIfjN+UH5PfjQKCjxiciAvPgoKV3JpdHRlbiBpbiBhIGZvcm0gdG8gY3JlYXRlIHRoZSBtYXRyaXggdXNpbmcgYHJhbWlmeWAgYXMgZm91bmQgaW4gQW5kZXJzZW46CgpQOiAyYSArIDRiICsgMGMgLSAxZCAtIDFlID0gMAo8YnIgLz4KSTogNGEgKyAwYiArIDBjIC0gMWQgLSAwZSA9IDAKPGJyIC8+Ckg6IDBhICsgMGIgKyAyYyArIDRkIC0gM2UgPSAwCjxiciAvPgpPOiAwYSArIDBiICsgMWMgKyAwZCAtIDRlID0gMAo8YnIgLz4KCjxiciAvPgoKU2V0IGUgPSAxIHRvIGNvbXBsZXRlIHRoZSBzeXN0ZW0gb2YgZXF1YXRpb25zCgpTZXQgdXAgdGhlIG1hdHJpeCBpbiBSIGFuZCB0aGVuIHNvbHZlCgo8YnIgLz4KCmBgYHtyLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgdGlkeSA9IFRSVUV9CmxpYnJhcnkocmFtaWZ5KQoKCmltcG9ydDo6ZnJvbShwcmFjbWEsIG1sZGl2aWRlKQojIGltcG9ydCBtbGRpdmlkZSBmcm9tIHRoZSBwcmFjbWEgcGFja2FnZQoKCkEgPC0gbWF0KCIyLCA0LCAwLCAtMSwgLTE7IDQsIDAsIDAsIC0xLCAwOyAwLCAwLCAyLCAtNCwgLTM7IDAsIDAsIDEsIDAsIC00OyAwLCAwLCAwLCAwLCAxIikKCkEKCgpiIDwtIG1hdCgiMDsgMDsgMDsgMDsgMSIpCgpiCgoKY29lZmZzNSA8LSBtbGRpdmlkZShBLCBiKSAjIHNvbHZlIHVzaW5nIHByYWNtYSBtbGRpdmlkZSAobGVmdCBkaXZpc2lvbiBvciBcKQojIGRldGVybWluZXMgdGhlIHZhbHVlcyBvZiB0aGUgY29lZmZpY2llbnRzCgpjb2VmZnM1Cgpjb2VmZnM1IDwtIGNvZWZmczUgLyBtaW4oY29lZmZzNSkKIyBhdHRlbXB0IHRvIG9idGFpbiB0aGUgY29lZmZpY2llbnRzIGFzIHdob2xlIGludGVnZXJzCgpjb2VmZnM1Cgpjb2VmZnM1IDwtIGNvZWZmczUgKiAxMAojIG9idGFpbnMgdGhlIGNvZWZmaWNpZW50cyBhcyB3aG9sZSBpbnRlZ2VycwoKY29lZmZzNQpgYGAKCmEgPSBgciBhYnMoY29lZmZzNVsxXSlgCjxiciAvPgpiID0gYHIgYWJzKGNvZWZmczVbMl0pYAo8YnIgLz4KYyA9IGByIGFicyhjb2VmZnM1WzNdKWAKPGJyIC8+CmQgPSBgciBhYnMoY29lZmZzNVs0XSlgCjxiciAvPgplID0gYHIgYWJzKGNvZWZmczVbNV0pYAoKIyMjIFRodXMsIHRoZSBmaW5hbCBzb2x1dGlvbiBpcyBgciBhYnMoY29lZmZzNVsxXSlgUH4yfkl+NH4gKyBgciBhYnMoY29lZmZzNVsyXSlgUH40fiArIGByIGFicyhjb2VmZnM1WzNdKWBIfjJ+TyAtLS0+IGByIGFicyhjb2VmZnM1WzRdKWBQSH40fkkgKyBgciBhYnMoY29lZmZzNVs1XSlgSH4zflB+T340Cgo8YnIgLz4KPGJyIC8+CgojIDYpIEJhbGFuY2UgdGhlIGZvbGxvd2luZyBlcXVhdGlvbiAoU2VuKQoKPGJyIC8+Cgpwb3Rhc3NpdW0gbml0cmF0ZSArIGNhcmJvbiB5aWVsZHMgcG90YXNzaXVtIGNhcmJvbmF0ZSArIGNhcmJvbiBtb25veGlkZSArIG5pdHJvZ2VuCgpLTk9+M34gKyBDIC0tLT4gS34yfkNPfjN+ICsgQ08gKyBOfjJ+Cgo8YnIgLz4KCldyaXR0ZW4gaW4gYSBmb3JtIHRvIGNyZWF0ZSB0aGUgbWF0cml4IHVzaW5nIGByYW1pZnlgIGFzIGZvdW5kIGluIFNlbjoKCks6IDFhICsgMGIgLSAyYyAtIDBkIC0gMGUKPGJyIC8+Ck46IDFhICsgMGIgLSAwYyAtIDBkIC0gMmUKPGJyIC8+Ck86IDNhICsgMGIgLSAzYyAtIDFkIC0gMGUKPGJyIC8+CkM6IDBhICsgMWIgLSAxYyAtIDFkIC0gMGUKPGJyIC8+Cgo8YnIgLz4KClNldCB1cCB0aGUgbWF0cml4IGluIFIgYW5kIHRoZW4gc29sdmUgdG8gb2J0YWluIHNpbWlsYXIgcmVzdWx0cyB0byB0aGUgTUFUTEFCIGNoZW1pbnBzb2x2ZXIgZnJvbSBTZW4KCjxiciAvPgoKYGBge3IsIHdhcm5pbmcgPSBGQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB0aWR5ID0gVFJVRX0KbGlicmFyeShyYW1pZnkpCgoKaW1wb3J0Ojpmcm9tKHByYWNtYSwgbWxkaXZpZGUpCiMgaW1wb3J0IG1sZGl2aWRlIGZyb20gdGhlIHByYWNtYSBwYWNrYWdlCgoKQSA8LSBtYXQoIjEsIDAsIC0yLCAwLCAwOyAxLCAwLCAwLCAwLCAtMjsgMywgMCwgLTMsIC0xLCAwOyAwLCAxLCAtMSwgLTEsIDAiKQoKYiA8LSBtYXQoIjA7IDA7IDA7IDAiKQoKCm0gPC0gZGltKEEpWzFdCgptCgoKbiA8LSBkaW0oQSlbMl0KCm4KCgpQIDwtIHJiaW5kKGNiaW5kKEEsIHplcm9zKG0sIG4pKSwgY2JpbmQoZXllKG4pLCAtZXllKG4pKSkKIyBub24taG9tb2dlbmVvdXMgc3lzdGVtIGVsZW1lbnQKClAKCgpsIDwtIHJiaW5kKHplcm9zKG0sIDEpLCBvbmVzKG4sIDEpKQojIG5vbi1ob21vZ2VuZW91cyBzeXN0ZW0gZWxlbWVudAoKbAoKCiMgUHkgPSBsCgpjb2VmZnM2IDwtIG1sZGl2aWRlKFAsIGwsIHBpbnYgPSBGQUxTRSkKCmNvZWZmczYKCmNvZWZmczYgPC0gY29lZmZzNlsxOjVdCgpjb2VmZnM2Cgpjb2VmZnM2IDwtIGNvZWZmczYgLyBtaW4oY29lZmZzNikKIyBvYnRhaW5zIHRoZSBjb2VmZmljaWVudHMgYXMgd2hvbGUgaW50ZWdlcnMKCmNvZWZmczYKYGBgCgphID0gYHIgYWJzKGNvZWZmczZbMV0pYAo8YnIgLz4KYiA9IGByIGFicyhjb2VmZnM2WzJdKWAKPGJyIC8+CmMgPSBgciBhYnMoY29lZmZzNlszXSlgCjxiciAvPgpkID0gYHIgYWJzKGNvZWZmczZbNF0pYAo8YnIgLz4KZSA9IGByIGFicyhjb2VmZnM2WzVdKWAKCiMjIyBUaHVzLCB0aGUgZmluYWwgc29sdXRpb24gaXMgYHIgYWJzKGNvZWZmczZbMV0pYEtOT34zfiArIGByIGFicyhjb2VmZnM2WzJdKWBDIC0tLT4gYHIgYWJzKGNvZWZmczZbM10pYEt+Mn5DT34zfiArIGByIGFicyhjb2VmZnM2WzRdKWBDTyArIGByIGFicyhjb2VmZnM2WzVdKWBOfjJ+Cgo8YnIgLz4KPGJyIC8+CgojIyBXb3JrcyBDaXRlZAoKUC4gSy4gQW5kZXJzZW4gYW5kIEcuIEJqZWRvdiwgRGVwYXJ0bWVudCBvZiBGcmVzaG1hbiBFbmdpbmVlcmluZywgUHVyZHVlIFVuaXZlcnNpdHksICJDaGVtaWNhbCBTdG9pY2hpb21ldHJ5IFVzaW5nIE1BVExBQiIgYnkgIGh0dHBzOi8vYmxvcW0uZmlsZXMud29yZHByZXNzLmNvbS8yMDE1LzAzL2VzdGVxdWlvbWV0cmlhLWNvbS1tYXRsYWIucGRmCgpQdXJkdWUgVW5pdmVyc2l0eSBDb2xsZWdlIG9mIFNjaWVuY2UgQ2hlbWljYWwgRWR1Y2F0aW9uIERpdmlzaW9uIEdyb3VwcyBEaXZpc2lvbiBvZiBDaGVtaWNhbCBFZHVjYXRpb24sIOKAnE5vbWVuY2xhdHVyZeKAnSwgaHR0cDovL2NoZW1lZC5jaGVtLnB1cmR1ZS5lZHUvZ2VuY2hlbS90b3BpY3Jldmlldy9icC9jaDIvbmFtZXMuaHRtbAoKUy4gSy4gU2VuLCBIYW5zIEFnYXJ3YWwsIFNhZ2FyIFNlbiwgIkNoZW1pY2FsIGVxdWF0aW9uIGJhbGFuY2luZzogQW4gaW50ZWdlciBwcm9ncmFtbWluZyBhcHByb2FjaCIsICpNYXRoZW1hdGljYWwgYW5kIENvbXB1dGVyIE1vZGVsbGluZyogNDQgKDIwMDYpIDY3OC02OTEsIGh0dHA6Ly93d3cuaXJpc2EuZnIvdHJpc2tlbGwvbWVtYmVycy9zYWdhcnNlbi9wYXBlcnMvZm9sZGVyLjIwMDktMTItMTUuMzA2NDM5NjQzOS9wbG9uZWV4ZmlsZS4yMDA5LTEyLTE1LjU3Mzc4Mjg2MzYvYXR0YWNobWVudF9kb3dubG9hZC9maWxlCgpVTkMtQ2hhcGVsIEhpbGwgRGVwYXJ0bWVudCBvZiBDaGVtaXN0cnkgLS0gQ2hlbWlzdHJ5IEZ1bmRhbWVudGFscyBQcm9ncmFtLCAiQmFsYW5jaW5nIEVxdWF0aW9ucyBVc2luZyBNYXRyaWNlcyIsIGh0dHBzOi8vd3d3LnNob2Rvci5vcmcvdW5jaGVtL21hdGgvbWF0cml4LyBhbmQgaHR0cHM6Ly93d3cuc2hvZG9yLm9yZy91bmNoZW0vbWF0aC9tYXRyaXgvYmFsYW5jZTMuaHRtbC4KCldpa2ltZWRpYSBGb3VuZGF0aW9uLCBJbmMuIFdpa2lwZWRpYSwgMjcgTWF5IDIwMTYsIOKAnFBob3NwaGluZeKAnSwgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUGhvc3BoaW5lLgoKPGJyIC8+CjxiciAvPgoKIyMgRWNvQ14yXlMgTGlua3MKCltFY29DJnN1cDI7UyBIb21lXShpbmRleC5odG1sKQo8YnIgLz4KW0Fib3V0IEVjb0Mmc3VwMjtTXShhYm91dF9lY29jMnMuaHRtbCkKPGJyIC8+CltFY29DJnN1cDI7UyBTZXJ2aWNlc10oKQo8YnIgLz4KW1Byb2R1Y3RzXShodHRwOi8vd3d3LnF1ZXN0aW9udW5pdmVyc2UuY29tL3Byb2R1Y3RzLmh0bWwpCjxiciAvPgpbRWNvQyZzdXAyO1MgTWVkaWFdKG1lZGlhLmh0bWwpCjxiciAvPgpbRWNvQyZzdXAyO1MgUmVzb3VyY2VzXShyZXNvdXJjZXMuaHRtbCkKPGJyIC8+CltSIFRyYWluaW5ncyBhbmQgUmVzb3VyY2VzIHByb3ZpZGVkIGJ5IEVjb0Mmc3VwMjtTIChJcnVja2EgRW1icnksIEUuSS5ULildKHJ0cmFpbmluZy5odG1sKQoKPGJyIC8+CjxiciAvPgoKIyMgQ29weXJpZ2h0IGFuZCBMaWNlbnNlCgpBbGwgUiBjb2RlIHdyaXR0ZW4gYnkgSXJ1Y2thIEVtYnJ5IGlzIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBHUEwtMyAob3IgbGF0ZXIpIGxpY2Vuc2UsIHNlZSB0aGUgW0dOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIChHUEwpIHBhZ2VdKGh0dHBzOi8vZ251Lm9yZy9saWNlbnNlcy9ncGwuaHRtbCkuCgpBbGwgd3JpdHRlbiBjb250ZW50IG9yaWdpbmFsbHkgY3JlYXRlZCBieSBJcnVja2EgRW1icnkgaXMgY29weXJpZ2h0ZWQgdW5kZXIgdGhlIENyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlLiBBbGwgb3RoZXIgd3JpdHRlbiBjb250ZW50IHJlbWFpbnMgYXMgdGhlIGNvcHlyaWdodCBvZiB0aGUgb3JpZ2luYWwgYXV0aG9yKHMpLgoKPHA+PGEgcmVsPSJsaWNlbnNlIiBocmVmPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1zYS80LjAvIj48aW1nIGFsdD0iQ3JlYXRpdmUgQ29tbW9ucyBMaWNlbnNlIiBzdHlsZT0iYm9yZGVyLXdpZHRoOjAiIHNyYz0iaHR0cHM6Ly9pLmNyZWF0aXZlY29tbW9ucy5vcmcvbC9ieS1zYS80LjAvODh4MzEucG5nIiAvPjwvYT48YnIgLz5UaGlzIHdvcmsgaXMgbGljZW5zZWQgdW5kZXIgYSA8YSByZWw9ImxpY2Vuc2UiIGhyZWY9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzQuMC8iPkNyZWF0aXZlIENvbW1vbnMgQXR0cmlidXRpb24tU2hhcmVBbGlrZSA0LjAgSW50ZXJuYXRpb25hbCBMaWNlbnNlPC9hPi48L3A+Cg==