boost::multiprecision::cpp_dec_float_50 overflow checking

559 views Asked by At

I am trying to use the boost::multiprecision library for floating (or in that case, fixed) point arithmetic. However, I am having trouble detecting potential overflow in the following way:

typedef boost::multiprecision::number<
                                      boost::multiprecision::cpp_dec_float<50>
                                     > flp_type;
typedef boost::multiprecision::number<
                                      boost::multiprecision::cpp_dec_float<100>
                                     > safe_flp_type;

flp_type _1 = std::numeric_limits<flp_type>::max();
flp_type _2("1");
flp_type _3 = std::numeric_limits<flp_type>::max();
flp_type dtNew;

// Here is the check
safe_flp_type _res = safe_flp_type(_1) + _2;

// **This condition is true for addition of _1 and _3,**
// but fails for _1 + _2
if(  (_res > std::numeric_limits<flp_type>::max())  // overflow
   ||(_res < std::numeric_limits<flp_type>::min())) // underflow
{
    BOOST_THROW_EXCEPTION(OverUnderflow() << SpecificErrInfo(L"Attempted floating point over/underflow"));
}

dtNew = _1 + _2;

Shouldn't even adding 1 to max() for the type trigger the throw of the exception? I have also checked the underlying type after the overflow, and it's not cpp_dec_float_inf, still cpp_dec_float_finite. Also, the value of dtNew is equal to std::numeric_limits::max()

Am I under a complete conceptual misapprehension here? If so, what would be the correct way to prevent a boost::multiprecision::cpp_dec_float<50> from overflowing?

1

There are 1 answers

0
namezero On BEST ANSWER

Ok, I have debugged into the library, and the "error" happens on this line:

// Check if the operation is out of range, requiring special handling.
if(v.iszero() || (ofs_exp > max_delta_exp))
{
   // Result is *this unchanged since v is negligible compared to *this.
   return *this;
}

Adding 1 to the numeric_limit of the type is negligible, so the addition is discarded. Hence it is not >=.

I was under the impression that the type was implemented as fixed point (dumb considering the name, I know), which it is not. This is from the boost doc

Operations involving cpp_dec_float are always truncating. However, note that since their are guard digits in effect, in practice this has no real impact on accuracy for most use cases.

Bummer that the multiprecision library doesn't seem to have a fixed precision type.

However, in order to check for overflow in cpp_dec_float, one can do this:

dtNew = _1 * _2;
if(dtNew.backend().isinf())
{
    BOOST_THROW_EXCEPTION(OverUnderflow() << SpecificErrInfo(L"Attempted floating point over/underflow"));
}