machine_factor/
wfactor.rs

1use crate::mfactor::{drbg, get_factor};
2use machine_prime::PRIME_TABLE_128;
3
4/// GCD(A,B) for 128-bit integers, where B is odd
5#[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            } // end loop
73
74            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/// Returns some prime factor of an 128-bit integer
101#[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            // if x^2 -1 failed try x^2+1
115            // No particular reason except to reuse some values
116            let coef = n.wrapping_sub(one); 
117            match pollard_brent_128(base, inv, coef, n) {
118                Some(factor) => return factor,
119                None => {
120                    // Loop that has a roughly 0.5 probability of factoring each iteration
121                    // The probability of being unable to factor a composite is 1/2^period and the period is likely very large
122                    // So the risk of error is vanishingly small
123                    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/// Factorization of a 128-bit integer
138#[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/// Complete factorization of 128-bit N
164#[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