Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
skip to main content
research-article
Open access

Algorithm 1048: A C++ Class for Robust Linear Barycentric Rational Interpolation

Published: 26 October 2024 Publication History

Abstract

Barycentric rational interpolation is a recent interpolation method with several favourable properties. In this article, we present the BRI class, which features a new C++ class template that contains all variables and functions related to linear barycentric rational interpolation. While several methods exist to evaluate a barycentric rational interpolant, the class is designed to autonomously select the best method to use on a case-by-case basis, as it takes into account the latest results regarding the efficiency and numerical stability of barycentric rational interpolation [15]. Moreover, we describe a new technique that makes the code robust and less prone to overflow and underflow errors. In addition to the standard C++ data types, the BRI template variables can also be defined with arbitrary precision because the BRI class is compatible with the Multiple Precision Floating-Point Reliable (MPFR) library [14].

1 Introduction

Barycentric rational interpolation (BRI) is an efficient and numerically robust interpolation method that performs well even in the case of equidistant nodes where polynomial interpolation can fail badly. Because of these favourable properties, BRI has recently become popular not only in mathematics, where it is used for the definition of quadrature rules [6, 22] and for solving partial differential equations [26, 27], but also in more applied contexts. For example, the method proposed by Floater and Hormann [13] is used in statistics [2], engineering [32], as well as in the medical [12], aerospace [21, 25], and chemical sciences [23, 24].
Given a set of \(n+1\) interpolation nodes \(X_{n}=(x_{0},x_{1},\dots,x_{n})\) with \(x_{0} \lt x_{1} \lt \dots \lt x_{n}\) and some associated data \(Y_{n}=(y_{0},y_{1},\dots,y_{n})\), any rational interpolant \(r\colon\mathbb{R}\to\mathbb{R}\) that interpolates \(y_{i}\) at \(x_{i}\) can be expressed in its second barycentric form as
\begin{align}r(x)=\frac{\sum_{i=0}^{n}\frac{w_{i}}{x-x_{i}}y_{i}}{\sum_{i=0}^{n}\frac{w_{i} }{x-x_{i}}},\end{align}
(1)
for some non-zero weights \(W_{n}=(w_{0},w_{1},\dots,w_{n})\) [7]. We focus on linear BRI, meaning that the denominator does not depend on the data \(Y_{n}\), and we use weights \(w_{i}\) that guarantee the absence of poles in the domain \([x_{0},x_{n}]\). The first to introduce a method that is linear and prevents poles was Berrut [3], who defined the weights as
\begin{align}w_{i}={(-1)}^{i},\qquad i=0,1,\dots,n.\end{align}
(2)
Afterwards, Floater and Hormann [13] proposed a new linear barycentric interpolant by considering a parameter \(d\in\{0,1,\dots,n\}\) and the barycentric weights
\begin{align}w_{i}=\sum_{k=\max(i-d,0)}^{\min(i,n-d)}{(-1)}^{k}\prod\limits_{j=k, j\neq i} ^{k+d}\frac{1}{x_{i}-x_{j}},\qquad i=0,1,\dots,n.\end{align}
(3)
Actually, this method is a generalization of Berrut's case since, for \(d=0\), the weights in Equation (3) are exactly the ones in Equation (2). Furthermore, the polynomial interpolant [8] can be expressed as in Equation (1) with weights
\begin{align}w_{i}=\prod_{j=0, j\neq i}^{n}\frac{1}{x_{i}-x_{j}},\qquad i=0,1,\dots,n,\end{align}
(4)
which can be also obtained from Equation (3) for \(d=n\).
The barycentric formula (1) is widely used to evaluate the interpolant \(r\) as it can be implemented with an efficient \(O(n)\) algorithm (see Algorithm 1) and the \(w_{i}\) can be rescaled by a common factor to prevent overflow and underflow errors [8]. Moreover, it has been proven [13] that this family of rational interpolants guarantees a fast convergence rate on the order of \(O(h^{d+1})\), where \(h\) denotes the maximum distance between consecutive nodes. However, there exists another mathematically equivalent formula to evaluate \(r\), namely the first barycentric form
\begin{align}r(x)=\frac{\sum_{i=0}^{n}\frac{w_{i}}{x-x_{i}}f_{i}}{\sum_{i=0}^{n-d}\lambda_{ i}(x)},\end{align}
(5)
where
\begin{align}\lambda_{i}(x)=\frac{{(-1)}^{i}}{(x-x_{i})\cdots(x-x_{i+d})},\qquad i=0,1, \dots,n-d.\end{align}
(6)
While this formula is slightly inferior in terms of efficiency because it requires \(O(nd)\) operations to be computed straightforwardly (see Algorithm 2), there exists a more efficient way of computing its denominator in \(O(n)\) operations. The resulting algorithm (see Algorithm 3) has the same computational cost as Equation (1), but it is slightly less numerically precise than the standard implementation [15]. Moreover, it may happen that Equation (5) is more numerically stable than Equation (1) for some configurations of nodes. In fact, it is known that the forward stability of both Equations (1) and (5) depends on the condition number \(\kappa(x;X_{n},Y_{n})\) related to the problem and on a second function that is different for both cases [15]. On the one hand, for the second barycentric form, the bound on the relative forward error is affected by the Lebesgue function \(\Lambda_{n}(x;X_{n})\), which is known to grow logarithmically in \(n\) and exponentially in \(d\) for equidistant nodes [10, 11]. On the other hand, the numerical stability of the first form depends on a function \(\Gamma_{d}(x;X_{n})\), which is independent of \(n\) (see Section 6), but the only proven upper bound so far depends on \(\mu^{d}\), where \(\mu\) is the mesh ratio of the nodes \(X_{n}\) [15]. However, numerical experiments indicate that \(\Gamma_{d}\) is usually considerably smaller than \(\Lambda_{n}\), suggesting that the first barycentric form may provide a more stable solution when the Lebesgue function related to \(X_{n}\) is large. Finally, the choice of the integer \(d\) is very important because, contrary to the approximation order, the numerical stability of the BRI may be compromised when \(d\) grows. For equidistant, quasi-equidistant [18], or conformally shifted nodes [5], this class of rational interpolants exhibits excellent approximation properties due to the favorable behavior of the Lebesgue function. In particular, for equidistant nodes, Güttel and Klein [16] provide insights on how to choose \(d\) with respect to \(n\) in order to preserve both the convergence rate and the stability. However, for cases like Chebyshev nodes, where polynomial interpolation is effective, these interpolants may become unstable under certain circumstances [4], so it is then better to use the polynomial interpolant in barycentric rational form by choosing \(d=n\).
The goal of this work is to present our class, named BRI, which contains all the necessary functions for handling a barycentric rational interpolant with all its features through a robust and efficient implementation. One main feature of the BRI class is that it provides the user with an “intelligent” function for evaluating \(r\), which computes the best result in terms of numerical stability, efficiency, or both by autonomously choosing one of the three evaluation options (Algorithms 13). The other main feature is the possibility to choose a “guarded” version of the evaluation algorithms, which avoids potential overflow and underflow errors by adaptively scaling the numerator and the denominator of \(r\). The functionality of our class exceeds those of currently available libraries [1, 9, 28, 30], which simply implement the second barycentric form in Equation (1) without any further considerations.
After a brief overview of all the functions contained in the BRI class (Section 2), we present some preliminary results needed to handle overflow and underflow errors in the guarded version (Section 3). Then, we discuss the implementations of the barycentric weights \(w_{i}\) in Equation (3) (Section 4) and of the interpolant \(r\) (Section 5). Finally, we describe the algorithms related to the computation of the functions \(\kappa\), \(\Lambda_{n}\), and \(\Gamma_{d}\) (Section 6).

2 Class Overview

