1mod errors;
2
3pub use errors::{Error, Result};
4use num::{
5 bigint::BigInt,
6 traits::{One, Zero},
7 Bounded, Num,
8};
9use std::ops::Shr;
10
11pub fn power_mod_fast<A>(a: A, e: A, m: A) -> A
13where
14 A: Copy + PartialOrd + Num + Bounded,
15 A: Shr<A, Output = A>,
16{
17 let zero: A = Zero::zero();
18 let one: A = One::one();
19 let two: A = one + one;
20 let max: A = Bounded::max_value();
21 assert!(m != zero);
22 assert!((m - one) < (max / (m - one)));
23
24 let mut result = one;
25 let mut base = a % m;
26 let mut exponent = e;
27
28 loop {
29 if exponent <= zero {
30 break;
31 }
32 if exponent % two == one {
33 result = (result * base) % m;
34 }
35 exponent = exponent >> one;
36 base = (base * base) % m;
37 }
38
39 result
40}
41
42pub fn power_mod<A, E, M>(a: &A, e: &E, m: &M) -> BigInt
43where
44 A: Into<BigInt> + Clone,
45 E: Into<BigInt> + Clone,
46 M: Into<BigInt> + Clone,
47{
48 let zero: BigInt = Zero::zero();
49 let a: BigInt = a.clone().into();
50 let e: BigInt = e.clone().into();
51 let m: BigInt = m.clone().into();
52 assert!(e >= zero);
53 a.modpow(&e, &m)
54}