Skip to content

Commit 46760e6

Browse files
committed
Fix calculation of resultant significand with downward rounding
1 parent 3afb4d8 commit 46760e6

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

include/boost/decimal/detail/add_impl.hpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ constexpr auto add_impl(const T& lhs, const T& rhs) noexcept -> ReturnType
3838
promoted_sig_type big_lhs {lhs.full_significand()};
3939
promoted_sig_type big_rhs {rhs.full_significand()};
4040
auto lhs_exp {lhs.biased_exponent()};
41-
const auto rhs_exp {rhs.biased_exponent()};
41+
auto rhs_exp {rhs.biased_exponent()};
4242

4343
// Align to larger exponent
4444
if (lhs_exp != rhs_exp)
@@ -69,12 +69,35 @@ constexpr auto add_impl(const T& lhs, const T& rhs) noexcept -> ReturnType
6969
{
7070
// If we are subtracting even disparate numbers we need to round down
7171
// E.g. "5e+95"_DF - "4e-100"_DF == "4.999999e+95"_DF
72-
73-
using sig_type = typename T::significand_type;
74-
75-
return big_lhs != 0U && (lhs_exp > rhs_exp) ?
76-
ReturnType{lhs.full_significand() - static_cast<sig_type>(lhs.isneg() != rhs.isneg()), lhs.biased_exponent(), lhs.isneg()} :
77-
ReturnType{rhs.full_significand() - static_cast<sig_type>(lhs.isneg() != rhs.isneg()), rhs.biased_exponent(), rhs.isneg()};
72+
const auto use_lhs {big_lhs != 0U && (lhs_exp > rhs_exp)};
73+
74+
// Need to check for the case where we have 1e+95 - anything = 9.99999... without losing a nine
75+
if (use_lhs)
76+
{
77+
const auto removed_zeros {detail::remove_trailing_zeros(big_lhs)};
78+
if (removed_zeros.trimmed_number == 1U)
79+
{
80+
--big_lhs;
81+
big_lhs *= 10U;
82+
big_lhs += 9U;
83+
--lhs_exp;
84+
}
85+
}
86+
else
87+
{
88+
const auto removed_zeros {detail::remove_trailing_zeros(big_rhs)};
89+
if (removed_zeros.trimmed_number == 1U)
90+
{
91+
--big_rhs;
92+
big_rhs *= 10U;
93+
big_rhs += 9U;
94+
--rhs_exp;
95+
}
96+
}
97+
98+
return use_lhs ?
99+
ReturnType{big_lhs, lhs_exp, lhs.isneg()} :
100+
ReturnType{big_rhs, rhs_exp, rhs.isneg()};
78101
}
79102
else
80103
{

0 commit comments

Comments
 (0)