The BRI class arises from the idea of providing the user with a class that holds both variables and functions related to BRI with a simple and intuitive interface and in an efficient programming environment. This idea results in a C++ class template, which comes with the advantage of having all input variables and function outputs defined as generic types. In addition to the basic data types available in C++, such as float or double, the BRI class supports arbitrary precision thanks to the compatibility with the Multiple Precision Floating-Point Reliable (MPFR) library [14] and the MPFR C++ interface [17]. The BRI class does not have any other dependencies other than the C++ standard libraries and, if arbitrary precision is used, the MPFR library.
To initialize a new instance of this class, the user has to specify the integer \(d\), the nodes \(X_{n}\), and the data \(Y_{n}\), and optionally their type and the type of the output results, which are both considered to be double by default. The vectors \(X_{n}\) and \(Y_{n}\) are stored internally as private vectors, but the class provides the user with some functions to access or modify them. Moreover, since they can be passed in different ways, the class includes different constructors. In particular, the user can pass both nodes and data by reference or they can be read from external files by specifying the filenames. Another constructor variant allows the user to pass one of the three keywords UNIFORM, CHEBYSHEV, or EXTENDED_CHEBYSHEV, together with the values \(a\), \(b\), and \(n\). In this case, the class automatically generates \(X_{n}\) as a vector of uniform nodes
\begin{align}x_{i}=a+(b-a)\frac{i}{n},\qquad i=0,1,\dots,n\end{align}
(7)
or Chebyshev nodes
\begin{align}x_{i}=\frac{a+b}{2}-\frac{b-a}{2}\cos\frac{(2i+1)\pi}{2n+2},\qquad i=0,1,\dots,n\end{align}
(8)
or extended Chebyshev nodes
\begin{align*}x_{i}=\frac{a+b}{2}-\frac{b-a}{2}\cos\frac{(2i+1)\pi}{2n+2}\bigg{/}\cos\frac{ \pi}{2n+2},\qquad i=0,1,\dots,n\end{align*}
over the interval \([a,b]\). Of course, it would be possible to extend the class to allow for other predefined sets of interpolation nodes. As for the data \(Y_{n}\), the user can also call the constructor with a pointer to a procedure f, which implements some function \(f\colon\mathbb{R}\to\mathbb{R}\), so that the data is automatically generated as \(f(X_{n})\) by the class. After having defined these initial parameters, the class allows the user to modify them at any moment. Furthermore, the constructors create the vector \(W_{n}\) of barycentric weights (3), which get updated automatically whenever the nodes \(X_{n}\) are changed. Like nodes and data, the weights are private and can be accessed using suitable functions.
The core of the BRI class is the evaluation of the barycentric rational interpolant \(r\), defined by the input \(X_{n}\), \(Y_{n}\), and \(d\), through the eval function. The latter takes \(x\) as input, which can be either a single evaluation point or a vector of points, and outputs \(r(x)\), which in turn is a point or a vector, respectively. If the user wants to specify explicitly which algorithm to use for the evaluation, the eval function has an optional second parameter, which is one of the following keywords: SECOND to evaluate \(r\) with the second barycentric form (Algorithm 1), FIRST_DEF to use the standard implementation of the first barycentric form (Algorithm 2), or FIRST_EFF for its more efficient variant (Algorithm 3). Without this second parameter, the code uses by default the algorithm that best balances efficiency and numerical stability. Likewise, the user can call the functions numerator and denominator to evaluate the numerator and denominator of \(r\), respectively. In case of the denominator, one of the three aforementioned keywords can be added to explicitly ask for the denominator to be computed by the corresponding algorithms.
The BRI class also provides three flags: the stability flag for controlling the numerical stability of the result, the efficiency flag for indicating a preference for the fastest evaluation routine whenever the first barycentric form is used, and the guard flag for activating additional checks that prevent overflow and underflow. The user can turn these flags on or off at any moment. In the following sections, we present in detail how the code decides which algorithm guarantees the numerically most stable or most efficient result if the respective flag is activated and how the guarding mechanism avoids possible overflow or underflow errors without affecting the numerical accuracy of the result.
Finally, the class also allows to evaluate all the functions that are related to the numerical stability of the barycentric rational interpolant, namely the condition number \(\kappa\), the Lebesgue function \(\Lambda_{n}\), and the function \(\Gamma_{d}\). They can be called either with an input \(x\), which again can be an evaluation point or a vector of evaluation points, or without any arguments, upon which the algorithm searches for the maximum of the function using Newton's method.

3 Preliminary Results on the Floating-Point Number System

