Skip to content

Commit

Permalink
Merge pull request #696 from cppalliance/sub64_128
Browse files Browse the repository at this point in the history
Improve 64 and 128 bit subtraction
  • Loading branch information
mborland authored Jul 2, 2024
2 parents b202107 + 50393e8 commit 2c81047
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 85 deletions.
21 changes: 2 additions & 19 deletions include/boost/decimal/decimal128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1594,13 +1594,6 @@ constexpr auto operator-(decimal128 lhs, decimal128 rhs) noexcept -> decimal128
}
#endif

if (!lhs.isneg() && rhs.isneg())
{
return lhs + (-rhs);
}

const bool abs_lhs_bigger {abs(lhs) > abs(rhs)};

auto sig_lhs {lhs.full_significand()};
auto exp_lhs {lhs.biased_exponent()};
detail::normalize<decimal128>(sig_lhs, exp_lhs);
Expand All @@ -1609,10 +1602,10 @@ constexpr auto operator-(decimal128 lhs, decimal128 rhs) noexcept -> decimal128
auto exp_rhs {rhs.biased_exponent()};
detail::normalize<decimal128>(sig_rhs, exp_rhs);

return {detail::d128_sub_impl<decimal128>(
return detail::d128_sub_impl<decimal128>(
sig_lhs, exp_lhs, lhs.isneg(),
sig_rhs, exp_rhs, rhs.isneg(),
abs_lhs_bigger)};
abs(lhs) > abs(rhs));
}

template <typename Integer>
Expand All @@ -1628,11 +1621,6 @@ constexpr auto operator-(decimal128 lhs, Integer rhs) noexcept
}
#endif

if (!lhs.isneg() && (rhs < 0))
{
return lhs + detail::make_positive_unsigned(rhs);
}

auto sig_rhs {static_cast<detail::uint128>(detail::make_positive_unsigned(rhs))};
const bool abs_lhs_bigger {abs(lhs) > sig_rhs};

Expand Down Expand Up @@ -1662,11 +1650,6 @@ constexpr auto operator-(Integer lhs, decimal128 rhs) noexcept
}
#endif

if (lhs >= 0 && rhs.isneg())
{
return lhs + (-rhs);
}

auto sig_lhs {static_cast<detail::uint128>(detail::make_positive_unsigned(lhs))};
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};

Expand Down
19 changes: 1 addition & 18 deletions include/boost/decimal/decimal128_fast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,17 +826,10 @@ constexpr auto operator-(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d
}
#endif

if (!lhs.isneg() && rhs.isneg())
{
return lhs + (-rhs);
}

const bool abs_lhs_bigger {abs(lhs) > abs(rhs)};

return detail::d128_sub_impl<decimal128_fast>(
lhs.significand_, lhs.biased_exponent(), lhs.sign_,
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
abs_lhs_bigger);
abs(lhs) > abs(rhs));
}

template <typename Integer>
Expand All @@ -852,11 +845,6 @@ constexpr auto operator-(decimal128_fast lhs, Integer rhs) noexcept
}
#endif

if (!lhs.isneg() && (rhs < 0))
{
return lhs + detail::make_positive_unsigned(rhs);
}

auto sig_rhs {static_cast<detail::uint128>(detail::make_positive_unsigned(rhs))};
const bool abs_lhs_bigger {abs(lhs) > sig_rhs};

Expand All @@ -882,11 +870,6 @@ constexpr auto operator-(Integer lhs, decimal128_fast rhs) noexcept
}
#endif

if (lhs >= 0 && rhs.isneg())
{
return lhs + (-rhs);
}

auto sig_lhs {static_cast<detail::uint128>(detail::make_positive_unsigned(lhs))};
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};

Expand Down
15 changes: 0 additions & 15 deletions include/boost/decimal/decimal64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1257,11 +1257,6 @@ constexpr auto operator-(decimal64 lhs, decimal64 rhs) noexcept -> decimal64
}
#endif

if (!lhs.isneg() && rhs.isneg())
{
return lhs + (-rhs);
}

const bool abs_lhs_bigger {abs(lhs) > abs(rhs)};

auto sig_lhs {lhs.full_significand()};
Expand Down Expand Up @@ -1291,11 +1286,6 @@ constexpr auto operator-(decimal64 lhs, Integer rhs) noexcept
}
#endif

if (!lhs.isneg() && (rhs < 0))
{
return lhs + detail::make_positive_unsigned(rhs);
}

auto sig_rhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(rhs))};
const bool abs_lhs_bigger {abs(lhs) > sig_rhs};

Expand Down Expand Up @@ -1326,11 +1316,6 @@ constexpr auto operator-(Integer lhs, decimal64 rhs) noexcept
}
#endif

if (lhs >= 0 && rhs.isneg())
{
return lhs + (-rhs);
}

auto sig_lhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(lhs))};
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};

Expand Down
29 changes: 6 additions & 23 deletions include/boost/decimal/decimal64_fast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -939,18 +939,11 @@ constexpr auto operator-(decimal64_fast lhs, decimal64_fast rhs) noexcept -> dec
}
#endif

if (!lhs.isneg() && rhs.isneg())
{
return lhs + (-rhs);
}

const bool abs_lhs_bigger {abs(lhs) > abs(rhs)};

return detail::d64_sub_impl<decimal64_fast>(
lhs.significand_, lhs.biased_exponent(), lhs.sign_,
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
abs_lhs_bigger
);
abs(lhs) > abs(rhs)
);
}

