dsalgo/
euler_criterion.rs1use crate::{
2 montgomery_modular_multiplication_64::MontgomeryMultiplication64,
3 power::pow_semigroup,
4};
5
6pub(crate) fn try_euler_criterion(
9 n: u64,
10 a: u64,
11) -> Result<u64, &'static str> {
12 assert!(2 < n && n & 1 == 1 && 0 < a && a < n);
13
14 assert!(a % n != 0);
15
16 let multiplier = MontgomeryMultiplication64::new(n);
17
18 let res = pow_semigroup(&|x, y| multiplier.mul(x, y), a, (n - 1) >> 1);
19
20 if res == 1 || res == n - 1 {
21 Ok(res)
22 } else {
23 Err("modulus n cannot be prime.")
24 }
25}
26
27pub fn euler_criterion(
31 p: u64,
32 a: u64,
33) -> u64 {
34 try_euler_criterion(p, a).unwrap()
36}
37
38#[cfg(test)]
39
40mod tests {
41
42 #[test]
43
44 fn test() {
45 use super::*;
46
47 assert_eq!(euler_criterion(5, 1), 1); assert_eq!(euler_criterion(5, 2), 4);
49
50 assert_eq!(euler_criterion(5, 3), 4);
51
52 assert_eq!(euler_criterion(5, 4), 1); }
54}