Skip to content

Commit 2c81047

Browse files
authored
Merge pull request #696 from cppalliance/sub64_128
Improve 64 and 128 bit subtraction
2 parents b202107 + 50393e8 commit 2c81047

File tree

5 files changed

+17
-85
lines changed

5 files changed

+17
-85
lines changed

include/boost/decimal/decimal128.hpp

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,13 +1594,6 @@ constexpr auto operator-(decimal128 lhs, decimal128 rhs) noexcept -> decimal128
15941594
}
15951595
#endif
15961596

1597-
if (!lhs.isneg() && rhs.isneg())
1598-
{
1599-
return lhs + (-rhs);
1600-
}
1601-
1602-
const bool abs_lhs_bigger {abs(lhs) > abs(rhs)};
1603-
16041597
auto sig_lhs {lhs.full_significand()};
16051598
auto exp_lhs {lhs.biased_exponent()};
16061599
detail::normalize<decimal128>(sig_lhs, exp_lhs);
@@ -1609,10 +1602,10 @@ constexpr auto operator-(decimal128 lhs, decimal128 rhs) noexcept -> decimal128
16091602
auto exp_rhs {rhs.biased_exponent()};
16101603
detail::normalize<decimal128>(sig_rhs, exp_rhs);
16111604

1612-
return {detail::d128_sub_impl<decimal128>(
1605+
return detail::d128_sub_impl<decimal128>(
16131606
sig_lhs, exp_lhs, lhs.isneg(),
16141607
sig_rhs, exp_rhs, rhs.isneg(),
1615-
abs_lhs_bigger)};
1608+
abs(lhs) > abs(rhs));
16161609
}
16171610

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

1631-
if (!lhs.isneg() && (rhs < 0))
1632-
{
1633-
return lhs + detail::make_positive_unsigned(rhs);
1634-
}
1635-
16361624
auto sig_rhs {static_cast<detail::uint128>(detail::make_positive_unsigned(rhs))};
16371625
const bool abs_lhs_bigger {abs(lhs) > sig_rhs};
16381626

@@ -1662,11 +1650,6 @@ constexpr auto operator-(Integer lhs, decimal128 rhs) noexcept
16621650
}
16631651
#endif
16641652

1665-
if (lhs >= 0 && rhs.isneg())
1666-
{
1667-
return lhs + (-rhs);
1668-
}
1669-
16701653
auto sig_lhs {static_cast<detail::uint128>(detail::make_positive_unsigned(lhs))};
16711654
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};
16721655

include/boost/decimal/decimal128_fast.hpp

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -826,17 +826,10 @@ constexpr auto operator-(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d
826826
}
827827
#endif
828828

829-
if (!lhs.isneg() && rhs.isneg())
830-
{
831-
return lhs + (-rhs);
832-
}
833-
834-
const bool abs_lhs_bigger {abs(lhs) > abs(rhs)};
835-
836829
return detail::d128_sub_impl<decimal128_fast>(
837830
lhs.significand_, lhs.biased_exponent(), lhs.sign_,
838831
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
839-
abs_lhs_bigger);
832+
abs(lhs) > abs(rhs));
840833
}
841834

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

855-
if (!lhs.isneg() && (rhs < 0))
856-
{
857-
return lhs + detail::make_positive_unsigned(rhs);
858-
}
859-
860848
auto sig_rhs {static_cast<detail::uint128>(detail::make_positive_unsigned(rhs))};
861849
const bool abs_lhs_bigger {abs(lhs) > sig_rhs};
862850

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

885-
if (lhs >= 0 && rhs.isneg())
886-
{
887-
return lhs + (-rhs);
888-
}
889-
890873
auto sig_lhs {static_cast<detail::uint128>(detail::make_positive_unsigned(lhs))};
891874
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};
892875

include/boost/decimal/decimal64.hpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,11 +1257,6 @@ constexpr auto operator-(decimal64 lhs, decimal64 rhs) noexcept -> decimal64
12571257
}
12581258
#endif
12591259

1260-
if (!lhs.isneg() && rhs.isneg())
1261-
{
1262-
return lhs + (-rhs);
1263-
}
1264-
12651260
const bool abs_lhs_bigger {abs(lhs) > abs(rhs)};
12661261

12671262
auto sig_lhs {lhs.full_significand()};
@@ -1291,11 +1286,6 @@ constexpr auto operator-(decimal64 lhs, Integer rhs) noexcept
12911286
}
12921287
#endif
12931288

1294-
if (!lhs.isneg() && (rhs < 0))
1295-
{
1296-
return lhs + detail::make_positive_unsigned(rhs);
1297-
}
1298-
12991289
auto sig_rhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(rhs))};
13001290
const bool abs_lhs_bigger {abs(lhs) > sig_rhs};
13011291

