diff --git a/doc/decimal/decimal128.adoc b/doc/decimal/decimal128.adoc index 6b1950a5b..a6b2c3d20 100644 --- a/doc/decimal/decimal128.adoc +++ b/doc/decimal/decimal128.adoc @@ -50,6 +50,8 @@ template constexpr decimal128& operator=(const Integeral& RHS) noexcept; // 3.2.4.4 Conversion to integral type +// If the value exceeds the range of the integral, +// or is non-finite std::numeric_limits::max() is returned explicit constexpr operator int() const noexcept; explicit constexpr operator unsigned() const noexcept; explicit constexpr operator long() const noexcept; diff --git a/doc/decimal/decimal128_fast.adoc b/doc/decimal/decimal128_fast.adoc index 8b0496831..0c39b529c 100644 --- a/doc/decimal/decimal128_fast.adoc +++ b/doc/decimal/decimal128_fast.adoc @@ -50,6 +50,8 @@ template constexpr decimal128_fast& operator=(const Integeral& RHS) noexcept; // 3.2.4.4 Conversion to integral type +// If the value exceeds the range of the integral, +// or is non-finite std::numeric_limits::max() is returned explicit constexpr operator int() const noexcept; explicit constexpr operator unsigned() const noexcept; explicit constexpr operator long() const noexcept; diff --git a/doc/decimal/decimal32.adoc b/doc/decimal/decimal32.adoc index 7c006b8f5..2fd48eac4 100644 --- a/doc/decimal/decimal32.adoc +++ b/doc/decimal/decimal32.adoc @@ -50,6 +50,8 @@ template constexpr decimal32& operator=(const Integeral& RHS) noexcept; // 3.2.2.4 Conversion to integral type +// If the value exceeds the range of the integral, +// or is non-finite std::numeric_limits::max() is returned explicit constexpr operator int() const noexcept; explicit constexpr operator unsigned() const noexcept; explicit constexpr operator long() const noexcept; diff --git a/doc/decimal/decimal32_fast.adoc b/doc/decimal/decimal32_fast.adoc index f98ed93b1..307c9e81d 100644 --- a/doc/decimal/decimal32_fast.adoc +++ b/doc/decimal/decimal32_fast.adoc @@ -50,6 +50,8 @@ template constexpr decimal32_fast& operator=(const Integeral& RHS) noexcept; // 3.2.2.4 Conversion to integral type +// If the value exceeds the range of the integral, +// or is non-finite std::numeric_limits::max() is returned explicit constexpr operator int() const noexcept; explicit constexpr operator unsigned() const noexcept; explicit constexpr operator long() const noexcept; diff --git a/doc/decimal/decimal64.adoc b/doc/decimal/decimal64.adoc index 59a48619c..08dd83f02 100644 --- a/doc/decimal/decimal64.adoc +++ b/doc/decimal/decimal64.adoc @@ -50,6 +50,8 @@ template constexpr decimal64& operator=(const Integeral& RHS) noexcept; // 3.2.3.4 Conversion to integral type +// If the value exceeds the range of the integral, +// or is non-finite std::numeric_limits::max() is returned explicit constexpr operator int() const noexcept; explicit constexpr operator unsigned() const noexcept; explicit constexpr operator long() const noexcept; diff --git a/doc/decimal/decimal64_fast.adoc b/doc/decimal/decimal64_fast.adoc index d7bf2efb4..417a22ad4 100644 --- a/doc/decimal/decimal64_fast.adoc +++ b/doc/decimal/decimal64_fast.adoc @@ -50,6 +50,8 @@ template constexpr decimal64_fast& operator=(const Integeral& RHS) noexcept; // 3.2.3.4 Conversion to integral type +// If the value exceeds the range of the integral, +// or is non-finite std::numeric_limits::max() is returned explicit constexpr operator int() const noexcept; explicit constexpr operator unsigned() const noexcept; explicit constexpr operator long() const noexcept; diff --git a/include/boost/decimal/detail/to_integral.hpp b/include/boost/decimal/detail/to_integral.hpp index d4a8efa67..203b32372 100644 --- a/include/boost/decimal/detail/to_integral.hpp +++ b/include/boost/decimal/detail/to_integral.hpp @@ -41,23 +41,19 @@ constexpr auto to_integral(Decimal val) noexcept if (isnan(val)) { errno = EINVAL; - return static_cast(0); + return static_cast(std::numeric_limits::max()); } if (isinf(val) || val > max_target_type || val < min_target_type) { errno = ERANGE; - return static_cast(0); + return static_cast(std::numeric_limits::max()); } auto result {static_cast(val.full_significand())}; auto expval {val.biased_exponent()}; const auto abs_exp_val {detail::make_positive_unsigned(expval)}; - if (abs_exp_val >= 19) - { - result = 0; - } - else if (expval > 0) + if (expval > 0) { result *= detail::pow10(static_cast(expval)); } @@ -84,23 +80,19 @@ constexpr auto to_integral_128(Decimal val) noexcept if (isnan(val)) { errno = EINVAL; - return static_cast(UINT64_C(0)); + return static_cast(std::numeric_limits::max()); } if (isinf(val) || val > max_target_type || val < min_target_type) { errno = ERANGE; - return static_cast(UINT64_C(0)); + return static_cast(std::numeric_limits::max()); } auto sig {val.full_significand()}; auto expval {val.biased_exponent()}; const auto abs_exp_val {detail::make_positive_unsigned(expval)}; - if (abs_exp_val >= 38) - { - sig = 0; - } - else if (expval > 0) + if (expval > 0) { sig *= detail::pow10(expval); } diff --git a/test/roundtrip_decimal128.cpp b/test/roundtrip_decimal128.cpp index 3974193f3..df9d80817 100644 --- a/test/roundtrip_decimal128.cpp +++ b/test/roundtrip_decimal128.cpp @@ -61,20 +61,20 @@ void test_conversion_to_integer() else { // Bad conversion so we use zero - BOOST_TEST_EQ(static_cast(-one), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-one), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; BOOST_TEST_EQ(static_cast(half), static_cast(0)) && BOOST_TEST_EQ(errno, 0); @@ -89,13 +89,13 @@ void test_conversion_to_integer() std::mt19937_64 rng(42); std::uniform_int_distribution dist(-100, -20); errno = 0; - BOOST_TEST_EQ(static_cast(decimal128(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal128(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal128(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal128(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal128(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal128(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } template diff --git a/test/roundtrip_decimal128_fast.cpp b/test/roundtrip_decimal128_fast.cpp index 54948c320..bdc5e27e0 100644 --- a/test/roundtrip_decimal128_fast.cpp +++ b/test/roundtrip_decimal128_fast.cpp @@ -61,20 +61,20 @@ void test_conversion_to_integer() else { // Bad conversion so we use zero - BOOST_TEST_EQ(static_cast(-one), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-one), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; BOOST_TEST_EQ(static_cast(half), static_cast(0)) && BOOST_TEST_EQ(errno, 0); @@ -89,13 +89,13 @@ void test_conversion_to_integer() std::mt19937_64 rng(42); std::uniform_int_distribution dist(-100, -20); errno = 0; - BOOST_TEST_EQ(static_cast(decimal128_fast(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal128_fast(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal128_fast(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal128_fast(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal128_fast(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal128_fast(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } template diff --git a/test/roundtrip_decimal32.cpp b/test/roundtrip_decimal32.cpp index 19c694aa9..8b96dab88 100644 --- a/test/roundtrip_decimal32.cpp +++ b/test/roundtrip_decimal32.cpp @@ -54,20 +54,20 @@ void test_conversion_to_integer() else { // Bad conversion so we use zero - BOOST_TEST_EQ(static_cast(-one), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-one), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; BOOST_TEST_EQ(static_cast(half), static_cast(0)) && BOOST_TEST_EQ(errno, 0); @@ -82,13 +82,13 @@ void test_conversion_to_integer() std::mt19937_64 rng(42); std::uniform_int_distribution dist(-100, -20); errno = 0; - BOOST_TEST_EQ(static_cast(decimal32(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal32(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal32(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal32(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal32(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal32(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } template diff --git a/test/roundtrip_decimal32_fast.cpp b/test/roundtrip_decimal32_fast.cpp index 71eb9c243..5d1430d24 100644 --- a/test/roundtrip_decimal32_fast.cpp +++ b/test/roundtrip_decimal32_fast.cpp @@ -52,20 +52,20 @@ void test_conversion_to_integer() else { // Bad conversion so we use zero - BOOST_TEST_EQ(static_cast(-one), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-one), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; BOOST_TEST_EQ(static_cast(half), static_cast(0)) && BOOST_TEST_EQ(errno, 0); @@ -80,13 +80,13 @@ void test_conversion_to_integer() std::mt19937_64 rng(42); std::uniform_int_distribution dist(-100, -20); errno = 0; - BOOST_TEST_EQ(static_cast(decimal32_fast(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal32_fast(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal32_fast(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal32_fast(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal32_fast(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal32_fast(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } template diff --git a/test/roundtrip_decimal64.cpp b/test/roundtrip_decimal64.cpp index 09216bdd3..d3c7d17cd 100644 --- a/test/roundtrip_decimal64.cpp +++ b/test/roundtrip_decimal64.cpp @@ -51,20 +51,20 @@ void test_conversion_to_integer() else { // Bad conversion so we use zero - BOOST_TEST_EQ(static_cast(-one), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-one), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(-std::numeric_limits::infinity()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::quiet_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; - BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), static_cast(0)) && BOOST_TEST_EQ(errno, EINVAL); + BOOST_TEST_EQ(static_cast(std::numeric_limits::signaling_NaN()), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, EINVAL); errno = 0; BOOST_TEST_EQ(static_cast(half), static_cast(0)) && BOOST_TEST_EQ(errno, 0); @@ -79,13 +79,13 @@ void test_conversion_to_integer() std::mt19937_64 rng(42); std::uniform_int_distribution dist(-100, -20); errno = 0; - BOOST_TEST_EQ(static_cast(decimal64(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal64(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal64(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal64(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); errno = 0; - BOOST_TEST_EQ(static_cast(decimal64(dist(rng))), static_cast(0)) && BOOST_TEST_EQ(errno, ERANGE); + BOOST_TEST_EQ(static_cast(decimal64(dist(rng))), std::numeric_limits::max()) && BOOST_TEST_EQ(errno, ERANGE); } template