We consider the binary floating-point number system [31], which is characterized by a precision \(t\in\mathbb{N}\) and two exponents \(E_{\smash{\min}},E_{\max}\in\mathbb{Z}\). For example, the standard float type in C++ represents a single precision floating-point number with \(t=23\), \(E_{\smash{\min}}=-125\), \(E_{\max}=128\), while the standard double type represents a double precision floating-point number with \(t=52\), \(E_{\smash{\min}}=-1021\), \(E_{\max}=1024\). Note that the IEEE standard 754 [20] specifies these numbers slightly differently in terms of the number of digits in the significand \(p=t+1\), the maximum exponent \(\mathit{emax}=E_{\max}-1\), and the minimum exponent \(\mathit{emin}=1-\mathit{emax}=E_{\smash{\min}}-1\). In such a system, every element of the set \(\mathbb{F}\) of floating point numbers is \(0\) or has the form \(\pm\mu\times 2^{E}\), with a mantissa (or significand) \(\mu\in[\mu_{\smash{\min}},\mu_{\max}]=[2^{-1},1-2^{-t}]\) and an exponent \(E\in\{E_{\smash{\min}},E_{\smash{\min}}+1,\dots,E_{\max}\}\), and the smallest and largest positive normal floating-point numbers are
\begin{align}F_{\smash{\min}}=\mu_{\smash{\min}}2^{E_{\smash{\min}}}\qquad\text{and}\qquad F _{\max}=\mu_{\max}2^{E_{\max}}.\end{align}
(9)
There also exist so-called subnormal floating-point numbers, but they have reduced precision and are not relevant in our context as all the rescale operations are performed with respect to the interval \([F_{\smash{\min}},F_{\max}]\).
In the following proposition, we present some basic facts about two arbitrary positive floating-point numbers that will be used frequently later.
Proposition 3.1.
Let \(a=+\alpha\times 2^{A}\in\mathbb{F}\) and \(b=+\beta\times 2^{B}\in\mathbb{F}\). Suppose we compute \(c=a\circledast b=\gamma\times 2^{C}\in\mathbb{F}\), where \(\circledast\in\{+,-,\cdot,\div\}\) is one of the standard arithmetic operations. Then, except in the case where \(c=0\), the exponent \(C\) is guaranteed to be in the range \(\{C_{\smash{\min}},C_{\smash{\min}}+1,\dots,C_{\max}\}\), where
\begin{align}(C_{\smash{\min}},C_{\max})=\begin{cases}(A+B-1,A+B), & \text{if } c=a\cdot b, \\(A-B,A-B+1), & \text{if } c=a\div b, \\(\max\{A,B\},\max\{A,B\}+1), & \text{if } c=a+b, \\(A-t+1,A-1), & \text{if } c=a-b \text{ and } A=B, \\(\max\{A,B\}-t,\max\{A,B\}), & \text{if } c=a-b \text{ and } {\lvert A-B\rvert}=1, \\(\max\{A,B\}-1,\max\{A,B\}), & \text{if } c=a-b \text{ and } {\lvert A-B\rvert} \gt 1.\end{cases}\end{align}
(10)
Proof.
The proof is straightforward and follows directly by some consideration on the interval that contains \(c\) for each case, recalling the fact that \(\gamma\in[\mu_{\smash{\min}},\mu_{\max}]=[1/2,1-2^{-t}]\). ∎
Let \(M,J,K\in\mathbb{N}\) and consider, for any \(i=0,1,\dots,M\), the numbers \(a_{i,j}=\alpha_{i,j}\times 2^{A_{i,j}}\in\mathbb{F}\) for \(j=1,2,\dots,J\) and \(b_{i,k}=\beta_{i,k}\times 2^{B_{i,k}}\in\mathbb{F}\) for \(k=1,2,\dots,K\). Denoting the products of these numbers by
\begin{align}r_{i}=\prod_{j=1}^{J}a_{i,j}\qquad\text{and}\qquad s_{i}=\prod_{k=1}^{K}b_{i,k},\end{align}
(11)
which can be expressed in floating point encoding as
\begin{align} r_{i} & =\rho_{i}\times 2^{R_{i}},\qquad\text{where}\quad\rho_{i}=\prod_{ j=1}^{J}\alpha_{i,j}\quad\text{and}\quad R_{i}=\sum_{j=1}^{J}A_{i,j},\end{align}
(12)
and
\begin{align} & =\sigma_{i}\times 2^{S_{i}},\qquad\text{where}\quad\sigma_{i}= \prod_{k=1}^{K}\beta_{i,k}\quad\text{and}\quad S_{i}=\sum_{k=1}^{K}B_{i,k},\end{align}
(13)
suppose we want to compute the quantity
\begin{align}f=\sum_{i=0}^{M}\frac{r_{i}}{s_{i}}.\end{align}
(14)
Even if we know that \(f\in[F_{\smash{\min}},F_{\max}]\), it may happen that the algorithm that implements \(f\) runs into overflow or underflow errors in some of its intermediate steps. However, we can try to avoid this problem by appropriately rescaling the intermediate floating-point values by some constant \(C\), so that they are kept far from the overflow and underflow regions. Moreover, if we use a rescale factor of the type \(2^{E}\), for some \(E\in\mathbb{Z}\), then this operation modifies only the exponent of each floating-point number without changing the mantissa, meaning that we are not introducing any additional rounding error. Therefore, the goal now is to properly define the exponent \(E\) so that we are sure that \(\hat{f}=2^{E}f\) can be safely computed without any overflow or underflow error.
Proposition 3.2.
Let \(M,J,K\in\mathbb{N}\) and consider \(r_{i}\) and \(s_{i}\) as in Equation (11), \(\rho_{i}\) and \(R_{i}\) as in Equation (12), \(\sigma_{i}\) and \(S_{i}\) as in Equation (13) for \(i=0,1,\dots,M\), and \(f\) as in Equation (14). Suppose that all \(p_{i}=r_{i}/s_{i}\) have the same sign and define
\begin{align}L=\min_{0\leq i\leq M}(R_{i}-S_{i})-J+1\qquad\text{and}\qquad U=\max_{0\leq i \leq M}(R_{i}-S_{i})+K+M\end{align}
(15)
and
\begin{align}E=\left\lceil\frac{E_{\max}+E_{\smash{\min}}-L-U}{2}\right\rceil.\end{align}
(16)
If \(U-L \lt E_{\max}-E_{\smash{\min}}\), then we can compute \(\hat{f}=2^{E}f\) without any overflow or underflow error using Algorithm 4.
Proof.
The goal is to show that all the operations in Algorithm 4 are performed in \(\mathbb{F}\). It follows from Equation (16) that
\begin{align*}\frac{E_{\max}+E_{\smash{\min}}-L-U}{2}\leq E\leq\frac{E_{\max}+E_{\smash{\min }}-L-U}{2}+\frac{1}{2},\end{align*}
which, together with Equation (15) and the hypothesis \(U-L \lt E_{\max}-E_{\smash{\min}}\), gives
\begin{align}E_{\smash{\min}}\leq E_{\smash{\min}}+J-1\leq R_{i}-S_{i}+E\leq E_{\max}-K-M < E _{\max},\end{align}
(17)
meaning that the computation of \(p_{i}\) in line 4 is always safe. By Proposition 3.1, we know that the multiplications in the loop of lines 5–6 can decrease the exponent \(R_{i}-S_{i}+E\) by at most \(J-1\) and the divisions in the loop of lines 7–8 can increase it by at most \(K\), but in both cases Equation (17) guarantees that \(p_{i}\in\mathbb{F}\). Finally, Proposition 3.1 guarantees that every summation in line 9 increases the exponent \(R_{i}-S_{i}+E\) by at most \(1\), for a maximum of \(M\) times. Again, by Equation (17), we can thus be sure that also \(\hat{f}\in\mathbb{F}\). ∎
Corollary 3.3.
Let \(M,J,K\in\mathbb{N}\) and consider \(r_{i}\) and \(s_{i}\) as in Equation (11), \(\rho_{i}\) and \(R_{i}\) as in Equation (12), \(\sigma_{i}\) and \(S_{i}\) as in Equation (13) for \(i=0,1,\dots,M\), and \(f\) as in Equation (14). Suppose that all \(p_{i}=r_{i}/s_{i}\) have the same sign that there exist some \(R_{\smash{\min}},R_{\max},S_{\smash{\min}},S_{\max}\in\mathbb{Z}\), such that \(R_{\smash{\min}}\leq R_{i}\leq R_{\max}\) and \(S_{\smash{\min}}\leq S_{i}\leq S_{\max}\) for \(i=0,1,\dots,M\), and define
\begin{align}L=R_{\smash{\min}}-S_{\max}-J+1\qquad\text{and}\qquad U=R_{\max}-S_{\smash{ \min}}+K+M\end{align}
(18)
and
\begin{align}E=\left\lceil\frac{E_{\max}+E_{\smash{\min}}-L-U}{2}\right\rceil.\end{align}
(19)
If \(U-L \lt E_{\max}-E_{\smash{\min}}\), then we can compute \(\hat{f}=2^{E}f\) without any overflow or underflow error using Algorithm 4.
Proof.
Since \(L\leq\min_{0\leq i\leq M}(R_{i}-S_{i})-J+1\) and \(U\geq\max_{0\leq i\leq M}(R_{i}-S_{i})+K+M\), the statement follows with the same arguments as in the proof of Proposition 3.2. ∎

4 Barycentric Weights

