machine_factor/
wfactor.rs1use crate::mfactor::{drbg, get_factor};
2use machine_prime::PRIME_TABLE_128;
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 if b.leading_zeros() != a.leading_zeros(){
22 a%=b;
23 }
24 else{
25 a -= b;
26 }
27 if a == 0 {
28 return b;
29 }
30 a >>= a.trailing_zeros();
31 }
32}
33
34const fn poly_eval_128(x: u128, subtrahend: u128, inv: u128, n: u128) -> u128 {
35 machine_prime::mont_sub_128(machine_prime::mont_sqr_128(x, inv, n), subtrahend, n)
36}
37
38const fn pollard_brent_128(base: u128, inv: u128, subtrahend: u128, n: u128) -> Option<u128> {
39 let m = 512;
40 let mut r = 1;
41 let mut q = 1;
42 let mut g = 1;
43 let mut ys = 1;
44 let mut y = base;
45 let mut x = y;
46 let mut cycle = 0;
47
48 while cycle < 33 {
49 cycle += 1;
50 x = y;
51
52 let mut yloop = 0;
53
54 while yloop < r {
55 yloop += 1;
56 y = poly_eval_128(y, subtrahend, inv,n);
57 }
58
59 let mut k = 0;
60
61 loop {
62 let mut i = 0;
63
64 while i < m * cycle {
65 if i >= r - k {
66 break;
67 }
68
69 y = poly_eval_128(y, subtrahend, inv, n);
70 q = machine_prime::mont_prod_128(q, x.abs_diff(y), inv, n);
71 i += 1;
72 } ys = y;
75 g = partial_gcd_128(q, n);
76 k += m;
77 if k >= r || g != 1 {
78 break;
79 }
80 }
81
82 r <<= 1;
83 if g != 1 {
84 break;
85 }
86 }
87
88 if g == n {
89 while g == 1 {
90 ys = poly_eval_128(ys, subtrahend, inv, n);
91 g = partial_gcd_128(x.abs_diff(ys), n);
92 }
93 }
94 if g != 1 && g != n && machine_prime::is_prime_wc_128(g) {
95 return Some(g);
96 }
97 None
98}
99
100#[no_mangle]
102pub const extern "C" fn get_factor_128(n: u128) -> u128 {
103 if n < 1u128 << 64 {
104 return get_factor(n as u64) as u128;
105 }
106
107 let inv = machine_prime::mul_inv2_128(n);
108 let one = machine_prime::one_mont_128(n);
109 let base = machine_prime::two_mont_128(one, n);
110
111 match pollard_brent_128(base, inv, one, n) {
112 Some(factor) => return factor,
113 None => {
114 let coef = n.wrapping_sub(one);
117 match pollard_brent_128(base, inv, coef, n) {
118 Some(factor) => return factor,
119 None => {
120 let mut param = drbg(n as u64);
124 loop {
125 let rand_base = (param as u128) % (n - 3) + 3;
126 match pollard_brent_128(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)]
139pub struct Factorization128 {
140 pub factors: [u128; 26],
141 pub powers: [u8; 26],
142 pub len: usize,
143}
144
145impl Factorization128 {
146 const fn new() -> Self {
147 Factorization128 {
148 factors: [0u128; 26],
149 powers: [0u8; 26],
150 len: 0,
151 }
152 }
153}
154
155const fn revert(n: u128) -> u128{
156 let n16 = n as u16;
157 let mut est : u16 = 3u16.wrapping_mul(n as u16) ^ 2;
158 est = 2u16.wrapping_sub(est.wrapping_mul(n16)).wrapping_mul(est);
159 2u16.wrapping_sub(est.wrapping_mul(n16)).wrapping_mul(est) as u128
160}
161
162
163#[no_mangle]
165pub const extern "C" fn factorize_128(mut n: u128) -> Factorization128 {
166 if n < 1u128 << 64 {
167 let mut zero = Factorization128::new();
168
169 let t = crate::mfactor::factorize(n as u64);
170
171 let mut i = 0;
172
173 while i < t.len {
174 zero.powers[i] = t.powers[i];
175 zero.factors[i] = t.factors[i] as u128;
176 i += 1;
177 }
178 zero.len = t.len;
179 return zero;
180 }
181
182 let mut t = Factorization128::new();
183
184 let mut idx = 0usize;
185
186 if n == 0 {
187 return t;
188 }
189 if n == 1 {
190 t.factors[0] = 1;
191 t.powers[1] = 1;
192 t.len = 1;
193 return t;
194 }
195
196 let twofactor = n.trailing_zeros();
197 if twofactor != 0 {
198 t.factors[0] = 2u128;
199 t.powers[0] = twofactor as u8;
200 n >>= twofactor;
201 idx += 1;
202 }
203
204 let mut primeidx = 0usize;
205
206
207 'trial : while primeidx < 256 && n > 1{
208
209 let pinv = PRIME_TABLE_128[primeidx];
210 let bound = PRIME_TABLE_128[primeidx+1];
211 let mut tmp = n;
212 let mut prod = n.wrapping_mul(pinv);
213
214 if prod <= bound{
215 t.factors[idx]=revert(pinv);
216 let mut power = 1u8;
217
218 loop{
219 tmp = prod;
220 prod = prod.wrapping_mul(pinv);
221 if prod > bound{
222 break;
223 }
224 power+=1;
225 if prod == 1{
226 break 'trial;
227 }
228 }
229
230 t.powers[idx]=power;
231 idx+=1;
232 }
233 primeidx+=2;
234 n=tmp;
235 }
236
237 if n == 1 {
238 t.len = idx;
239 return t;
240 }
241
242 if machine_prime::is_prime_wc_128(n) {
243 t.factors[idx] = n;
244 t.powers[idx] = 1;
245 idx += 1;
246 t.len = idx;
247 return t;
248 }
249 while n != 1 {
250 let k = get_factor_128(n);
251 t.factors[idx] = k;
252 let mut count = 0u8;
253 while n % k == 0 {
254 count += 1;
255 n /= k;
256 }
257 t.powers[idx] = count;
258 idx += 1;
259 if n == 1 {
260 t.len = idx;
261 return t;
262 }
263 if machine_prime::is_prime_wc_128(n) {
264 t.factors[idx] = n;
265 t.powers[idx] = 1;
266 idx += 1;
267 t.len = idx;
268 return t;
269 }
270 }
271 t
272}
273