@@ -22,7 +22,7 @@ extern crate std;
22
22
extern crate num_traits as traits;
23
23
24
24
use core:: mem;
25
- use core:: ops:: Add ;
25
+ use core:: ops:: { Add , Neg , Shr } ;
26
26
use core:: cmp:: Ordering ;
27
27
28
28
use traits:: { Num , NumRef , RefNum , Signed , Zero } ;
@@ -1064,6 +1064,30 @@ pub fn inverse<T: Integer + NumRef + Clone>(a: T, n: &T) -> Option<T>
1064
1064
}
1065
1065
}
1066
1066
1067
+ /// Calculate base^exp (mod modulus).
1068
+ pub fn powm < T > ( base : & T , exp : & T , modulus : & T ) -> T
1069
+ where T : Integer + NumRef + Clone + Neg < Output = T > + Shr < i32 , Output = T > ,
1070
+ for < ' a > & ' a T : RefNum < T >
1071
+ {
1072
+ let zero = T :: zero ( ) ;
1073
+ let one = T :: one ( ) ;
1074
+ let two = & one + & one;
1075
+ let mut exp = exp. clone ( ) ;
1076
+ let mut result = one. clone ( ) ;
1077
+ let mut base = base % modulus;
1078
+ if exp < zero {
1079
+ exp = -exp;
1080
+ base = inverse ( base, modulus) . unwrap ( ) ;
1081
+ }
1082
+ while exp > zero {
1083
+ if & exp % & two == one {
1084
+ result = ( result * & base) % modulus;
1085
+ }
1086
+ exp = exp >> 1 ;
1087
+ base = ( & base * & base) % modulus;
1088
+ }
1089
+ result
1090
+ }
1067
1091
1068
1092
/// An iterator over binomial coefficients.
1069
1093
pub struct IterBinomial < T > {
@@ -1239,6 +1263,12 @@ fn test_inverse() {
1239
1263
assert_eq ! ( inverse( 5 , & 7 ) . unwrap( ) , 3 ) ;
1240
1264
}
1241
1265
1266
+ #[ test]
1267
+ fn test_powm ( ) {
1268
+ // `i64::pow` would overflow.
1269
+ assert_eq ! ( powm( & 11 , & 19 , & 7 ) , 4 ) ;
1270
+ }
1271
+
1242
1272
#[ test]
1243
1273
fn test_iter_binomial ( ) {
1244
1274
macro_rules! check_simple {
0 commit comments