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