From 827663a25a14967a6f618b63b7f14b02cf3168d2 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 14 Jan 2026 09:24:17 -0500 Subject: [PATCH 1/3] Add comparison of u256 and std::uint64_t --- include/boost/decimal/detail/u256.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/decimal/detail/u256.hpp b/include/boost/decimal/detail/u256.hpp index edfd7eab3..0dac46b42 100644 --- a/include/boost/decimal/detail/u256.hpp +++ b/include/boost/decimal/detail/u256.hpp @@ -373,6 +373,11 @@ constexpr bool operator>(const u256& lhs, const int128::uint128_t& rhs) noexcept return lhs[3] > 0U || lhs[2] > 0U || int128::uint128_t{lhs[1], lhs[0]} > rhs; } +constexpr bool operator>(const u256& lhs, const std::uint64_t rhs) noexcept +{ + return lhs[3] != 0U || lhs[2] != 0U || lhs[1] != 0U || lhs[0] > rhs; +} + //===================================== // Greater Equal Operator //===================================== From 6e808edec327962ea040019ab69c5609b1957e44 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 14 Jan 2026 09:24:29 -0500 Subject: [PATCH 2/3] Use new d128 addition impl in d64 fma --- include/boost/decimal/detail/cmath/fma.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/decimal/detail/cmath/fma.hpp b/include/boost/decimal/detail/cmath/fma.hpp index 50230b834..8c9ede307 100644 --- a/include/boost/decimal/detail/cmath/fma.hpp +++ b/include/boost/decimal/detail/cmath/fma.hpp @@ -116,7 +116,7 @@ constexpr auto d64_fma_impl(T x, T y, T z) noexcept -> T detail::expand_significand(z_components.sig, z_components.exp); detail::expand_significand(first_res.sig, first_res.exp); - return detail::d128_add_impl(first_res, z_components, abs(complete_lhs) > abs(z)); + return detail::d128_add_impl_new(first_res, z_components); } template From 21f218e640cdbc8dba2f172f27fb5bf1bec7fe96 Mon Sep 17 00:00:00 2001 From: Matt Borland Date: Wed, 14 Jan 2026 09:25:34 -0500 Subject: [PATCH 3/3] Remove now unused d128 addition impl --- include/boost/decimal/detail/add_impl.hpp | 200 ---------------------- 1 file changed, 200 deletions(-) diff --git a/include/boost/decimal/detail/add_impl.hpp b/include/boost/decimal/detail/add_impl.hpp index a2e834d57..813a65e75 100644 --- a/include/boost/decimal/detail/add_impl.hpp +++ b/include/boost/decimal/detail/add_impl.hpp @@ -375,210 +375,10 @@ constexpr auto d128_add_impl_new(const T& lhs, const T& rhs) noexcept -> ReturnT return ReturnType{return_sig, lhs_exp, return_sign}; } -template -constexpr auto d128_add_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 -{ - auto delta_exp {lhs_exp > rhs_exp ? lhs_exp - rhs_exp : rhs_exp - lhs_exp}; - - #ifdef BOOST_DECIMAL_DEBUG_ADD - std::cerr << "Starting sig lhs: " << lhs_sig - << "\nStarting exp lhs: " << lhs_exp - << "\nStarting sig rhs: " << rhs_sig - << "\nStarting exp rhs: " << rhs_exp << std::endl; - #endif - - if (delta_exp > detail::precision_v + 1) - { - // If the difference in exponents is more than the digits of accuracy - // we return the larger of the two - // - // e.g. 1e20 + 1e-20 = 1e20 - - auto round {_boost_decimal_global_rounding_mode}; - - #ifndef BOOST_DECIMAL_NO_CONSTEVAL_DETECTION - - if (!BOOST_DECIMAL_IS_CONSTANT_EVALUATED(lhs)) - { - round = fegetround(); - } - - #endif - - if (BOOST_DECIMAL_LIKELY(round != rounding_mode::fe_dec_downward && round != rounding_mode::fe_dec_upward)) - { - return lhs_sig != 0U && (lhs_exp > rhs_exp) ? - ReturnType{lhs_sig, lhs_exp, lhs_sign} : - ReturnType{rhs_sig, rhs_exp, rhs_sign}; - } - else if (round == rounding_mode::fe_dec_downward) - { - // If we are subtracting even disparate numbers we need to round down - // E.g. "5e+95"_DF - "4e-100"_DF == "4.999999e+95"_DF - const auto use_lhs {lhs_sig != 0U && (lhs_exp > rhs_exp)}; - - // Need to check for the case where we have 1e+95 - anything = 9.99999... without losing a nine - if (use_lhs) - { - if (rhs_sig != 0U && (lhs_sign != rhs_sign)) - { - if (is_power_of_10(lhs_sig)) - { - --lhs_sig; - lhs_sig *= 10U; - lhs_sig += 9U; - --lhs_exp; - } - else - { - --lhs_sig; - } - } - - return ReturnType{lhs_sig, lhs_exp, lhs_sign}; - } - else - { - if (lhs_sig != 0U && (lhs_sign != rhs_sign)) - { - if (is_power_of_10(rhs_sig)) - { - --rhs_sig; - rhs_sig *= 10U; - rhs_sig += 9U; - --rhs_exp; - } - else - { - --rhs_sig; - } - } - - return ReturnType{rhs_sig, rhs_exp, rhs_sign}; - } - } - else - { - // rounding mode == fe_dec_upward - // Unconditionally round up. Could be 5e+95 + 4e-100 -> 5.000001e+95 - const bool use_lhs {lhs_sig != 0U && (lhs_exp > rhs_exp)}; - - if (use_lhs) - { - if (rhs_sig != 0U) - { - if (lhs_sign != rhs_sign) - { - if (is_power_of_10(lhs_sig)) - { - --lhs_sig; - lhs_sig *= 10U; - lhs_sig += 9U; - --lhs_exp; - } - else - { - --lhs_sig; - } - } - else - { - ++lhs_sig; - } - } - - return ReturnType{lhs_sig, lhs_exp, lhs_sign} ; - } - else - { - if (lhs_sig != 0U) - { - if (rhs_sign != lhs_sign) - { - --rhs_sig; - rhs_sig *= 10U; - rhs_sig += 9U; - --rhs_exp; - } - else - { - ++rhs_sig; - } - } - - return ReturnType{rhs_sig, rhs_exp, rhs_sign}; - } - } - } - - // The two numbers can be added together without special handling - // - // If we can add to the lhs sig rather than dividing we can save some precision - // 32-bit signed int can have 9 digits and our normalized significand has 7 - - auto& sig_bigger {abs_lhs_bigger ? lhs_sig : rhs_sig}; - auto& exp_bigger {abs_lhs_bigger ? lhs_exp : rhs_exp}; - auto& sig_smaller {abs_lhs_bigger ? rhs_sig : lhs_sig}; - auto& sign_smaller {abs_lhs_bigger ? rhs_sign : lhs_sign}; - auto& sign_bigger {abs_lhs_bigger ? lhs_sign : rhs_sign}; - - if (delta_exp <= 3) - { - sig_bigger *= pow10(static_cast(delta_exp)); - exp_bigger -= delta_exp; - delta_exp = 0; - } - else - { - sig_bigger *= 1000U; - delta_exp -= 3; - exp_bigger -= 3; - - if (delta_exp > 1) - { - sig_smaller /= pow10(static_cast(delta_exp - 1)); - delta_exp = 1; - } - - if (delta_exp == 1) - { - detail::fenv_round(sig_smaller, sign_smaller); - } - } - - // Cast the results to signed types so that we can apply a sign at the end if necessary - // Both of the significands are maximally 24 bits, so they fit into a 32-bit signed type just fine - auto signed_sig_lhs {detail::make_signed_value(sig_bigger, sign_bigger)}; - auto signed_sig_rhs {detail::make_signed_value(sig_smaller, sign_smaller)}; - - const auto new_sig {signed_sig_lhs + signed_sig_rhs}; - const auto new_exp {exp_bigger}; - const auto new_sign {new_sig < 0}; - const auto res_sig {detail::make_positive_unsigned(new_sig)}; - - #ifdef BOOST_DECIMAL_DEBUG_ADD - std::cerr << "Final sig lhs: " << lhs_sig - << "\nFinal sig rhs: " << rhs_sig - << "\nResult sig: " << new_sig << std::endl; - #endif - - return {res_sig, new_exp, new_sign}; -} - #ifdef _MSC_VER # pragma warning(pop) #endif -template -constexpr auto d128_add_impl(const decimal128_t_components& lhs, const decimal128_t_components& rhs, const bool abs_lhs_bigger) noexcept -> ReturnType -{ - return d128_add_impl(lhs.sig, lhs.exp, lhs.sign, - rhs.sig, rhs.exp, rhs.sign, - abs_lhs_bigger); -} - } // namespace detail } // namespace decimal } // namespace boost