As for the barycentric weights in Equation (3), the simplest method to implement them is to follow their definition, thus obtaining an algorithm that computes all \(w_{i}\) in \(O(nd^{2})\) operations. However, Hormann and Schaefer [19] proposed a pyramid algorithm that requires only \(O(nd)\) operations and has the same precision [15]. This algorithm starts with the values
\begin{align}v^{d}_{i}=1,\qquad i=0,1,\dots,n-d\end{align}
(20)
and iteratively defines
\begin{align} v^{l}_{i} & =\frac{v^{l+1}_{i-1}}{x_{i+l}-x_{i-1}}+\frac{v^{l+1}_{i}}{x_{i+l+ 1}-x_{i}},\qquad i=0,1,\dots,n-l,\end{align}
(21)
for \(l=d-1,d-2,\dots,0\), tacitly assuming that \(v^{l}_{i}=0\) for \(i \lt 0\) and \(i \gt n-l\). The barycentric weights are then given as
\begin{align*}w_{i}=(-1)^{i-d}v_{i}^{0},\qquad i=0,1,\dots,n.\end{align*}
To save memory, the BRI class uses the vector of weights also to store the intermediate values \(v^{l}_{i}\) in \(w_{i}\), which requires the assignment in Equation (21) to be performed in reverse order (see Algorithm 5).
After having initialized a new instance of the BRI class with the variables \(X_{n}\), \(Y_{n}\), and \(d\), the vector \(W_{n}\) is automatically computed as described above, which is efficient and robust. However, there are cases, albeit extreme, in which the Weights function runs into overflow or underflow errors.
Example 4.1
If we consider \(10\) Chebyshev nodes (8) (that is, \(n=9\)) over \([0,10^{-12}]\) and \(d=3\), then
\begin{align}w_{0}=\frac{-1}{(x_{3}-x_{0})(x_{2}-x_{0})(x_{1}-x_{0})}\approx-5.5257\times 1 0^{38},\end{align}
(22)
and if the variable types are set to float for both input and output, then Algorithm 5 overflows in line 7 in the last iteration, when \(l=0\), so that \(w_{0}=-\texttt{inf}\), because the smallest negative floating-point number in single precision is \(-F_{\max}=-2^{127}(2-2^{-23})\approx-3.4028\times 10^{38}\). In fact, we get \(w_{i}=(-1)^{i+1}\texttt{inf}\) for all \(i=0,\dots,9\) in this example.
Example 4.2
Let us consider \(3333\) equidistant nodes over \([-1,1]\) and \(d=333\). This choice of \(n\) and \(d\) guarantees the best balance between the theoretical and the actual numerical error of the barycentric rational interpolant, for example, if the data are sampled from the function \(f(x)=\log(1.2-x)/(x^{2}+2)\) [16]. However, if we compute the weights with Algorithm 5, using double for both input and output, we run into overflow problems and all weights turn out to be \(w_{i}=(-1)^{i+1}\texttt{inf}\).
Example 4.3
The BRI class also covers polynomial interpolation, that is, the case \(d=n\), and in this setting underflow and overflow errors are even more common. For example, Pachón [29] shows that the weights can be computed safely for \(500\) Chebyshev nodes in \([-2,2]\) in double precision, while problems arise, if the interval is changed to \([-0.2,0.2]\) or \([-20,20]\), leading to overflow in the former and underflow in the latter case. Furthermore, increasing the value of \(n\) may result in similar issues. For example, for \(1500\) Chebyshev nodes in \([-2,2]\), Algorithm 5 causes the first and the last \(51\) weights to underflow.
It is precisely for situations like these that we provide the guard flag, which, if activated, calls code that tries to prevent overflow and underflow errors. The basic idea is to rescale intermediate floating-point values, so that they are kept far from the overflow and underflow regions. To do this, we multiply the values \(v_{i}^{l}\) in Equation (21) for \(i=0,1,\dots,n-l\) in each step of the pyramid algorithm with a suitable common constant \(2^{C_{l}}\), with \(C_{l}\in\mathbb{Z}\). Of course, we need to define these constants appropriately to make sure that these rescaling operations are safe and do not in turn cause any overflow or underflow errors. To this end, we shall first work out intervals \(I_{l}=\bigl{[}\mu_{\smash{\min}}2^{L_{l}},\mu_{\max}2^{U_{l}}\bigr{]}\) that are guaranteed to contain all \(v^{l}_{i}\). Before delving into these details, it is worth recalling that such rescaling operations do not change the second barycentric formula in Equation (1).
Proposition 4.4.
Let \(L_{d}=U_{d}=0\) and
\begin{align}L_{l}=L_{l+1}-H_{\max}-E_{l}-1\qquad\text{and}\qquad U_{l}=U_{l+1}-H_{\smash{ \min}}-E_{l}+2,\qquad l=d-1,d-2,\dots,0,\end{align}
(23)
where \(E_{l}=\lfloor\log_{2}(l+1)\rfloor\) and \(H_{\smash{\min}},H_{\max}\in\mathbb{Z}\) are the exponents of the floating-point representation of the minimal and the maximal distance between neighbouring nodes, that is,
\begin{align*}h_{\smash{\min}}=\min_{1\leq i\leq n}(x_{j}-x_{j-1})=\eta_{1}\times 2^{H_{ \smash{\min}}}\qquad\text{and}\qquad h_{\max}=\max_{1\leq i\leq n}(x_{j}-x_{j- 1})=\eta_{2}\times 2^{H_{\max}}.\end{align*}
Then, \(v_{i}^{l}\in I_{l}=\bigl{[}\mu_{\smash{\min}}2^{L_{l}},\mu_{\max}2^{U_{l}} \bigr{]}\) for \(i=0,1,\dots,n-l\) and any \(l\in\{0,1,\dots,d-1\}\).
Proof.
Assume that \(B_{\smash{\min}}^{l+1}\leq v^{l+1}_{i}\leq B_{\max}^{l+1}\) for \(i=0,1,\dots,n-l-1\) and some \(l\in\{0,1,\dots,d-1\}\). Then, letting
\begin{align}B_{\smash{\min}}^{l}=\frac{B_{\smash{\min}}^{l+1}}{(l+1)h_{\max}}\qquad\text{ and}\qquad B_{\max}^{l}=\frac{2B_{\max}^{l+1}}{(l+1)h_{\smash{\min}}}\end{align}
(24)
and noticing that
\begin{align}0 < (k-j)h_{\smash{\min}}\leq x_{k}-x_{j}\leq(k-j)h_{\max},\end{align}
(25)
for any \(j \lt k\), it follows from Equation (21) that
\begin{align}B_{\smash{\min}}^{l}\leq\frac{v_{i-1}^{l+1}}{(l+1)h_{\max}}+\frac{v_{i}^{l+1}} {(l+1)h_{\max}}\leq v_{i}^{l}\leq\frac{v_{i-1}^{l+1}}{(l+1)h_{\smash{\min}}}+ \frac{v_{i}^{l+1}}{(l+1)h_{\smash{\min}}}\leq B_{\max}^{l}\end{align}
(26)
for \(i=0,1,\dots,n-l\). Consequently, defining \(B_{\smash{\min}}^{d}=B_{\max}^{d}=1\) and \(B_{\smash{\min}}^{l}\) and \(B_{\max}^{l}\) recursively as in Equation (24) for \(l=d-1,d-2,\dots,0\), it follows by induction that \(v_{i}^{l}\in\bigl{[}B_{\smash{\min}}^{l},B_{\max}^{l}\bigr{]}\) for \(i=0,1,\dots,n-l\) and any \(l\in\{0,1,\dots,d-1\}\).
Denoting the exponents of the floating-point representation of \(B_{\smash{\min}}^{l}\) and \(B_{\max}^{l}\) by \(P_{\smash{\min}}^{l},P_{\max}^{l}\in\mathbb{Z}\) and noticing that
\begin{align}2^{E_{l}}\leq l+1\leq 2^{E_{l}+1},\end{align}
(27)
it then follows from Proposition 3.1 and Equation (24) that
\begin{align*}B_{\smash{\min}}^{l}\geq\mu_{\smash{\min}}2^{P_{\smash{\min}}^{l+1}-H_{\max}-E _{l}-1}\qquad\text{and}\qquad B_{\max}^{l}\leq\mu_{\max}2^{P_{\max}^{l+1}-H_{ \smash{\min}}-E_{l}+2},\end{align*}
and therefore \(v_{i}^{l}\in\bigl{[}B_{\smash{\min}}^{l},B_{\max}^{l}\bigr{]}\subset\bigl{[} \mu_{\smash{\min}}2^{L_{l}},\mu_{\max}2^{U_{l}}\bigr{]}\), where \(L_{l}\) and \(U_{l}\) are defined as in Equation (23). ∎
Considering the floating-point representation of each value \(v_{i}^{l+1}=\nu_{i}\times 2^{V_{i}}\) and the differences \(x_{i+l+1}-x_{i}=\xi_{i}\times 2^{X_{i}}\), for some \(l\in\{0,1,\dots,d-1\}\) and \(i=0,1,\dots,n-l\), we know from Proposition 4.4 that \(L_{l+1}\leq V_{i}\leq U_{l+1}\) and, from Equations (25) and (27), that \(H_{\smash{\min}}+E_{l}\leq X_{i}\leq H_{\max}+E_{l}+1\). Moreover, we can observe that the expression for the values \(v_{i}^{l}\) in Equation (21) fits into the more general formula Equation (14) for \(M=J=K=1\). This means that \(L_{l}\) and \(U_{l}\) in Equation (23) are exactly \(L\) and \(U\) in Equation (18), where \(R_{\smash{\min}}=L_{l+1}\), \(R_{\max}=U_{l+1}\), \(S_{\smash{\min}}=H_{\smash{\min}}+E_{l}\), and \(S_{\max}=H_{\max}+E_{l}+1\). Consequently, by Corollary 3.3, if \(U_{l}-L_{l} \lt E_{\max}-E_{\smash{\min}}\), then we can define
\begin{align*}C_{l}=\left\lceil\frac{E_{\max}+E_{\smash{\min}}-L_{l}-U_{l}}{2}\right\rceil\end{align*}
and compute \(2^{C_{l}}v_{i}^{l}\) for \(i=0,1,\dots,n-l\) without any overflow or underflow error using Algorithm 4.
Therefore, the “guarded” version of the pyramid algorithm (see Algorithm 6) rescales the values \(v_{i}^{l}\) by the constant \(2^{C_{l}}\) in each step \(l=d-1,d-2,\dots,0\). Therefore, if we first compute \(L_{l}\) and \(U_{l}\) as in Equation (23) and find that \(U_{l}-L_{l} \lt E_{\max}-E_{\smash{\min}}\), then we can be sure that computing the values \(2^{C_{l}}v^{l}_{i}\) with Algorithm 4 will not cause any overflow or underflow. If this latter condition is not satisfied for some \(\hat{l}\in\{0,1,\dots,d-1\}\), it means that we cannot be sure anymore that all \(v_{i}^{l}\) are normal floating-point numbers. Therefore, we try to repeat the same procedure by first re-defining
\begin{align}L_{\hat{l}}=\min_{0\leq i\leq n-l}{V_{i}}-1\qquad\text{and}\qquad U_{\hat{l}}= \max_{0\leq i\leq n-l}{V_{i}}.\end{align}
(28)
If it fails again, then the algorithm proceeds normally by updating the weights as in lines 3–7 of Algorithm 5. If the calculations are successful for every \(i=0,1,\dots,n-\hat{l}\) without overflow nor underflow errors, then we define \(L_{\hat{l}}\) and \(U_{\hat{l}}\) as in Equation (28), and we continue with the remaining iterations. Otherwise, the code stops and reports an error message to the user. At the end, the weights are rescaled with respect to the constant \(2^{C_{w}}\), where
\begin{align}C_{w}=\sum_{l=0}^{d-1}C_{l}.\end{align}
(29)
For example, considering the setting of Example 4.1, we can solve the overflow problem with Algorithm 6, which returns the weights rescaled by the constant \(C_{w}=2^{-127}\).

