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

# you will need to have GNU Octave (check the RcppOctave CRAN page for more details) installed on your system, then you can use the code below:

install.load::install_package("ramify", "ggplot2", "ggpmisc", "RcppOctave")
# install and/or load the packages and their dependencies, including the extra system dependencies (this process may take a while depending on the number of dependencies)


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

import::from(pracma, golden_ratio, fminbnd)
# import golden_ratio, fminbnd from the pracma package


Example 1 (modified from Source 1 and Wickham)



# Source 1 begins

# option 1
integrate_vector <- Vectorize(integrate, vectorize.args = c("f", "lower", "upper"))

funcs <- list(function(x) x^5 - 7 * x^4 + 9 * x^2 - 3 * x + 1, function(x) 8 * 
    sin(x) + 3 * cos(x), function(x) 8 * exp(x)/x^4)

integrate_vector(funcs, lower = c(0, -4 * pi, 5), upper = c(100, 4 * pi, 30))
##              [,1]         [,2]         [,3]      
## value        152669651767 -5.58059e-15 122584887 
## abs.error    0.001694974  3.323246e-08 128.3941  
## subdivisions 1            2            1         
## message      "OK"         "OK"         "OK"      
## call         Expression   Expression   Expression
# option 2
f1 <- c(f = function(x) x^5 - 7 * x^4 + 9 * x^2 - 3 * x + 1, l = 0, u = 100)

f2 <- c(f = function(x) 8 * sin(x) + 3 * cos(x), l = -4 * pi, u = 4 * pi)

f3 <- c(f = function(x) 8 * exp(x)/x^4, l = 5, u = 30)

funs <- list(f1, f2, f3)

lapply(funs, function(x) integrate(x[["f"]], x[["l"]], x[["u"]]))
## [[1]]
## 152669651767 with absolute error < 0.0017
## 
## [[2]]
## -5.58059e-15 with absolute error < 3.3e-08
## 
## [[3]]
## 122584887 with absolute error < 128
# option 3
functions <- list(function(x) x^5 - 7 * x^4 + 9 * x^2 - 3 * x + 1, function(x) 8 * 
    sin(x) + 3 * cos(x), function(x) 8 * exp(x)/x^4)

lower <- c(0, -4 * pi, 5)

upper <- c(100, 4 * pi, 30)

mapply(integrate, functions, lower, upper)
##              [,1]         [,2]         [,3]      
## value        152669651767 -5.58059e-15 122584887 
## abs.error    0.001694974  3.323246e-08 128.3941  
## subdivisions 1            2            1         
## message      "OK"         "OK"         "OK"      
## call         Expression   Expression   Expression
# Source 1 ends



Example 2

“Suppose you have measured temperatures at a number of coordinates on the surface of a rectangular heated plate”:

“T(2, 1) = 60
T(9, 1) = 57.5
T(2, 6) = 55
T(9, 6) = 70”

“Use bilinear interpolation to estimate the temperature at xi = 5.25 and yi = 4.8.” (Chapra 381)



library(ramify)

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


x <- mat("2, 9")
x
##      [,1] [,2]
## [1,]    2    9
y <- mat("1, 6")
y
##      [,1] [,2]
## [1,]    1    6
z <- mat("60, 57.5; 55, 70")
z
##      [,1] [,2]
## [1,]   60 57.5
## [2,]   55 70.0
T <- interp2(x, y, z, 5.25, 4.8)

T
## [1] 61.21429

The “temperature at xi = 5.25 and yi = 4.8” is 61."



Using GNU Octave through RcppOctave to obtain the answer for Chapra 381:



library(RcppOctave)