template <typename Integer>
Expand All @@ -967,11 +960,6 @@ constexpr auto operator-(decimal64_fast lhs, Integer rhs) noexcept
}
#endif

if (!lhs.isneg() && (rhs < 0))
{
return lhs + detail::make_positive_unsigned(rhs);
}

auto sig_rhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(rhs))};
const bool abs_lhs_bigger {abs(lhs) > detail::make_positive_unsigned(rhs)};

Expand All @@ -980,8 +968,8 @@ constexpr auto operator-(decimal64_fast lhs, Integer rhs) noexcept
const auto final_sig_rhs {static_cast<decimal64_fast::significand_type>(sig_rhs)};

return detail::d64_sub_impl<decimal64_fast>(lhs.significand_, lhs.biased_exponent(), lhs.sign_,
final_sig_rhs, exp_rhs, (rhs < 0),
abs_lhs_bigger);
final_sig_rhs, exp_rhs, (rhs < 0),
abs_lhs_bigger);
}

template <typename Integer>
Expand All @@ -998,11 +986,6 @@ constexpr auto operator-(Integer lhs, decimal64_fast rhs) noexcept
}
#endif

if (lhs >= 0 && rhs.isneg())
{
return lhs + (-rhs);
}

auto sig_lhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(lhs))};
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};

Expand All @@ -1011,8 +994,8 @@ constexpr auto operator-(Integer lhs, decimal64_fast rhs) noexcept
const auto final_sig_lhs {static_cast<decimal64_fast::significand_type>(sig_lhs)};

return detail::d64_sub_impl<decimal64_fast>(final_sig_lhs, exp_lhs, (lhs < 0),
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
abs_lhs_bigger);
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
abs_lhs_bigger);
}

constexpr auto operator*(decimal64_fast lhs, decimal64_fast rhs) noexcept -> decimal64_fast
Expand Down
18 changes: 8 additions & 10 deletions include/boost/decimal/detail/sub_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ constexpr auto d64_sub_impl(T lhs_sig, U lhs_exp, bool lhs_sign,

if (delta_exp > 1)
{
sig_smaller /= pow10<std::remove_reference_t<decltype(sig_smaller)>>(delta_exp - 1);
sig_smaller /= pow10<sub_type>(delta_exp - 1);
delta_exp = 1;
}

Expand All @@ -140,8 +140,7 @@ constexpr auto d64_sub_impl(T lhs_sig, U lhs_exp, bool lhs_sign,

// Both of the significands are less than 9'999'999'999'999'999, so we can safely
// cast them to signed 64-bit ints to calculate the new significand
const sub_type new_sig {rhs_sign && !lhs_sign ? signed_sig_lhs + signed_sig_rhs :
signed_sig_lhs - signed_sig_rhs};
const auto new_sig {signed_sig_lhs - signed_sig_rhs};

const auto new_exp {abs_lhs_bigger ? lhs_exp : rhs_exp};
const auto new_sign {new_sig < 0};
Expand All @@ -150,10 +149,9 @@ constexpr auto d64_sub_impl(T lhs_sig, U lhs_exp, bool lhs_sign,
return {res_sig, new_exp, new_sign};
}

template <typename ReturnType, BOOST_DECIMAL_INTEGRAL T1, BOOST_DECIMAL_INTEGRAL U1,
BOOST_DECIMAL_INTEGRAL T2, BOOST_DECIMAL_INTEGRAL U2>
constexpr auto d128_sub_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign,
T2 rhs_sig, U2 rhs_exp, bool rhs_sign,
template <typename ReturnType, BOOST_DECIMAL_INTEGRAL T, BOOST_DECIMAL_INTEGRAL U>
constexpr auto d128_sub_impl(T lhs_sig, U lhs_exp, bool lhs_sign,
T rhs_sig, U rhs_exp, bool rhs_sign,
bool abs_lhs_bigger) noexcept -> ReturnType
{
#if defined(BOOST_DECIMAL_HAS_INT128) && (!defined(__clang_major__) || __clang_major__ > 13)
Expand All @@ -172,8 +170,8 @@ constexpr auto d128_sub_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign,
// we return the larger of the two
//
// e.g. 1e20 - 1e-20 = 1e20
return abs_lhs_bigger ? ReturnType{detail::shrink_significand<detail::uint128>(lhs_sig, lhs_exp), lhs_exp, false} :
ReturnType{detail::shrink_significand<detail::uint128>(rhs_sig, rhs_exp), rhs_exp, true};
return abs_lhs_bigger ? ReturnType{lhs_sig, lhs_exp, false} :
ReturnType{rhs_sig, rhs_exp, true};
}

// The two numbers can be subtracted together without special handling
Expand Down Expand Up @@ -213,7 +211,7 @@ constexpr auto d128_sub_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign,
const auto signed_sig_lhs {detail::make_signed_value(static_cast<unsigned_sub_type>(lhs_sig), lhs_sign)};
const auto signed_sig_rhs {detail::make_signed_value(static_cast<unsigned_sub_type>(rhs_sig), rhs_sign)};

const auto new_sig {rhs_sign && !lhs_sign ? signed_sig_lhs + signed_sig_rhs : signed_sig_lhs - signed_sig_rhs};
const auto new_sig {signed_sig_lhs - signed_sig_rhs};

const auto new_exp {abs_lhs_bigger ? lhs_exp : rhs_exp};
const auto new_sign {new_sig < 0};
Expand Down

0 comments on commit 2c81047

Please sign in to comment.