5 Evaluation of the Barycentric Rational Interpolant

As already mentioned in Section 2, the evaluation of the barycentric rational interpolant \(r\) can be realized by using the second rational barycentric form with Algorithm 1 or the first form with either Algorithm 2 or 3. The BRI class allows the user to choose one of the three algorithms by calling the eval function with two input parameters: the first is the evaluation point or vector \(x\) and the second is one of the three keywords FIRST_DEF, FIRST_EFF, or SECOND. However, the second parameter can be omitted, obtaining Algorithm 7 that autonomously chooses the best algorithm to use. Let us now focus on the latter case.
By default, the class is always called Algorithm 1 because it is generally the one that best combines numerical stability and efficiency of the method. On the other hand, if the user asks for the most stable solution by turning on the stability flag, then the code first evaluates \(\operatorname{\kappa}(x)\) and \(\Lambda_{n}(x)\) and decides, based on these values, which is the best algorithm to use. In particular, it is known that the condition number affects the upper bound on the relative forward error of both the first and the second barycentric form [15], so if \(\operatorname{\kappa}(x) \gt 10^{3}\), then the class warns the user about this and continues without interruption. It is further known that the stability of Equation (1) depends on the function \(\Lambda_{n}\), which grows with \(n\), whereas the stability of Equation (5) depends on the function \(\Gamma_{d}\), whose upper bound is independent of \(n\). However, numerical experiments show that the estimated upper bound on \(\Gamma_{d}\) seems to be always much larger than \(\Gamma_{d}\) itself. For this reason, if \(\Lambda_{n}(x) \gt 10^{2}\), then the result is computed with Algorithm 2. If it happens that also \(\Gamma_{d}(x) \gt 10^{2}\), then the user simply receives a warning without the code stopping. Finally, if both the stability and the efficiency flags are active and it turns out that the most stable solution is given by the first barycentric form, then it is computed with Algorithm 3, which computes all the \(\lambda_{i}\) with a more efficient iterative strategy. From a computational point of view, we are improving by switching from an \(O(nd)\) algorithm to an \(O(n)\) algorithm, therefore we know that for small \(d\) there is no big gain, but, as \(d\) increases, the efficient implementation can result in a lower execution time, without losing much in terms of stability. For example, Figure 1 compares the stability and the running time of the two algorithms considering \(n+1\) equidistant interpolation nodes \(x_{i}\in[0,1]\) for \(n=150\) with associated data \(y_{i}=0\), for \(i=0,\dots,n-1\) and \(y_{n}=1\). In particular, on the left we see the maximum of both relative forward errors evaluated at \(1{,}000\) random points in \([0,1]\) and on the right their execution times in seconds as a function of \(d\in\{1,2,\dots,n\}\). We observe that Algorithm 2 is slightly more precise than Algorithm 3, as expected, but the latter always wins in terms of efficiency, especially in the neighborhood of \(d=n/2\). It is worth noting that, if the stability flag is turned off, then the efficiency flag does not play any role, because Algorithm 7 takes the second barycentric form by default.
Fig. 1.
Fig. 1. Maximal relative forward error of the first barycentric form for \(n+1\) equidistant nodes, \(n=150\), and \(d\in\{1,2,\dots,n\}\) at \(1{,}000\) random evaluation points with data sampled from the \(n\)-th Lagrange basis polynomial on a logarithmic scale (left) and overall running time in seconds (right) using Algorithm 2 (asterisks) and Algorithm 3 (circles).
As for the weights, also in this case the user can decide to turn on the guard flag to prevent overflow and underflow errors. The basic idea is again the same as in Section 4 for the weights, that is, rescaling the numerator and the denominator properly in order to perform all floating-point operations far from the overflow and underflow regions and to avoid introducing any further rounding errors. In this case, we have to further take into account that the summations in the numerator and denominator of Equations (1) and (5) involve both subtractions and additions that may lead to cancellation errors. Moreover, from Proposition 3.1, preventing non-underflow subtractions could be tricky, especially if we are subtracting numbers of similar magnitudes. However, we recall that cancellation errors are already taken into consideration in the study of the numerical stability of the interpolant [15], so, if the method is stable, then it is proven that they cannot happen. Otherwise, one option would be to split each summation into one for the positive terms and one for the negative terms, which, in case the condition of Proposition 3.2 is satisfied, can be safely computed using Algorithm 4 and making only one final subtraction. The problem with this procedure is that, from our experiments, it seems to lose precision compared to the normal iterative algorithm when there are cancellation errors. Furthermore, since the two summations consist only of additions, if the addends have high orders of magnitude and \(n\) is large, then it is much more likely to run into overflow errors. For these reasons, we decided to safely compute only the addends of the summations in Equations (1) and (5) using Proposition 3.2 (for the special case \(M=0\)), and finally to calculate the sums with the classic iterative algorithm. Therefore, no adjustment is considered that could prevent overflow or underflow errors during the summations, but we check only afterwards if something like this has happened. In particular, considering the floating-point representation of each weight \(w_{i}=\omega_{i}\times 2^{W_{i}}\), data \(y_{i}=\upsilon_{i}\times 2^{Y_{i}}\), and difference \(x-x_{i}=\xi_{i}\times 2^{X_{i}}\), we let
\begin{align*}L_{1} & =\min_{0\leq i\leq n}(W_{i}+Y_{i}-X_{i})-1, & U_{1} & =\max_{0\leq i\leq n}(W_{i}+Y_{i}-X_{i})+1, \\L_{2} & =\min_{0\leq i\leq n}(W_{i}-X_{i}), & U_{2} & =\max_{0\leq i\leq n}(W_{i}-X_{i})+1, \\L_{3} & =\min_{0\leq i\leq n-d}(-X_{i}-\dots-X_{i+d}), & U_{3} & =\max_{0\leq i\leq n-d}(-X_{i}-\dots-X_{i+d})+d+1,\end{align*}
and we define
\begin{align}&C_{1}=\left\lceil\frac{E_{\max}+E_{\smash{\min}}-L_{1}-U_{1}}{2}\right\rceil, \qquad C_{2}=\left\lceil\frac{E_{\max}+E_{\smash{\min}}-L_{2}-U_{2}}{2}\right \rceil,\qquad\\&C_{3}=\left\lceil\frac{E_{\max}+E_{\smash{\min}}-L_{3}-U_{3}}{2} \right\rceil.\end{align}
(30)
After that, denoting the common numerator of Equations (1) and (5), the denominator of Equation (1), and the denominator of Equation (5) by \(N\), \(D_{s}\), and \(D_{f}\), respectively, if \(U_{j}-L_{j} \lt E_{\max}-E_{\smash{\min}}\) for all \(j\in\{1,2,3\}\), then we can compute
\begin{align*}\hat{N}=2^{C_{1}}N,\qquad\hat{D}_{s}=2^{C_{2}}D_{s},\qquad\text{and}\qquad\hat {D}_{f}=2^{C_{3}}D_{f}\end{align*}
with Algorithm 4, but, since the exponents in Equation (30) do not consider additions and subtractions, at the end it is necessary to check whether overflow or underflow errors have happened. Finally, if every operation was computed safely, then we get the result with the second barycentric form as
\begin{align*}r(x)=2^{C_{2}-C_{1}}\frac{\hat{N}(x)}{\hat{D}_{s}(x)}\end{align*}
or with the first barycentric form as
\begin{align*}r(x)=2^{C_{3}-C_{1}-C_{w}}\frac{\hat{N}(x)}{\hat{D}_{f}(x)}.\end{align*}
Otherwise, the code stops and gives an error message to the user. Note that the guarded result of the first form involves also the rescale factor \(C_{w}\) in Equation (29), because its denominator does not depend on the weights. If \(U_{j}-L_{j}\geq E_{\max}-E_{\smash{\min}}\) for some \(j\in\{1,2,3\}\), then the algorithm tries to compute the corresponding summation as in Algorithm 1, 2, or 3. Again, if some overflow or underflow error happens, then the code stops, otherwise the corresponding rescale factor \(C_{j}\) is set to \(0\) for \(j\in\{1,2,3\}\) and the final result is computed as before.
Example 5.1
As in Example 4.1, we consider \(n=9\) and \(n+1\) Chebyshev interpolation nodes in \([0,10^{-12}]\), but we take \(d=2\) so that the weights do not overflow even in non-guarded mode. We then define \(y_{i}=f(x_{i})\) for \(i=0,1,\dots,n\), where
\begin{align}f(x)=\tfrac{3}{4}e^{-\frac{(9x-2)^{2}}{4}}+\tfrac{3}{4}e^{-\frac{(9x+1)^{2}}{4 9}}+\tfrac{1}{2}e^{-\frac{(9x-7)^{2}}{4}}+\tfrac{1}{5}e^{-(9x-4)^{2}},\end{align}
(31)
\(x=10^{-12}/2\) and all variables in input and output are set as float. In this case, both Algorithms 1 and 2 return \(-\texttt{nan}\), while Algorithms 8 and 9 give the same result in single precision, with \(6\) digits equal to the exact value \(r(x)=1.01076...\). More precisely, they compute
\begin{align*}N(x)=2^{44}5.13436,\qquad D_{s}(x)=2^{43}10.1594,\qquad\text{and}\qquad D_{f}(x)=2^{125+C_{w}}40.6375,\end{align*}
where \(C_{w}=-84\) in this setting.
Finally, we analysed how much the guard and the stability flags can affect the computational cost of the method. In particular, we conducted several tests to compare the running times with these flags both turned on and off and also considering variations in the input, such as \(d\), the number of nodes and data \(n\), and the number of evaluation points. Notably, if we activate only the guard flag, then we observed a maximum increase in the execution time of one order of magnitude. Instead, in the worst-case scenario where we enable both the guard and the stability flag, the increase can reach at most two orders of magnitude.

