Skip to content

Commit a1db020

Browse files
committed
Improve decimal128 multiplication
1 parent cb7f7b0 commit a1db020

File tree

2 files changed

+26
-19
lines changed

2 files changed

+26
-19
lines changed

include/boost/decimal/decimal128.hpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,15 +1682,9 @@ constexpr auto operator*(decimal128 lhs, decimal128 rhs) noexcept -> decimal128
16821682

16831683
auto lhs_sig {lhs.full_significand()};
16841684
auto lhs_exp {lhs.biased_exponent()};
1685-
const auto lhs_zeros {detail::remove_trailing_zeros(lhs_sig)};
1686-
lhs_sig = lhs_zeros.trimmed_number;
1687-
lhs_exp += static_cast<std::int32_t>(lhs_zeros.number_of_removed_zeros);
16881685

16891686
auto rhs_sig {rhs.full_significand()};
16901687
auto rhs_exp {rhs.biased_exponent()};
1691-
const auto rhs_zeros {detail::remove_trailing_zeros(rhs_sig)};
1692-
rhs_sig = rhs_zeros.trimmed_number;
1693-
rhs_exp += static_cast<std::int32_t>(rhs_zeros.number_of_removed_zeros);
16941688

16951689
return detail::d128_mul_impl<decimal128>(
16961690
lhs_sig, lhs_exp, lhs.isneg(),

include/boost/decimal/detail/mul_impl.hpp

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -171,22 +171,35 @@ constexpr auto d128_mul_impl(T1 lhs_sig, std::int32_t lhs_exp, bool lhs_sign,
171171
{
172172
bool sign {lhs_sign != rhs_sign};
173173

174-
// Once we have the normalized significands and exponents all we have to do is
175-
// multiply the significands and add the exponents
176-
auto res_sig {detail::umul256(lhs_sig, rhs_sig)};
177-
auto res_exp {lhs_exp + rhs_exp};
178-
179-
const auto sig_dig {detail::num_digits(res_sig)};
174+
const auto lhs_dig {detail::num_digits(lhs_sig)};
175+
const auto rhs_dig {detail::num_digits(rhs_sig)};
180176

181-
if (sig_dig > std::numeric_limits<detail::uint128>::digits10)
177+
// If we can avoid it don't do 256 bit multiplication because it is slow
178+
if (lhs_dig * rhs_dig <= std::numeric_limits<uint128>::digits10)
182179
{
183-
const auto digit_delta {sig_dig - std::numeric_limits<detail::uint128>::digits10};
184-
res_sig /= detail::uint256_t(pow10(detail::uint128(digit_delta)));
185-
res_exp += digit_delta;
180+
auto res_sig {lhs_sig * rhs_sig};
181+
auto res_exp {lhs_exp + rhs_exp};
182+
return {res_sig, res_exp, sign};
183+
}
184+
else
185+
{
186+
// Once we have the normalized significands and exponents all we have to do is
187+
// multiply the significands and add the exponents
188+
auto res_sig {detail::umul256(lhs_sig, rhs_sig)};
189+
auto res_exp {lhs_exp + rhs_exp};
190+
191+
const auto sig_dig {detail::num_digits(res_sig)};
192+
193+
if (sig_dig > std::numeric_limits<detail::uint128>::digits10)
194+
{
195+
const auto digit_delta {sig_dig - std::numeric_limits<detail::uint128>::digits10};
196+
res_sig /= detail::uint256_t(pow10(detail::uint128(digit_delta)));
197+
res_exp += digit_delta;
198+
}
199+
200+
BOOST_DECIMAL_ASSERT(res_sig.high == uint128(0, 0));
201+
return {res_sig.low, res_exp, sign};
186202
}
187-
188-
BOOST_DECIMAL_ASSERT(res_sig.high == uint128(0,0));
189-
return {res_sig.low, res_exp, sign};
190203
}
191204

192205
template <typename ReturnType, BOOST_DECIMAL_INTEGRAL T1, BOOST_DECIMAL_INTEGRAL U1,

0 commit comments

Comments
 (0)