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