#[cfg(feature = "radix")]
#[inline]
pub(crate) fn u128_divisor(radix: u32) -> (u64, usize, u32) {
match radix {
2 => (9223372036854775808, 63, 0), 3 => (12157665459056928801, 40, 0), 4 => (4611686018427387904, 31, 1), 5 => (7450580596923828125, 27, 1), 6 => (4738381338321616896, 24, 1), 7 => (3909821048582988049, 22, 2), 8 => (9223372036854775808, 21, 0), 9 => (12157665459056928801, 20, 0), 10 => (10000000000000000000, 19, 0), 11 => (5559917313492231481, 18, 1), 12 => (2218611106740436992, 17, 3), 13 => (8650415919381337933, 17, 1), 14 => (2177953337809371136, 16, 3), 15 => (6568408355712890625, 16, 1), 16 => (1152921504606846976, 15, 3), 17 => (2862423051509815793, 15, 2), 18 => (6746640616477458432, 15, 1), 19 => (15181127029874798299, 15, 0), 20 => (1638400000000000000, 14, 3), 21 => (3243919932521508681, 14, 2), 22 => (6221821273427820544, 14, 1), 23 => (11592836324538749809, 14, 0), 24 => (876488338465357824, 13, 4), 25 => (1490116119384765625, 13, 3), 26 => (2481152873203736576, 13, 2), 27 => (4052555153018976267, 13, 2), 28 => (6502111422497947648, 13, 1), 29 => (10260628712958602189, 13, 0), 30 => (15943230000000000000, 13, 0), 31 => (787662783788549761, 12, 4), 32 => (1152921504606846976, 12, 3), 33 => (1667889514952984961, 12, 3), 34 => (2386420683693101056, 12, 2), 35 => (3379220508056640625, 12, 2), 36 => (4738381338321616896, 12, 1), _ => unreachable!(),
}
}
#[cfg(not(feature = "radix"))]
#[inline]
#[allow(dead_code)]
pub(crate) fn u128_divisor(_: u32) -> (u64, usize, u32) {
(10000000000000000000, 19, 0) }
#[inline]
pub(crate) fn u128_divrem(n: u128, d: u64, d_cltz: u32) -> (u128, u64) {
debug_assert_eq!(d_cltz, d.leading_zeros());
let high = (n >> 64) as u64;
if high == 0 {
let low = n as u64;
return ((low / d) as u128, low % d);
}
let sr = 65 + d_cltz - high.leading_zeros();
let mut q: u128 = n << (128 - sr);
let mut r: u128 = n >> sr;
let mut carry: u64 = 0;
let mut i = 0;
while i < sr {
i += 1;
r = (r << 1) | (q >> 127);
q = (q << 1) | carry as u128;
let s = (d as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127;
carry = (s & 1) as u64;
r -= (d as u128) & s as u128;
}
((q << 1) | carry as u128, r as u64)
}
#[cfg(feature = "table")]
pub(crate) fn u128_divrem_1e19(n: u128) -> (u128, u64) {
u128_divrem(n, 10000000000000000000, 0)
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "std")]
proptest! {
#[test]
fn u128_divrem_proptest(i in u128::min_value()..u128::max_value()) {
let (d, _, d_cltz) = u128_divisor(10);
let expected = (i / d as u128, (i % d as u128) as u64);
let actual = u128_divrem(i, d, d_cltz);
prop_assert_eq!(actual, expected);
}
}
}