5.1 Evaluation Close to a Node

One of the properties of the set \(\mathbb{F}\) is that it is not equally spaced, but it becomes denser in the proximity of \(F_{\smash{\min}}\). In particular, the floating-point numbers are equally spaced in each interval \(\big{[}2^{E},2^{E+1}\big{]}\) and at a distance of \(h_{E}=2^{E-t}\). Hence, if we want to evaluate \(r\) very close to a node \(x_{j}\in\big{[}2^{E},2^{E+1}\big{]}\) for some \(E\in\mathbb{N}\), then we cannot get any closer than \(h_{E}\). Consequentially, if the evaluation point is \(x=x_{j}+h\) and \(x_{j}\) and \(h\) have different orders of magnitude, then we can lose accuracy because too small increments are ignored. Similarly, if we get too close to \(x_{j}\), in view of the continuity of the interpolant \(r\), we have \(r(x_{j}+h)=y_{j}+u\) and if \(u\in\mathbb{R}\) is too small, then the code could round the final result to \(y_{j}\). However, we note that
\begin{align*}r(x_{j}+h;X_{n},Y_{n})=\frac{\sum_{i=0}^{n}\frac{w_{i}}{x_{j}+h-x_{i}}y_{i}}{ \sum_{i=0}^{n}\frac{w_{i}}{x_{j}+h-x_{i}}}=\frac{\sum_{i=0}^{n}\frac{w_{i}}{h- (x_{i}-x_{j})}(y_{i}-y_{j})}{\sum_{i=0}^{n}\frac{w_{i}}{h-(x_{i}-x_{j})}}+y_{j }=r(h;X_{n}-x_{j},Y_{n}-y_{j})+y_{j},\end{align*}
so that shifting the domain and the range by \(x_{j}\) and \(y_{j}\), respectively, we can compute \(u=r(h)\) and get the final result as \(y_{j}+u\). The advantage of this procedure is that both \(h\) and \(u\) are more accurate and reach up to a magnitude of \(2^{E_{\smash{\min}}-1-t}\), that is, the distance between floating point numbers in \(\big{[}2^{E_{\smash{\min}}-1},2^{E_{\smash{\min}}}\big{]}\). For this reason, the BRI class automatically uses this strategy if the eval function receives as input the index \(j\) and the value \(h\) and it returns \(u\).
Example 5.2
Consider \(n=9\), \(d=2\), and \(n+1\) equidistant interpolation nodes \(x_{i}\in[1,2]\) with associated data \(y_{i}=f(x_{i})\) for \(i=0,1,\dots,n\) and \(f(x)=x\). Suppose we want to evaluate the interpolant \(r\) very close to the first node \(x_{0}=1\) at \(x=x_{0}+h\) for \(h=10^{-20}\), and we set all variables in input and output as double. Since the closest double floating-point number to \(x_{0}=1\) is \(1+\epsilon\), where \(\epsilon=2.2204\times 10^{-16}\), using any of the three algorithms discussed in Section 5, we get \(r(x)=y_{0}=1\), because \(x\) is rounded to \(x_{0}=1\) in double precision. Instead, with the new strategy we obtain \(u=r(h)=9.9999999999999949376\times 10^{-21}\), meaning that \(r(x)=y_{0}+u=1.00000000000000000001\), which is also what we would get by computing \(r(x)\) in multiple-precision (1024 bits).

