@@ -2023,43 +2023,26 @@ constexpr void div_mod_impl(const u128& lhs, const std::uint64_t rhs, u128& quot
2023
2023
remainder .low %= rhs;
2024
2024
}
2025
2025
}
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
- }
2042
2026
else
2043
2027
{
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);
2049
2029
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);
2055
2033
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);
2057
2037
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);
2059
2041
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
+ }
2063
2046
}
2064
2047
2065
2048
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
2272
2255
2273
2256
#endif
2274
2257
}
2275
- else if (rhs > lhs )
2258
+ else if ((lhs. high == 0 && rhs. high != 0 ) || rhs. low == 0 )
2276
2259
{
2277
- // This would imply rhs.high != 0 and lhs.high == 0 which is always 0
2278
2260
return {0 , 0 };
2279
2261
}
2262
+ else if (lhs.high == 0 )
2263
+ {
2264
+ return { 0 , lhs.low / rhs.low };
2265
+ }
2280
2266
else
2281
2267
{
2282
2268
u128 quotient {};
0 commit comments