pub fn mod_power(a: usize, exp: usize, m: usize) -> usize {
if exp == 0 {
return 1;
} else if exp == 1 {
return a;
}
if exp % 2 == 1 {
return (a * mod_power((a * a) % m, exp / 2, m)) % m;
} else {
return mod_power((a * a) % m, exp / 2, m);
}
}
fn ext_gcd(a: isize, b: isize, c: isize) -> (isize, isize) {
if b == 0 {
return (a / c, 0);
} else {
let r = a % b;
let q = a / b;
let (s, t) = ext_gcd(b, r, c);
return (t, s - q * t);
}
}
pub fn is_coprime(a: usize, b: usize) -> bool {
if b == 1 {
return true;
} else {
if a % b == 0 {
return false;
}
return is_coprime(b, a % b);
}
}
pub fn mod_inv(a: usize, m: usize) -> usize {
assert!(is_coprime(a, m));
let (a, m) = (a as isize, m as isize);
let (mut x, _) = ext_gcd(a, -m, 1);
loop {
if x < 1 {
x += m;
} else {
break;
}
}
return x as usize;
}