Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries
Numerical Libraries
XIN YI, National University of Defense Technology, China
LIQIAN CHEN, National University of Defense Technology, China
XIAOGUANG MAO∗ , National University of Defense Technology, China
TAO JI, National University of Defense Technology, China
Floating point computation is by nature inexact, and numerical libraries that intensively involve floating-point
computations may encounter high floating-point errors. Due to the wide use of numerical libraries, it is highly
desired to reduce high floating-point errors in them. Using higher precision will degrade performance and may
also introduce extra errors for certain precision-specific operations in numerical libraries. Using mathematical
rewriting that mostly focuses on rearranging floating-point expressions or taking Taylor expansions may not
fit for reducing high floating-point errors evoked by ill-conditioned problems that are in the nature of the
mathematical feature of many numerical programs in numerical libraries.
In this paper, we propose a novel approach for efficient automated repair of high floating-point errors in
numerical libraries. Our main idea is to make use of the mathematical feature of a numerical program for
detecting and reducing high floating-point errors. The key components include a detecting method based on
two algorithms for detecting high floating-point errors and a repair method for deriving an approximation of
a mathematical function to generate patch to satisfy a given repair criterion. We implement our approach
by constructing a new tool called AutoRNP. Our experiments are conducted on 20 numerical programs in
GNU Scientific Library (GSL). Experimental results show that our approach can efficiently repair (with 100%
accuracy over all randomly sampled points) high floating-point errors for 19 of the 20 numerical programs.
Additional Key Words and Phrases: Floating-point errors, automated repair, numerical program
∗ Corresponding author
Authors’ addresses: Xin Yi, Laboratory of Software Engineering for Complex Systems, College of Computer, National
University of Defense Technology, China, [email protected]; Liqian Chen, Laboratory of Software Engineering for
Complex Systems, College of Computer, National University of Defense Technology, China, [email protected]; Xiaoguang
Mao, Laboratory of Software Engineering for Complex Systems, College of Computer, National University of Defense
Technology, China, [email protected]; Tao Ji, Laboratory of Software Engineering for Complex Systems, College of
Computer, National University of Defense Technology, China, [email protected].
Permission to make digital or hard copies of part or all of this work for personal or classroom use is granted without fee
provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and
the full citation on the first page. Copyrights for third-party components of this work must be honored. For all other uses,
contact
This worktheisowner/author(s).
licensed under a Creative Commons Attribution 4.0 International License.
© 2019 Copyright held by the owner/author(s).
2475-1421/2019/1-ART56
https://doi.org/10.1145/3290369
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56
56:2 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
1 INTRODUCTION
Using floating-point representation instead of real arithmetic in numerical programs aims to make
the calculation fast. However, the floating-point arithmetic accompanied with roundoff and trunca-
tion errors cannot guarantee that the results of numerical programs always have sufficient accuracy.
Numerical programs in numerical libraries that intensively involve floating-point computations
may encounter high floating-point errors. Hence, it is highly desired to reduce high floating-point
errors in widely used numerical libraries.
One method to reduce high floating-point errors is to use higher precision to perform floating-
point calculation of the original program. For example, one may replace a 32-bit single precision
with a 64-bit double precision to improve the accuracy of results. However, higher precision
execution will slow down the execution, sometimes even a thousand times slower [Benz et al. 2012].
In addition, higher precision execution may introduce extra errors and thus may not be able to
improve the accuracy of numerical programs in numerical libraries which may involve certain
precision-specific operations [Wang et al. 2016].
Mathematical rewriting is another choice, which reduces floating-point errors by rearranging
floating-point expressions or taking Taylor expansions. Using this method does not need higher
precision but requires users know the finer details of floating-point arithmetic. Along this direction,
tools like Herbie [Panchekha et al. 2015] and Salsa [Damouche and Martel 2018] were developed to
utilize mathematical rewriting to generate more accurate floating-point expressions automatically.
However, the mathematical rewriting may also fail to find a more accurate expression within
a limited search space constrained by the number of laws of mathematical transformation. In
particular, the mathematical rewriting may not fit for reducing a high floating-point error evoked
by an ill-conditioned problem (indicated by a large condition number, see ğ2) that is in the nature
of the mathematical feature of many numerical programs in numerical libraries.
This paper aims to provide an efficient approach for automated repair of high floating-point errors
in numerical libraries. To this end, several challenges need to be addressed. The first challenge
is to detect high floating-point errors efficiently in numerical programs. The set of 64-bit floating
point inputs of a numerical program is a huge search space, which makes the exhaustive search not
practical. Moreover, numerical programs in numerical libraries are supposed to be already designed
delicately for accuracy and inputs that can trigger the remaining high floating-point errors should
localize in some small parts of the whole input domain, which makes the detecting more challenging.
An efficient detecting method is desired to search for inputs that can trigger high floating-point
errors in the huge search space. The second challenge which is also a key challenge is to reduce
high floating-point errors to satisfy a given repair criterion. As mentioned before, using higher
precision not only degrades performance, but also may introduce extra errors, while mathematical
rewriting is constrained by limited search space and cannot handle the ill-conditioned problem. In
particular, high floating-point errors evoked by ill-conditioned problem are hard to be repaired
even for experienced developers of numerical libraries1 . The third challenge is to reduce time
overhead of repaired programs compared with the original programs. Performance is important for
numerical libraries, and thus repaired programs should not introduce too much time overhead.
This paper addresses these challenges mainly by exploiting the mathematical feature of numerical
programs. We suppose that a numerical program in numerical libraries is used to simulate a
mathematical function. First, we make use of the condition number of the mathematical function
and combine it with search algorithms to help detect high floating-point errors in the numerical
1 Forexample, Di Franco et al. [2017] find a phenomenon that a bug (#6368: https://github.com/scipy/scipy/pull/6368) in
Scipy was first repaired by mathematical rewriting, and developers recognized later that the bug is due to an ill-conditioned
problem and it may still remain even after repair.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:3
program (the first challenge). Then we directly extract an approximation based on the inputs
and outputs of the mathematical function to generate a patch for repairing the numerical program
to satisfy a given repair criterion (the second challenge). During the above process, we use a
simple but efficient method to approximate the mathematical function and a search optimization
to improve the performance of the generated patch, both of which are useful for reducing time
overhead of repaired programs (the third challenge). The contributions of this paper are as
follows:
• We present a detecting method that includes two novel algorithms (namely DEMC and PTB)
for detecting high floating-point errors in numerical programs. More specifically, based on
the guide of condition number, we use two global optimization algorithms (the Differential
Evolution algorithm and the Monte Carlo Markov Chain (MCMC) algorithm) to help us find the
input that can trigger the possible maximum floating-point error. As far as we know, there is
no existing work combining condition number and MCMC for finding the input triggering
maximum errors. Moreover, our detecting method not only finds the input that can trigger
the maximum floating-point error (like existing detecting methods [Chiang et al. 2014] [Zou
et al. 2015] [Yi et al. 2017b]), but also searches for inputs that can trigger floating-point errors
higher than a given repair criterion. (See ğ4.1.)
• We present a repair method to produce patch automatically to reduce floating-point errors in
a numerical program to satisfy a given repair criterion. We prove the guarantee of termina-
tion of our repair method for an arbitrary given repair criterion. Unlike existing methods
that search for repairs by making changes of the implementation of the original numerical
program, our method uses a piecewise quadratic function to approximate the corresponding
mathematical function of the numerical program to generate patches. Therefore, the approxi-
mation is independent of the implementation of the numerical program and can be applied
to a numerical program in other numerical libraries that simulates the same mathematical
function. Moreover, our method uses a search optimization to improve the performance of a
generated patch to reduce time overhead of repaired programs. (See ğ4.2 and ğ4.3.)
• We develop a prototype tool called AutoRNP and evaluate our approach by conducting
experiments on 20 numerical programs of GSL. Experimental results show that our approach
can efficiently repair high floating-point errors in 19 of 20 numerical programs of GSL (with
100% accuracy, i.e., after repair, 100% of our randomly sampled inputs yielding outputs that
satisfy the given repair criterion). (See ğ5.)
The rest of the paper is organized as follows. We first introduce the basics of floating-point
representation, the definition of high floating-point error and the ill-conditioned problem in ğ2. We
then give an overview of our approach through an example in ğ3 and detail our approach in ğ4. We
provide the details of implementation together with experimental results in ğ5. The limitations of
our work are discussed in ğ6. In ğ7 we summarize related work. We end the paper with conclusions
and future work (ğ8).
2 PRELIMINARIES
Floating-point representation According to the IEEE-754 Standard [Kahan 1996], a floating-
point number can be represented in scientific notation:
f = (−1) S × M × 2 E (1)
where S ∈ {0, 1} is the 1-bit sign of x, which represents that x is positive (when S = 0) or negative
(when S = 1); M = m 0 .m 1m 2 . . . m p is called the significand, where f = .m 1m 2 . . . m p represents a
p-bit fraction and m 0 is the hidden bit without need of storage; E = e − bias is called the exponent,
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:4 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
where e is a biased e-bit unsigned integer and bias = 2e−1 − 1. Taking the 64-bit double-precision
format as an example, e = 11 (and thus bias = 1023), p = 52.
High floating-point error We give the definition of a high floating-point error as below:
Definition 1. Let f (x) represent a mathematical function, fp (x) represent the correspond-
ing numerical program implementing f (x ). Given an error threshold ε, for an input x 0 , if
ErrorFunction(f (x0 ), fp (x0 )) > ε, we say the input x 0 triggers a high floating-point error.
The ErrorFunction in Definition 1 is a function for measuring the floating-point error between the
outputs of mathematical function and numerical program. In this paper, we define the floating-point
error as the number of floating-point values between the mathematical function output Or and
numerical program output Of , following [Panchekha et al. 2015]. This error can be represented by
Eq. 2 and characterized by Eq. 3.
FPNum{Or , Of } = |{ai ∈ F|min(Or , Of ) ≤ ai ≤ max (Or , Of )}| (2)
ErrBits{Or , Of } = log2 (FPNum{Or , Of }) (3)
FPNum{Or , Of } in Eq. 2 represents the number of floating-
fp
point values between the mathematical function output Or
f
and numerical program output Of including themselves. fp(x)
∆x
ErrBits{Or , Of } in Eq. 3 counts the number of most-significant f (x + ∆x)
bits that the approximate and the exact results agree on2 .
Compared with relative error and absolute error in real,
FPNum{Or , Of } and ErrBits{Or , Of } can keep consistent over x
the input space and avoid special handling for infinite and
denormalized values. Fig. 1. Backward error
Ill-conditioned problem For a mathematical function f (x ),
its condition number function can be expressed as follows:
f ′ (x) · x
C(x) = (4)
f (x)
where f ′ (x ) denotes the derivative of the mathematical function f (x ).
Condition number is an important quantity for measuring how sensitive a function is to errors
in the input. It has been mainly used to investigate instability of numerical programs [Bao and
Zhang 2013] [Tang et al. 2017]. To illustrate the influence of condition number to floating-point
error, we first introduce the notion of backward error. If we map the value given by a numerical
program fp (x ) to its corresponding mathematical function f (x), as shown in Fig. 1, we can get
fp (x) ≃ f (x + △x) (5)
We call △x the backward error B, and let δ = △x/x. We follow the assumption of [Fu et al. 2015]
that the mathematical function f is smooth in a neighborhood of x and the backward error is small.
Then by the Taylor expansion, we have
f (x) − fp (x) f (x) − f (x + δ · x) f ′ (x) · x
Forward_error = = ≈ |δ | · + Θ(δ 2 ) (6)
f (x) f (x) f (x)
2 Forexample, FPNum{1.0, 2.0 } = 4503599627370497 means there are 4503599627370497 number of floating-point values
between 1.0 and 2.0 including themselves, and Er r Bit s {1.0, 2.0} = loд2(FPNum{1.0, 2.0}) = 52 means that the number
2.0 has 52 bits error compared to 1.0. The value range of error threshold ε can be limited to [1, 264 ) by Eq. 2 and [0, 64) by
Eq. 3.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:5
Eq. 6 shows that the forward error is mainly influenced by the backward error B = |δ | and the
f ′ (x) · x
condition number , i.e.,
f (x)
Forward_error ≈ B · C(x) (7)
The ill-conditioned problem happens when the value of C (x ) is large. As shown in Eq. 7, if the
value of C (x ) is large enough, even a small backward error B would lead to a large forward error.
Note that the value of C (x ) is inherent in the mathematical function f (x) (according to Eq. 4) while
independent of the implementation of numerical program fp (x). Theoretically, it is very difficult to
repair the high floating-point error evoked by the ill-conditioned problem.
Notations For mathematical function f (x ) and its corresponding numerical program fp (x), we
use X ⊆ F to denote their input domain. We use the rounding function f l : R → F to convert a
real number to a floating-point number. In this paper, we consider a floating-point input interval I
which represents a set of floating-point numbers, i.e., I = [x 0 , x n ] = {x 0 , x 1 , x 2 , ..., x n }. We use
the default rounding mode łrounding to nearest even" of IEEE 754 standard in this paper. We use
{+, −, ×, /} to denote real-valued operations and {⊕, ⊖, ⊗, ⊘} to denote floating-point operations.
We assume that each floating-point operation is left-associative. We use the same definition of ulp
function (in double-precision) as [Lee et al. 2017] who follows the Goldberg’s definition [Goldberg
1991]:
2k −52 if |r | ∈ [2k , 2k +1 ) where k ∈ [−1022, 1023] ∩ Z
For r ∈ R, ulp(r) =
2−1074 if |r | ∈ [0, 2−1022 ) (8)
where ulp (unit in the last place) is the gap between the two floating-point numbers nearest to
r, even if r is one of them. Formally, if a and b are two adjacent floating-point numbers around r
satisfying (r ≥ 0.0 ∧ a ≤ r < b) ∨ (r < 0.0 ∧ a < r ≤ b), then we have ulp(r) = |a − b|.
3 OVERVIEW
i n t gsl_sf_legendre_P3_e ( double x , g s l _ s f _ r e s u l t ∗ r e s u l t )
{
r e s u l t −> v a l = 0.5*x*(5.0*x*x - 3.0);
r e s u l t −> e r r = GSL_DBL_EPSILON ∗ ( f a b s ( r e s u l t −> v a l ) + 0 . 5 ∗ f a b s ( x ) ∗ (
fabs ( 5 . 0 ∗ x∗x ) + 3.0) ) ;
r e t u r n GSL_SUCCESS ;
}
In this section, we give an overview of our approach by illustrating how our approach repairs the
high floating-point errors in a motivating example. The example is the program gsl_sf _legendre_P3
in GSL. The source code of the gsl_sf _legendre_P3 is shown in Fig. 2. The example implements
the Legendre functions Pn (x) with n = 3. The code in Fig. 2 shows that the result of the program
is calculated by the polynomial ł0.5 ∗ x ∗ (5.0 ∗ x ∗ x − 3.0)ž. The ill-conditioned problem exists
around the roots of the polynomial. If letting x = x0 = 0.7745966692414834, the polynomial returns
output zero, while the mathematical output of legendre_P3 at x0 in real-number arithmetic should be
8.1726185204e-17. In this case, the result of FPNum(0, 8.1726185204e-17 ) is around 4.36611485515e+18
which implies around 61.9 bits error. More specifically, the expression 5.0 ⊗ x ⊗ x has a roundoff
error 2e-16 for the input x0 , and the roundoff error is small for the value of 5.0 ⊗ x ⊗ x (which is
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:6 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
rounded to 3.0), but huge for 5.0 ⊗ x ⊗ x ⊖ 3.0 (which is rounded to 0.0). Thus, the bad cancellation
comes from the minus operation in the expression 5.0 ⊗ x ⊗ x ⊖ 3.0 which makes the roundoff
error in 5.0 ⊗ x ⊗ x become a large relative error. The condition number at the input x0 is around
7.341588237629298e+16, so even the small rounding error introduced in 5.0 ⊗ x ⊗ x will be enlarged
and propagated to the output due to the large condition number (according to Eq. 7).
The work-flow of our approach is shown in Fig. 3. We now introduce the repair process step by
step.
Fig. 3. Work-flow of our approach. fp : numerical program, f : the corresponding mathematical function of fp ,
Iinit : input domain of fp , MeanErr : the mean error of numerical program fp in Iinit , MaxErr: the maximum
error of numerical program fp in Iinit , τ : parameter given by users to adjust the error threshold in interval
[MeanErr, MaxErr] (in Eq. 18)
Detecting high floating-point errors. In this step, we try to find an input interval which
includes inputs that can trigger floating-point errors higher than an error threshold ε. As shown
in Fig. 3, first, we use the DEMC algorithm (ğ4.1) to search for an input xm that can trigger a
possible maximum floating-point error MaxErr. Then, we apply the PTB algorithm (ğ4.1) to find an
input interval Ierr which includes inputs that can trigger floating-point errors larger than the error
threshold ε. Finally, the input interval Ierr and error threshold ε will be passed to next step.
For the motivating example, we get the input x0 = 0.7745966692414834 that can trigger a possible
maximum floating-point error. Then, under the given threshold ε = 6.8, we get the input interval
Ierr = [0.7719792508475998, 0.7771878196880129], as shown in Fig. 4(a).
Deriving an approximation of the mathematical function. After getting the input interval
Ierr , we will derive an approximation of the mathematical function f over Ierr to satisfy the error
threshold ε. We use a piecewise quadratic function (ğ4.2) to approximate the mathematical function
over Ierr . As shown in Fig. 3, we first use a linear function to approximate the mathematical
function f , then use a quadratic function to compensate the error between the linear function and
mathematical function f (ğ4.2) to make the approximation closer to the mathematical function
f . Unfortunately, the approximation using only one linear function with error compensation of
quadratic function may be not accurate enough to satisfy the error threshold, so we adopt an
iterative refinement algorithm (ğ4.2) to iteratively use more pieces of linear approximation with
error compensation to generate a piecewise quadratic function to approximate a mathematical
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:7
60 60
50 50
Ierr Ierr
40 [0.7719792508475998, 0.7771878196880129]
40 [0.7719792508475998, 0.7771878196880129]
ErrBits
ErrBits
30 30
x0 = 0.7745966692414834 x0 = 0.7745966692414834
20 20
10 ε =6.8 10 ε =6.8
0 0
0.772 0.773 0.774 0.775 0.776 0.777 0.772 0.773 0.774 0.775 0.776 0.777
Input Input
function over Ierr . In the end of the process, we can get Σ(l, c) which represents the piecewise
quadratic function.
For the motivating example, under the error threshold ε = 6.8, a piecewise quadratic function
with around 1000 pieces is produced after iterative refinement to approximate the mathematical
function within the input interval Ierr (including more than 4691 billion double-precision floating-
point inputs) to satisfy the error threshold ε.
i n t gsl_sf_legendre_P3_e ( double x , g s l _ s f _ r e s u l t ∗ r e s u l t )
{
i f ( ( x < = 0 . 7 7 7 1 8 7 8 1 9 6 8 8 0 1 2 9 ) &&(x > = 0 . 7 7 1 9 7 9 2 5 0 8 4 7 5 9 9 8 ) ) {
r e s u l t −> v a l = a c c u r a c y _ i m p r o v e _ p a t c h _ o f _ g s l _ s f _ l e g e n d r e _ P 3 ( x ) ;
r e s u l t −> e r r = GSL_DBL_EPSILON ∗ f a b s ( r e s u l t −> v a l ) ;
r e t u r n GSL_SUCCESS ;
}
r e s u l t −> v a l = 0.5*x*(5.0*x*x - 3.0);
r e s u l t −> e r r = GSL_DBL_EPSILON ∗ ( f a b s ( r e s u l t −> v a l ) + 0 . 5 ∗ f a b s ( x ) ∗ (
fabs ( 5 . 0 ∗ x∗x ) + 3.0) ) ;
r e t u r n GSL_SUCCESS ;
}
Producing patch. Finally, we convert the piecewise quadratic function Σ(l, c) to patch. The
piecewise quadratic function is implemented in the following manner: For an input x in the input
interval Ierr , we first find which piece of the piecewise quadratic function x belongs to, then we call
the function representing the piece to compute the output for the input x. To reduce time overhead
of searching for the right piece for an input, we apply a search optimization (ğ4.3) to accelerate the
process of searching the piece of the piecewise quadratic function x belongs to. After optimization,
we convert Σ(l, c) with search optimization to a function in C code. We would like to induce as
little as possible the influence of patch on the readability of original code, so we package the details
of the piecewise quadratic function in a separate function. As a result, a patch includes two parts:
1) A function in C code which is stored in a separate file to implement the piecewise quadratic
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:8 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
function; 2) A branch code fragment that is inserted into the source code of numerical program to
decide whether to call the added function.
For the motivating example, the program after repair is shown in Fig. 5. From Fig. 5, we see that
the patch of gsl_sf _legendre_P3 is packaged in the function accuracy_improve_patch_of _gsl_sf _
legendre_P3. The ErrBits distribution of the program after repair is shown in Fig. 4(b).
In summary, under a given error threshold, our approach localizes inputs that can trigger
high floating-point errors, encloses them as a certain input interval, derives an approximation of
mathematical function that satisfies the error threshold, and converts the approximation to a patch
which is then inserted into source code to complete the repair.
Existing methods on the example To the best of our knowledge, no efficient way by mathemat-
ical rewriting can improve the accuracy of the polynomial ł0.5 ∗ x ∗ (5.0 ∗ x ∗ x − 3.0)ž around
x0 . Factoring is a possible solution of mathematical rewriting to reduce errors around a root of a
polynomial. When evaluating a polynomial ploy(x) = (x ⊖ r) ⊗ Q(x) near root r , the execution of
x ⊖ r in floating-point arithmetic is exact (according to Sterbenz’s theorem [Sterbenz 1973], see
ğ4.3). However, the factoring requires that the root r can be expressed exactly in floating-point
number, otherwise, the small roundoff error of r will also lead to a large relative error (according
to Eq. 7). In the example, the root of ł0.5 ∗ x ∗ (5.0 ∗ x ∗ x − 3.0)ž cannot be exactly expressed by
a floating-point number, so the idea of factoring does not work for the example. Note that, the
ill-conditioned nature of the problem also suggests that mathematical rewriting techniques (such
as Herbie) will fail to reduce errors in the example3 .
Using higher precision can reduce errors around x0 but will degrade the performance of the basic
function gsl_sf _legendre_P3 which is also called by other functions in GSL. For example, if we use
128-bit precision to calculate the polynomial ł0.5 ∗ x ∗ (5.0 ∗ x ∗ x − 3.0)ž, the execution time is
around 3.5 times slower than the original execution under 64-bit precision.
4 APPROACH
In this section, we details our approach in three parts which correspond to the work-flow in Fig. 3.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:9
Fig. 6. Logic flow for detecting high floating-point errors. fp : numerical program, f : corresponding math-
Si (k)
ematical function of fp , Iinit : input domain of fp , MaxErr: the maximum error in Iinit − Ierr , ε: error
k =0
threshold
(0)
then we search for an input interval Ierr around xm that encloses inputs that can trigger floating-
point errors higher than ε. The detecting method will terminate if the current MaxErr (i) found is
(i)
less than ε, otherwise the method will iteratively find all Ierr . Now, we introduce two algorithms to
(i) (i)
help us find MaxErr and Ierr .
Detecting the possible maximum floating-point error (MaxErr) We propose an algorithm
called DEMC, based on two search algorithms namely Differential Evolution algorithm [Storn and
Price 1997] and Monte Carlo Markov Chain (MCMC) algorithm [Andrieu et al. 2003], to search for an
input that can trigger the possible maximum floating-point error. Differential evolution algorithm is
a simple and efficient global optimization algorithm over continuous space. The algorithm operates
on real numbers and naturally fits for numerical optimization. We use the algorithm to help us find
the input triggering the possible maximum condition number over the whole input domain of a
numerical program. The MCMC algorithm is a sampling method that draws samples from the target
(usually unknown) distribution. MCMC has been used to search the maximum backward error [Fu
et al. 2015] and to achieve high coverage for floating-point code [Fu and Su 2017], and has also been
applied in STOKE [Schkufza et al. 2014] for stochastic search of floating-point optimization. We
configure the MCMC sampling such that it tends to attain the inputs that may trigger maximum
floating-point errors with higher probability than the other points. We use the MCMC algorithm
to avoid local maxima and to find the input triggering maximum floating-point error in a relative
smaller search space.
First, we formalize the problem of detecting the maximum floating-point error as follows:
Definition 2. Let f (x) represent a mathematical function, fp (x) represent the corresponding
numerical program, D ∈ F denote the valid input domain. The detecting problem is to search
for an input xm ∈ D , such that ∀xi ∈ D, ErrBits(f (xm ), fp (xm )) ≥ ErrBits(f (xi ), fp (xi )).
Then, we use two fitness functions to guide our DEMC method to find such an input xm .
Fit1: ErrBits. In this paper, we use ErrBits (defined in Eq. 3) to evaluate the error associated to an
output of a numerical program. Hence ErrBits becomes a fitness function of our approach.
Fit2: Appro(C(x)). We use the approximate value of condition number C (x ) (Eq. 4) of the mathe-
matical function f (x) as our second fitness function, that is
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:10 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
We use the Fit2 function to guide the search algorithm to find the possible inputs that may trigger
the ill-conditioned problem (if there exists) in a numerical program. The approximation (C (x ) to
Appro(C(x))) makes us free from the exact calculation of the mathematical function f (x) which
needs high precision and may lead to high time overhead.
The DEMC algorithm is shown in Algorithm 1. The inputs of the DEMC algorithm include the
numerical program fp together with its corresponding mathematical function f , the input domain
Iinit of fp , and two fitness functions (Fit1 and Fit2). In brief, we first partition the search space (the
whole input domain) into many smaller parts, then apply the differential evolution algorithm using
Fit2 (which can be calculated fast) as guide to search in each part, and finally call MCMC using Fit1
as guide to refine the search results. As shown in Algorithm 1, the input domain is first partitioned
into many smaller parts (subintervals) by the Partition function which is designed according to the
distribution of floating-point numbers. After that, we first call the differential evolution algorithm
to search for the input that can trigger large condition number in each small input subinterval Ii .
Next, we perform the MCMC algorithm to find the possible maximum floating-point error max_errt
around each input xi that is found previously by the differential evolution algorithm. In other words,
we employ the MCMC algorithm to search higher errors in the neighborhood of xi . Finally, the
DEMC algorithm returns the maximum floating-point MaxErr and the corresponding input xm .
Generating the target input interval (Ierr ). To generate the input interval Ierr enclosing the
neighbors of xm with respect to the given error threshold ε, we propose a so-called Point-to-Bound
(PTB) algorithm.
Intuitively, around the input xm producing the maximum floating-point error, there may exist
some other inputs causing high floating-point errors. According to the formula Forward_error ≈
B · C (x ) (Eq. 7), a high floating-point error evoked by an ill-conditioned problem may decline with
the decreasing of the value of condition number C (x ). Moreover, if the mathematical function is
close to a linear function, the derivate |f ′ (x)| of the mathematical function is almost a stable value
in a small interval around xm , and thus the value of |f ′ (x) · x | is also almost a stable value in a
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:11
small interval around xm , which means that the value of |f (x)| becomes the main influential factor
of condition number C(x) = f ′ (x) · x/f (x) (Eq. 4).
Based on above analysis, we know that floating-point errors triggered by inputs around xm
will decrease with the increasing of the value of |f (x)|. Meanwhile, the formula (Eq. 2) we use to
evaluate the floating-point error is also implicitly related with the ulp value of |f (x)|. Thus we have
the intuition that the floating-point errors triggered by inputs around xm may be a stepwise decline
trend with the value of ulp(f (x)). For example, as shown in Fig. 4(a), x0 is the input triggering
maximum error and also the input (closest to the root of the function) making ulp(f (x)) smallest,
and the values of errors have a stepwise decline trend around x 0 .
We design the PTB algorithm mainly based on the possible stepwise decline trend of floating-
point errors triggered by inputs around xm . The PTB algorithm is shown in Algorithm 2. The
inputs of the PTB algorithm include the numerical program fp together with its corresponding
mathematical function f , the input xm as the starting point, the error threshold ε, and an initial
step for search bound. The output of the algorithm is the target Ierr .
To generate an Ierr as small as possible which includes all inputs around xm that can trig-
ger floating-point error higher than the given error threshold ε, we first search a tight upper
bound (Up_bound) of Ierr which is larger than xm (Line 1). The temporary value of Up_bound is
saved in variable temp_bound (Line 6) and variable step (Line 7) is used to refresh the value of
temp_bound. We use variable temp_max_error to record the local maximum floating-point errors
around temp_bound. Note that Max_error_find (Line 10) finds the maximal floating-point error in
a small interval (decided by the value of step) around temp_bound. The value of times is large than
2.0 and the value of temp_max_error ⊘ ε is used to adjust (Line 12) the value of step. temp_bound
will keep changing by step ⊗ sign until temp_max_error ≤ ε (Lines 8 - 9). The value of step may
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:12 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
increase too large, which leads temp_bound to be far away from the possible smallest Up_bound,
so we call the IterationBack function to refine the last_step to find a tighter Up_bound. Then,
we perform a similar process to find the possible largest lower bound Lower_bound of Ierr . After
finding the lower bound and upper bound of Ierr (Lines 1 - 2), the algorithm will return the target
input interval: Ierr = [Lower_bound, Up_bound].
Definition 3. Given an error threshold ε and an input interval Ierr , for a mathematical
function f : R → R, if there exists a function f : F → F, such that for any floating-point input
xi ∈ Ierr , ErrBits(f (xi ), f (xi )) ≤ ε holds, then f is said to be an approximation of f in the
given Ierr that satisfies the given error threshold ε.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:13
Theorem 4.2 shows that for a mathematical function (over floating-point inputs), there always
exists a piecewise linear function that can satisfy a given error threshold ε, e.g., Σ l (x) in the
worst case. Note that Σ l (x) is equivalent to Df (in Theorem 4.1). Based on Theorem 4.2, we can
continuously reduce the error at the point that does not satisfy the error threshold ε yet by creating
a new line segment. After a limited iteration number, we can find a piecewise linear function Σl (x)
to satisfy ErrBits(Σl (xi ), f (xi )) ≤ ε, and in the worst case we can have Σl (xi ) = Σ l (xi ) . For example,
for the intermediate point (xk , Ok ) in Fig. 7, a possible error ε k exists between Ok l and Ok . If ε k is
smaller than a given error threshold ε, we say that we have already found a linear approximation
for f (x) at the three points, otherwise, a piecewise linear function Σl (x) consisting of two new line
segments (l1 and l2 ) will replace l(x), to make ErrBits(Σl (xk ), f (xk )) = 0 ≤ ε.
Error compensation Using purely linear approximation may result in too many pieces of linear
functions to express an accurate enough approximation of a mathematical function even in a small
input interval Ier r . Therefore, we add an error compensation on each piece of the piecewise linear
function to reduce the error between the linear approximation and the mathematical function.
To conduct the error compensation on each linear function l (x ), we first introduce a function
AbsErr (x) : F → F to express the absolute error between a linear function and the original
mathematical function:
For any x ∈ Ierr , AbsErr (x) = fl(f (x)) ⊖ l(x) (12)
The calculation of the function AbsErr (x) needs to calculate the mathematical function f (x) (which
cannot be implemented exactly in our patch using finite precision), so we use a error compensation
function to approximate AbsErr (x). According to Eq. 11, for the two end points of a line segment,
we have AbsErr (xs ) = AbsErr (xe ) = 0. Consider the possible nonlinear feature of the mathematical
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:14 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
function in Ierr and the fact that we already know two roots (xs , xe ) of a quadratic function, we use
the following quadratic function to approximate AbsErr (x):
For any x ∈ Ierr , AbsErr (x) ≈ λ ⊗ (x ⊖ xs ) ⊗ (x ⊖ xe ) (13)
We choose the middle point xm of xs and xe to calculate the value of λ. Then we have λ =
AbsErr (xm ) ⊘ ((xm ⊖ xs ) ⊗ (xm ⊖ xe )) wherein AbsErr (xm ) can be computed though fl(f (xm )) ⊖
l (xm ) following Eq. 12.
Finally, we define the error compensation function as c(x) = λ ⊗ (x ⊖ xs ) ⊗ (x ⊖ xe ) and add it
back to the linear function. Then we can have the following possible more accurate approximation
of a mathematical function:
For any x ∈ Ierr , lc (x ) = l (x ) ⊕ c (x ) (14)
The error compensation helps us to get a more accurate approximation of a mathematical
function. For example, as shown in Fig. 8(a), for the mathematical function bessel_J1, we compare
AbsErr (x) with lc(x) ⊖ l(x) to show the effectiveness of error compensation, where we use the
l(x) ⊖ l(x) as the baseline. From Fig. 8(a), we can see that for this example one line segment with
one time of error compensation (red line) fits well the original mathematical function (bold yellow
line).
×10−13 ×10−20
0.0 6
AbsErr(x)
lc(x) ⊖ l(x)
−0.5 4 l(x) ⊖ l(x)
−1.0
2
Output
Output
−1.5
0
−2.0
−2
−2.5
AbsErr(x) −4
lc(x) ⊖ l(x)
−3.0
l(x) ⊖ l(x)
−6
0.000004 0.000005 0.000006 0.000007 0.000008 −9.00 −8.75 −8.50 −8.25 −8.00 −7.75 −7.50 −7.25
Input +3.8317 Input ×10−7 − 4.34016609×102
However, not all functions can be well approximated to satisfy a given error threshold ε by a
line segment with one time of error compensation. E.g., as shown in Fig. 8(b), even though we
have two line segments with error compensations, it may still be not accurate enough for a small
error threshold ε and thus more line segments with error compensations may be needed to satisfy
the ε. Thus, we propose an iterative refinement algorithm to call the previous two steps (linear
approximation and error compensation) iteratively to satisfy a given error threshold ε.
Iterative refinement The iterative refinement algorithm iteratively applies linear approximation
and error compensation to generate a piecewise quadratic function f that can satisfy the given
error threshold ε.
As shown in Algorithm 3, the inputs of the iterative refinement algorithm include the mathe-
matical function f , the given error threshold ε and input interval Ierr : [Lower_bound, Up_bound]
that is the output of Algorithm 2. In Algorithm 3, we maintain a global list Line_list to store all
pieces of linear functions with error compensations and return it as the output of the algorithm.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:15
Algorithm 3 first calls the function LinearApproximate (Line 6) to generate a linear function l.
After getting l, the algorithm calls the function ErrorCompensation (Line 7) to generate the error
compensation c for l. After getting l and c, the algorithm generates the approximation function
f (Line 8) for f within Ierr . Then, the maximum error MaxErrf between f and f is found by the
function MaxErrorSearch (Line 9). The recursive function IterLineApprox will exit if the value of
MaxErrf is smaller than the given threshold ε and at the same time the linear approximation with
error compensation (i.e., (l, c)) will be stored in the global list Line_list (Line 11). Otherwise, two
new input intervals [Lower_bound, xnext ] and [xnext , Up_bound] will be passed to the recursive
function to do another new iteration on the new input intervals, where xnext is the found input that
triggers the possible maximum error MaxErrl in l.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:16 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
Effectiveness analysis. The effectiveness of the algorithm is mainly influenced by the mathe-
matical feature of the mathematical function f . For example, as shown in Fig. 8(a), the bessel_J1 is
not a quadratic function, but it has a quadratic polynomial feature in a small input interval and
thus can be well approximated by the lc(x) function (in Eq. 14), while the function airy_Ai (in Fig.
8(b)) may need more iterations to satisfy the same given error threshold ε.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:17
5 https://docs.scipy.org/doc/scipy-1.0.0/reference/optimize.html
6 https://docs.scipy.org/doc/numpy/reference/generated/numpy.polyfit.html
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:18 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:19
To evaluate the repair results, we define the accuracy of repair using the following formula:
PassNum
AccRepair = ∗ 100% (19)
TestNum
where PassNum = |{x |ErrBits(f (x), fp (x)) ≤ ε, x ∈ Ierr }|, TestNum = Min(|{x |x ∈ Ierr }|, 100000). As
shown in Eq. 19, we evaluate the accuracy of repair by checking how many inputs whose floating
point errors of the outputs of fp (x) are less than the given error threshold ε in TestNum times
random sampling tests.
Moreover, we also investigate the change of the maximum floating-point error and the average
floating-point error over the input interval Ierr after repairing.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:20 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
and found that AutoRNP can complete the repair of P20 to satisfy the low error threshold Lε within
8 hours. Moreover, we find that GSL uses different formulas to implement the gsl_sf _psi_1 function.
As shown in Fig. 11, when the input x satisfying x ≤ −5, the GSL program implements a formula
(6.4.7 in [Abramowitz 1974]) which is different with the case x > −5.0, while the mathematical
function (in mpmath) keeps using the same formula (6.4.6 in [Abramowitz 1974]) for both cases. If
we change the implementation of gsl_sf _psi_1 according to the formula 6.4.6 for x ≤ −5, the high
floating-point errors of gsl_sf _psi_1 in Ierr disappear.
What stands out in Table 2 is the łAccuracy of Repairž which is 100% for all three levels of error
thresholds and for all programs except P20. The results show that most subjects have a polynomial
feature in their small input interval Ierr and can be well approximated by our approach.
Fig. 12 shows the bits correct for maximum error and average error after repair under different
levels of error thresholds. Accuracy in Fig. 12(a) is measured by Errbits, and the maximum error
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:21
Program ID
P8 P8
P9 P9
P10 P10
P11 P11
P12 P12
P13 P13
P14 P14
P15 P15
P16 P16
P17 P17
P18 P18
P19 P19
0 8 16 24 32 40 48 56 64 0 8 16 24 32 40 48 56 64
Program ID
P8 P8
P9 P9
P10 P10
P11 P11
P12 P12
P13 P13
P14 P14
P15 P15
P16 P16
P17 P17
P18 P18
P19 P19
0 8 16 24 32 40 48 56 64 0 8 16 24 32 40 48 56 64
Program ID
P8 P8
P9 P9
P10 P10
P11 P11
P12 P12
P13 P13
P14 P14
P15 P15
P16 P16
P17 P17
P18 P18
P19 P19
0 8 16 24 32 40 48 56 64 0 8 16 24 32 40 48 56 64
(a) Bits correct for maximum error (b) Bits correct for average error
(longer is better) (longer is better)
Fig. 12. Each row represents the improvement in accuracy achieved by AutoNRP on a single benchmark. The
thick arrow starts at the accuracy of the program before repair, and ends at the accuracy of the program after
repair. A triangle is drawn at the value of error threshold for each subject . A pentagram is drawn at the
value of mean error of each subject in its whole input domain.
is found by our DEMC algorithm (in ğ4). Accuracy in Fig. 12(b) is measured by Errbits, averaged
across 100 000 random input points in the Ierr of a program8 . As shown in Fig. 12, for all given
thresholds (Hε , Mε , Lε ) and subjects excepts P20, AutoRNP successfully improves the accuracy
such that the maximum error does not exceed the given error threshold and the resulting average
error decreases. Interestingly, for P11 , after repairing, its maximum error is almost getting close to
the mean error as shown in Fig. 12. And the timings for repairing P11 are also quite small, actually
8 If the number of floating point inputs in I e r r is less 100 000, then we test all floating-point inputs in Ierr .
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:22 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
the least one for Hε , as shown in Table 2. In fact, the gsl_sf _legendre_P2 (i.e., P11) is a quadratic
function which is a natural fit for our approach.
50
Ierr size with Lε 3093 123 3448 3510 2148
log2 value of Time(s) and Size of Ierr
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10 P11 P12 P13 P14 P15 P16 P17 P18 P19
Program ID
Fig. 13. Repair time and size of Ierr under three level error thresholds
Fig. 13 shows the log2 value of repair time and size of Ierr for each subject under three thresholds.
The size of Ierr is the quantity of floating-point numbers in Ierr (evaluated by Eq. 2). Note that we
label the number of pieces in the approximation function f (i.e., the piecewise quadratic function)
on each dot of the three lines of Ierr (the blue lines in the upper of Fig. 13). As shown in Fig. 13, the
higher level of error thresholds, the more repair time needed by our approach, the larger size of
Ierr , and the more pieces in the piecewise quadratic function.
In summary, the above results suggest that our approach can efficiently repair high floating-point
errors in numerical libraries to satisfy a given error threshold.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:23
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:24 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
100 100
80 80
60 60
40 40
20 20
Lε Lε
Mε Mε
Hε Hε
0 0
0.5 0.6 0.7 0.8 0.9 1.0 0.85 0.90 0.95 1.00 1.05 1.10
(a) Time overhead on Ierr (b) Time overhead on the whole input domain
Fig. 14. AutoRNP time overhead ratio (left is better) on 19 successfully repaired programs
Storage overhead Extra storages are needed for storing the patch. We evaluate the storage
overhead by the size of patch file. As shown in Table 4, the storage overhead is increasing with the
level of error thresholds. Note that there exist significant difference between the subjects over the
storage overhead for the high level error threshold H ε .
Program ID
Threshold
P1 P2 P3 P4 P5 P6 P7 P8 P9 P10
Lε 1.68 1.69 1.82 1.82 1.73 1.73 1.73 2.04 1.69 1.73
Mε 1.69 1.69 1.82 1.82 4.05 4.67 9.61 15.15 3.25 8.21
Hε 2.15 5.10 7.42 4.78 67.92 149.08 479.39 393.82 107.46 211.58
P11 P12 P13 P14 P15 P16 P17 P18 P19
Lε 1.78 1.77 2.39 1.60 2.22 1.58 1.67 3.01 2.82
Mε 2.24 4.54 23.38 3.79 18.89 7.59 7.37 4.39 4.37
Hε 20.69 157.09 591.47 66.51 533.47 542.30 332.95 72.46 32.44
Readability The process (in ğ4.2) of deriving the approximation of mathematical function only
bases on the input and output of f , and does not involve the implementation of numerical program.
The patch is also independent of the implementation of original subject. Thus we can package
the main implementation of a patch in a function and store it in an individual file. In the source
code of original program, we just need to add a new branch to decide whether to call the function
in the patch, as shown in Fig. 5. Our approach based on simple linear approximation and error
compensation also makes the patch code (in Fig. 9) easily understand.
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:25
programs (Table 1) are also implemented by 16 numerical programs in SciPy. We also detect high
floating-point errors in 14 of those 16 numerical programs in SciPy on the same Ier r (as GSL). We
convert our approximation to python code and successfully repair those 14 numerical programs in
SciPy.
6 DISCUSSION
Execution of mathematical function The higher precision execution of original numerical
programs may introduce extra errors for numerical programs in numerical libraries that involve
some precision-specific operations [Wang et al. 2016], so we do not use the higher precision
execution as the choice for obtaining mathematical result. In our experiments, we use the package
mpmath to supply the corresponding mathematical functions of original numerical programs in
GSL. mpmath [Johansson et al. 2013] is an open-source library for real and complex floating-point
arithmetic with arbitrary precision, and many computer algebra systems (e.g., SageMath) use
mpmath as the underlying library. Since the corresponding functions supplied by mpmath are via
arbitrary precision, we assume that they should not include precision-specific operations and thus
can supply the (nearly) mathematical results of numerical programs in GSL.
Accuracy of repair A reasonable explanation for the 100% of AccRepair for all subjects (except
P20) might be that the search algorithm is very accurate to find the maximum floating-point error
in a small search space. A higher level of error thresholds needs an approximation function with
more pieces to reduce the error. Then the search space is partitioned more fine-grained, which
also decreases the difficulty to find a maximum floating-point error in the smaller search space
and increases the accuracy of the search algorithm. We have also repeated our experiments many
times with different random seeds, and the accuracy of repair keeps 100%. However, we can not
guarantee the accuracy of repair be always 100% for all programs.
Influence on functional correctness According to Theorem 4.1 and Theorem 4.2, in principle,
our approach can produce a repair semantically equivalent to the mathematical function by setting
the error threshold ε equal to zero (in the worst case by storing the mathematical result for
each floating-point input inside Ierr ). Besides, for a numerical program involving ill-conditioned
problems, the original implementation already affected the functional correctness, and rewrite-
based approaches are not fit for fixing it. However, as a dynamic analysis method, we cannot
guarantee the soundness of our approach unless we take an exhaustive search (i.e., testing all
inputs).
Form of approximation An interesting question is why we choose the piecewise quadratic
function to approximate a mathematical function. Accurately implementing approximations is
critical for approximating mathematical functions. Using quadratic approximations, we can have
strategies (in Sect 4.3) to make the subtraction operations (in approximations) exact and thus can
keep high accuracy during the implementation (while other approximations may not have such
properties). Moreover, we choose a simple way to solve the problem and our experimental results
show that our approach is effective on most subjects.
7 RELATED WORK
Floating-point error detection Since the work of Benz et al. [2012], the study of dynamically
detecting floating-point error has gained momentum. Benz et al. [2012] developed a tool called
FpDebug, which is built based on MPFR [Fousse et al. 2007] and Valgrind [Nethercote and Seward
2007], and can do a shadow execution of the original program in a higher precision to detect
floating-point errors for every instruction. Based on FpDebug, Zou et al. [2015] proposed a detection
approach called LSGA to search for input that can trigger possible maximum floating-point error
in a numerical program. Recently, Herbgrind, which is a similar tool of FpDebug, is developed by
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:26 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
Sanchez-Stern et al. [2018]. Besides supporting similar functionalities of FpDebug, Herbgrind can
find the root cause of floating-point error and extract the corresponding floating-point expressions.
However, the above approaches or tools are all based on the assumption that the semantics of
floating-point code in the higher precision is closer to the semantics of mathematical function.
Hence they could not deal with the precision-specific operations [Wang et al. 2016] and may
introduce unexpected errors. Aware of the precision-specific operations in numerical program, Yi
et al. [2017b] verified that many of high floating-point errors in GSL reported by Zou et al. [2015]
are in fact false alarms. Yi et al. [2017b] also proposed a new search algorithm called EAGT with a
new fitness function from error analysis.
Compared with previous detecting methods, as far as we know, there is no existing work
combining condition number and MCMC for finding the input triggering maximum error. Moreover,
our detecting method not only uses the DEMC algorithm to search the input that can trigger the
maximum floating-point error (like existing detecting methods [Chiang et al. 2014] [Zou et al. 2015]
[Yi et al. 2017b]), but also uses the PTB algorithm to localize inputs that can trigger floating-point
errors higher than a given repair criterion.
Automated improving accuracy of floating-point expressions Tools for automated improv-
ing accuracy of floating-point expressions can be classified by the underling analytic methods
(static or dynamic). Static analysis of floating-point code tries to provide a sound bound of errors
but may have low precision due to too conservative over-approximations and may have limited
scalability. In contrast, dynamic analysis can scale for large program and find exact floating-point
errors during dynamically executing of numerical program but cannot guarantee a sound bound of
errors for a given input interval.
Static tools: Salsa [Damouche and Martel 2018] is a tool constructed under sound abstract inter-
pretation [Cousot and Cousot 1977] and uses mathematical equivalent transformation [Damouche
et al. 2017] to improve the accuracy of floating-point programs. Salsa can analyze numerical pro-
grams with loops and functions, but cannot deal with complex data structures like arrays, function
pointers, library function calls, etc.
Compared with Salsa, our work is based on dynamic analysis. Thus, we cannot guarantee a
sound bound of errors for a given input intervals like Salsa, but our experimental results show that
we produce a high accuracy rate (100%) of repair to reduce high floating-point error to satisfy a
given error threshold over a large amount of floating-point inputs.
Dynamic tools: Herbie [Panchekha et al. 2015] is a tool for automatically improving the accuracy
of floating-point expressions. Like Salsa, Herbie uses mathematical rewriting to improving accuracy.
To apply Herbie to numerical programs, the same authors of Herbie develop the tool Herbgrind
[Sanchez-Stern et al. 2018] to find root cause of floating-point error and extract the corresponding
floating-point expressions that can be analyzed by Herbie. The combination of Herbie and Herbgrind
is called HBG in our paper and its detailed implementation is introduced in ğ5.2. AutoFP [Yi et al.
2017a] is a similar tool of HBG, but is constructed based on FpDebug [Benz et al. 2012] and Herbie.
AutoFP tries to divide program into blocks to improve accuracy in every block to decrease the
complexity of analysis. Although Yi et al. [2017a] first try to use AutoFP to repair high accuracies in
numerical programs, AutoFP uses FpDebug with Herbie and thus is quite similar as HBG (Herbgrind
with Herbie). Moreover, AutoFP does not support numerical programs with complex data structures
in GSL.
Compared with the above work, our work targets at a different goal and uses different meth-
ods. Concerning the target, we focus on automatically repair high floating-point error under a
given threshold rather than improving accuracy without a given criterion or target. Concerning
methodology, our approach uses the linear approximation with error compensation to derive an
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:27
ACKNOWLEDGMENTS
We thank Pavel Panchekha for his discussions on using Herbie and Herbgrind, and Zhengfeng
Yang for his helpful suggestions on this work. We also thank the anonymous reviewers for their
valuable comments. This work is supported by the National Key R&D Program of China (No.
2017YFB1001802), and the National Natural Science Foundation of China (Nos. 61672529, 61872445,
61502015).
REFERENCES
Milton Abramowitz. 1974. Handbook of Mathematical Functions, With Formulas, Graphs, and Mathematical Tables,. Dover
Publications, Inc., New York, NY, USA.
Christophe Andrieu, Nando de Freitas, Arnaud Doucet, and Michael I. Jordan. 2003. An Introduction to MCMC for Machine
Learning. Machine Learning 50, 1 (01 Jan 2003), 5ś43. https://doi.org/10.1023/A:1020281327116
Tao Bao and Xiangyu Zhang. 2013. On-the-fly Detection of Instability Problems in Floating-point Program Execution. In
Proceedings of the 2013 ACM SIGPLAN International Conference on Object Oriented Programming Systems Languages &
Applications (OOPSLA ’13). ACM, New York, NY, USA, 817ś832. https://doi.org/10.1145/2509136.2509526
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
56:28 Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji
Florian Benz, Andreas Hildebrandt, and Sebastian Hack. 2012. A Dynamic Program Analysis to Find Floating-point Accuracy
Problems. In Proceedings of the 33rd ACM SIGPLAN Conference on Programming Language Design and Implementation
(PLDI ’12). ACM, New York, NY, USA, 453ś462. https://doi.org/10.1145/2254064.2254118
Florian Cajori. 1911. Horner’s method of approximation anticipated by Ruffini. Bull. Amer. Math. Soc. 17, 8 (1911), 409ś414.
https://doi.org/10.1090/S0002-9904-1911-02072-9
Wei-Fan Chiang, Ganesh Gopalakrishnan, Zvonimir Rakamaric, and Alexey Solovyev. 2014. Efficient Search for Inputs
Causing High Floating-point Errors. SIGPLAN Not. 49, 8 (Feb. 2014), 43ś52. https://doi.org/10.1145/2692916.2555265
Patrick Cousot and Radhia Cousot. 1977. Abstract Interpretation: A Unified Lattice Model for Static Analysis of Programs
by Construction or Approximation of Fixpoints. In Proceedings of the 4th ACM SIGACT-SIGPLAN Symposium on Principles
of Programming Languages (POPL ’77). ACM, New York, NY, USA, 238ś252. https://doi.org/10.1145/512950.512973
Nasrine Damouche and Matthieu Martel. 2018. Salsa: An Automatic Tool to Improve the Numerical Accuracy of Programs.
In Automated Formal Methods (Kalpa Publications in Computing), Natarajan Shankar and Bruno Dutertre (Eds.), Vol. 5.
EasyChair, 63ś76. https://doi.org/10.29007/j2fd
Nasrine Damouche, Matthieu Martel, and Alexandre Chapoutot. 2017. Numerical Accuracy Improvement by Interprocedural
Program Transformation. In Proceedings of the 20th International Workshop on Software and Compilers for Embedded
Systems (SCOPES ’17). ACM, New York, NY, USA, 1ś10. https://doi.org/10.1145/3078659.3078662
Favio DeMarco, Jifeng Xuan, Daniel Le Berre, and Martin Monperrus. 2014. Automatic Repair of Buggy if Conditions and
Missing Preconditions with SMT. In Proceedings of the 6th International Workshop on Constraints in Software Testing,
Verification, and Analysis (CSTVA ’14). ACM, New York, NY, USA, 30ś39. https://doi.org/10.1145/2593735.2593740
Anthony Di Franco, Hui Guo, and Cindy Rubio-González. 2017. A Comprehensive Study of Real-world Numerical Bug
Characteristics. In Proceedings of the 32Nd IEEE/ACM International Conference on Automated Software Engineering (ASE
’17). IEEE Press, Piscataway, NJ, USA, 509ś519. http://dl.acm.org/citation.cfm?id=3155562.3155627
Thomas Durieux and Martin Monperrus. 2016. DynaMoth: Dynamic Code Synthesis for Automatic Program Repair. In
Proceedings of the 11th International Workshop on Automation of Software Test (AST ’16). ACM, New York, NY, USA, 85ś91.
https://doi.org/10.1145/2896921.2896931
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. Softw. 33, 2, Article 13 (June 2007).
https://doi.org/10.1145/1236463.1236468
Zhoulai Fu, Zhaojun Bai, and Zhendong Su. 2015. Automated Backward Error Analysis for Numerical Code. In Proceedings
of the 2015 ACM SIGPLAN International Conference on Object-Oriented Programming, Systems, Languages, and Applications
(OOPSLA ’15). ACM, New York, NY, USA, 639ś654. https://doi.org/10.1145/2814270.2814317
Zhoulai Fu and Zhendong Su. 2017. Achieving High Coverage for Floating-point Code via Unconstrained Programming. In
Proceedings of the 38th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI ’17). ACM,
New York, NY, USA, 306ś319. https://doi.org/10.1145/3062341.3062383
David Goldberg. 1991. What Every Computer Scientist Should Know About Floating-point Arithmetic. ACM Comput. Surv.
23, 1 (March 1991), 5ś48. https://doi.org/10.1145/103162.103163
Divya Gopinath, Muhammad Zubair Malik, and Sarfraz Khurshid. 2011. Specification-based Program Repair Using SAT. In
Proceedings of the 17th International Conference on Tools and Algorithms for the Construction and Analysis of Systems:
Part of the Joint European Conferences on Theory and Practice of Software (TACAS’11/ETAPS’11). Springer-Verlag, Berlin,
Heidelberg, 173ś188. http://dl.acm.org/citation.cfm?id=1987389.1987408
Fredrik Johansson et al. 2013. mpmath: a Python library for arbitrary-precision floating-point arithmetic (version 0.18).
http://mpmath.org/.
William Kahan. 1996. IEEE standard 754 for binary floating-point arithmetic. Lecture Notes on the Status of IEEE 754,
94720-1776 (1996), 11.
Wonyeol Lee, Rahul Sharma, and Alex Aiken. 2017. On Automatically Proving the Correctness of Math.H Implementations.
Proc. ACM Program. Lang. 2, POPL, Article 47 (Dec. 2017), 32 pages. https://doi.org/10.1145/3158135
Fan Long and Martin Rinard. 2015. Staged Program Repair with Condition Synthesis. In Proceedings of the 2015 10th
Joint Meeting on Foundations of Software Engineering (ESEC/FSE ’15). ACM, New York, NY, USA, 166ś178. https:
//doi.org/10.1145/2786805.2786811
Fan Long and Martin Rinard. 2016. Automatic Patch Generation by Learning Correct Code. SIGPLAN Not. 51, 1 (Jan. 2016),
298ś312. https://doi.org/10.1145/2914770.2837617
Sebastian R. Lamelas Marcote and Martin Monperrus. 2015. Automatic Repair of Infinite Loops. CoRR abs/1504.05078 (2015).
arXiv:1504.05078 http://arxiv.org/abs/1504.05078
Sergey Mechtaev, Jooyong Yi, and Abhik Roychoudhury. 2015. DirectFix: Looking for Simple Program Repairs. In Proceedings
of the 37th International Conference on Software Engineering - Volume 1 (ICSE ’15). IEEE Press, Piscataway, NJ, USA,
448ś458. http://dl.acm.org/citation.cfm?id=2818754.2818811
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.
Efficient Automated Repair of High Floating-Point Errors in Numerical Libraries 56:29
Sergey Mechtaev, Jooyong Yi, and Abhik Roychoudhury. 2016. Angelix: Scalable Multiline Program Patch Synthesis via
Symbolic Analysis. In Proceedings of the 38th International Conference on Software Engineering (ICSE ’16). ACM, New
York, NY, USA, 691ś701. https://doi.org/10.1145/2884781.2884807
Nicholas Nethercote and Julian Seward. 2007. Valgrind: A Framework for Heavyweight Dynamic Binary Instrumentation.
SIGPLAN Not. 42, 6 (June 2007), 89ś100. https://doi.org/10.1145/1273442.1250746
Hoang Duong Thien Nguyen, Dawei Qi, Abhik Roychoudhury, and Satish Chandra. 2013. SemFix: Program Repair via
Semantic Analysis. In Proceedings of the 2013 International Conference on Software Engineering (ICSE ’13). IEEE Press,
Piscataway, NJ, USA, 772ś781. http://dl.acm.org/citation.cfm?id=2486788.2486890
Pavel Panchekha, Alex Sanchez-Stern, James R. Wilcox, and Zachary Tatlock. 2015. Automatically Improving Accuracy for
Floating Point Expressions. In Proceedings of the 36th ACM SIGPLAN Conference on Programming Language Design and
Implementation (PLDI ’15). ACM, New York, NY, USA, 1ś11. https://doi.org/10.1145/2737924.2737959
Yuhua Qi, Xiaoguang Mao, Yan Lei, Ziying Dai, and Chengsong Wang. 2014. The Strength of Random Search on Automated
Program Repair. In Proceedings of the 36th International Conference on Software Engineering (ICSE ’14). ACM, New York,
NY, USA, 254ś265. https://doi.org/10.1145/2568225.2568254
Alex Sanchez-Stern, Pavel Panchekha, Sorin Lerner, and Zachary Tatlock. 2018. Finding Root Causes of Floating Point Error.
In Proceedings of the 39th ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI ’18).
ACM, New York, NY, USA, 256ś269. https://doi.org/10.1145/3192366.3192411
Eric Schkufza, Rahul Sharma, and Alex Aiken. 2014. Stochastic Optimization of Floating-point Programs with Tunable
Precision. In Proceedings of the 35th ACM SIGPLAN Conference on Programming Language Design and Implementation
(PLDI ’14). ACM, New York, NY, USA, 53ś64. https://doi.org/10.1145/2594291.2594302
Pat H Sterbenz. 1973. Floating-point computation. Prentice Hall, Englewood Cliffs, N.J.
Rainer Storn and Kenneth Price. 1997. Differential Evolution ś A Simple and Efficient Heuristic for global Optimization over
Continuous Spaces. Journal of Global Optimization 11, 4 (01 Dec 1997), 341ś359. https://doi.org/10.1023/A:1008202821328
Enyi Tang, Xiangyu Zhang, Norbert Th. Muller, Zhenyu Chen, and Xuandong Li. 2017. Software Numerical Instability De-
tection and Diagnosis by Combining Stochastic and Infinite-Precision Testing. IEEE Transactions on Software Engineering
43, 10 (Oct 2017), 975ś994. https://doi.org/10.1109/TSE.2016.2642956
David J. Wales and Jonathan P. K. Doye. 1997. Global Optimization by Basin-Hopping and the Lowest Energy Structures of
Lennard-Jones Clusters Containing up to 110 Atoms. The Journal of Physical Chemistry A 101, 28 (1997), 5111ś5116.
https://doi.org/10.1021/jp970984n
Ran Wang, Daming Zou, Xinrui He, Yingfei Xiong, Lu Zhang, and Gang Huang. 2016. Detecting and Fixing Precision-specific
Operations for Measuring Floating-point Errors. In Proceedings of the 2016 24th ACM SIGSOFT International Symposium
on Foundations of Software Engineering (FSE ’16). ACM, New York, NY, USA, 619ś630. https://doi.org/10.1145/2950290.
2950355
Westley Weimer, ThanhVu Nguyen, Claire Le Goues, and Stephanie Forrest. 2009. Automatically Finding Patches Using
Genetic Programming. In Proceedings of the 31st International Conference on Software Engineering (ICSE ’09). IEEE
Computer Society, Washington, DC, USA, 364ś374. https://doi.org/10.1109/ICSE.2009.5070536
Jifeng Xuan, Matias Martinez, Favio DeMarco, Maxime Clement, Sebastian Lamelas Marcote, Thomas Durieux, Daniel
Le Berre, and Martin Monperrus. 2017. Nopol: Automatic Repair of Conditional Statement Bugs in Java Programs. IEEE
Trans. Softw. Eng. 43, 1 (Jan. 2017), 34ś55. https://doi.org/10.1109/TSE.2016.2560811
Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji. 2017a. Automated Repair of High Inaccuracies in Numerical Programs. In
2017 IEEE International Conference on Software Maintenance and Evolution (ICSME ’17). 514ś518. https://doi.org/10.1109/
ICSME.2017.45
Xin Yi, Liqian Chen, Xiaoguang Mao, and Tao Ji. 2017b. Efficient Global Search for Inputs Triggering High Floating-Point
Inaccuracies. In 2017 24th Asia-Pacific Software Engineering Conference (APSEC ’17). 11ś20. https://doi.org/10.1109/
APSEC.2017.7
Daming Zou, Ran Wang, Yingfei Xiong, Lu Zhang, Zhendong Su, and Hong Mei. 2015. A Genetic Algorithm for Detecting
Significant Floating-point Inaccuracies. In Proceedings of the 37th International Conference on Software Engineering -
Volume 1 (ICSE ’15). IEEE Press, Piscataway, NJ, USA, 529ś539. http://dl.acm.org/citation.cfm?id=2818754.2818820
Proc. ACM Program. Lang., Vol. 3, No. POPL, Article 56. Publication date: January 2019.