use crate::{
montgomery_modular_multiplication_64::MontgomeryMultiplication64,
power::pow_semigroup,
};
pub(crate) fn try_euler_criterion(
n: u64,
a: u64,
) -> Result<u64, &'static str> {
assert!(2 < n && n & 1 == 1 && 0 < a && a < n);
assert!(a % n != 0);
let multiplier = MontgomeryMultiplication64::new(n);
let res = pow_semigroup(&|x, y| multiplier.mul(x, y), a, (n - 1) >> 1);
if res == 1 || res == n - 1 {
Ok(res)
} else {
Err("modulus n cannot be prime.")
}
}
pub fn euler_criterion(
p: u64,
a: u64,
) -> u64 {
try_euler_criterion(p, a).unwrap()
}
#[cfg(test)]
mod tests {
#[test]
fn test() {
use super::*;
assert_eq!(euler_criterion(5, 1), 1); assert_eq!(euler_criterion(5, 2), 4);
assert_eq!(euler_criterion(5, 3), 4);
assert_eq!(euler_criterion(5, 4), 1); }
}