@@ -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
192206template <typename ReturnType, BOOST_DECIMAL_INTEGRAL T1, BOOST_DECIMAL_INTEGRAL U1,
0 commit comments