@@ -22,7 +22,7 @@ extern crate std;
22
22
23
23
extern crate num_traits as traits;
24
24
25
- use core:: ops:: Add ;
25
+ use core:: ops:: { Add , Neg , Shr } ;
26
26
use core:: mem;
27
27
use core:: cmp:: Ordering ;
28
28
@@ -735,6 +735,30 @@ pub fn inverse<T: Integer + NumRef + Clone>(a: T, n: &T) -> Option<T>
735
735
}
736
736
}
737
737
738
+ /// Calculate base^exp (mod modulus).
739
+ pub fn powm < T > ( base : & T , exp : & T , modulus : & T ) -> T
740
+ where T : Integer + NumRef + Clone + Neg < Output = T > + Shr < i32 , Output = T > ,
741
+ for < ' a > & ' a T : RefNum < T >
742
+ {
743
+ let zero = T :: zero ( ) ;
744
+ let one = T :: one ( ) ;
745
+ let two = & one + & one;
746
+ let mut exp = exp. clone ( ) ;
747
+ let mut result = one. clone ( ) ;
748
+ let mut base = base % modulus;
749
+ if exp < zero {
750
+ exp = -exp;
751
+ base = inverse ( base, modulus) . unwrap ( ) ;
752
+ }
753
+ while exp > zero {
754
+ if & exp % & two == one {
755
+ result = ( result * & base) % modulus;
756
+ }
757
+ exp = exp >> 1 ;
758
+ base = ( & base * & base) % modulus;
759
+ }
760
+ result
761
+ }
738
762
739
763
/// An iterator over binomial coefficients.
740
764
pub struct IterBinomial < T > {
@@ -901,6 +925,12 @@ fn test_inverse() {
901
925
assert_eq ! ( inverse( 5 , & 7 ) . unwrap( ) , 3 ) ;
902
926
}
903
927
928
+ #[ test]
929
+ fn test_powm ( ) {
930
+ // `i64::pow` would overflow.
931
+ assert_eq ! ( powm( & 11 , & 19 , & 7 ) , 4 ) ;
932
+ }
933
+
904
934
#[ test]
905
935
fn test_iter_binomial ( ) {
906
936
macro_rules! check_simple {
0 commit comments