@@ -29,6 +29,108 @@ pub fn canon_egcd(a: i64, b: i64, c: i64) -> Option<(i64, i64, i64)> {
29
29
}
30
30
}
31
31
32
+ fn pos_mod ( n : i64 , m : i64 ) -> i64 {
33
+ if n < 0 {
34
+ n + m
35
+ } else {
36
+ n
37
+ }
38
+ }
39
+
40
+ fn mod_mul ( a : i64 , b : i64 , m : i64 ) -> i64 {
41
+ pos_mod ( ( a as i128 * b as i128 % m as i128 ) as i64 , m)
42
+ }
43
+
44
+ /// Assuming m >= 1 and exp >= 0, finds base ^ exp % m in logarithmic time
45
+ fn mod_exp ( mut base : i64 , mut exp : i64 , m : i64 ) -> i64 {
46
+ assert ! ( m >= 1 ) ;
47
+ assert ! ( exp >= 0 ) ;
48
+ let mut ans = 1 % m;
49
+ base = base % m;
50
+ while exp > 0 {
51
+ if exp % 2 == 1 {
52
+ ans = mod_mul ( ans, base, m) ;
53
+ }
54
+ base = mod_mul ( base, base, m) ;
55
+ exp /= 2 ;
56
+ }
57
+ pos_mod ( ans, m)
58
+ }
59
+
60
+ fn is_strong_probable_prime ( n : i64 , d : i64 , r : i64 , a : i64 ) -> bool {
61
+ let mut x = mod_exp ( a, d, n) ;
62
+ if x == 1 || x == n - 1 {
63
+ return true ;
64
+ }
65
+ for _ in 0 ..( r - 1 ) {
66
+ x = mod_mul ( x, x, n) ;
67
+ if x == n - 1 {
68
+ return true ;
69
+ }
70
+ }
71
+ false
72
+ }
73
+
74
+ const BASES : [ i64 ; 12 ] = [ 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 ] ;
75
+ /// Assuming x >= 0, returns true if x is prime
76
+ pub fn is_prime ( n : i64 ) -> bool {
77
+ assert ! ( n >= 0 ) ;
78
+ match n {
79
+ 0 | 1 => return false ,
80
+ 2 | 3 => return true ,
81
+ _ if n % 2 == 0 => return false ,
82
+ _ => { }
83
+ } ;
84
+ let r = ( n - 1 ) . trailing_zeros ( ) as i64 ;
85
+ let d = ( n - 1 ) >> r;
86
+ BASES
87
+ . iter ( )
88
+ . all ( |& base| base > n - 2 || is_strong_probable_prime ( n, d, r, base) )
89
+ }
90
+
91
+ fn pollard_rho ( n : i64 ) -> i64 {
92
+ for a in 1 ..n {
93
+ let f = |x| pos_mod ( mod_mul ( x, x, n) + a, n) ;
94
+ let mut x = 2 ;
95
+ let mut y = 2 ;
96
+ loop {
97
+ x = f ( x) ;
98
+ y = f ( f ( y) ) ;
99
+ let p = num:: fast_gcd ( x - y, n) ;
100
+ if p > 1 {
101
+ if p == n {
102
+ break ;
103
+ } else {
104
+ return p;
105
+ }
106
+ }
107
+ }
108
+ }
109
+ panic ! ( "No divisor found!" ) ;
110
+ }
111
+
112
+ /// Assuming x >= 1, finds the prime factorization of n
113
+ pub fn factorize ( n : i64 ) -> Vec < i64 > {
114
+ assert ! ( n >= 1 ) ;
115
+ let r = n. trailing_zeros ( ) ;
116
+ let mut factors = vec ! [ 2 ; r as usize ] ;
117
+ let mut stack = match n >> r {
118
+ 1 => Vec :: new ( ) ,
119
+ x => vec ! [ x]
120
+ } ;
121
+ while let Some ( top) = stack. pop ( ) {
122
+ if is_prime ( top) {
123
+ factors. push ( top) ;
124
+ } else {
125
+ let div = pollard_rho ( top) ;
126
+ stack. push ( div) ;
127
+ stack. push ( top / div) ;
128
+ }
129
+ }
130
+ factors. sort_unstable ( ) ;
131
+ factors
132
+ }
133
+
32
134
#[ cfg( test) ]
33
135
mod test {
34
136
use super :: * ;
@@ -44,4 +146,38 @@ mod test {
44
146
assert_eq ! ( canon_egcd( a, b, d) , Some ( ( d, -2 , 1 ) ) ) ;
45
147
assert_eq ! ( canon_egcd( b, a, d) , Some ( ( d, -1 , 3 ) ) ) ;
46
148
}
149
+
150
+ #[ test]
151
+ fn test_modexp ( ) {
152
+ let m = 1_000_000_007 ;
153
+ assert_eq ! ( mod_exp( 0 , 0 , m) , 1 ) ;
154
+ assert_eq ! ( mod_exp( 0 , 1 , m) , 0 ) ;
155
+ assert_eq ! ( mod_exp( 0 , 10 , m) , 0 ) ;
156
+ assert_eq ! ( mod_exp( 123 , 456 , m) , 565291922 ) ;
157
+ }
158
+
159
+ #[ test]
160
+ fn test_miller ( ) {
161
+ assert_eq ! ( is_prime( 2 ) , true ) ;
162
+ assert_eq ! ( is_prime( 4 ) , false ) ;
163
+ assert_eq ! ( is_prime( 6 ) , false ) ;
164
+ assert_eq ! ( is_prime( 8 ) , false ) ;
165
+ assert_eq ! ( is_prime( 269 ) , true ) ;
166
+ assert_eq ! ( is_prime( 1000 ) , false ) ;
167
+ assert_eq ! ( is_prime( 1_000_000_007 ) , true ) ;
168
+ assert_eq ! ( is_prime( ( 1 << 61 ) - 1 ) , true ) ;
169
+ assert_eq ! ( is_prime( 7156857700403137441 ) , false ) ;
170
+ }
171
+
172
+ #[ test]
173
+ fn test_pollard ( ) {
174
+ assert_eq ! ( factorize( 1 ) , Vec :: new( ) ) ;
175
+ assert_eq ! ( factorize( 2 ) , vec![ 2 ] ) ;
176
+ assert_eq ! ( factorize( 4 ) , vec![ 2 , 2 ] ) ;
177
+ assert_eq ! ( factorize( 12 ) , vec![ 2 , 2 , 3 ] ) ;
178
+ assert_eq ! (
179
+ factorize( 7156857700403137441 ) ,
180
+ vec![ 11 , 13 , 17 , 19 , 29 , 37 , 41 , 43 , 61 , 97 , 109 , 127 ]
181
+ ) ;
182
+ }
47
183
}
0 commit comments