Skip to content

Commit 9341dc7

Browse files
committed
Simplify mixed width div
1 parent 10771cb commit 9341dc7

File tree

1 file changed

+19
-33
lines changed

1 file changed

+19
-33
lines changed

include/boost/decimal/detail/u128.hpp

+19-33
Original file line numberDiff line numberDiff line change
@@ -2023,43 +2023,26 @@ constexpr void div_mod_impl(const u128& lhs, const std::uint64_t rhs, u128& quot
20232023
remainder.low %= rhs;
20242024
}
20252025
}
2026-
2027-
// Setup for Knuth Division
2028-
// Includes the normalization step here instead of in main function for simplicity
2029-
const auto offset { countl_zero(static_cast<std::uint32_t>(rhs >> 32)) };
2030-
2031-
std::uint32_t u[5]{};
2032-
2033-
if (offset != 0)
2034-
{
2035-
u[0] = static_cast<std::uint32_t>(lhs.low << offset);
2036-
u[1] = static_cast<std::uint32_t>(lhs.low >> (32 - offset));
2037-
u[2] = static_cast<std::uint32_t>(lhs.high << offset) |
2038-
static_cast<std::uint32_t>(lhs.low >> (64 - offset));
2039-
u[3] = static_cast<std::uint32_t>(lhs.high >> (32 - offset));
2040-
u[4] = static_cast<std::uint32_t>(lhs.high >> (64 - offset));
2041-
}
20422026
else
20432027
{
2044-
u[0] = static_cast<std::uint32_t>(lhs.low);
2045-
u[1] = static_cast<std::uint32_t>(lhs.low >> 32);
2046-
u[2] = static_cast<std::uint32_t>(lhs.high);
2047-
u[3] = static_cast<std::uint32_t>(lhs.high >> 32);
2048-
}
2028+
const auto rhs32 = static_cast<std::uint32_t>(rhs);
20492029

2050-
std::uint32_t v[2]
2051-
{
2052-
static_cast<std::uint32_t>(rhs << offset),
2053-
static_cast<std::uint32_t>(rhs >> (32 - offset))
2054-
};
2030+
auto current = static_cast<std::uint64_t>(lhs.high >> 32U);
2031+
quotient.high = static_cast<std::uint64_t>(static_cast<std::uint64_t>(static_cast<std::uint32_t>(current / rhs32)) << 32U);
2032+
remainder.low = static_cast<std::uint64_t>(current % rhs32);
20552033

2056-
std::uint32_t q[3]{};
2034+
current = static_cast<std::uint64_t>(remainder.low << 32U) | static_cast<std::uint32_t>(lhs.high);
2035+
quotient.high |= static_cast<std::uint32_t>(current / rhs32);
2036+
remainder.low = static_cast<std::uint64_t>(current % rhs32);
20572037

2058-
divide_knuth_core(u, v, q);
2038+
current = static_cast<std::uint64_t>(remainder.low << 32U) | static_cast<std::uint32_t>(lhs.low >> 32U);
2039+
quotient.low = static_cast<std::uint64_t>(static_cast<std::uint64_t>(static_cast<std::uint32_t>(current / rhs32)) << 32U);
2040+
remainder.low = static_cast<std::uint64_t>(current % rhs32);
20592041

2060-
quotient.low = (static_cast<std::uint64_t>(q[1]) << 32) | q[0];
2061-
quotient.high = q[2];
2062-
remainder.low = (static_cast<std::uint64_t>(u[1]) << (32 - offset)) | (static_cast<std::uint64_t>(u[0]) >> offset);
2042+
current = remainder.low << 32U | static_cast<std::uint32_t>(lhs.low);
2043+
quotient.low |= static_cast<std::uint32_t>(current / rhs32);
2044+
remainder.low = static_cast<std::uint32_t>(current % rhs32);
2045+
}
20632046
}
20642047

20652048
BOOST_DECIMAL_FORCE_INLINE constexpr void div_mod_impl(const u128& lhs, const u128& rhs, u128& quotient, u128& remainder) noexcept
@@ -2272,11 +2255,14 @@ constexpr u128 operator/(const u128 lhs, const u128 rhs) noexcept
22722255

22732256
#endif
22742257
}
2275-
else if (rhs > lhs)
2258+
else if ((lhs.high == 0 && rhs.high != 0) || rhs.low == 0)
22762259
{
2277-
// This would imply rhs.high != 0 and lhs.high == 0 which is always 0
22782260
return {0, 0};
22792261
}
2262+
else if (lhs.high == 0)
2263+
{
2264+
return { 0, lhs.low / rhs.low };
2265+
}
22802266
else
22812267
{
22822268
u128 quotient {};

0 commit comments

Comments
 (0)