@@ -17,6 +17,72 @@ namespace boost {
1717namespace decimal {
1818namespace detail {
1919
20+ template <typename ReturnType, typename T, typename U>
21+ BOOST_DECIMAL_FORCE_INLINE constexpr auto new_sub_impl (T lhs_sig, U lhs_exp, bool lhs_sign,
22+ T rhs_sig, U rhs_exp, bool rhs_sign,
23+ bool abs_lhs_bigger) noexcept -> ReturnType
24+ {
25+ using sub_type = std::int_fast32_t ;
26+
27+ auto delta_exp {lhs_exp > rhs_exp ? lhs_exp - rhs_exp : rhs_exp - lhs_exp};
28+ auto signed_sig_lhs {detail::make_signed_value (static_cast <sub_type>(lhs_sig), lhs_sign)};
29+ auto signed_sig_rhs {detail::make_signed_value (static_cast <sub_type>(rhs_sig), rhs_sign)};
30+
31+ if (delta_exp > detail::precision + 1 )
32+ {
33+ // If the difference in exponents is more than the digits of accuracy
34+ // we return the larger of the two
35+ //
36+ // e.g. 1e20 - 1e-20 = 1e20
37+ return abs_lhs_bigger ? ReturnType{lhs_sig, lhs_exp, false } :
38+ ReturnType{rhs_sig, rhs_exp, true };
39+ }
40+
41+ // The two numbers can be subtracted together without special handling
42+
43+ auto & sig_bigger {abs_lhs_bigger ? signed_sig_lhs : signed_sig_rhs};
44+ auto & exp_bigger {abs_lhs_bigger ? lhs_exp : rhs_exp};
45+ auto & sig_smaller {abs_lhs_bigger ? signed_sig_rhs : signed_sig_lhs};
46+ auto & smaller_sign {abs_lhs_bigger ? rhs_sign : lhs_sign};
47+
48+ if (delta_exp == 1 )
49+ {
50+ sig_bigger *= 10 ;
51+ --delta_exp;
52+ --exp_bigger;
53+ }
54+ else
55+ {
56+ if (delta_exp >= 2 )
57+ {
58+ sig_bigger *= 100 ;
59+ delta_exp -= 2 ;
60+ exp_bigger -= 2 ;
61+ }
62+
63+ if (delta_exp > 1 )
64+ {
65+ sig_smaller /= pow10 (delta_exp - 1 );
66+ delta_exp = 1 ;
67+ }
68+
69+ if (delta_exp == 1 )
70+ {
71+ detail::fenv_round (sig_smaller, smaller_sign);
72+ }
73+ }
74+
75+ // Both of the significands are less than 9'999'999, so we can safely
76+ // cast them to signed 32-bit ints to calculate the new significand
77+ const auto new_sig {signed_sig_lhs - signed_sig_rhs};
78+
79+ const auto new_exp {abs_lhs_bigger ? lhs_exp : rhs_exp};
80+ const auto new_sign {new_sig < 0 };
81+ const auto res_sig {detail::make_positive_unsigned (new_sig)};
82+
83+ return {res_sig, new_exp, new_sign};
84+ }
85+
2086template <typename ReturnType, typename T, typename U>
2187BOOST_DECIMAL_FORCE_INLINE constexpr auto sub_impl (T lhs_sig, U lhs_exp, bool lhs_sign,
2288 T rhs_sig, U rhs_exp, bool rhs_sign,
0 commit comments