@@ -1326,11 +1316,6 @@ constexpr auto operator-(Integer lhs, decimal64 rhs) noexcept
13261316
}
13271317
#endif
13281318

1329-
if (lhs >= 0 && rhs.isneg())
1330-
{
1331-
return lhs + (-rhs);
1332-
}
1333-
13341319
auto sig_lhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(lhs))};
13351320
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};
13361321

include/boost/decimal/decimal64_fast.hpp

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -939,18 +939,11 @@ constexpr auto operator-(decimal64_fast lhs, decimal64_fast rhs) noexcept -> dec
939939
}
940940
#endif
941941

942-
if (!lhs.isneg() && rhs.isneg())
943-
{
944-
return lhs + (-rhs);
945-
}
946-
947-
const bool abs_lhs_bigger {abs(lhs) > abs(rhs)};
948-
949942
return detail::d64_sub_impl<decimal64_fast>(
950943
lhs.significand_, lhs.biased_exponent(), lhs.sign_,
951944
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
952-
abs_lhs_bigger
953-
);
945+
abs(lhs) > abs(rhs)
946+
);
954947
}
955948

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

970-
if (!lhs.isneg() && (rhs < 0))
971-
{
972-
return lhs + detail::make_positive_unsigned(rhs);
973-
}
974-
975963
auto sig_rhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(rhs))};
976964
const bool abs_lhs_bigger {abs(lhs) > detail::make_positive_unsigned(rhs)};
977965

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

982970
return detail::d64_sub_impl<decimal64_fast>(lhs.significand_, lhs.biased_exponent(), lhs.sign_,
983-
final_sig_rhs, exp_rhs, (rhs < 0),
984-
abs_lhs_bigger);
971+
final_sig_rhs, exp_rhs, (rhs < 0),
972+
abs_lhs_bigger);
985973
}
986974

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

1001-
if (lhs >= 0 && rhs.isneg())
1002-
{
1003-
return lhs + (-rhs);
1004-
}
1005-
1006989
auto sig_lhs {static_cast<promoted_significand_type>(detail::make_positive_unsigned(lhs))};
1007990
const bool abs_lhs_bigger {sig_lhs > abs(rhs)};
1008991

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

1013996
return detail::d64_sub_impl<decimal64_fast>(final_sig_lhs, exp_lhs, (lhs < 0),
1014-
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
1015-
abs_lhs_bigger);
997+
rhs.significand_, rhs.biased_exponent(), rhs.sign_,
998+
abs_lhs_bigger);
1016999
}
10171000

10181001
constexpr auto operator*(decimal64_fast lhs, decimal64_fast rhs) noexcept -> decimal64_fast

include/boost/decimal/detail/sub_impl.hpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ constexpr auto d64_sub_impl(T lhs_sig, U lhs_exp, bool lhs_sign,
128128

129129
if (delta_exp > 1)
130130
{
131-
sig_smaller /= pow10<std::remove_reference_t<decltype(sig_smaller)>>(delta_exp - 1);
131+
sig_smaller /= pow10<sub_type>(delta_exp - 1);
132132
delta_exp = 1;
133133
}
134134

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

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

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

153-
template <typename ReturnType, BOOST_DECIMAL_INTEGRAL T1, BOOST_DECIMAL_INTEGRAL U1,
154-
BOOST_DECIMAL_INTEGRAL T2, BOOST_DECIMAL_INTEGRAL U2>
155-
constexpr auto d128_sub_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign,
156-
T2 rhs_sig, U2 rhs_exp, bool rhs_sign,
152+
template <typename ReturnType, BOOST_DECIMAL_INTEGRAL T, BOOST_DECIMAL_INTEGRAL U>
153+
constexpr auto d128_sub_impl(T lhs_sig, U lhs_exp, bool lhs_sign,
154+
T rhs_sig, U rhs_exp, bool rhs_sign,
157155
bool abs_lhs_bigger) noexcept -> ReturnType
158156
{
159157
#if defined(BOOST_DECIMAL_HAS_INT128) && (!defined(__clang_major__) || __clang_major__ > 13)
@@ -172,8 +170,8 @@ constexpr auto d128_sub_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign,
172170
// we return the larger of the two
173171
//
174172
// e.g. 1e20 - 1e-20 = 1e20
175-
return abs_lhs_bigger ? ReturnType{detail::shrink_significand<detail::uint128>(lhs_sig, lhs_exp), lhs_exp, false} :
176-
ReturnType{detail::shrink_significand<detail::uint128>(rhs_sig, rhs_exp), rhs_exp, true};
173+
return abs_lhs_bigger ? ReturnType{lhs_sig, lhs_exp, false} :
174+
ReturnType{rhs_sig, rhs_exp, true};
177175
}
178176

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

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

218216
const auto new_exp {abs_lhs_bigger ? lhs_exp : rhs_exp};
219217
const auto new_sign {new_sig < 0};

0 commit comments

Comments
 (0)