boostorg / boostorg/multiprecision

Potential error read-string overflow/underflow in bin-float?

Open
#726 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
265
Forks
128
Avg merge
4h 48m
Merged PRs (30d)
2

Description

Hi folks,

Here is an interesting case that I found while doing extreme amounts of enhanced edge-case testing in Multiprecision. There is a reduced (albeit still rather long) test in the code sample below.

The test is intended to read the string input and check the expected non-normal-ness for overflow and underflow. When you read the string that overflows, you sould get `fpclassify(flt_ovf) == FP_INFINITE` and when you read the string that underflows, you should get `fpclassify(flt_und) == FP_ZERO`.

And it works for `cpp_dec_float` and for the newly-created `cpp_double_double`. But these tests fail for `cpp_bin_float`.

I believe the failure is non-bogus and might represent an actual bug or weakness. And it is within the string read of `cpp_bin_float`.

I don't see a real hurry to look into or (if needed) correct this one, we can do that after August and for the next release cycle.

Cc: @jzmaddock and @mborland

```
#include
#include
#include

#include

#include
#include

template auto my_generator_overflow() noexcept -> FloatType;
template auto my_generator_underflow() noexcept -> FloatType;

namespace local
{
template
bool test_edges_ovf_und()
{
using float_type = FloatType;

const float_type flt_ovf = ::my_generator_overflow();
const float_type flt_und = ::my_generator_underflow();

const bool result_ovf_is_ok { (fpclassify(flt_ovf) == FP_INFINITE) && isinf(flt_ovf) };
const bool result_und_is_ok { (fpclassify(flt_und) == FP_ZERO) };

BOOST_TEST(result_ovf_is_ok);
BOOST_TEST(result_und_is_ok);

const bool result_is_ok { (result_ovf_is_ok && result_und_is_ok) };

return result_is_ok;
}
} // namespace local

auto main() -> int
{
{
using dec_float_backend_type = boost::multiprecision::cpp_dec_float<50>;
using dec_float_type = boost::multiprecision::number;

std::cout << "Testing type: " << typeid(dec_float_type).name() << std::endl;

static_cast(local::test_edges_ovf_und());
}

#if 1
{
using bin_float_backend_type = boost::multiprecision::cpp_bin_float<50>;
using bin_float_type = boost::multiprecision::number;

std::cout << "Testing type: " << typeid(bin_float_type).name() << std::endl;

// TBD: This seemingly trivial test fails for cpp_bin_float.
static_cast(local::test_edges_ovf_und());
}
#endif

{
using double_float_type = boost::multiprecision::cpp_double_double;

std::cout << "Testing type: " << typeid(double_float_type).name() << std::endl;

static_cast(local::test_edges_ovf_und());
}

return boost::report_errors();
}

template
static auto
overflow_expval_maker
{
[]()
{
std::stringstream strm { };

using float_type = FloatType;

strm << std::numeric_limits::max_exponent10 + 4;

return strm.str();
}
};

template
static auto
underflow_expval_maker
{
[]()
{
std::stringstream strm { };

using float_type = FloatType;

strm << std::numeric_limits::min_exponent10 - 4;

return strm.str();
}
};

template
auto my_generator_overflow() noexcept -> FloatType
{
using float_type = FloatType;

const float_type flt_ovf("1.23E" + overflow_expval_maker());

const float_type result(flt_ovf);

return result;
}

template
auto my_generator_underflow() noexcept -> FloatType
{
using float_type = FloatType;

float_type flt_und("1.23E" + underflow_expval_maker());

const float_type result(flt_und);

return result;
}
```

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.