machine_factor/
mfactor.rs1use crate::primes::PRIMES_101;
2
3pub const fn drbg(mut x: u64) -> u64 {
5 x ^= x.wrapping_shr(12);
6 x ^= x.wrapping_shl(25);
7 x ^= x.wrapping_shr(27);
8 x.wrapping_mul(0x2545F4914F6CDD1D)
9}
10
11#[no_mangle]
13pub const extern "C" fn partial_gcd(mut a: u64, mut b: u64) -> u64 {
14 if a == 0 {
15 return b;
16 }
17
18 let self_two_factor = a.trailing_zeros();
19
20 a >>= self_two_factor;
21
22 loop {
23 if b > a {
24 let interim = b;
25 b = a;
26 a = interim;
27 }
28 a -= b;
29
30 if a == 0 {
31 return b;
32 }
33 a >>= a.trailing_zeros();
34 }
35}
36
37const fn poly_eval(x: u64, subtrahend: u64, n: u64, npi: u64) -> u64 {
38 machine_prime::mont_sub(machine_prime::mont_prod(x, x, n, npi), subtrahend, n)
39}
40
41const fn pollard_brent(base: u64, inv: u64, subtrahend: u64, n: u64) -> Option<u64> {
42 let m = 128;
43 let mut r = 1;
44 let mut q = 1;
45 let mut g = 1;
46 let mut ys = 1;
47 let mut y = base;
48 let mut x = y;
49 let mut cycle = 0;
50
51 while cycle < 17 {
52 cycle += 1;
53 x = y;
54
55 let mut yloop = 0;
56
57 while yloop < r {
58 yloop += 1;
59 y = poly_eval(y, subtrahend, n, inv);
60 }
61
62 let mut k = 0;
63
64 loop {
65 let mut i = 0;
66
67 while i < m * cycle {
68 if i >= r - k {
69 break;
70 }
71
72 y = poly_eval(y, subtrahend, n, inv);
73 q = machine_prime::mont_prod(q, x.abs_diff(y), n, inv);
74 i += 1;
75 } ys = y;
78 g = partial_gcd(q, n);
79 k += m;
80 if k >= r || g != 1 {
81 break;
82 }
83 }
84
85 r <<= 1;
86 if g != 1 {
87 break;
88 }
89 }
90
91 if g == n {
92 while g == 1 {
93 ys = poly_eval(ys, subtrahend, n, inv);
94 g = partial_gcd(x.abs_diff(ys), n);
95 }
96 }
97
98 if g != 1 && g != n && machine_prime::is_prime_wc(g) {
99 return Some(g);
100 }
101 None
102}
103
104#[no_mangle]
108pub const extern "C" fn get_factor(n: u64) -> u64 {
109 let inv = machine_prime::mul_inv2(n);
110 let one = machine_prime::one_mont(n);
111 let base = machine_prime::two_mont(one, n);
112
113 match pollard_brent(base, inv, one, n) {
114 Some(factor) => return factor,
115 None => {
116 let coef = n.wrapping_sub(one); match pollard_brent(base, inv, coef, n) {
120 Some(factor) => return factor,
121 None => {
122 let mut param = drbg(n);
124 loop {
125 let rand_base = param % (n - 3) + 3;
126 match pollard_brent(rand_base, inv, one, n) {
127 Some(factor) => return factor,
128 None => param = drbg(param),
129 }
130 }
131 }
132 }
133 }
134 }
135}
136
137#[repr(C)]
141pub struct Factorization {
142 pub factors: [u64; 15],
143 pub powers: [u8; 15],
144 pub len: usize,
145}
146
147impl Factorization {
148 const fn new() -> Self {
149 Factorization {
150 factors: [0u64; 15],
151 powers: [0u8; 15],
152 len: 0,
153 }
154 }
155}
156
157#[no_mangle]
159pub const extern "C" fn factorize(mut n: u64) -> Factorization {
160 let mut t = Factorization::new();
161
162 let mut idx = 0usize;
163
164 if n == 0 {
165 return t;
166 }
167 if n == 1 {
168 t.factors[0] = 1;
169 t.powers[1] = 1;
170 t.len = 1;
171 return t;
172 }
173
174 let twofactor = n.trailing_zeros();
175
176 if twofactor != 0 {
177 t.factors[0] = 2u64;
178 t.powers[0] = twofactor as u8;
179 n >>= twofactor;
180 idx += 1;
181 }
182
183 let mut i = 0usize;
184
185 while i < 101 {
186 let fctr = PRIMES_101[i] as u64;
187 if n % fctr == 0 {
189 t.factors[idx] = fctr;
190 let mut count = 0u8;
191 while n % fctr == 0 {
192 count += 1;
193 n /= fctr;
194 }
195 t.powers[idx] = count;
196 idx += 1;
197 }
198 i += 1;
199 }
200
201 if n == 1 {
202 t.len = idx;
203 return t;
204 }
205
206 if machine_prime::is_prime_wc(n) {
207 t.factors[idx] = n;
208 t.powers[idx] = 1;
209 idx += 1;
210 t.len = idx;
211 return t;
212 }
213 while n != 1 {
214 let k = get_factor(n);
215 t.factors[idx] = k;
216 let mut count = 0u8;
217 while n % k == 0 {
218 count += 1;
219 n /= k;
220 }
221 t.powers[idx] = count;
222 idx += 1;
223 if n == 1 {
224 t.len = idx;
225 return t;
226 }
227 if machine_prime::is_prime_wc(n) {
228 t.factors[idx] = n;
229 t.powers[idx] = 1;
230 idx += 1;
231 t.len = idx;
232 return t;
233 }
234 }
235 t
236}