pub fn mod_inverse(a: u64, modulus: u64) -> u64 {
let mut t: i128 = 0;
let mut new_t: i128 = 1;
let mut r: i128 = modulus as i128;
let mut new_r: i128 = a as i128;
while new_r != 0 {
let quotient = r / new_r;
let tmp_t = t - quotient * new_t;
t = new_t;
new_t = tmp_t;
let tmp_r = r - quotient * new_r;
r = new_r;
new_r = tmp_r;
}
if r != 1 {
panic!("mod_inverse: value is not invertible");
}
if t < 0 {
t += modulus as i128;
}
t as u64
}
pub fn crt_compose_2(a0: u64, a1: u64, q0: u64, q1: u64, q0_inv_mod_q1: u64) -> u64 {
let a0_mod_q1 = a0 % q1;
let diff = if a1 >= a0_mod_q1 {
a1 - a0_mod_q1
} else {
(a1 + q1) - a0_mod_q1
};
let t = ((diff as u128 * q0_inv_mod_q1 as u128) % q1 as u128) as u64;
a0 + q0 * t
}
#[inline]
pub fn crt_decompose_2(value: u64, q0: u64, q1: u64) -> (u64, u64) {
(value % q0, value % q1)
}
pub fn crt_modulus(moduli: &[u64]) -> u64 {
moduli
.iter()
.copied()
.fold(1u64, |acc, m| acc.saturating_mul(m))
}