Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 0 additions & 200 deletions include/boost/decimal/detail/add_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename ReturnType, typename T, typename U>
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<decimal128_t> + 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<boost::int128::uint128_t>(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<boost::int128::uint128_t>(delta_exp - 1));
delta_exp = 1;
}

if (delta_exp == 1)
{
detail::fenv_round<decimal128_t>(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 <typename ReturnType>
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<ReturnType>(lhs.sig, lhs.exp, lhs.sign,
rhs.sig, rhs.exp, rhs.sign,
abs_lhs_bigger);
}

} // namespace detail
} // namespace decimal
} // namespace boost
Expand Down
2 changes: 1 addition & 1 deletion include/boost/decimal/detail/cmath/fma.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ constexpr auto d64_fma_impl(T x, T y, T z) noexcept -> T
detail::expand_significand<promoted_type>(z_components.sig, z_components.exp);
detail::expand_significand<promoted_type>(first_res.sig, first_res.exp);

return detail::d128_add_impl<T>(first_res, z_components, abs(complete_lhs) > abs(z));
return detail::d128_add_impl_new<T>(first_res, z_components);
}

template <bool, BOOST_DECIMAL_DECIMAL_FLOATING_TYPE T>
Expand Down
5 changes: 5 additions & 0 deletions include/boost/decimal/detail/u256.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
//=====================================
Expand Down