machine_factor/
mfactor.rs1use machine_prime::PRIME_TABLE;
2pub const fn drbg(mut x: u64) -> u64 {
4 x ^= x.wrapping_shr(12);
5 x ^= x.wrapping_shl(25);
6 x ^= x.wrapping_shr(27);
7 x.wrapping_mul(0x2545F4914F6CDD1D)
8}
9
10#[no_mangle]
12pub const extern "C" fn partial_gcd(mut a: u64, mut b: u64) -> u64 {
13 if a == 0 {
14 return b;
15 }
16
17 let self_two_factor = a.trailing_zeros();
18
19 a >>= self_two_factor;
20
21 loop {
22 if b > a {
23 let interim = b;
24 b = a;
25 a = interim;
26 }
27 a -= b;
28
29 if a == 0 {
30 return b;
31 }
32 a >>= a.trailing_zeros();
33 }
34}
35
36const fn poly_eval(x: u64, subtrahend: u64, inv: u64, n: u64) -> u64 {
37 machine_prime::mont_sub(machine_prime::mont_prod(x, x, inv, n), subtrahend, n)
38}
39
40
41const fn pollard_brent(base: u64, inv: u64, subtrahend: u64, n: u64) -> Option<u64> {
45 let m = 128;
46 let mut r = 1;
47 let mut q = 1;
48 let mut g = 1;
49 let mut ys = 1;
50 let mut y = base;
51 let mut x = y;
52 let mut cycle = 0;
53 while cycle < 17 {
56 cycle += 1;
57 x = y;
58
59 let mut yloop = 0;
60
61 while yloop < r {
62 yloop += 1;
63 y = poly_eval(y, subtrahend, inv, n);
64 }
65
66 let mut k = 0;
67
68 loop {
69 let mut i = 0;
70
71 while i < m * cycle {
72 if i >= r - k {
73 break;
74 }
75
76 y = poly_eval(y, subtrahend, inv, n);
77 q = machine_prime::mont_prod(q, x.abs_diff(y), inv, n);
78 i += 1;
79 } ys = y;
82 g = partial_gcd(q, n);
83 k += m;
84 if k >= r || g != 1 {
85 break;
86 }
87 }
88
89 r <<= 1;
90 if g != 1 {
91 break;
92 }
93 }
94
95 if g == n {
96 while g == 1 {
97 ys = poly_eval(ys, subtrahend, inv,n);
98 g = partial_gcd(x.abs_diff(ys), n);
99 }
100 }
101
102 if g != 1 && g != n && machine_prime::is_prime_wc(g) {
103 return Some(g);
104 }
105 None
106}
107
108
109#[no_mangle]
113pub const extern "C" fn get_factor(n: u64) -> u64 {
114 let inv = machine_prime::mul_inv2(n);
115 let one = machine_prime::one_mont(n);
116 let base = machine_prime::two_mont(one, n);
117
118 match pollard_brent(base, inv, one, n) {
119 Some(factor) => return factor,
120 None => {
121 let coef = n.wrapping_sub(one);
124 match pollard_brent(base, inv, coef, n) {
125 Some(factor) =>return factor,
126 None => {
127 let mut param = drbg(n);
129 loop {
130 let rand_base = param % (n - 3) + 3; match pollard_brent(rand_base, inv, one, n) {
132 Some(factor) => return factor,
133 None => param = drbg(param),
134 }
135 }
136 }
137 }
138 }
139 }
140}
141
142
143
144
145
146#[repr(C)]
150pub struct Factorization {
151 pub factors: [u64; 15],
152 pub powers: [u8; 15],
153 pub len: usize,
154}
155
156impl Factorization {
157 const fn new() -> Self {
158 Factorization {
159 factors: [0u64; 15],
160 powers: [0u8; 15],
161 len: 0,
162 }
163 }
164}
165
166const fn revert(n: u64) -> u64{
167 let n16 = n as u16;
168 let mut est : u16 = 3u16.wrapping_mul(n as u16) ^ 2;
169 est = 2u16.wrapping_sub(est.wrapping_mul(n16)).wrapping_mul(est);
170 2u16.wrapping_sub(est.wrapping_mul(n16)).wrapping_mul(est) as u64
171}
172
173#[no_mangle]
176pub const extern "C" fn factorize(mut n: u64) -> Factorization {
177 let mut t = Factorization::new();
178
179 let mut idx = 0usize;
180
181 if n == 0 {
182 return t;
183 }
184 if n == 1 {
185 t.factors[0] = 1;
186 t.powers[1] = 1;
187 t.len = 1;
188 return t;
189 }
190
191 let twofactor = n.trailing_zeros();
192
193 if twofactor != 0 {
194 t.factors[0] = 2u64;
195 t.powers[0] = twofactor as u8;
196 n >>= twofactor;
197 idx += 1;
198 }
199
200 let mut primeidx = 0usize;
201
202
203 'trial : while primeidx < 256 && n > 1{
204
205 let pinv = PRIME_TABLE[primeidx];
206 let bound = PRIME_TABLE[primeidx+1];
207 let mut tmp = n;
208 let mut prod = n.wrapping_mul(pinv);
209
210 if prod <= bound{
211 t.factors[idx]=revert(pinv);
212 let mut power = 1u8;
213
214 loop{
215 tmp = prod;
216 prod = prod.wrapping_mul(pinv);
217 if prod > bound{
218 break;
219 }
220 power+=1;
221 if prod == 1{
222 break 'trial;
223 }
224 }
225
226 t.powers[idx]=power;
227 idx+=1;
228 }
229 primeidx+=2;
230 n=tmp;
231 }
232
233 if n == 1 {
234 t.len = idx;
235 return t;
236 }
237
238 if machine_prime::is_prime_wc(n) {
239 t.factors[idx] = n;
240 t.powers[idx] = 1;
241 idx += 1;
242 t.len = idx;
243 return t;
244 }
245 while n != 1 {
246 let k = get_factor(n);
247 t.factors[idx] = k;
248 let mut count = 0u8;
249 while n % k == 0 {
250 count += 1;
251 n /= k;
252 }
253 t.powers[idx] = count;
254 idx += 1;
255 if n == 1 {
256 t.len = idx;
257 return t;
258 }
259 if machine_prime::is_prime_wc(n) {
260 t.factors[idx] = n;
261 t.powers[idx] = 1;
262 idx += 1;
263 t.len = idx;
264 return t;
265 }
266 }
267 t
268}