6 Stability-Related Functions

As mentioned in Section 5, the BRI class uses the functions \(\Lambda_{n}\), \(\Gamma_{d}\), and \(\operatorname{\kappa}\) internally to decide, if needed, which method should be used for the computation of \(r(x)\). Moreover, it also allows the user to evaluate them explicitly by using the functions leb, gamma, and cond with the evaluation point or vector \(x\) as input. However, for purposes of numerical stability, what really matters is the maximum of these functions in the range \([x_{0},x_{n}]\) and this is what these functions return when they have no argument as input. Let us see how they compute it.
First, we recall that \(\Lambda_{n}\), \(\Gamma_{d}\), and \(\operatorname{\kappa}\) can all be written in the common form
\begin{align}g(x)=\sum_{i=0}^{n}{\bigg{\lvert}\frac{b_{i}(x)}{\sum_{i=0}^{n}b_{i}(x)}\bigg{\rvert}},\end{align}
(32)
where \(b_{i}(x)=w_{i}/(x-x_{i})\) for \(\Lambda_{n}\), \(b_{i}(x)=(-1)^{i}/\prod_{j=i}^{i+d}(x-x_{j})\) for \(\Gamma_{d}\), and \(b_{i}(x)=w_{i}y_{i}/(x-x_{i})\) for \(\operatorname{\kappa}\). One possible way to compute their maxima is to sample these functions very densely on the domain and search for the largest values, but, to be really accurate, we have to consider a big number of samples, thus losing efficiency. However, it is clear from the triangle inequality that a general function of the type (32) is greater than or equal to \(1\). Furthermore, in the specific case of \(\Lambda_{n}\), \(\Gamma_{d}\), and \(\operatorname{\kappa}\), the minimum with value 1 is assumed exactly at the nodes \(x_{i}\) and, from numerical experiments (see Figure 2), it appears that they are all concave in every sub-interval \([x_{i},x_{i+1}]\). This means that, considering these functions locally in every open sub-interval \((x_{i},x_{i+1})\), the point where the first derivative vanishes is a local maximum. Therefore, we apply Newton's method to find the root of \(\Lambda^{\prime}_{n}\), \(\Gamma^{\prime}_{d}\), and \(\operatorname{\kappa}^{\prime}\) in each sub-interval \((x_{i},x_{i+1})\) and we finally search for the maximum point among them. In general, in order to find a root \(t\in\mathbb{R}\) of a function \(g\colon\mathbb{R}\to\mathbb{R}\), Newton's method starts with some \(t_{0}\in\mathbb{R}\) and then generates a sequence of \(t_{1},t_{2},\dots\in\mathbb{R}\) by applying the iterative formula
\begin{align}t_{j+1}=t_{j}-\frac{g(t_{j})}{g^{\prime}(t_{j})}.\end{align}
(33)
Fig. 2.
Fig. 2. Plots of \(\Lambda_{n}\) (top), \(\Gamma_{d}\) (middle), and \(\operatorname{\kappa}\) (bottom) for \(n+1\) equidistant nodes and \(x\in[0,1]\), all on a logarithmic scale, for \(d=3\) and three choices of \(n\) (left, middle, right). For the computation of the condition number \(\operatorname{\kappa}\), the data are sampled from Runge's function \(f(x)=1/(1+25x^{2})\).
Although this method usually converges quadratically, it may also fail, for example, if the initial guess \(t_{0}\) is too far from the correct solution. Consequently, the choice of the initial value \(t_{0}\) is an important step of Newton's method. Figure 2 shows that \(\Lambda_{n}\), \(\Gamma_{d}\), and \(\operatorname{\kappa}\) take their local maxima approximately in the midpoint of every sub-interval \([x_{i},x_{i+1}]\), so that we consider \(t_{0}=(x_{i}+x_{i+1})/2\) in each sub-interval \((x_{i},x_{i+1})\). After that, by Equation (32), it is easy to see that the method can be implemented straightforwardly by computing at each iteration \(j\) first
\begin{align*}g^{\prime}(t_{j})=\sum_{i=0}^{n}\operatorname{sign}\biggl{(}{\frac{b_{i}(t_{j}) }{\sum_{i=0}^{n}b_{i}(t_{j})}\biggr{)}}\frac{b^{\prime}_{i}(t_{j})\sum_{i=0}^ {n}b_{i}(t_{j})-b_{i}(t_{j})\sum_{i=0}^{n}b^{\prime}_{i}(t_{j})}{(\sum_{i=0}^{ n}b_{i}(t_{j}))^{2}}\end{align*}
and
\begin{align*}g^{\prime\prime}(t_{j})=\sum_{i=0}^{n}\operatorname{sign}\biggl{(}{\frac{b_{i} (t_{j})}{\sum_{i=0}^{n}b_{i}(t_{j})}\biggr{)}}\frac{b^{\prime\prime}_{i}(t_{j}) \sum_{i=0}^{n}b_{i}(t_{j})-b_{i}(t_{j})\sum_{i=0}^{n}b^{\prime\prime}_{i}(t_{ j})}{(\sum_{i=0}^{n}b_{i}(t_{j}))^{2}}-2\frac{g^{\prime}(t_{j})}{\sum_{i=0}^{n }b_{i}(t_{j})}\sum_{i=0}^{n}b^{\prime}_{i}(t_{j}),\end{align*}
and then using Equation (33) to set \(t_{j+1}=t_{j}-g^{\prime}(t_{j})/g^{\prime\prime}(t_{j})\), until the error \({\lvert t_{j+1}-t_{j}\rvert} \lt 10\epsilon\), where \(\epsilon\) is the machine epsilon.

References

