Skip to content

Commit 91811d0

Browse files
authored
Merge pull request #733 from cppalliance/faster_dec128_mul
Faster dec128 mul
2 parents 9e61fca + c4bd2af commit 91811d0

File tree

3 files changed

+45
-25
lines changed

3 files changed

+45
-25
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/decimal128_fast.hpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -909,9 +909,21 @@ constexpr auto operator*(decimal128_fast lhs, decimal128_fast rhs) noexcept -> d
909909
}
910910
#endif
911911

912-
return detail::d128_fast_mul_impl<decimal128_fast>(
913-
lhs.significand_, lhs.biased_exponent(), lhs.sign_,
914-
rhs.significand_, rhs.biased_exponent(), rhs.sign_);
912+
auto lhs_sig {lhs.full_significand()};
913+
auto lhs_exp {lhs.biased_exponent()};
914+
const auto lhs_zeros {detail::remove_trailing_zeros(lhs_sig)};
915+
lhs_sig = lhs_zeros.trimmed_number;
916+
lhs_exp += static_cast<std::int32_t>(lhs_zeros.number_of_removed_zeros);
917+
918+
auto rhs_sig {rhs.full_significand()};
919+
auto rhs_exp {rhs.biased_exponent()};
920+
const auto rhs_zeros {detail::remove_trailing_zeros(rhs_sig)};
921+
rhs_sig = rhs_zeros.trimmed_number;
922+
rhs_exp += static_cast<std::int32_t>(rhs_zeros.number_of_removed_zeros);
923+
924+
return detail::d128_mul_impl<decimal128_fast>(
925+
lhs_sig, lhs_exp, lhs.sign_,
926+
rhs_sig, rhs_exp, rhs.sign_);
915927
}
916928

917929
template <typename Integer>

include/boost/decimal/detail/mul_impl.hpp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -165,28 +165,42 @@ BOOST_DECIMAL_FORCE_INLINE constexpr auto d64_mul_impl(T lhs_sig, U lhs_exp, boo
165165
return {res_sig_64, res_exp, sign};
166166
}
167167

168-
template <typename ReturnType, typename T1, typename T2>
169-
constexpr auto d128_mul_impl(T1 lhs_sig, std::int32_t lhs_exp, bool lhs_sign,
170-
T2 rhs_sig, std::int32_t rhs_exp, bool rhs_sign) noexcept -> ReturnType
168+
template <typename ReturnType, BOOST_DECIMAL_INTEGRAL T1, BOOST_DECIMAL_INTEGRAL U1,
169+
BOOST_DECIMAL_INTEGRAL T2, BOOST_DECIMAL_INTEGRAL U2>
170+
constexpr auto d128_mul_impl(T1 lhs_sig, U1 lhs_exp, bool lhs_sign,
171+
T2 rhs_sig, U2 rhs_exp, bool rhs_sign) noexcept -> ReturnType
171172
{
172173
bool sign {lhs_sign != rhs_sign};
173174

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)};
175+
const auto lhs_dig {detail::num_digits(lhs_sig)};
176+
const auto rhs_dig {detail::num_digits(rhs_sig)};
180177

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

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

0 commit comments

Comments
 (0)