Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#9104 closed Bugs (fixed)

boost::math::ellint_2 bug in x86_64 double precision

Reported by: julian.panetta@… Owned by: John Maddock
Milestone: To Be Determined Component: math
Version: Boost 1.54.0 Severity: Problem
Keywords: Cc:


The way ellint_e_imp reduces its input angle into the range |phi| <= pi/2 has a bug when executing in double precision mode on intel chips (as opposed to the default double extended-precision mode) that results in errors as great as 100%.

The relevant lines are at boost/math/special_functions/ellint_2.hpp:

T rphi = boost::math::tools::fmod_workaround(phi, T(constants::pi<T>() / 2));
T m = floor((2 * phi) / constants::pi<T>());

Compiled with optimizations on both g++ and clang++, fmod_workaround() essentially becomes a "fprem" instruction, and (2 * phi) / pi() becomes an "fdivr" instruction. "fprem" ignores the precision mode and always produces exact results. "fdivr," however, gives less accurate results in plain double precision mode. This leads to the following error when, for example, phi = M_PI (slightly less than boost's more accurate pi()):

In plain double precision, rphi is computed as slightly less than pi()/2 (correct since M_PI < pi()). However, m = 2 (incorrect, rounded result). The end result is m * pi()/2 + rphi is close to 3pi/2 instead of M_PI, causing the computed integral to be 50% too large. In extended precision, the "fdivr" is accurate enough to yield m = 1 correctly.

There are two ways I can see of avoiding this:

T rphi = boost::math::tools::fmod_workaround(phi, T(constants::pi<T>() / 2));
T m = (phi - rphi) / T(constants::pi<T>() / 2);

and the less verbose:

T m = floor(phi / T(constants::pi<T>() / 2));
T rphi = phi - m * T(constants::pi<T>() / 2);

Both would ensure rphi and m are consistent with the original phi. Note: in the second formula for m, T(constants::pi<T>() / 2) is folded into a constant that is exactly pi()/2, whereas the floor() argument in the original version generated extra code to double phi.

Attachments (0)

Change History (2)

comment:1 Changed 4 years ago by John Maddock

Resolution: fixed
Status: newclosed

(In [85678]) Suppress warning in fraction.hpp. Fix internal consistency of argument reduction in elliptic integrals when the argument is very close to a multiple of PI/2. Fixes #9107. Fixes #9104.

comment:2 Changed 4 years ago by John Maddock

(In [85987]) Merge accumulated patches from Trunk. Refs #8384, Refs #8855, refs #9107, refs #9109, refs #8333, refs #8621, refs #8732, refs #8733, refs #8837, refs #8940, refs #9042, refs #9087, refs #9104, refs #9126.

Modify Ticket

Change Properties
Set your email in Preferences
as closed The owner will remain John Maddock.
The resolution will be deleted.

Add Comment

E-mail address and name can be saved in the Preferences.

Note: See TracTickets for help on using tickets.