From 596259874b1ff910d137e7c7c0d0b25357836744 Mon Sep 17 00:00:00 2001 From: jzmaddock Date: Wed, 12 Aug 2020 11:43:55 +0100 Subject: [PATCH] Fix frexp for mpfr: Make sure we call the correct API, add motivating test case. --- include/boost/multiprecision/mpfr.hpp | 28 ++++++++++++++++++++++----- test/Jamfile.v2 | 1 + test/git_issue_265.cpp | 27 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 test/git_issue_265.cpp diff --git a/include/boost/multiprecision/mpfr.hpp b/include/boost/multiprecision/mpfr.hpp index d987845f..b774e60e 100644 --- a/include/boost/multiprecision/mpfr.hpp +++ b/include/boost/multiprecision/mpfr.hpp @@ -1366,16 +1366,34 @@ inline void eval_ldexp(mpfr_float_backend& result, const template inline void eval_frexp(mpfr_float_backend& result, const mpfr_float_backend& val, int* e) { - long v; - mpfr_get_d_2exp(&v, val.data(), GMP_RNDN); + if (mpfr_zero_p(val.data())) + { + *e = 0; + result = val; + return; + } + mp_exp_t v = mpfr_get_exp(val.data()); *e = v; - eval_ldexp(result, val, -v); + if (v) + eval_ldexp(result, val, -v); + else + result = val; } template inline void eval_frexp(mpfr_float_backend& result, const mpfr_float_backend& val, long* e) { - mpfr_get_d_2exp(e, val.data(), GMP_RNDN); - return eval_ldexp(result, val, -*e); + if (mpfr_zero_p(val.data())) + { + *e = 0; + result = val; + return; + } + mp_exp_t v = mpfr_get_exp(val.data()); + *e = v; + if(v) + eval_ldexp(result, val, -v); + else + result = val; } template diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 16959a5f..593857cd 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -1014,6 +1014,7 @@ test-suite misc : [ run git_issue_167.cpp ] [ run git_issue_175.cpp ] [ run git_issue_248.cpp ] + [ run git_issue_265.cpp : : : [ check-target-builds ../config//has_mpfr : gmp mpfr : no ] ] [ compile git_issue_98.cpp : [ check-target-builds ../config//has_float128 : TEST_FLOAT128 quadmath : ] [ check-target-builds ../config//has_gmp : TEST_GMP gmp : ] diff --git a/test/git_issue_265.cpp b/test/git_issue_265.cpp new file mode 100644 index 00000000..5f6b97cb --- /dev/null +++ b/test/git_issue_265.cpp @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2020 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#include +#include +#include "test.hpp" + +using namespace boost::multiprecision; + +int main() +{ + mpfr_float_50 half = 0.5; + mpfr_float_50 under_half = boost::math::float_prior(half); + BOOST_CHECK_NE(half, under_half); + int e1, e2; + mpfr_float_50 norm1, norm2; + norm1 = frexp(half, &e1); + norm2 = frexp(under_half, &e2); + BOOST_CHECK_EQUAL(norm1, half); + BOOST_CHECK_EQUAL(e1, 0); + BOOST_CHECK_GT(1, norm2); + BOOST_CHECK_LE(0.5, norm2); + BOOST_CHECK_EQUAL(e2, -1); + return boost::report_errors(); +}