use super::UInt;
use crate::Limb;
impl<const LIMBS: usize> UInt<LIMBS> {
pub const fn inv_mod2k(&self, k: usize) -> Self {
let mut x = Self::ZERO;
let mut b = Self::ONE;
let mut i = 0;
while i < k {
let mut x_i = Self::ZERO;
let j = b.limbs[0].0 & 1;
x_i.limbs[0] = Limb(j);
x = x.bitor(&x_i.shl_vartime(i));
let t = b.wrapping_sub(self);
b = Self::ct_select(b, t, j.wrapping_neg()).shr_vartime(1);
i += 1;
}
x
}
}
#[cfg(test)]
mod tests {
use crate::U256;
#[test]
fn inv_mod2k() {
let v = U256::from_be_slice(&[
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
0xff, 0xff, 0xfc, 0x2f,
]);
let e = U256::from_be_slice(&[
0x36, 0x42, 0xe6, 0xfa, 0xea, 0xac, 0x7c, 0x66, 0x63, 0xb9, 0x3d, 0x3d, 0x6a, 0x0d,
0x48, 0x9e, 0x43, 0x4d, 0xdc, 0x01, 0x23, 0xdb, 0x5f, 0xa6, 0x27, 0xc7, 0xf6, 0xe2,
0x2d, 0xda, 0xca, 0xcf,
]);
let a = v.inv_mod2k(256);
assert_eq!(e, a);
let v = U256::from_be_slice(&[
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfe, 0xba, 0xae, 0xdc, 0xe6, 0xaf, 0x48, 0xa0, 0x3b, 0xbf, 0xd2, 0x5e, 0x8c,
0xd0, 0x36, 0x41, 0x41,
]);
let e = U256::from_be_slice(&[
0x26, 0x17, 0x76, 0xf2, 0x9b, 0x6b, 0x10, 0x6c, 0x76, 0x80, 0xcf, 0x3e, 0xd8, 0x30,
0x54, 0xa1, 0xaf, 0x5a, 0xe5, 0x37, 0xcb, 0x46, 0x13, 0xdb, 0xb4, 0xf2, 0x00, 0x99,
0xaa, 0x77, 0x4e, 0xc1,
]);
let a = v.inv_mod2k(256);
assert_eq!(e, a);
}
}