Skip to content

Commit

Permalink
Speed up mul_impl for decimal32 and add additional impl for dec32_fast
Browse files Browse the repository at this point in the history
  • Loading branch information
mborland committed Jun 25, 2024
1 parent 016d1d8 commit a8f3259
Showing 1 changed file with 22 additions and 4 deletions.
26 changes: 22 additions & 4 deletions include/boost/decimal/detail/mul_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,32 @@ namespace detail {

template <typename ReturnType, typename T, typename U>
BOOST_DECIMAL_FORCE_INLINE constexpr auto mul_impl(T lhs_sig, U lhs_exp, bool lhs_sign,
T rhs_sig, U rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t<detail::is_decimal_floating_point_v<ReturnType>, ReturnType>
T rhs_sig, U rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t<std::is_same<ReturnType, decimal32_fast>::value, ReturnType>
{
using mul_type = std::uint_fast64_t;

auto res_sig {static_cast<mul_type>(lhs_sig) * static_cast<mul_type>(rhs_sig)};
auto res_exp {lhs_exp + rhs_exp};
const auto res_sig {static_cast<mul_type>(lhs_sig) * static_cast<mul_type>(rhs_sig)};
const auto res_exp {lhs_exp + rhs_exp};

return {res_sig, res_exp, lhs_sign != rhs_sign && res_sig != static_cast<mul_type>(0)};
}

template <typename ReturnType, typename T, typename U>
BOOST_DECIMAL_FORCE_INLINE constexpr auto mul_impl(T lhs_sig, U lhs_exp, bool lhs_sign,
T rhs_sig, U rhs_exp, bool rhs_sign) noexcept -> std::enable_if_t<std::is_same<ReturnType, decimal32>::value, ReturnType>
{
using mul_type = std::uint_fast64_t;

// The constructor needs to calculate the number of digits in the significand which for uint128 is slow
// Since we know the value of res_sig is constrained to [1'000'000^2, 9'999'999^2] which equates to
// either 13 or 14 decimal digits we can use a single division to make binary search occur with
// uint32_t instead. 14 - 5 = 9 or 13 - 5 = 8 which are both still greater than or equal to
// digits10 + 1 for rounding which is 8 decimal digits

auto res_sig {(static_cast<mul_type>(lhs_sig) * static_cast<mul_type>(rhs_sig)) / pow10(static_cast<mul_type>(5))};
auto res_exp {lhs_exp + rhs_exp + static_cast<U>(5)};

return {res_sig, res_exp, lhs_sign != rhs_sign && res_sig != 0};
return {static_cast<std::uint32_t>(res_sig), res_exp, lhs_sign != rhs_sign && res_sig != static_cast<mul_type>(0)};
}

template <typename ReturnType, typename T, typename U>
Expand Down

0 comments on commit a8f3259

Please sign in to comment.