[1]
Nikhar Agrawal, Anton Bikineev, Matthew Borland, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos, Hubert Holin, Bruno Lalande, John Maddock, Evan Miller, Jeremy Murphy, Matthew Pulver, Johan Råde, Gautam Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg, Daryle Walker, and Xiaogang Zhang. 2022. BOOST 1.81.0 Library Documentation – Math Toolkit 3.3.0 – Interpolation – Barycentric Rational Interpolation. Retrieved February 23, 2023 from https://www.boost.org/doc/libs/1_81_0/libs/math/doc/html/math_toolkit/barycentric.html
[2]
Rose D. Baker and Ian G. McHale. 2015. Time varying ratings in association football: The all-time greatest team is. J. Royal Stat. Soc. Ser. A 178, 2 (Feb. 2015), 481–492. DOI:
[3]
Jean-Paul Berrut. 1988. Rational functions for guaranteed and experimentally well-conditioned global interpolation. Comput. Math. Appl. 15, 1 (1988), 1–16. DOI:
[4]
Jean-Paul Berrut. 2017. Linear barycentric rational interpolation with guaranteed degree of exactness. In Approximation Theory XV: San Antonio 2016. Gregory E. Fasshauer and Larry L. Schumaker (Eds.), Springer International Publishing, Cham, 1–20.
[5]
Jean-Paul Berrut. 2022. The conditioning of a linear barycentric rational interpolant. In Realization and Model Reduction of Dynamical Systems. Christopher Beattie, Peter Benner, Mark Embree, Serkan Gugercin, and Sanda Lefteriu (Eds.), Springer, Cham, 23–37. DOI:
[6]
Jean-Paul Berrut, S. A. Hosseini, and Georges Klein. 2014. The linear barycentric rational quadrature method for Volterra integral equations. SIAM J. Sci. Comput. 36, 1 (2014), A105–A123. DOI:
[7]
Jean-Paul Berrut and Hans D. Mittelmann. 1997. Matrices for the direct determination of the barycentric weights of rational interpolation. J. Comput. Appl. Math. 78, 2 (1997), 355–370. DOI:
[8]
Jean-Paul Berrut and Lloyd N. Trefethen. 2004. Barycentric Lagrange interpolation. SIAM Rev. 46, 3 (Sep. 2004), 501–517. DOI:
[9]
Sergey Bochkanov. 2022. ALGLIB 3.20.0 User Guide – Interpolation and fitting – Rational interpolation. Retrieved February 23, 2023 from http://www.alglib.net/interpolation/rational.php
[10]
Len Bos, Stefano De Marchi, and Kai Hormann. 2011. On the Lebesgue constant of Berrut's rational interpolant at equidistant nodes. J. Comput. Appl. Math. 236, 4 (Sep. 2011), 504–510. DOI:
[11]
Len Bos, Stefano De Marchi, Kai Hormann, and Georges Klein. 2012. On the Lebesgue constant of barycentric rational interpolation at equidistant nodes. Numer. Math. 121, 3 (Jul. 2012), 461–471. DOI:
[12]
Ada J. Ellingsrud, Nicolas Boullé, Patrick E. Farrell, and Marie E. Rognes. 2021. Accurate numerical simulation of electrodiffusion and water movement in brain tissue. Math. Med. Biol. J. IMA 38, 4 (Dec. 2021), 516–551. DOI:
[13]
Michael S. Floater and Kai Hormann. 2007. Barycentric rational interpolation with no poles and high rates of approximation. Numer. Math. 107, 2 (Aug. 2007), 315–331. DOI:
[14]
Laurent Fousse, Guillaume Hanrot, Vincent Lefèvre, Patrick Pélissier, and Paul Zimmermann. 2007. MPFR: A multiple-precision binary floating-point library with correct rounding. ACM Trans. Math. Software 33, 2 (Jun. 2007), Article 13, 15 pages. DOI:. The MPFR library can be found at https://www.mpfr.org
[15]
Chiara Fuda, Rosanna Campagna, and Kai Hormann. 2022. On the numerical stability of linear barycentric rational interpolation. Numer. Math. 152, 4 (Dec. 2022), 761–786. DOI:
[16]
Stefan Güttel and Georges Klein. 2012. Convergence of linear barycentric rational interpolation for analytic functions. SIAM J. Numer. Anal. 50, 5 (2012), 2560–2580. DOI:
[17]
Pavel Holoborodko. 2008. Multiple Precision Floating Point Arithmetic Library for C++. Retrieved June 17, 2024 from http://www.holoborodko.com/pavel/mpfr/
[18]
Kai Hormann, Georges Klein, and Stefano De Marchi. 2012. Barycentric rational interpolation at quasi-equidistant nodes. Dolomites Res. Notes Approx. 5 (2012), 1–6. DOI:
[19]
Kai Hormann and Scott Schaefer. 2016. Pyramid algorithms for barycentric rational interpolation. Comput. Aided Geometr. Des. 42 (Feb. 2016), 1–6. DOI:
[20]
IEEE Computer Society. 2019. IEEE Standard for Floating-Point Arithmetic. IEEE Computer Society, New York, NY. DOI:. IEEE Std 754-2019 (Revision of IEEE Std 754-2008)
[21]
Wang Jianying, Liang Haizhao, Qi Zheng, and Ye Dong. 2019. Mapped Chebyshev pseudospectral methods for optimal trajectory planning of differentially flat hypersonic vehicle systems. Aerospace Sci. Technol. 89 (Jun. 2019), 420–430. DOI:
[22]
Georges Klein and Jean-Paul Berrut. 2012. Linear barycentric rational quadrature. BIT Numer. Math. 52, 2 (Jun. 2012), 407–424. DOI:
[23]
Tai-Sung Lee, Brian K. Radak, Ming Huang, Kin-Yiu Wong, and Darrin M. York. 2014. Roadmaps through free energy landscapes calculated using the multidimensional vFEP approach. J. Chem. Theory Comput. 10, 1 (Jan. 2014), 24–34. DOI:
[24]
Tai-Sung Lee, Brian K. Radak, Anna Pabis, and Darrin M. York. 2013. A new maximum likelihood approach for free energy profile construction from molecular simulations. J. Chem. Theory Comput. 9, 1 (Jan. 2013), 153–164. DOI:
[25]
Joshua Leffell, Scott Murman, and Thomas Pulliam. 2013. An extension of the time-spectral method to overset solvers. In Proceedings of the 51st AIAA Aerospace Sciences Meeting including the New Horizons Forum and Aerospace Exposition. American Institute of Aeronautics and Astronautics, Reston, VA, 25 pages. DOI:
[26]
Jin Li and Yongling Cheng. 2021. Linear barycentric rational collocation method for solving heat conduction equation. Numer. Methods Partial Differ. Equ. 37, 1 (Jan. 2021), 533–545. DOI:
[27]
Wei-Hua Luo, Ting-Zhu Huang, Xian-Ming Gu, and Yi Liu. 2017. Barycentric rational collocation methods for a class of nonlinear parabolic partial differential equations. Appl. Math. Lett. 68 (Jun. 2017), 13–19. DOI:
[28]
Don MacMillen. 2021. BaryRational. Retrieved February 23, 2023 from https://github.com/macd/BaryRational.jl
[29]
Ricardo Pachón. 2010. Algorithms for Polynomial and Rational Approximation. Ph.D. Dissertation. University of Oxford.
[30]
Saul Teukolsky, Brian P. Flannery, William T. Vetterling, and William H. Press. 2007. Numerical Recipes in C: The Art of Scientific Computing (third ed.). Cambridge University Press, New York, Chapter 3.4.1, 127–129.
[31]
Lloyd N. Trefethen and David Bau. 1997. Numerical Linear Algebra. SIAM, Philadelphia.
[32]
Yuanying Zhuo, Bing Wu, Linquan Yao, Guangwen Xiao, and Quan Shen. 2022. Numerical simulation of the temperature in a train brake disc by barycentric rational interpolation collocation method. SSRN Electron. J. (2022), 22 pages. DOI:

Index Terms

  1. Algorithm 1048: A C++ Class for Robust Linear Barycentric Rational Interpolation

    Recommendations

    Comments

    Information & Contributors

    Information

    Published In

    cover image ACM Transactions on Mathematical Software
    ACM Transactions on Mathematical Software  Volume 50, Issue 3
    September 2024
    129 pages
    EISSN:1557-7295
    DOI:10.1145/3613616
    Issue’s Table of Contents
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike International 4.0 License.

    Publisher

    Association for Computing Machinery

    New York, NY, United States

    Publication History

    Published: 26 October 2024
    Online AM: 27 August 2024
    Accepted: 27 June 2024
    Revised: 18 June 2024
    Received: 29 March 2023
    Published in TOMS Volume 50, Issue 3

    Check for updates

    Badges

    Author Tags

    1. interpolation
    2. stability
    3. floating-point arithmetic
    4. C++ class template

    Qualifiers

    • Research-article

    Contributors

    Other Metrics

    Bibliometrics & Citations

    Bibliometrics

    Article Metrics

    • 0
      Total Citations
    • 218
      Total Downloads
    • Downloads (Last 12 months)218
    • Downloads (Last 6 weeks)140
    Reflects downloads up to 10 Nov 2024

    Other Metrics

    Citations

    View Options

    View options

    PDF

    View or Download as a PDF file.

    PDF

    eReader

    View online with eReader.

    eReader

    Get Access

    Login options

    Full Access

    Media

    Figures

    Other

    Tables

    Share

    Share

    Share this Publication link

    Share on social media