o_source(text = "
x = [2 9]

y = [1 6]

z = [60 57.5; 55 70]

interp2(x, y, z, 5.25, 4.8)
")
## x =
## 
##    2   9
## 
## y =
## 
##    1   6
## 
## z =
## 
##    60.000   57.500
##    55.000   70.000
## 
## ans =  61.214



Example 3

“Determine the point of maximum deflection of a beam using the golden-section search.” (Chapra 184) / Problem 7.16



install.load::load_package("ggplot2", "ggpmisc")
# load needed packages using the load_package function from the install.load
# package (it is assumed that you have already installed these packages)

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


source("https://raw.githubusercontent.com/ggrothendieck/gsubfn/master/R/list.R")


y <- function(x) {
    y1 <- (w0/(120 * E * I * L)) * (-x^5 + 2 * L^2 * x^3 - L^4 * x)
    return(y1)
}

L <- 600  # cm

E <- 50000  # kN/cm^2

I <- 30000  # cm^2

w0 <- 2.5  # kN/cm

epsilons <- 1/100  # %

xl <- 0

xu <- L

list[xmin, fmin, iter, ea] <- golden_ratio(y, xl, xu, tol = epsilons)

xmin
## [1] 268.3303
fmin
## [1] -0.5151901
iter
## [1] 20
ea
## [1] 0.009363442
# use ggplot2 to create the figure
ggplot(data.frame(x = xl:xu, y = y(xl:xu)), aes(x, y)) + geom_line() + labs(x = "Length (cm)", 
    y = "Deflection (cm)", title = "Beam Deflection") + stat_valleys(colour = "purple") + 
    stat_valleys(y.label.fmt = "%1.2f", geom = "text", colour = "red", vjust = 1.5, 
        aes(label = paste(..y.label.., "cm at", ..x.label.., "cm"))) + theme_bw()  # Source 2



Using GNU Octave through RcppOctave to obtain the answer for Chapra 184 / Problem 7.16:



library(RcppOctave)

o_source(text = "
L = 600 % cm

E = 50000 % kN/cm^2

I = 30000 % cm^2

w0 = 2.5 % kN/cm

epsilons = 1 / 100 % %

xl = 0

xu = L


z = @(x) (w0 / (120 * E * I * L)) * (-x ^ 5 + 2 * L ^ 2 * x ^ 3 - L ^ 4 * x)


function [x, k] = golden_section( f, a, b, tol, maxiter, verbose )
  %---------------------------------------------------------------------------
  % Jonathan R. Senning <jonathan.senning@gordon.edu>
  % Gordon College
  % Written May 3, 1999
  % Revised May 4, 2005
  % Revised December 18, 2008 - Works with both Matlab and Octave
  %
  % Implements the golden section search as described on pages 555-556 of
  % Numerical Mathematics and Computing, 4th Edition, by Cheney & Kincaid,
  % Brooks/Cole, 1999 except that y is calculated as an offset from b rather
  % than from a.
  %---------------------------------------------------------------------------

  if ( nargin <= 5 )
    verbose = 0;
  end

  % Set things up to begin the iteration
  r  = ( sqrt( 5 ) - 1 ) / 2;   % Golden ratio
  x = a + r * ( b - a );
  y = b - r * ( b - a );
  u = f( x );
  v = f( y );

  % Main loop
  k = 0;
  if ( verbose ~= 0 )
    fprintf( '%4d: Interval is [%f, %f]; y = %f, x = %f\n', k, a, b, y, x );
  end
  while ( abs( b - a ) >= 2 * tol && k < maxiter )
    k = k + 1;
    if ( u > v )        % minimum must be in [a, x]
      b = x;
      x = y;
      u = v;
      y = b - r * ( b - a );
      v = f( y );
    else                % minimum must be in [y, b]
      a = y;
      y = x;
      v = u;
      x = a + r * ( b - a );
      u = f( x );
    end
    if ( verbose ~= 0 )
      fprintf( '%4d: Interval is [%f, %f]; y = %f, x = %f\n', k, a, b, y, x );
    end
  end

  % All done; best estimate of solution is midpoint of final interval
  x = 0.5 * ( a + b );

endfunction % needed for GNU Octave only



[xmin, iter] = golden_section(z, 0, 8, tol = 1e-08, maxiter = 100)


xmin

iter
")



Example 4

“Determine the critical travel time and concentration” using the Streeter-Phelps model. (Chapra 185) / Problem 7.25



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


source("https://raw.githubusercontent.com/ggrothendieck/gsubfn/master/R/list.R")

o <- function(t) {
    o1 <- os - ((kd * L0/(kd + ks - ka)) * (exp(-ka * t) - exp((-kd + ks) * 
        t))) - Sb/ka * (1 - exp(-ka * t))
    return(o1)
}

os <- 10  # mg/L

kd <- 0.1  # d^-1

ka <- 0.6  # d^-1

ks <- 0.05  # d^-1

L0 <- 50  # mg/L

Sb <- 1  # mg/L/d

list[oc, tc] <- fminbnd(o, 0, 5)

oc
## [1] 4.772125
tc
## [1] 0.3102083



Using GNU Octave through RcppOctave to obtain the answer for Chapra 184 / Problem 7.16:



library(RcppOctave)

o_source(text = "
function o1 = o(t)
global os kd L0 ks ka Sb
o1 = os - ((kd * L0 / (kd + ks - ka)) * (exp(-ka * t) - exp((-kd + ks) * t))) - Sb / ka * (1 - exp(-ka * t));
endfunction % only needed for GNU Octave


global os kd L0 ks ka Sb
os = 10 % mg/L

kd = 0.1 % d^-1

ka = 0.6 % d^-1

ks = 0.05 % d^-1

L0 = 50 % mg/L

Sb = 1 % mg/L/d

[oc, tc] = fminbnd(@o, 0, 5)

oc

tc
")
## os =  10
## kd =  0.10000
## ka =  0.60000
## ks =  0.050000
## L0 =  50
## Sb =  1
## oc =  4.7721
## tc =  0.31021
## oc =  4.7721
## tc =  0.31021



Sources used in the R code

Source 1
anonymous function exercise in Wickham’s Advanced R book (integration of 3 functions in list) - Stack Overflow answered by jlhoward on Dec 19 2014 & answered and edited by Khashaa on Dec 19 2014. See https://stackoverflow.com/questions/27572408/anonymous-function-exercise-in-wickhams-advanced-r-book.

Source 2
Using R for photobiology: R tips 3: ggpmisc adds new stats to ‘ggplot2’ by Pedro J. Aphalo, 2016-01-30. See http://www.r4photobiology.info/2016/01/ggpmisc-adds-new-stats-to-ggplot2/.



Works Cited

Hadley Wickham, Advanced R (Online), “Functional programming”, http://adv-r.had.co.nz/Functional-programming.html

Jonathan R. Senning, “golden_section GNU Octave/MATLAB program, Gordon College, Revised December 18, 2008, http://www.math-cs.gordon.edu/courses/mat342/octave/golden_section.m.

Steven C. Chapra, Applied Numerical Methods with MATLAB for Engineers and Scientists, 2nd Edition, Boston, Massachusetts: McGraw-Hill, 2008, pages 184-185, 381.



LS0tCnRpdGxlOiAiTnVtZXJpY2FsIE1ldGhvZHMgRXhhbXBsZXMgd2l0aCBSIgphdXRob3I6ICJJcnVja2EgRW1icnksIEUuSS5ULiIKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6Cmh0bWxfZG9jdW1lbnQ6Cm1hdGhqYXg6IGRlZmF1bHQKLS0tCgo8YnIgLz4KPGJyIC8+CgpOb3RlOiBJZiB5b3Ugd2lzaCB0byByZXBsaWNhdGUgdGhlIFIgY29kZSBiZWxvdywgdGhlbiB5b3Ugd2lsbCBuZWVkIHRvIGNvcHkgYW5kIHBhc3RlIHRoZSBmb2xsb3dpbmcgY29tbWFuZHMgaW4gUiBmaXJzdCAodG8gbWFrZSBzdXJlIHlvdSBoYXZlIGFsbCB0aGUgcGFja2FnZXMgYW5kIHRoZWlyIGRlcGVuZGVuY2llcyk6CgpgYGB7ciBldmFsID0gRkFMU0V9Cmluc3RhbGwucGFja2FnZXMoImluc3RhbGwubG9hZCIpCiMgaW5zdGFsbCB0aGUgaW5zdGFsbC5sb2FkIHBhY2thZ2UKCiMgeW91IHdpbGwgbmVlZCB0byBoYXZlIEdOVSBPY3RhdmUgKGNoZWNrIHRoZSBSY3BwT2N0YXZlIENSQU4gcGFnZSBmb3IgbW9yZSBkZXRhaWxzKSBpbnN0YWxsZWQgb24geW91ciBzeXN0ZW0sIHRoZW4geW91IGNhbiB1c2UgdGhlIGNvZGUgYmVsb3c6CgppbnN0YWxsLmxvYWQ6Omluc3RhbGxfcGFja2FnZSgicmFtaWZ5IiwgImdncGxvdDIiLCAiZ2dwbWlzYyIsICJSY3BwT2N0YXZlIikKIyBpbnN0YWxsIGFuZC9vciBsb2FkIHRoZSBwYWNrYWdlcyBhbmQgdGhlaXIgZGVwZW5kZW5jaWVzLCBpbmNsdWRpbmcgdGhlIGV4dHJhIHN5c3RlbSBkZXBlbmRlbmNpZXMgKHRoaXMgcHJvY2VzcyBtYXkgdGFrZSBhIHdoaWxlIGRlcGVuZGluZyBvbiB0aGUgbnVtYmVyIG9mIGRlcGVuZGVuY2llcykKCgppbnN0YWxsLnBhY2thZ2VzKCJpbXBvcnQiKQojIGluc3RhbGwgdGhlIGltcG9ydCBwYWNrYWdlCgppbXBvcnQ6OmZyb20ocHJhY21hLCBnb2xkZW5fcmF0aW8sIGZtaW5ibmQpCiMgaW1wb3J0IGdvbGRlbl9yYXRpbywgZm1pbmJuZCBmcm9tIHRoZSBwcmFjbWEgcGFja2FnZQpgYGAKCjxiciAvPgoKIyBFeGFtcGxlIDEgKG1vZGlmaWVkIGZyb20gU291cmNlIDEgYW5kIFdpY2toYW0pCgo8YnIgLz4KPGJyIC8+CgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHRpZHkgPSBUUlVFfQojIFNvdXJjZSAxIGJlZ2lucwoKIyBvcHRpb24gMQppbnRlZ3JhdGVfdmVjdG9yIDwtIFZlY3Rvcml6ZShpbnRlZ3JhdGUsIHZlY3Rvcml6ZS5hcmdzID0gYygiZiIsICJsb3dlciIsICJ1cHBlciIpKQoKZnVuY3MgPC0gbGlzdChmdW5jdGlvbiAoeCkgeCBeIDUgLSA3ICogeCBeIDQgKyA5ICogeCBeIDIgLSAzICogeCArIDEsIGZ1bmN0aW9uKHgpIDggKiBzaW4oeCkgKyAzICogY29zKHgpLCBmdW5jdGlvbih4KSA4ICogZXhwKHgpIC8geCBeIDQpCgppbnRlZ3JhdGVfdmVjdG9yKGZ1bmNzLCBsb3dlciA9IGMoMCwgLTQgKiBwaSwgNSksIHVwcGVyID0gYygxMDAsIDQgKiBwaSwgMzApKQoKCiMgb3B0aW9uIDIKZjEgPC0gYyhmID0gZnVuY3Rpb24oeCkgeCBeIDUgLSA3ICogeCBeIDQgKyA5ICogeCBeIDIgLSAzICogeCArIDEsIGwgPSAwLCB1ID0gMTAwKQoKZjIgPC0gYyhmID0gZnVuY3Rpb24oeCkgOCAqIHNpbih4KSArIDMgKiBjb3MoeCksIGwgPSAtNCAqIHBpLCB1ID0gNCAqIHBpKQoKZjMgPC0gYyhmID0gZnVuY3Rpb24oeCkgOCAqIGV4cCh4KSAvIHggXiA0LCBsID0gNSwgdSA9IDMwKQoKZnVucyA8LSBsaXN0KGYxLCBmMiwgZjMpCgpsYXBwbHkoZnVucywgZnVuY3Rpb24oeCkgaW50ZWdyYXRlKHhbWyJmIl1dLCB4W1sibCJdXSwgeFtbInUiXV0pKQoKCiMgb3B0aW9uIDMKZnVuY3Rpb25zIDwtIGxpc3QoZnVuY3Rpb24oeCkgeCBeIDUgLSA3ICogeCBeIDQgKyA5ICogeCBeIDIgLSAzICogeCArIDEsIGZ1bmN0aW9uKHgpIDggKiBzaW4oeCkgKyAzICogY29zKHgpLCBmdW5jdGlvbih4KSA4ICogZXhwKHgpIC8geCBeIDQpCgpsb3dlciA8LSBjKDAsIC00ICogcGksIDUpCgp1cHBlciA8LSBjKDEwMCwgNCAqIHBpLCAzMCkKCm1hcHBseShpbnRlZ3JhdGUsIGZ1bmN0aW9ucywgbG93ZXIsIHVwcGVyKQojIFNvdXJjZSAxIGVuZHMKYGBgCgo8YnIgLz4KPGJyIC8+CgojIEV4YW1wbGUgMgoKIlN1cHBvc2UgeW91IGhhdmUgbWVhc3VyZWQgdGVtcGVyYXR1cmVzIGF0IGEgbnVtYmVyIG9mIGNvb3JkaW5hdGVzIG9uIHRoZSBzdXJmYWNlIG9mIGEgcmVjdGFuZ3VsYXIgaGVhdGVkIHBsYXRlIjoKCiJUKDIsIDEpID0gNjA8YnIgLz4KVCg5LCAxKSA9IDU3LjU8YnIgLz4KVCgyLCA2KSA9IDU1PGJyIC8+ClQoOSwgNikgPSA3MCI8YnIgLz4KCiJVc2UgYmlsaW5lYXIgaW50ZXJwb2xhdGlvbiB0byBlc3RpbWF0ZSB0aGUgdGVtcGVyYXR1cmUgYXQgeH4qaSp+ID0gNS4yNSBhbmQgeX4qaSp+ID0gNC44LiIgKENoYXByYSAzODEpCgo8YnIgLz4KPGJyIC8+CgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHRpZHkgPSBUUlVFfQpsaWJyYXJ5KHJhbWlmeSkKCmltcG9ydDo6ZnJvbShwcmFjbWEsIGludGVycDIpCiMgaW1wb3J0IGludGVycDIgZnJvbSB0aGUgcHJhY21hIHBhY2thZ2UKCgp4IDwtIG1hdCgiMiwgOSIpOyB4Cgp5IDwtIG1hdCgiMSwgNiIpOyB5Cgp6IDwtIG1hdCgiNjAsIDU3LjU7IDU1LCA3MCIpOyB6CgpUIDwtIGludGVycDIoeCwgeSwgeiwgNS4yNSwgNC44KQoKVApgYGAKClRoZSAidGVtcGVyYXR1cmUgYXQgeH4qaSp+ID0gNS4yNSBhbmQgeX4qaSp+ID0gNC44IiBpcyBgciByb3VuZChUKWAuIgoKPGJyIC8+CjxiciAvPgoKVXNpbmcgR05VIE9jdGF2ZSB0aHJvdWdoIFJjcHBPY3RhdmUgdG8gb2J0YWluIHRoZSBhbnN3ZXIgZm9yIENoYXByYSAzODE6Cgo8YnIgLz4KPGJyIC8+CgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHRpZHkgPSBUUlVFfQpsaWJyYXJ5KFJjcHBPY3RhdmUpCgpvX3NvdXJjZSh0ZXh0ID0gIgp4ID0gWzIgOV0KCnkgPSBbMSA2XQoKeiA9IFs2MCA1Ny41OyA1NSA3MF0KCmludGVycDIoeCwgeSwgeiwgNS4yNSwgNC44KQoiKQpgYGAKCjxiciAvPgo8YnIgLz4KCiMgRXhhbXBsZSAzCgoiRGV0ZXJtaW5lIHRoZSBwb2ludCBvZiBtYXhpbXVtIGRlZmxlY3Rpb24gb2YgYSBiZWFtIHVzaW5nIHRoZSBnb2xkZW4tc2VjdGlvbiBzZWFyY2guIiAoQ2hhcHJhIDE4NCkgLyBQcm9ibGVtIDcuMTYKCjxiciAvPgo8YnIgLz4KCmBgYHtyLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgdGlkeSA9IFRSVUV9Cmluc3RhbGwubG9hZDo6bG9hZF9wYWNrYWdlKCJnZ3Bsb3QyIiwgImdncG1pc2MiKQojIGxvYWQgbmVlZGVkIHBhY2thZ2VzIHVzaW5nIHRoZSBsb2FkX3BhY2thZ2UgZnVuY3Rpb24gZnJvbSB0aGUgaW5zdGFsbC5sb2FkIHBhY2thZ2UgKGl0IGlzIGFzc3VtZWQgdGhhdCB5b3UgaGF2ZSBhbHJlYWR5IGluc3RhbGxlZCB0aGVzZSBwYWNrYWdlcykKCmltcG9ydDo6ZnJvbShwcmFjbWEsIGdvbGRlbl9yYXRpbykKIyBpbXBvcnQgZ29sZGVuX3JhdGlvIGZyb20gdGhlIHByYWNtYSBwYWNrYWdlCgoKc291cmNlKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZ2dyb3RoZW5kaWVjay9nc3ViZm4vbWFzdGVyL1IvbGlzdC5SIikKCgp5IDwtIGZ1bmN0aW9uKHgpIHsKeTEgPC0gKHcwIC8gKDEyMCAqIEUgKiBJICogTCkpICogKC14IF4gNSArIDIgKiBMIF4gMiAqIHggXiAzIC0gTCBeIDQgKiB4KQpyZXR1cm4oeTEpCn0KCkwgPC0gNjAwICMgY20KCkUgPC0gNTAwMDAgIyBrTi9jbV4yCgpJIDwtIDMwMDAwICMgY21eMgoKdzAgPC0gMi41ICMga04vY20KCmVwc2lsb25zIDwtIDEgLyAxMDAgIyAlCgp4bCA8LSAwCgp4dSA8LSBMCgpsaXN0W3htaW4sIGZtaW4sIGl0ZXIsIGVhXSA8LSBnb2xkZW5fcmF0aW8oeSwgeGwsIHh1LCB0b2wgPSBlcHNpbG9ucykKCnhtaW4KCmZtaW4KCml0ZXIKCmVhCgoKCiMgdXNlIGdncGxvdDIgdG8gY3JlYXRlIHRoZSBmaWd1cmUKZ2dwbG90KGRhdGEuZnJhbWUoeCA9IHhsOnh1LCB5ID0geSh4bDp4dSkpLCBhZXMoeCwgeSkpICsgZ2VvbV9saW5lKCkgKyBsYWJzKHggPSAiTGVuZ3RoIChjbSkiLCB5ID0gIkRlZmxlY3Rpb24gKGNtKSIsIHRpdGxlID0gIkJlYW0gRGVmbGVjdGlvbiIpICsgc3RhdF92YWxsZXlzKGNvbG91ciA9ICJwdXJwbGUiKSArIHN0YXRfdmFsbGV5cyh5LmxhYmVsLmZtdCA9ICIlMS4yZiIsIGdlb20gPSAidGV4dCIsIGNvbG91ciA9ICJyZWQiLCB2anVzdCA9IDEuNSwgYWVzKGxhYmVsID0gcGFzdGUoLi55LmxhYmVsLi4sICJjbSBhdCIsIC4ueC5sYWJlbC4uLCAiY20iKSkpICsgdGhlbWVfYncoKSAjIFNvdXJjZSAyCmBgYAoKPGJyIC8+CjxiciAvPgoKVXNpbmcgR05VIE9jdGF2ZSB0aHJvdWdoIFJjcHBPY3RhdmUgdG8gb2J0YWluIHRoZSBhbnN3ZXIgZm9yIENoYXByYSAxODQgLyBQcm9ibGVtIDcuMTY6Cgo8YnIgLz4KPGJyIC8+CgpgYGB7ciwgZXZhbCA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRX0KbGlicmFyeShSY3BwT2N0YXZlKQoKb19zb3VyY2UodGV4dCA9ICIKTCA9IDYwMCAlIGNtCgpFID0gNTAwMDAgJSBrTi9jbV4yCgpJID0gMzAwMDAgJSBjbV4yCgp3MCA9IDIuNSAlIGtOL2NtCgplcHNpbG9ucyA9IDEgLyAxMDAgJSAlCgp4bCA9IDAKCnh1ID0gTAoKCnogPSBAKHgpICh3MCAvICgxMjAgKiBFICogSSAqIEwpKSAqICgteCBeIDUgKyAyICogTCBeIDIgKiB4IF4gMyAtIEwgXiA0ICogeCkKCgpmdW5jdGlvbiBbeCwga10gPSBnb2xkZW5fc2VjdGlvbiggZiwgYSwgYiwgdG9sLCBtYXhpdGVyLCB2ZXJib3NlICkKICAlLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgJSBKb25hdGhhbiBSLiBTZW5uaW5nIDxqb25hdGhhbi5zZW5uaW5nQGdvcmRvbi5lZHU+CiAgJSBHb3Jkb24gQ29sbGVnZQogICUgV3JpdHRlbiBNYXkgMywgMTk5OQogICUgUmV2aXNlZCBNYXkgNCwgMjAwNQogICUgUmV2aXNlZCBEZWNlbWJlciAxOCwgMjAwOCAtIFdvcmtzIHdpdGggYm90aCBNYXRsYWIgYW5kIE9jdGF2ZQogICUKICAlIEltcGxlbWVudHMgdGhlIGdvbGRlbiBzZWN0aW9uIHNlYXJjaCBhcyBkZXNjcmliZWQgb24gcGFnZXMgNTU1LTU1NiBvZgogICUgTnVtZXJpY2FsIE1hdGhlbWF0aWNzIGFuZCBDb21wdXRpbmcsIDR0aCBFZGl0aW9uLCBieSBDaGVuZXkgJiBLaW5jYWlkLAogICUgQnJvb2tzL0NvbGUsIDE5OTkgZXhjZXB0IHRoYXQgeSBpcyBjYWxjdWxhdGVkIGFzIGFuIG9mZnNldCBmcm9tIGIgcmF0aGVyCiAgJSB0aGFuIGZyb20gYS4KICAlLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgogIGlmICggbmFyZ2luIDw9IDUgKQogICAgdmVyYm9zZSA9IDA7CiAgZW5kCgogICUgU2V0IHRoaW5ncyB1cCB0byBiZWdpbiB0aGUgaXRlcmF0aW9uCiAgciAgPSAoIHNxcnQoIDUgKSAtIDEgKSAvIDI7ICAgJSBHb2xkZW4gcmF0aW8KICB4ID0gYSArIHIgKiAoIGIgLSBhICk7CiAgeSA9IGIgLSByICogKCBiIC0gYSApOwogIHUgPSBmKCB4ICk7CiAgdiA9IGYoIHkgKTsKCiAgJSBNYWluIGxvb3AKICBrID0gMDsKICBpZiAoIHZlcmJvc2Ugfj0gMCApCiAgICBmcHJpbnRmKCAnJTRkOiBJbnRlcnZhbCBpcyBbJWYsICVmXTsgeSA9ICVmLCB4ID0gJWZcbicsIGssIGEsIGIsIHksIHggKTsKICBlbmQKICB3aGlsZSAoIGFicyggYiAtIGEgKSA+PSAyICogdG9sICYmIGsgPCBtYXhpdGVyICkKICAgIGsgPSBrICsgMTsKICAgIGlmICggdSA+IHYgKSAgICAgICAgJSBtaW5pbXVtIG11c3QgYmUgaW4gW2EsIHhdCiAgICAgIGIgPSB4OwogICAgICB4ID0geTsKICAgICAgdSA9IHY7CiAgICAgIHkgPSBiIC0gciAqICggYiAtIGEgKTsKICAgICAgdiA9IGYoIHkgKTsKICAgIGVsc2UgICAgICAgICAgICAgICAgJSBtaW5pbXVtIG11c3QgYmUgaW4gW3ksIGJdCiAgICAgIGEgPSB5OwogICAgICB5ID0geDsKICAgICAgdiA9IHU7CiAgICAgIHggPSBhICsgciAqICggYiAtIGEgKTsKICAgICAgdSA9IGYoIHggKTsKICAgIGVuZAogICAgaWYgKCB2ZXJib3NlIH49IDAgKQogICAgICBmcHJpbnRmKCAnJTRkOiBJbnRlcnZhbCBpcyBbJWYsICVmXTsgeSA9ICVmLCB4ID0gJWZcbicsIGssIGEsIGIsIHksIHggKTsKICAgIGVuZAogIGVuZAoKICAlIEFsbCBkb25lOyBiZXN0IGVzdGltYXRlIG9mIHNvbHV0aW9uIGlzIG1pZHBvaW50IG9mIGZpbmFsIGludGVydmFsCiAgeCA9IDAuNSAqICggYSArIGIgKTsKCmVuZGZ1bmN0aW9uICUgbmVlZGVkIGZvciBHTlUgT2N0YXZlIG9ubHkKCgoKW3htaW4sIGl0ZXJdID0gZ29sZGVuX3NlY3Rpb24oeiwgMCwgOCwgdG9sID0gMWUtMDgsIG1heGl0ZXIgPSAxMDApCgoKeG1pbgoKaXRlcgoiKQpgYGAKCjxiciAvPgo8YnIgLz4KCiMgRXhhbXBsZSA0CgoiRGV0ZXJtaW5lIHRoZSBjcml0aWNhbCB0cmF2ZWwgdGltZSBhbmQgY29uY2VudHJhdGlvbiIgdXNpbmcgdGhlIFN0cmVldGVyLVBoZWxwcyBtb2RlbC4gKENoYXByYSAxODUpIC8gUHJvYmxlbSA3LjI1Cgo8YnIgLz4KPGJyIC8+CgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHRpZHkgPSBUUlVFfQppbXBvcnQ6OmZyb20ocHJhY21hLCBmbWluYm5kKQojIGltcG9ydCBmbWluYm5kIGZyb20gdGhlIHByYWNtYSBwYWNrYWdlCgoKc291cmNlKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZ2dyb3RoZW5kaWVjay9nc3ViZm4vbWFzdGVyL1IvbGlzdC5SIikKCm8gPC0gZnVuY3Rpb24odCkgewpvMSA8LSBvcyAtICgoa2QgKiBMMCAvIChrZCArIGtzIC0ga2EpKSAqIChleHAoLWthICogdCkgLSBleHAoKC1rZCArIGtzKSAqIHQpKSkgLSBTYiAvIGthICogKDEgLSBleHAoLWthICogdCkpCnJldHVybihvMSkKfQoKb3MgPC0gMTAgIyBtZy9MCgprZCA8LSAwLjEgIyBkXi0xCgprYSA8LSAwLjYgIyBkXi0xCgprcyA8LSAwLjA1ICMgZF4tMQoKTDAgPC0gNTAgIyBtZy9MCgpTYiA8LSAxICMgbWcvTC9kCgpsaXN0W29jLCB0Y10gPC0gZm1pbmJuZChvLCAwLCA1KQoKb2MKCnRjCmBgYAoKPGJyIC8+CjxiciAvPgoKVXNpbmcgR05VIE9jdGF2ZSB0aHJvdWdoIFJjcHBPY3RhdmUgdG8gb2J0YWluIHRoZSBhbnN3ZXIgZm9yIENoYXByYSAxODQgLyBQcm9ibGVtIDcuMTY6Cgo8YnIgLz4KPGJyIC8+CgpgYGB7ciwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHRpZHkgPSBUUlVFfQpsaWJyYXJ5KFJjcHBPY3RhdmUpCgpvX3NvdXJjZSh0ZXh0ID0gIgpmdW5jdGlvbiBvMSA9IG8odCkKZ2xvYmFsIG9zIGtkIEwwIGtzIGthIFNiCm8xID0gb3MgLSAoKGtkICogTDAgLyAoa2QgKyBrcyAtIGthKSkgKiAoZXhwKC1rYSAqIHQpIC0gZXhwKCgta2QgKyBrcykgKiB0KSkpIC0gU2IgLyBrYSAqICgxIC0gZXhwKC1rYSAqIHQpKTsKZW5kZnVuY3Rpb24gJSBvbmx5IG5lZWRlZCBmb3IgR05VIE9jdGF2ZQoKCmdsb2JhbCBvcyBrZCBMMCBrcyBrYSBTYgpvcyA9IDEwICUgbWcvTAoKa2QgPSAwLjEgJSBkXi0xCgprYSA9IDAuNiAlIGReLTEKCmtzID0gMC4wNSAlIGReLTEKCkwwID0gNTAgJSBtZy9MCgpTYiA9IDEgJSBtZy9ML2QKCltvYywgdGNdID0gZm1pbmJuZChAbywgMCwgNSkKCm9jCgp0YwoiKQpgYGAKCjxiciAvPgo8YnIgLz4KCiMjIFNvdXJjZXMgdXNlZCBpbiB0aGUgUiBjb2RlCgpTb3VyY2UgMTxiciAvPgphbm9ueW1vdXMgZnVuY3Rpb24gZXhlcmNpc2UgaW4gV2lja2hhbeKAmXMgQWR2YW5jZWQgUiBib29rIChpbnRlZ3JhdGlvbiBvZiAzIGZ1bmN0aW9ucyBpbiBsaXN0KSAtIFN0YWNrIE92ZXJmbG93IGFuc3dlcmVkIGJ5IGpsaG93YXJkIG9uIERlYyAxOSAyMDE0ICYgYW5zd2VyZWQgYW5kIGVkaXRlZCBieSBLaGFzaGFhIG9uIERlYyAxOSAyMDE0LiBTZWUgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjc1NzI0MDgvYW5vbnltb3VzLWZ1bmN0aW9uLWV4ZXJjaXNlLWluLXdpY2toYW1zLWFkdmFuY2VkLXItYm9vay4KClNvdXJjZSAyPGJyIC8+ClVzaW5nIFIgZm9yIHBob3RvYmlvbG9neTogUiB0aXBzIDM6IGdncG1pc2MgYWRkcyBuZXcgc3RhdHMgdG8g4oCYZ2dwbG90MuKAmSBieSBQZWRybyBKLiBBcGhhbG8sIDIwMTYtMDEtMzAuIFNlZSBodHRwOi8vd3d3LnI0cGhvdG9iaW9sb2d5LmluZm8vMjAxNi8wMS9nZ3BtaXNjLWFkZHMtbmV3LXN0YXRzLXRvLWdncGxvdDIvLgoKPGJyIC8+CjxiciAvPgoKIyMgV29ya3MgQ2l0ZWQKCkhhZGxleSBXaWNraGFtLCAqQWR2YW5jZWQgUiogKE9ubGluZSksIOKAnEZ1bmN0aW9uYWwgcHJvZ3JhbW1pbmfigJ0sIGh0dHA6Ly9hZHYtci5oYWQuY28ubnovRnVuY3Rpb25hbC1wcm9ncmFtbWluZy5odG1sCgpKb25hdGhhbiBSLiBTZW5uaW5nLCAiZ29sZGVuX3NlY3Rpb24gR05VIE9jdGF2ZS9NQVRMQUIgcHJvZ3JhbSwgR29yZG9uIENvbGxlZ2UsIFJldmlzZWQgRGVjZW1iZXIgMTgsIDIwMDgsIGh0dHA6Ly93d3cubWF0aC1jcy5nb3Jkb24uZWR1L2NvdXJzZXMvbWF0MzQyL29jdGF2ZS9nb2xkZW5fc2VjdGlvbi5tLgoKU3RldmVuIEMuIENoYXByYSwgKkFwcGxpZWQgTnVtZXJpY2FsIE1ldGhvZHMgd2l0aCBNQVRMQUIgZm9yIEVuZ2luZWVycyBhbmQgU2NpZW50aXN0cyosIDJuZCBFZGl0aW9uLCBCb3N0b24sIE1hc3NhY2h1c2V0dHM6IE1jR3Jhdy1IaWxsLCAyMDA4LCBwYWdlcyAxODQtMTg1LCAzODEuCgo8YnIgLz4KPGJyIC8+CgojIyBFY29DXjJeUyBMaW5rcwoKW0Vjb0Mmc3VwMjtTIEhvbWVdKGluZGV4Lmh0bWwpCjxiciAvPgpbQWJvdXQgRWNvQyZzdXAyO1NdKGFib3V0X2Vjb2Mycy5odG1sKQo8YnIgLz4KW0Vjb0Mmc3VwMjtTIFNlcnZpY2VzXSgpCjxiciAvPgpbUHJvZHVjdHNdKGh0dHA6Ly93d3cucXVlc3Rpb251bml2ZXJzZS5jb20vcHJvZHVjdHMuaHRtbCkKPGJyIC8+CltFY29DJnN1cDI7UyBNZWRpYV0obWVkaWEuaHRtbCkKPGJyIC8+CltFY29DJnN1cDI7UyBSZXNvdXJjZXNdKHJlc291cmNlcy5odG1sKQo8YnIgLz4KW1IgVHJhaW5pbmdzIGFuZCBSZXNvdXJjZXMgcHJvdmlkZWQgYnkgRWNvQyZzdXAyO1MgKElydWNrYSBFbWJyeSwgRS5JLlQuKV0ocnRyYWluaW5nLmh0bWwpCgo8YnIgLz4KPGJyIC8+CgojIyBDb3B5cmlnaHQgYW5kIExpY2Vuc2UKCkFsbCBSIGNvZGUgd3JpdHRlbiBieSBJcnVja2EgRW1icnkgaXMgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIEdQTC0zIChvciBsYXRlcikgbGljZW5zZSwgc2VlIHRoZSBbR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgKEdQTCkgcGFnZV0oaHR0cHM6Ly9nbnUub3JnL2xpY2Vuc2VzL2dwbC5odG1sKS4KCkFsbCB3cml0dGVuIGNvbnRlbnQgb3JpZ2luYWxseSBjcmVhdGVkIGJ5IElydWNrYSBFbWJyeSBpcyBjb3B5cmlnaHRlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2UuIEFsbCBvdGhlciB3cml0dGVuIGNvbnRlbnQgcmVtYWlucyBhcyB0aGUgY29weXJpZ2h0IG9mIHRoZSBvcmlnaW5hbCBhdXRob3IocykuCgo8cD48YSByZWw9ImxpY2Vuc2UiIGhyZWY9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL2xpY2Vuc2VzL2J5LXNhLzQuMC8iPjxpbWcgYWx0PSJDcmVhdGl2ZSBDb21tb25zIExpY2Vuc2UiIHN0eWxlPSJib3JkZXItd2lkdGg6MCIgc3JjPSJodHRwczovL2kuY3JlYXRpdmVjb21tb25zLm9yZy9sL2J5LXNhLzQuMC84OHgzMS5wbmciIC8+PC9hPjxiciAvPlRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciBhIDxhIHJlbD0ibGljZW5zZSIgaHJlZj0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5zZXMvYnktc2EvNC4wLyI+Q3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1TaGFyZUFsaWtlIDQuMCBJbnRlcm5hdGlvbmFsIExpY2Vuc2U8L2E+LjwvcD4K