mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-02-19 14:32:35 +00:00
Fix handling of NaN's and Infinities in basic arithmetic.
Added more test cases to catch bugs. See issue: https://svn.boost.org/trac/boost/ticket/12090.
This commit is contained in:
@@ -581,8 +581,8 @@ inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponen
|
||||
res = a;
|
||||
return;
|
||||
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
||||
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
|
||||
res.sign() = false;
|
||||
res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
||||
res.sign() = true;
|
||||
res.bits() = static_cast<limb_type>(0u);
|
||||
return; // result is a NaN.
|
||||
case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
||||
|
||||
@@ -662,6 +662,12 @@ cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, Expone
|
||||
return operator=(v);
|
||||
}
|
||||
|
||||
if((v.isnan)() || (v.isinf)())
|
||||
{
|
||||
*this = v;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Get the offset for the add/sub operation.
|
||||
static const ExponentType max_delta_exp = static_cast<ExponentType>((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10);
|
||||
|
||||
|
||||
@@ -993,6 +993,74 @@ void test_float_ops(const boost::mpl::int_<boost::multiprecision::number_kind_fl
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Operations involving NaN's as one argument:
|
||||
//
|
||||
if(std::numeric_limits<Real>::has_quiet_NaN)
|
||||
{
|
||||
v = 20.25;
|
||||
r = std::numeric_limits<Real>::quiet_NaN();
|
||||
BOOST_CHECK((boost::math::isnan)(v + r));
|
||||
BOOST_CHECK((boost::math::isnan)(r + v));
|
||||
BOOST_CHECK((boost::math::isnan)(r - v));
|
||||
BOOST_CHECK((boost::math::isnan)(v - r));
|
||||
BOOST_CHECK((boost::math::isnan)(r * v));
|
||||
BOOST_CHECK((boost::math::isnan)(v * r));
|
||||
BOOST_CHECK((boost::math::isnan)(r / v));
|
||||
BOOST_CHECK((boost::math::isnan)(v / r));
|
||||
Real t = v;
|
||||
BOOST_CHECK((boost::math::isnan)(t += r));
|
||||
t = r;
|
||||
BOOST_CHECK((boost::math::isnan)(t += v));
|
||||
t = r;
|
||||
BOOST_CHECK((boost::math::isnan)(t -= v));
|
||||
t = v;
|
||||
BOOST_CHECK((boost::math::isnan)(t -= r));
|
||||
t = r;
|
||||
BOOST_CHECK((boost::math::isnan)(t *= v));
|
||||
t = v;
|
||||
BOOST_CHECK((boost::math::isnan)(t *= r));
|
||||
t = r;
|
||||
BOOST_CHECK((boost::math::isnan)(t /= v));
|
||||
t = v;
|
||||
BOOST_CHECK((boost::math::isnan)(t /= r));
|
||||
}
|
||||
//
|
||||
// Operations involving infinities as one argument:
|
||||
//
|
||||
if(std::numeric_limits<Real>::has_infinity)
|
||||
{
|
||||
v = 20.25;
|
||||
r = std::numeric_limits<Real>::infinity();
|
||||
BOOST_CHECK((boost::math::isinf)(v + r));
|
||||
BOOST_CHECK((boost::math::isinf)(r + v));
|
||||
BOOST_CHECK((boost::math::isinf)(r - v));
|
||||
BOOST_CHECK((boost::math::isinf)(v - r));
|
||||
BOOST_CHECK_LT(v - r, 0);
|
||||
BOOST_CHECK((boost::math::isinf)(r * v));
|
||||
BOOST_CHECK((boost::math::isinf)(v * r));
|
||||
BOOST_CHECK((boost::math::isinf)(r / v));
|
||||
BOOST_CHECK_EQUAL(v / r, 0);
|
||||
Real t = v;
|
||||
BOOST_CHECK((boost::math::isinf)(t += r));
|
||||
t = r;
|
||||
BOOST_CHECK((boost::math::isinf)(t += v));
|
||||
t = r;
|
||||
BOOST_CHECK((boost::math::isinf)(t -= v));
|
||||
t = v;
|
||||
BOOST_CHECK((boost::math::isinf)(t -= r));
|
||||
t = v;
|
||||
BOOST_CHECK(t -= r < 0);
|
||||
t = r;
|
||||
BOOST_CHECK((boost::math::isinf)(t *= v));
|
||||
t = v;
|
||||
BOOST_CHECK((boost::math::isinf)(t *= r));
|
||||
t = r;
|
||||
BOOST_CHECK((boost::math::isinf)(t /= v));
|
||||
t = v;
|
||||
BOOST_CHECK((t /= r) == 0);
|
||||
}
|
||||
|
||||
test_float_funcs<Real>(boost::mpl::bool_<std::numeric_limits<Real>::is_specialized>());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user