pub fn mod_exp(a: u64, b: u64, m: u64) -> u64 {
if m == 1 {
return 0;
}
let mut result = 1;
let mut base = a % m;
let mut exp = b;
while exp > 0 {
if exp % 2 == 1 {
result = (result * base) % m;
}
exp >>= 1;
base = (base * base) % m;
}
result
}
pub fn gcd(a: u64, b: u64) -> u64 {
if b == 0 {
return a;
}
gcd(b, a % b)
}
pub fn mod_inv(a: u64, m: u64) -> Option<u64> {
if m == 0 || m == 1 {
return None; }
let a = a % m;
if a == 0 {
return None; }
let mut a = a as i64;
let m_orig = m as i64;
let mut m = m_orig;
let mut x0: i64 = 1;
let mut x1: i64 = 0;
while a > 1 {
if m == 0 {
return None; }
let q = a / m;
let temp = m;
m = a % m;
a = temp;
let temp = x1;
x1 = x0 - q * x1;
x0 = temp;
}
if x0 < 0 {
x0 += m_orig;
}
if a == 1 {
Some(x0 as u64)
} else {
None
}
}
pub fn mod_add(a: u64, b: u64, m: u64) -> u64 {
(a + b) % m
}
pub fn mod_sub(a: u64, b: u64, m: u64) -> u64 {
(a + m - (b % m)) % m
}
pub fn mod_mul(a: u64, b: u64, m: u64) -> u64 {
(a * b) % m
}