@@ -22,7 +22,7 @@ extern crate std;
2222extern crate num_traits as traits;
2323
2424use core:: mem;
25- use core:: ops:: Add ;
25+ use core:: ops:: { Add , Neg , Shr } ;
2626use core:: cmp:: Ordering ;
2727
2828use traits:: { Num , NumRef , RefNum , Signed , Zero } ;
@@ -1064,6 +1064,30 @@ pub fn inverse<T: Integer + NumRef + Clone>(a: T, n: &T) -> Option<T>
10641064 }
10651065}
10661066
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+ }
10671091
10681092/// An iterator over binomial coefficients.
10691093pub struct IterBinomial < T > {
@@ -1239,6 +1263,12 @@ fn test_inverse() {
12391263 assert_eq ! ( inverse( 5 , & 7 ) . unwrap( ) , 3 ) ;
12401264}
12411265
1266+ #[ test]
1267+ fn test_powm ( ) {
1268+ // `i64::pow` would overflow.
1269+ assert_eq ! ( powm( & 11 , & 19 , & 7 ) , 4 ) ;
1270+ }
1271+
12421272#[ test]
12431273fn test_iter_binomial ( ) {
12441274 macro_rules! check_simple {
0 commit comments