Definition

The Taylor series of a generic function \(f(x)\) in the point \(x = x_0\) is the following power series: \[ f(x_0) + \frac{f^{'}(x_0)}{1!} (x - x_0) + \frac{f^{''}(x_0)}{2!} (x - x_0)^2 + \frac{f^{'''}(x_0)}{3!} (x - x_0)^3 + \ldots \]

Taylor series for the square function

Let consider the function: \[f(x) = x^2\]

Suppose now to be interested in the Mac-Laurin approximation of order 0, 1, 2 and 3.

For our function \(f(x) = x^2\), only the first derivative is different from zero: - \(f^'(x) = 2\) The subsequent derivates are indeed all null: - \(f^{n}(x) = 0, n \ge 2\)

Let us define an R-function for each approximation:

#approximation of order 0
x2order0 <- function(x, x0=0) x0^2
#approximation of order 1
x2order1 <- function(x, x0=0) x0^2 + (x - x0)*2*x0
#approximation of order 2
x2order2 <- function(x, x0=0) 
  x0^2 + (x - x0)*2*x0 + (x - x0)^2 * 2 / factorial(2)
#since the derivates, starting from the order 3, are null
#we can avoid to define the higher order approximations

Note 1: in defining the components of the Taylor’s series, the default value 0 has been used for the point in which the function is approximated. This is the MacLaurin approximation, i.e. the Taylor series evaluated in the point \(x_0 = 0\).

Note 2: the following alternative solution exploits the lower order approximations in computing the higher order approximations:

x2order0 <- function(x, x0=0) x0^2
x2order1 <- function(x, x0=0) x2order0(x, x0) + (x - x0)*2*x0
x2order2 <- function(x, x0=0) 
  x2order0(x, x0) + x2order1(x, x0) + (x - x0)^2 * 2 / factorial(2)
#prova di chiamata dell'approssimazione di ordine 2 in due punti usando x0=1
x2order0(0)
[1] 0
x2order0(10)
[1] 0
#prova di chiamata della funzione per l'approssimazione di ordine 2 in due punti
x2order0(c(0, 10))
[1] 0
#per fare valutare la funzione in ciascun valore del vettore in input è necessario
#utilizzare la funzione Vectorize
x2order0vec <- Vectorize(x2order0, vectorize.args="x")
x2order0vec(c(0, 10))
[1] 0 0
#nell'approssimazione di ordine 0 è necessario usare la funzione Vectorize
#poichè la funzione è costante e non dipende da x
#non è necessario per le approssimazioni di ordine superiore
x2order1(c(0, 10))
[1] 0 0
x2order2(c(0, 10))
[1]   0 100
#preparo un vettore di interi sequenziali da usare come ascisse
ascisse <- -100:100
#rappresento la funzione da approssimare usando una linea nera
#il parametro main permette di impostare il titolo
#impostando il parametro type="l" ottengo una linea
#la funzione expression permette di utilizzare espressioni matematiche
plot(ascisse, ascisse^2, type="l", col="black", xlab="x", ylab="f(x)",
     main=expression(paste("f(x)=",x^2)))
#l'approssimazione di ordine 0 usando una linea rossa
lines(ascisse, x2order0vec(ascisse), col="red")
#l'approssimazione di ordine 1 usando una linea blue
lines(ascisse, x2order1(ascisse), col="blue")
#l'approssimazione di ordine 2 usando una linea verde tratteggiata (argomento 2)
#con uno spessore maggiore (argomento lwd)
lines(ascisse, x2order2(ascisse), col="green", lwd=5, lty=2)

#cambiando il punto di valutazione dell'approssimazione (argomento x0) si ottiene:
plot(ascisse, ascisse^2, type="l", col="black", xlab="x", ylab="f(x)",
     main=expression(paste("f(x)=",x^2)))     
lines(ascisse, x2order0vec(ascisse, x0=10), col="red")
lines(ascisse, x2order1(ascisse, x0=10), col="blue")
lines(ascisse, x2order2(ascisse, x0=10), col="green", lwd=5, lty=2)

Taylor series for the exponential function

Let consider now the exponential function: \[f(x) = exp(x)\] This is a particular function, since all the derivates are equal to the function itself: \[f^{(i)}(x) = exp(x), \forall i \ge 1\]

For such a function it is interesting to consider the Taylor series using a different number of components of such a series.

Let define an R-function for the first five subsequent terms of the Taylor series:

#Taylor approximation of order 0
expXorder0 <- function(x, x0=0) exp(x0)
#Taylor approximation of order 1
expXorder1 <- function(x, x0=0) exp(x0) + (x - x0)*exp(x0)
#Taylor approximation of order 2
expXorder2 <- function(x, x0=0) 
  exp(x0) + (x - x0)*exp(x0) + (x - x0)^2 * exp(x0) / factorial(2)
#Taylor approximation of order 3
expXorder3 <- function(x, x0=0) 
  exp(x0) + (x - x0)*exp(x0) + 
  (x - x0)^2 * exp(x0) / factorial(2) +
  (x - x0)^3 * exp(x0) / factorial(3)
#Taylor approximation of order 4
expXorder4 <- function(x, x0=0) 
  exp(x0) + (x - x0)*exp(x0) + 
  (x - x0)^2 * exp(x0) / factorial(2) +
  (x - x0)^3 * exp(x0) / factorial(3) +   
  (x - x0)^4 * exp(x0) / factorial(4)
#Taylor approximation of order 5
expXorder5 <- function(x, x0=0) 
  exp(x0) + (x - x0)*exp(x0) + 
  (x - x0)^2 * exp(x0) / factorial(2) +
  (x - x0)^3 * exp(x0) / factorial(3) + 
  (x - x0)^4 * exp(x0) / factorial(4) + 
  (x - x0)^5 * exp(x0) / factorial(5)

Since the first component is constant, we need to exploit the Vectorize function so to have a return value for each component of input vector:

expXorder0vec <- Vectorize(expXorder0, vectorize.args="x")

In order to plot the original function as well as its subsequent approximations, it is useful to define a sequence of integers:

abscissa <- 0:5

The following plot depicts the original function (solid black line) along with the first 5 approximation of the Taylor series (lines of different colors):

#rappresento la funzione da approssimare usando una linea nera
#NOTA: la funzione expressione permette di utilizzare formule sulle
#      rappresentazioni grafiche
#      Per una carrellata delle opzioni disponibili consultare
#      demo(plotmath) e example(plotmath)
plot(abscissa, exp(abscissa), 
     type="l", col="black", xlab="x", ylab="f(x)",
     main=expression(paste("f(x)=",e^x)))
#l'approssimazione di ordine 0 usando una linea rossa
lines(abscissa, expXorder0vec(abscissa), col="red")
#l'approssimazione di ordine 1 usando una linea blue
lines(abscissa, expXorder1(abscissa), col="blue")
#l'approssimazione di ordine 2 usando una linea verde
lines(abscissa, expXorder2(abscissa), col="green")
#l'approssimazione di ordine 3 usando una linea magenta
lines(abscissa, expXorder3(abscissa), col="magenta")
#l'approssimazione di ordine 4 usando una linea marrone
lines(abscissa, expXorder4(abscissa), col="brown")
#l'approssimazione di ordine 5 usando una linea arancione
lines(abscissa, expXorder5(abscissa), col="orange")

What happens if we change the value \(x_0\) in which the function is approximated? Here is the answer for the case \(x_0 = 10\):

#cambiando il punto di valutazione dell'approssimazione (argomento x0) si ottiene:
plot(abscissa, exp(abscissa), 
     type="l", col="black", xlab="x", ylab="f(x)",
     main=expression(paste("f(x)=",e^x)))
lines(abscissa, expXorder0vec(abscissa, x0=3), col="red")
lines(abscissa, expXorder1(abscissa, x0=3), col="blue")
lines(abscissa, expXorder2(abscissa, x0=3), col="green")
lines(abscissa, expXorder3(abscissa, x0=3), col="magenta")
lines(abscissa, expXorder4(abscissa, x0=3), col="brown")
lines(abscissa, expXorder5(abscissa, x0=3), col="orange")

LS0tCnRpdGxlOiAiVGF5bG9yIHNlcmllcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBEZWZpbml0aW9uClRoZSBUYXlsb3Igc2VyaWVzIG9mIGEgZ2VuZXJpYyBmdW5jdGlvbiAkZih4KSQgaW4gdGhlIHBvaW50ICR4ID0geF8wJCBpcyB0aGUgZm9sbG93aW5nIHBvd2VyIHNlcmllczoKJCQKZih4XzApICsgXGZyYWN7Zl57J30oeF8wKX17MSF9ICh4IC0geF8wKSArIFxmcmFje2ZeeycnfSh4XzApfXsyIX0gKHggLSB4XzApXjIgKyBcZnJhY3tmXnsnJyd9KHhfMCl9ezMhfSAoeCAtIHhfMCleMyArIFxsZG90cwokJAoKIyBUYXlsb3Igc2VyaWVzIGZvciB0aGUgc3F1YXJlIGZ1bmN0aW9uCgpMZXQgY29uc2lkZXIgdGhlIGZ1bmN0aW9uOgokJGYoeCkgPSB4XjIkJAoKU3VwcG9zZSBub3cgdG8gYmUgaW50ZXJlc3RlZCBpbiB0aGUgTWFjLUxhdXJpbiBhcHByb3hpbWF0aW9uIG9mIG9yZGVyIDAsIDEsIDIgYW5kIDMuCgpGb3Igb3VyIGZ1bmN0aW9uICRmKHgpID0geF4yJCwgb25seSB0aGUgZmlyc3QgZGVyaXZhdGl2ZSBpcyBkaWZmZXJlbnQgZnJvbSB6ZXJvOgotICRmXicoeCkgPSAyJApUaGUgc3Vic2VxdWVudCBkZXJpdmF0ZXMgYXJlIGluZGVlZCBhbGwgbnVsbDoKLSAkZl57bn0oeCkgPSAwLCBuIFxnZSAyJAoKTGV0IHVzIGRlZmluZSBhbiBSLWZ1bmN0aW9uIGZvciBlYWNoIGFwcHJveGltYXRpb246CmBgYHtyfQojYXBwcm94aW1hdGlvbiBvZiBvcmRlciAwCngyb3JkZXIwIDwtIGZ1bmN0aW9uKHgsIHgwPTApIHgwXjIKI2FwcHJveGltYXRpb24gb2Ygb3JkZXIgMQp4Mm9yZGVyMSA8LSBmdW5jdGlvbih4LCB4MD0wKSB4MF4yICsgKHggLSB4MCkqMip4MAojYXBwcm94aW1hdGlvbiBvZiBvcmRlciAyCngyb3JkZXIyIDwtIGZ1bmN0aW9uKHgsIHgwPTApIAogIHgwXjIgKyAoeCAtIHgwKSoyKngwICsgKHggLSB4MCleMiAqIDIgLyBmYWN0b3JpYWwoMikKI3NpbmNlIHRoZSBkZXJpdmF0ZXMsIHN0YXJ0aW5nIGZyb20gdGhlIG9yZGVyIDMsIGFyZSBudWxsCiN3ZSBjYW4gYXZvaWQgdG8gZGVmaW5lIHRoZSBoaWdoZXIgb3JkZXIgYXBwcm94aW1hdGlvbnMKYGBgCk5vdGUgMTogaW4gZGVmaW5pbmcgdGhlIGNvbXBvbmVudHMgb2YgdGhlIFRheWxvcidzIHNlcmllcywgdGhlIGRlZmF1bHQgdmFsdWUgMCBoYXMgYmVlbiB1c2VkIGZvciB0aGUgcG9pbnQgaW4gd2hpY2ggdGhlIGZ1bmN0aW9uIGlzIGFwcHJveGltYXRlZC4gVGhpcyBpcyB0aGUgTWFjTGF1cmluIGFwcHJveGltYXRpb24sIGkuZS4gdGhlIFRheWxvciBzZXJpZXMgZXZhbHVhdGVkIGluIHRoZSBwb2ludCAkeF8wID0gMCQuCgpOb3RlIDI6IHRoZSBmb2xsb3dpbmcgYWx0ZXJuYXRpdmUgc29sdXRpb24gZXhwbG9pdHMgdGhlIGxvd2VyIG9yZGVyCmFwcHJveGltYXRpb25zIGluIGNvbXB1dGluZyB0aGUgaGlnaGVyIG9yZGVyIGFwcHJveGltYXRpb25zOgpgYGB7cn0KeDJvcmRlcjAgPC0gZnVuY3Rpb24oeCwgeDA9MCkgeDBeMgp4Mm9yZGVyMSA8LSBmdW5jdGlvbih4LCB4MD0wKSB4Mm9yZGVyMCh4LCB4MCkgKyAoeCAtIHgwKSoyKngwCngyb3JkZXIyIDwtIGZ1bmN0aW9uKHgsIHgwPTApIAogIHgyb3JkZXIwKHgsIHgwKSArIHgyb3JkZXIxKHgsIHgwKSArICh4IC0geDApXjIgKiAyIC8gZmFjdG9yaWFsKDIpCmBgYAoKYGBge3J9CiNmdW5jdGlvbiBjYWxsIGluIHR3byBkaXN0aW5jdCBwb2ludHMKeDJvcmRlcjAoMCkKeDJvcmRlcjAoMTApCiNmdW5jdGlvbiBjYWxsIHBhc3NpbmcgdGhlIHR3byBwb2ludHMgaW4gYSB1bmlxdWUgY2FsbAp4Mm9yZGVyMChjKDAsIDEwKSkKYGBgCgpgYGB7cn0KI3RoZSBWZWN0b3JpemUgZnVuY3Rpb24gaXMgbmVlZGVkIGluIG9yZGVyIHRvIGV2YWx1YXRlIHRoZSBmdW5jdGlvbgojc2VwYXJhdGVseSBmb3IgZWFjaCBlbGVtZW50IG9mIHRoZSBpbnB1dCB2ZWN0b3IKeDJvcmRlcjB2ZWMgPC0gVmVjdG9yaXplKHgyb3JkZXIwLCB2ZWN0b3JpemUuYXJncz0ieCIpCngyb3JkZXIwdmVjKGMoMCwgMTApKQpgYGAKCmBgYHtyfQojdGhlIHVzZSBvZiB0aGUgVmVjdG9yaXplIGZ1bmN0aW9uIGlzIG5lZWRlZCBvbmx5IGZvciB0aGUgb3JkZXIgMCAKI2FwcHJveGltYXRpb24sIHNpbmNlIHRoZSBmdW5jdGlvbiBpcyBjb3N0YW50IGFuZCBkb2VzIG5vdCBkZXBlbmQgb24geAojd2hpbGUgaXQgaXMgbm90IG5lZWRlZCBmb3IgaGlnaGVyIG9yZGVyIGFwcHJveGltYXRpb25zCngyb3JkZXIxKGMoMCwgMTApKQp4Mm9yZGVyMihjKDAsIDEwKSkKYGBgCgpgYGB7cn0KI3ZlY3RvciBvZiBwb2ludHMgaW4gd2hpY2ggdGhlIGZ1bmN0aW9uIGlzIGV2YWx1YXRlZAphYnNjaXNzYSA8LSAtMTAwOjEwMApgYGAKCmBgYHtyfQojdGhlIHNxdWFyZSBmdW5jdGlvbiBpcyBwbG90dGVkIHVzaW5nIGEgc29saWQgYmxhY2sgbGluZQojdGhlIG1haW4gYXJndW1lbnQgaXMgdXNlZCB0byBzZXQgdGhlIHBsb3QgdGl0bGUKI3RoZSBhcmd1bWVudCB0eXBlPSJsIiBpcyB1c2VkIHRvIG9idGFpbiBhIGxpbmUKI3RoZSBleHByZXNzaW9uIGZ1bmN0aW9uIGlzIHVzZWQgdG8gbGFiZWwgdGhlIHBsb3QgdXNpbmcgZm9ybXVsYXMKcGxvdChhYnNjaXNzYSwgYWJzY2lzc2FeMiwgdHlwZT0ibCIsIGNvbD0iYmxhY2siLCB4bGFiPSJ4IiwgeWxhYj0iZih4KSIsCiAgICAgbWFpbj1leHByZXNzaW9uKHBhc3RlKCJmKHgpPSIseF4yKSkpCiN0aGUgb3JkZXIgMCBhcHByb3hpbWF0aW9uIGlzIHBsb3R0ZWQgdXNpbmcgYSByZWQgbGluZQpsaW5lcyhhYnNjaXNzYSwgeDJvcmRlcjB2ZWMoYWJzY2lzc2EpLCBjb2w9InJlZCIpCiN0aGUgb3JkZXIgMSBhcHByb3hpbWF0aW9uIGlzIHBsb3R0ZWQgdXNpbmcgYSBibHVlIGxpbmUKbGluZXMoYWJzY2lzc2EsIHgyb3JkZXIxKGFic2Npc3NhKSwgY29sPSJibHVlIikKI3RoZSBvcmRlciAyIGFwcHJveGltYXRpb24gaXMgcGxvdHRlZCB1c2luZyBhIGRhc2hlZCBncmVlbiBsaW5lCiN0aGUgYXJndW1lbnQgbHdkIGlzIHVzZWQgdG8gb2J0YWluIGEgdGhpY2tlciBsaW5lCmxpbmVzKGFic2Npc3NhLCB4Mm9yZGVyMihhYnNjaXNzYSksIGNvbD0iZ3JlZW4iLCBsd2Q9NSwgbHR5PTIpCmBgYAoKYGBge3J9CiN0aGUgc2FtZSBwbG90IGlzIG5vdyBvYnRhaW5lZCBjaGFuZ2lnIHRoZSBwb2ludCB4MCBpbiB3aGljaCB0aGUKI2Z1bmN0aW9uIGlzIGFwcHJveGltYXRlZApwbG90KGFic2Npc3NhLCBhYnNjaXNzYV4yLCB0eXBlPSJsIiwgY29sPSJibGFjayIsIHhsYWI9IngiLCB5bGFiPSJmKHgpIiwKICAgICBtYWluPWV4cHJlc3Npb24ocGFzdGUoImYoeCk9Iix4XjIpKSkgICAgIApsaW5lcyhhc2Npc3NlLCB4Mm9yZGVyMHZlYyhhYnNjaXNzYSwgeDA9MTApLCBjb2w9InJlZCIpCmxpbmVzKGFzY2lzc2UsIHgyb3JkZXIxKGFic2Npc3NhLCB4MD0xMCksIGNvbD0iYmx1ZSIpCmxpbmVzKGFzY2lzc2UsIHgyb3JkZXIyKGFic2Npc3NhLCB4MD0xMCksIGNvbD0iZ3JlZW4iLCBsd2Q9NSwgbHR5PTIpCmBgYAoKIyMgVGF5bG9yIHNlcmllcyBmb3IgdGhlIGV4cG9uZW50aWFsIGZ1bmN0aW9uCkxldCBjb25zaWRlciBub3cgdGhlIGV4cG9uZW50aWFsIGZ1bmN0aW9uOgokJGYoeCkgPSBleHAoeCkkJApUaGlzIGlzIGEgcGFydGljdWxhciBmdW5jdGlvbiwgc2luY2UgYWxsIHRoZSBkZXJpdmF0ZXMgYXJlIGVxdWFsIHRvIHRoZSBmdW5jdGlvbiBpdHNlbGY6CiQkZl57KGkpfSh4KSA9IGV4cCh4KSwgXGZvcmFsbCBpIFxnZSAxJCQgCgpGb3Igc3VjaCBhIGZ1bmN0aW9uIGl0IGlzIGludGVyZXN0aW5nIHRvIGNvbnNpZGVyIHRoZSBUYXlsb3Igc2VyaWVzIHVzaW5nIGEgZGlmZmVyZW50IG51bWJlciBvZiBjb21wb25lbnRzIG9mIHN1Y2ggYSBzZXJpZXMuCgpMZXQgZGVmaW5lIGFuIFItZnVuY3Rpb24gZm9yIHRoZSBmaXJzdCBmaXZlIHN1YnNlcXVlbnQgdGVybXMgb2YgdGhlIFRheWxvciBzZXJpZXM6CgpgYGB7cn0KI1RheWxvciBhcHByb3hpbWF0aW9uIG9mIG9yZGVyIDAKZXhwWG9yZGVyMCA8LSBmdW5jdGlvbih4LCB4MD0wKSBleHAoeDApCiNUYXlsb3IgYXBwcm94aW1hdGlvbiBvZiBvcmRlciAxCmV4cFhvcmRlcjEgPC0gZnVuY3Rpb24oeCwgeDA9MCkgZXhwKHgwKSArICh4IC0geDApKmV4cCh4MCkKI1RheWxvciBhcHByb3hpbWF0aW9uIG9mIG9yZGVyIDIKZXhwWG9yZGVyMiA8LSBmdW5jdGlvbih4LCB4MD0wKSAKICBleHAoeDApICsgKHggLSB4MCkqZXhwKHgwKSArICh4IC0geDApXjIgKiBleHAoeDApIC8gZmFjdG9yaWFsKDIpCiNUYXlsb3IgYXBwcm94aW1hdGlvbiBvZiBvcmRlciAzCmV4cFhvcmRlcjMgPC0gZnVuY3Rpb24oeCwgeDA9MCkgCiAgZXhwKHgwKSArICh4IC0geDApKmV4cCh4MCkgKyAKICAoeCAtIHgwKV4yICogZXhwKHgwKSAvIGZhY3RvcmlhbCgyKSArCiAgKHggLSB4MCleMyAqIGV4cCh4MCkgLyBmYWN0b3JpYWwoMykKI1RheWxvciBhcHByb3hpbWF0aW9uIG9mIG9yZGVyIDQKZXhwWG9yZGVyNCA8LSBmdW5jdGlvbih4LCB4MD0wKSAKICBleHAoeDApICsgKHggLSB4MCkqZXhwKHgwKSArIAogICh4IC0geDApXjIgKiBleHAoeDApIC8gZmFjdG9yaWFsKDIpICsKICAoeCAtIHgwKV4zICogZXhwKHgwKSAvIGZhY3RvcmlhbCgzKSArICAgCiAgKHggLSB4MCleNCAqIGV4cCh4MCkgLyBmYWN0b3JpYWwoNCkKI1RheWxvciBhcHByb3hpbWF0aW9uIG9mIG9yZGVyIDUKZXhwWG9yZGVyNSA8LSBmdW5jdGlvbih4LCB4MD0wKSAKICBleHAoeDApICsgKHggLSB4MCkqZXhwKHgwKSArIAogICh4IC0geDApXjIgKiBleHAoeDApIC8gZmFjdG9yaWFsKDIpICsKICAoeCAtIHgwKV4zICogZXhwKHgwKSAvIGZhY3RvcmlhbCgzKSArIAogICh4IC0geDApXjQgKiBleHAoeDApIC8gZmFjdG9yaWFsKDQpICsgCiAgKHggLSB4MCleNSAqIGV4cCh4MCkgLyBmYWN0b3JpYWwoNSkKYGBgCgpTaW5jZSB0aGUgZmlyc3QgY29tcG9uZW50IGlzIGNvbnN0YW50LCB3ZSBuZWVkIHRvIGV4cGxvaXQgdGhlIFZlY3Rvcml6ZSBmdW5jdGlvbiBzbyB0byBoYXZlIGEgcmV0dXJuIHZhbHVlIGZvciBlYWNoIGNvbXBvbmVudCBvZgppbnB1dCB2ZWN0b3I6CmBgYHtyfQpleHBYb3JkZXIwdmVjIDwtIFZlY3Rvcml6ZShleHBYb3JkZXIwLCB2ZWN0b3JpemUuYXJncz0ieCIpCmBgYAoKSW4gb3JkZXIgdG8gcGxvdCB0aGUgb3JpZ2luYWwgZnVuY3Rpb24gYXMgd2VsbCBhcyBpdHMgc3Vic2VxdWVudCBhcHByb3hpbWF0aW9ucywgaXQgaXMgdXNlZnVsIHRvIGRlZmluZSBhIHNlcXVlbmNlIG9mIGludGVnZXJzOgpgYGB7cn0KYWJzY2lzc2EgPC0gMDo1CmBgYAoKVGhlIGZvbGxvd2luZyBwbG90IGRlcGljdHMgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uIChzb2xpZCBibGFjayBsaW5lKSBhbG9uZyB3aXRoIHRoZSBmaXJzdCA1IGFwcHJveGltYXRpb24gb2YgdGhlIFRheWxvciBzZXJpZXMgKGxpbmVzIG9mIGRpZmZlcmVudCBjb2xvcnMpOgpgYGB7cn0KI3NvbGlkIGJsYWNrIGxpbmUgZm9yIHRoZSBmdW5jdGlvbgojTk9URTogdGhlIGV4cHJlc3Npb24gZnVuY3Rpb24gYWxsb3dzIHRvIHVzZSBmb3JtdWxhcyB0byBsYWJlbAojICAgICAgdGhlIHBsb3QKIyAgICAgIFNlZSBkZW1vKHBsb3RtYXRoKSBhbmQgZXhhbXBsZShwbG90bWF0aCkgZm9yIGEgY29tcGxldGUgZ2FsbGVyeQpwbG90KGFic2Npc3NhLCBleHAoYWJzY2lzc2EpLCAKICAgICB0eXBlPSJsIiwgY29sPSJibGFjayIsIHhsYWI9IngiLCB5bGFiPSJmKHgpIiwKICAgICBtYWluPWV4cHJlc3Npb24ocGFzdGUoImYoeCk9IixlXngpKSkKI3JlZCBsaW5lIGZvciB0aGUgYXBwcm94aW1hdGlvbiBvZiBvcmRlciAwCmxpbmVzKGFic2Npc3NhLCBleHBYb3JkZXIwdmVjKGFic2Npc3NhKSwgY29sPSJyZWQiKQojYmx1ZSBsaW5lIGZvciB0aGUgYXBwcm94aW1hdGlvbiBvZiBvcmRlciAxCmxpbmVzKGFic2Npc3NhLCBleHBYb3JkZXIxKGFic2Npc3NhKSwgY29sPSJibHVlIikKI2dyZWVuIGxpbmUgZm9yIHRoZSBhcHByb3hpbWF0aW9uIG9mIG9yZGVyIDIKbGluZXMoYWJzY2lzc2EsIGV4cFhvcmRlcjIoYWJzY2lzc2EpLCBjb2w9ImdyZWVuIikKI21hZ2VudGEgbGluZSBmb3IgdGhlIGFwcHJveGltYXRpb24gb2Ygb3JkZXIgMwpsaW5lcyhhYnNjaXNzYSwgZXhwWG9yZGVyMyhhYnNjaXNzYSksIGNvbD0ibWFnZW50YSIpCiNicm93biBsaW5lIGZvciB0aGUgYXBwcm94aW1hdGlvbiBvZiBvcmRlciA0CmxpbmVzKGFic2Npc3NhLCBleHBYb3JkZXI0KGFic2Npc3NhKSwgY29sPSJicm93biIpCiNvcmFuZ2UgbGluZSBmb3IgdGhlIGFwcHJveGltYXRpb24gb2Ygb3JkZXIgNQpsaW5lcyhhYnNjaXNzYSwgZXhwWG9yZGVyNShhYnNjaXNzYSksIGNvbD0ib3JhbmdlIikKYGBgCgpXaGF0IGhhcHBlbnMgaWYgd2UgY2hhbmdlIHRoZSB2YWx1ZSAkeF8wJCBpbiB3aGljaCB0aGUgZnVuY3Rpb24gaXMgYXBwcm94aW1hdGVkPyBIZXJlIGlzIHRoZSBhbnN3ZXIgZm9yIHRoZSBjYXNlICR4XzAgPSAxMCQ6CmBgYHtyfQpwbG90KGFic2Npc3NhLCBleHAoYWJzY2lzc2EpLCAKICAgICB0eXBlPSJsIiwgY29sPSJibGFjayIsIHhsYWI9IngiLCB5bGFiPSJmKHgpIiwKICAgICBtYWluPWV4cHJlc3Npb24ocGFzdGUoImYoeCk9IixlXngpKSkKbGluZXMoYWJzY2lzc2EsIGV4cFhvcmRlcjB2ZWMoYWJzY2lzc2EsIHgwPTMpLCBjb2w9InJlZCIpCmxpbmVzKGFic2Npc3NhLCBleHBYb3JkZXIxKGFic2Npc3NhLCB4MD0zKSwgY29sPSJibHVlIikKbGluZXMoYWJzY2lzc2EsIGV4cFhvcmRlcjIoYWJzY2lzc2EsIHgwPTMpLCBjb2w9ImdyZWVuIikKbGluZXMoYWJzY2lzc2EsIGV4cFhvcmRlcjMoYWJzY2lzc2EsIHgwPTMpLCBjb2w9Im1hZ2VudGEiKQpsaW5lcyhhYnNjaXNzYSwgZXhwWG9yZGVyNChhYnNjaXNzYSwgeDA9MyksIGNvbD0iYnJvd24iKQpsaW5lcyhhYnNjaXNzYSwgZXhwWG9yZGVyNShhYnNjaXNzYSwgeDA9MyksIGNvbD0ib3JhbmdlIikKYGBg