Skip to content

Commit

Permalink
Fix handling of signed 0s
Browse files Browse the repository at this point in the history
  • Loading branch information
mborland committed Jun 25, 2024
1 parent 7255a0a commit 5bc4459
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 25 deletions.
2 changes: 1 addition & 1 deletion include/boost/decimal/decimal64_fast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ constexpr auto operator*(decimal64_fast lhs, decimal64_fast rhs) noexcept -> dec
auto res_sig {static_cast<unsigned_int128_type>(lhs.significand_) * static_cast<unsigned_int128_type>(rhs.significand_)};

auto res_exp {lhs.biased_exponent() + rhs.biased_exponent()};
bool sign {lhs.sign_ != rhs.sign_ && res_sig != 0};
bool sign {lhs.sign_ != rhs.sign_};

return {res_sig, res_exp, sign};

Expand Down
27 changes: 3 additions & 24 deletions include/boost/decimal/detail/mul_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto mul_impl(T lhs_sig, U lhs_exp, bool lh
const auto res_sig {static_cast<mul_type>(lhs_sig) * static_cast<mul_type>(rhs_sig)};
const auto res_exp {lhs_exp + rhs_exp};

return {res_sig, res_exp, lhs_sign != rhs_sign && res_sig != static_cast<mul_type>(0)};
return {res_sig, res_exp, lhs_sign != rhs_sign};
}

template <typename ReturnType, typename T, typename U>
Expand All @@ -51,7 +51,7 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto mul_impl(T lhs_sig, U lhs_exp, bool lh
auto res_sig {(static_cast<mul_type>(lhs_sig) * static_cast<mul_type>(rhs_sig)) / pow10(static_cast<mul_type>(5))};
auto res_exp {lhs_exp + rhs_exp + static_cast<U>(5)};

return {static_cast<std::uint32_t>(res_sig), res_exp, lhs_sign != rhs_sign && res_sig != static_cast<mul_type>(0)};
return {static_cast<std::uint32_t>(res_sig), res_exp, lhs_sign != rhs_sign};
}

template <typename ReturnType, typename T, typename U>
Expand Down Expand Up @@ -92,11 +92,6 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto mul_impl(T lhs_sig, U lhs_exp, bool lh
<< "\nres exp: " << res_exp << std::endl;
#endif

if (res_sig_32 == 0)
{
sign = false;
}

return {res_sig_32, res_exp, sign};
}

Expand Down Expand Up @@ -124,7 +119,7 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto d64_mul_impl(T lhs_sig, U lhs_exp, boo
auto res_sig {(static_cast<unsigned_int128_type>(lhs_sig) * static_cast<unsigned_int128_type>(rhs_sig)) / pow10(static_cast<unsigned_int128_type>(13))};
auto res_exp {lhs_exp + rhs_exp + static_cast<U>(13)};

return {static_cast<std::uint64_t>(res_sig), res_exp, lhs_sign != rhs_sign && res_sig != 0};
return {static_cast<std::uint64_t>(res_sig), res_exp, lhs_sign != rhs_sign};
}

template <typename ReturnType, BOOST_DECIMAL_INTEGRAL T, BOOST_DECIMAL_INTEGRAL U>
Expand Down Expand Up @@ -167,12 +162,6 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto d64_mul_impl(T lhs_sig, U lhs_exp, boo
<< "\nres exp: " << res_exp << std::endl;
#endif

// Always return positive zero
if (res_sig_64 == 0)
{
sign = false;
}

return {res_sig_64, res_exp, sign};
}

Expand All @@ -196,11 +185,6 @@ constexpr auto d128_mul_impl(T1 lhs_sig, std::int32_t lhs_exp, bool lhs_sign,
res_exp += digit_delta;
}

if (res_sig == 0)
{
sign = false;
}

BOOST_DECIMAL_ASSERT(res_sig.high == uint128(0,0));
return {res_sig.low, res_exp, sign};
}
Expand All @@ -224,11 +208,6 @@ constexpr auto d128_fast_mul_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign,
res_sig /= detail::pow10(static_cast<uint256_t>(sig_dig - max_dig));
res_exp += sig_dig - max_dig;

if (res_sig == 0)
{
sign = false;
}

BOOST_DECIMAL_ASSERT(res_sig.high == uint128(0,0));
return {res_sig.low, res_exp, sign};
}
Expand Down
12 changes: 12 additions & 0 deletions test/random_decimal128_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ void random_multiplication(T lower, T upper)
const decimal128 res = dec1 * dec2;
const auto res_int = static_cast<T>(res);

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res_int, val1 * val2))
{
// LCOV_EXCL_START
Expand Down Expand Up @@ -286,6 +292,12 @@ void random_mixed_multiplication(T lower, T upper)
const decimal128 res {dec1 * dec2};
const T res_int {static_cast<T>(res)};

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res_int, val1 * val2))
{
// LCOV_EXCL_START
Expand Down
12 changes: 12 additions & 0 deletions test/random_decimal32_fast_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ void random_multiplication(T lower, T upper)
const decimal32_fast res {dec1 * dec2};
const decimal32_fast res_int {val1 * val2};

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res, res_int))
{
// LCOV_EXCL_START
Expand Down Expand Up @@ -284,6 +290,12 @@ void random_mixed_multiplication(T lower, T upper)
const decimal32_fast res {dec1 * dec2};
const decimal32_fast res_int {val1 * val2};

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res, res_int))
{
// LCOV_EXCL_START
Expand Down
12 changes: 12 additions & 0 deletions test/random_decimal32_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,12 @@ void random_multiplication(T lower, T upper)
const decimal32 res {dec1 * dec2};
const decimal32 res_int {val1 * val2};

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res, res_int))
{
// LCOV_EXCL_START
Expand Down Expand Up @@ -284,6 +290,12 @@ void random_mixed_multiplication(T lower, T upper)
const decimal32 res {dec1 * dec2};
const decimal32 res_int {val1 * val2};

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res, res_int))
{
// LCOV_EXCL_START
Expand Down
12 changes: 12 additions & 0 deletions test/random_decimal64_fast_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ void random_multiplication(T lower, T upper)
const decimal64_fast res {dec1 * dec2};
const decimal64_fast res_int {val1 * val2};

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res, res_int))
{
// LCOV_EXCL_START
Expand Down Expand Up @@ -275,6 +281,12 @@ void random_mixed_multiplication(T lower, T upper)
const decimal64_fast res {dec1 * dec2};
const decimal64_fast res_int {val1 * val2};

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res, res_int))
{
// LCOV_EXCL_START
Expand Down
6 changes: 6 additions & 0 deletions test/random_decimal64_math.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,12 @@ void random_multiplication(T lower, T upper)
const decimal64 res {dec1 * dec2};
const decimal64 res_int {val1 * val2};

if (val1 * val2 == 0)
{
// Integers don't have signed 0 but decimal does
continue;
}

if (!BOOST_TEST_EQ(res, res_int))
{
// LCOV_EXCL_START
Expand Down

0 comments on commit 5bc4459

Please sign in to comment.