@@ -24,8 +24,9 @@ extern crate num_traits as traits;
24
24
25
25
use core:: ops:: Add ;
26
26
use core:: mem;
27
+ use core:: cmp:: Ordering ;
27
28
28
- use traits:: { Num , Signed } ;
29
+ use traits:: { Num , NumRef , RefNum , Signed } ;
29
30
30
31
mod roots;
31
32
pub use roots:: Roots ;
@@ -684,6 +685,57 @@ impl_integer_for_usize!(usize, test_integer_usize);
684
685
#[ cfg( has_i128) ]
685
686
impl_integer_for_usize ! ( u128 , test_integer_u128) ;
686
687
688
+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
689
+ pub struct GcdResult < T > {
690
+ /// Greatest common divisor.
691
+ pub gcd : T ,
692
+ /// Coefficients such that: gcd(a, b) = c1*a + c2*b
693
+ pub c1 : T , pub c2 : T ,
694
+ }
695
+
696
+ /// Calculate greatest common divisor and the corresponding coefficients.
697
+ pub fn extended_gcd < T : Integer + NumRef > ( a : T , b : T ) -> GcdResult < T >
698
+ where for < ' a > & ' a T : RefNum < T >
699
+ {
700
+ // Euclid's extended algorithm
701
+ let ( mut s, mut old_s) = ( T :: zero ( ) , T :: one ( ) ) ;
702
+ let ( mut t, mut old_t) = ( T :: one ( ) , T :: zero ( ) ) ;
703
+ let ( mut r, mut old_r) = ( b, a) ;
704
+
705
+ while r != T :: zero ( ) {
706
+ let quotient = & old_r / & r;
707
+ old_r = old_r - & quotient * & r; std:: mem:: swap ( & mut old_r, & mut r) ;
708
+ old_s = old_s - & quotient * & s; std:: mem:: swap ( & mut old_s, & mut s) ;
709
+ old_t = old_t - quotient * & t; std:: mem:: swap ( & mut old_t, & mut t) ;
710
+ }
711
+
712
+ let _quotients = ( t, s) ; // == (a, b) / gcd
713
+
714
+ GcdResult { gcd : old_r, c1 : old_s, c2 : old_t }
715
+ }
716
+
717
+ /// Find the standard representation of a (mod n).
718
+ pub fn normalize < T : Integer + NumRef > ( a : T , n : & T ) -> T {
719
+ let a = a % n;
720
+ match a. cmp ( & T :: zero ( ) ) {
721
+ Ordering :: Less => a + n,
722
+ _ => a,
723
+ }
724
+ }
725
+
726
+ /// Calculate the inverse of a (mod n).
727
+ pub fn inverse < T : Integer + NumRef + Clone > ( a : T , n : & T ) -> Option < T >
728
+ where for < ' a > & ' a T : RefNum < T >
729
+ {
730
+ let GcdResult { gcd, c1 : c, .. } = extended_gcd ( a, n. clone ( ) ) ;
731
+ if gcd == T :: one ( ) {
732
+ Some ( normalize ( c, n) )
733
+ } else {
734
+ None
735
+ }
736
+ }
737
+
738
+
687
739
/// An iterator over binomial coefficients.
688
740
pub struct IterBinomial < T > {
689
741
a : T ,
@@ -831,6 +883,24 @@ fn test_lcm_overflow() {
831
883
check ! ( u64 , 0x8000_0000_0000_0000 , 0x02 , 0x8000_0000_0000_0000 ) ;
832
884
}
833
885
886
+ #[ test]
887
+ fn test_extended_gcd ( ) {
888
+ assert_eq ! ( extended_gcd( 240 , 46 ) , GcdResult { gcd: 2 , c1: -9 , c2: 47 } ) ;
889
+ }
890
+
891
+ #[ test]
892
+ fn test_normalize ( ) {
893
+ assert_eq ! ( normalize( 10 , & 7 ) , 3 ) ;
894
+ assert_eq ! ( normalize( 7 , & 7 ) , 0 ) ;
895
+ assert_eq ! ( normalize( 5 , & 7 ) , 5 ) ;
896
+ assert_eq ! ( normalize( -3 , & 7 ) , 4 ) ;
897
+ }
898
+
899
+ #[ test]
900
+ fn test_inverse ( ) {
901
+ assert_eq ! ( inverse( 5 , & 7 ) . unwrap( ) , 3 ) ;
902
+ }
903
+
834
904
#[ test]
835
905
fn test_iter_binomial ( ) {
836
906
macro_rules! check_simple {
0 commit comments