1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use crate::num::arithmetic::traits::ModPowerOf2Inverse;
use crate::num::basic::unsigneds::PrimitiveUnsigned;
pub_test! {mod_power_of_2_inverse_fast<T: PrimitiveUnsigned>(x: T, pow: u64) -> Option<T> {
assert_ne!(x, T::ZERO);
assert!(pow <= T::WIDTH);
assert!(x.significant_bits() <= pow);
if x.even() {
return None;
} else if x == T::ONE {
return Some(T::ONE);
}
let mut small_pow = 2;
let mut inverse = x.mod_power_of_2(2);
while small_pow < pow {
small_pow <<= 1;
if small_pow > pow {
small_pow = pow;
}
inverse.mod_power_of_2_mul_assign(
T::TWO.mod_power_of_2_sub(
inverse.mod_power_of_2_mul(x.mod_power_of_2(small_pow), small_pow),
small_pow,
),
small_pow,
);
}
Some(inverse)
}}
macro_rules! impl_mod_power_of_2_inverse {
($u:ident) => {
impl ModPowerOf2Inverse for $u {
type Output = $u;
#[inline]
fn mod_power_of_2_inverse(self, pow: u64) -> Option<$u> {
mod_power_of_2_inverse_fast(self, pow)
}
}
};
}
apply_to_unsigneds!(impl_mod_power_of_2_inverse);