1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
use num::integer::{ExtendedGcd, Integer}; use num::traits::{PrimInt, Signed}; pub fn mod_inv<A: Copy + Integer + Signed>(a: A, modulo: A) -> A { let ExtendedGcd { x, .. } = a.extended_gcd(&modulo); (modulo + x) % modulo } pub fn mod_pow<A: Copy + Integer + Signed + PrimInt>(x: A, n: A, m: A) -> A { let mut res = A::one(); let mut x = x; let mut n = n; while n > A::zero() { if n & A::one() == A::one() { res = (res * x) % m; } x = (x * x) % m; n = n >> 1; } res } #[cfg(test)] mod test { use super::*; macro_rules! impl_modulo_test(($ty:ty) => { assert_eq!(1, mod_inv(1 as $ty, MOD)); assert_eq!(4, mod_inv(2 as $ty, MOD)); assert_eq!(5, mod_inv(3 as $ty, MOD)); assert_eq!(2, mod_pow(2 as $ty, 4 as $ty, MOD)); assert_eq!(1, mod_pow(3 as $ty, 6 as $ty, MOD)); assert_eq!(2, mod_pow(5 as $ty, 100 as $ty, MOD)); assert_eq!(4, mod_pow(11 as $ty, 1000 as $ty, MOD)); }); #[test] fn test_isize_mod() -> () { const MOD: isize = 7; impl_modulo_test!(isize); } #[test] fn test_i64_mod() -> () { const MOD: i64 = 7; impl_modulo_test!(i64); } #[test] fn test_i32_mod() -> () { const MOD: i32 = 7; impl_modulo_test!(i32); } }