diff --git a/include/boost/numeric/interval/detail/c99sub_rounding_control.hpp b/include/boost/numeric/interval/detail/c99sub_rounding_control.hpp index a8684df..00084c9 100644 --- a/include/boost/numeric/interval/detail/c99sub_rounding_control.hpp +++ b/include/boost/numeric/interval/detail/c99sub_rounding_control.hpp @@ -18,7 +18,7 @@ namespace numeric { namespace interval_lib { namespace detail { -extern "C" { double rint(double); } +extern "C" { double rint(double); long double rintl(long double); } struct c99_rounding_control { @@ -33,6 +33,7 @@ struct c99_rounding_control template static T to_int(const T& r) { return rint(r); } + static long double to_int(const long double& r) { return rintl(r); } }; } // namespace detail diff --git a/include/boost/numeric/interval/detail/ppc_rounding_control.hpp b/include/boost/numeric/interval/detail/ppc_rounding_control.hpp index f7e6781..45d3e6d 100644 --- a/include/boost/numeric/interval/detail/ppc_rounding_control.hpp +++ b/include/boost/numeric/interval/detail/ppc_rounding_control.hpp @@ -64,6 +64,7 @@ struct ppc_rounding_control extern "C" { float rintf(float); double rint(double); + long double rintl(long double); } #endif @@ -114,7 +115,7 @@ struct rounding_control: #endif return r_; } - static long double to_int(const long double& r) { return rint(r); } + static long double to_int(const long double& r) { return rintl(r); } }; } // namespace interval_lib diff --git a/include/boost/numeric/interval/detail/sparc_rounding_control.hpp b/include/boost/numeric/interval/detail/sparc_rounding_control.hpp index 2b08bec..88e557e 100644 --- a/include/boost/numeric/interval/detail/sparc_rounding_control.hpp +++ b/include/boost/numeric/interval/detail/sparc_rounding_control.hpp @@ -77,6 +77,7 @@ struct sparc_rounding_control extern "C" { float rintf(float); double rint(double); + long double rintl(long double); } template<> @@ -100,7 +101,7 @@ struct rounding_control: detail::sparc_rounding_control { static const long double& force_rounding(const long double& x) { return x; } - static long double to_int(const long double& x) { return rint(x); } + static long double to_int(const long double& x) { return rintl(x); } }; } // namespace interval_lib diff --git a/test/fmod.cpp b/test/fmod.cpp index 11e88ed..40a5f00 100644 --- a/test/fmod.cpp +++ b/test/fmod.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include "bugs.hpp" @@ -35,6 +36,15 @@ using namespace interval_lib; typedef change_rounding, save_state_nothing >::type I; +// to_int must round a long double with rintl: rint converts it to double +// first, and fmod(2^60 + 1, 1) then misses 0. +void test_long_double() { + typedef interval L; + if (std::numeric_limits::digits < 62) return; + long double big = 1152921504606846977.0L, one = 1; // 2^60 + 1 + BOOST_TEST(in_zero(fmod(L(big), L(one)))); +} + int main() { BOOST_TEST(equal(fmod(I(6,9), 7), I(6,9))); @@ -49,5 +59,7 @@ int main() { BOOST_TEST(equal(fmod(-17, I(7,8)), I(4,7))); BOOST_TEST(equal(fmod(I(-17,-13), I(7,8)), I(4,11))); + test_long_double(); + return boost::report_errors(); }