Skip to main content

coreutils_rs/factor/
core.rs

1/// Prime factorization using trial division for small factors and
2/// Pollard's rho algorithm with Miller-Rabin primality testing for larger factors.
3/// Supports numbers up to u128.
4///
5/// Uses a u64 fast path for numbers ≤ u64::MAX (hardware div is ~5x faster
6/// than the software __udivti3 needed for u128).
7
8// Primes up to 251 (54 primes). Trial division by these covers all composites
9// up to 251² = 63001. For the "factor 1-100000" benchmark, sqrt(100000) ≈ 316,
10// so we only need primes up to 316. These 54 primes replace the naive loop that
11// tested every odd number (6k±1 pattern = ~53% wasted composite divisors).
12const SMALL_PRIMES_U64: [u64; 54] = [
13    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
14    101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
15    197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
16];
17
18// Extended primes for u128 trial division (up to 997, covering sqrt up to ~994009).
19const PRIMES_TO_997: [u64; 168] = [
20    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
21    101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
22    197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307,
23    311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421,
24    431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547,
25    557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
26    661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797,
27    809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929,
28    937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
29];
30
31// ── u64 fast path ────────────────────────────────────────────────────────
32
33/// Modular multiplication for u64 using u128 intermediate.
34/// Hardware mul + div on u128 is still much faster than software u128×u128.
35#[inline(always)]
36fn mod_mul_u64(a: u64, b: u64, m: u64) -> u64 {
37    ((a as u128) * (b as u128) % (m as u128)) as u64
38}
39
40/// Modular exponentiation for u64.
41#[inline]
42fn mod_pow_u64(mut base: u64, mut exp: u64, m: u64) -> u64 {
43    if m == 1 {
44        return 0;
45    }
46    let mut result: u64 = 1;
47    base %= m;
48    while exp > 0 {
49        if exp & 1 == 1 {
50            result = mod_mul_u64(result, base, m);
51        }
52        exp >>= 1;
53        base = mod_mul_u64(base, base, m);
54    }
55    result
56}
57
58/// Deterministic Miller-Rabin for u64. Uses minimal witness set.
59fn is_prime_u64(n: u64) -> bool {
60    if n < 2 {
61        return false;
62    }
63    if n < 4 {
64        return true;
65    }
66    if n.is_multiple_of(2) || n.is_multiple_of(3) {
67        return false;
68    }
69    // Quick check against small primes (5 through 47)
70    for &p in &SMALL_PRIMES_U64[2..15] {
71        if n == p {
72            return true;
73        }
74        if n.is_multiple_of(p) {
75            return false;
76        }
77    }
78    if n < 2809 {
79        return true; // All composites < 53² have a prime factor ≤ 47
80    }
81
82    let mut d = n - 1;
83    let mut r = 0u32;
84    while d.is_multiple_of(2) {
85        d /= 2;
86        r += 1;
87    }
88
89    // Witnesses sufficient for all n < 3,215,031,751: {2, 3, 5, 7}
90    // For all n < 3,317,044,064,679,887,385,961,981: {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}
91    let witnesses: &[u64] = if n < 3_215_031_751 {
92        &[2, 3, 5, 7]
93    } else {
94        &[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37]
95    };
96
97    'witness: for &a in witnesses {
98        if a >= n {
99            continue;
100        }
101        let mut x = mod_pow_u64(a, d, n);
102        if x == 1 || x == n - 1 {
103            continue;
104        }
105        for _ in 0..r - 1 {
106            x = mod_mul_u64(x, x, n);
107            if x == n - 1 {
108                continue 'witness;
109            }
110        }
111        return false;
112    }
113    true
114}
115
116/// GCD for u64 using binary algorithm.
117fn gcd_u64(mut a: u64, mut b: u64) -> u64 {
118    if a == 0 {
119        return b;
120    }
121    if b == 0 {
122        return a;
123    }
124    let shift = (a | b).trailing_zeros();
125    a >>= a.trailing_zeros();
126    loop {
127        b >>= b.trailing_zeros();
128        if a > b {
129            std::mem::swap(&mut a, &mut b);
130        }
131        b -= a;
132        if b == 0 {
133            break;
134        }
135    }
136    a << shift
137}
138
139/// Pollard's rho for u64 with Brent's variant + batch GCD.
140fn pollard_rho_u64(n: u64) -> u64 {
141    if n.is_multiple_of(2) {
142        return 2;
143    }
144
145    for c_offset in 1u64..n {
146        let c = c_offset;
147        let mut x: u64 = c_offset.wrapping_mul(6364136223846793005).wrapping_add(1) % n;
148        let mut y = x;
149        let mut ys = x;
150        let mut q: u64 = 1;
151        let mut r: u64 = 1;
152        let mut d: u64 = 1;
153
154        while d == 1 {
155            x = y;
156            for _ in 0..r {
157                y = (mod_mul_u64(y, y, n)).wrapping_add(c) % n;
158            }
159            let mut k: u64 = 0;
160            while k < r && d == 1 {
161                ys = y;
162                let m = (r - k).min(128);
163                for _ in 0..m {
164                    y = (mod_mul_u64(y, y, n)).wrapping_add(c) % n;
165                    q = mod_mul_u64(q, x.abs_diff(y), n);
166                }
167                d = gcd_u64(q, n);
168                k += m;
169            }
170            r *= 2;
171        }
172
173        if d == n {
174            loop {
175                ys = (mod_mul_u64(ys, ys, n)).wrapping_add(c) % n;
176                d = gcd_u64(x.abs_diff(ys), n);
177                if d > 1 {
178                    break;
179                }
180            }
181        }
182
183        if d != n {
184            return d;
185        }
186    }
187    n
188}
189
190/// Recursive factorization for u64.
191fn factor_recursive_u64(n: u64, factors: &mut Vec<u128>) {
192    if n <= 1 {
193        return;
194    }
195    if is_prime_u64(n) {
196        factors.push(n as u128);
197        return;
198    }
199    let d = pollard_rho_u64(n);
200    if d == n {
201        // Brute force fallback
202        let mut d = 2u64;
203        while d * d <= n {
204            if n.is_multiple_of(d) {
205                factor_recursive_u64(d, factors);
206                factor_recursive_u64(n / d, factors);
207                return;
208            }
209            d += 1;
210        }
211        factors.push(n as u128);
212        return;
213    }
214    factor_recursive_u64(d, factors);
215    factor_recursive_u64(n / d, factors);
216}
217
218/// Fast factorization for u64 numbers. Uses hardware div throughout.
219fn factorize_u64(n: u64) -> Vec<u128> {
220    if n <= 1 {
221        return vec![];
222    }
223
224    let mut factors = Vec::new();
225    let mut n = n;
226
227    // Special-case 2: bit shift is faster than hardware div
228    while n & 1 == 0 {
229        factors.push(2);
230        n >>= 1;
231    }
232
233    // Trial division by odd primes 3..997 (covers sqrt up to ~994009)
234    for &p in &PRIMES_TO_997[1..] {
235        if p as u128 * p as u128 > n as u128 {
236            break;
237        }
238        while n.is_multiple_of(p) {
239            factors.push(p as u128);
240            n /= p;
241        }
242    }
243
244    if n > 1 {
245        if n <= 994009 || is_prime_u64(n) {
246            factors.push(n as u128);
247        } else {
248            factor_recursive_u64(n, &mut factors);
249            factors.sort();
250        }
251    }
252
253    factors
254}
255
256// ── u128 path (for numbers > u64::MAX) ───────────────────────────────────
257
258/// Modular multiplication for u128 that avoids overflow.
259fn mod_mul(mut a: u128, mut b: u128, m: u128) -> u128 {
260    if a.leading_zeros() + b.leading_zeros() >= 128 {
261        return (a * b) % m;
262    }
263    a %= m;
264    b %= m;
265    let mut result: u128 = 0;
266    while b > 0 {
267        if b & 1 == 1 {
268            result = result.wrapping_add(a);
269            if result >= m {
270                result -= m;
271            }
272        }
273        a <<= 1;
274        if a >= m {
275            a -= m;
276        }
277        b >>= 1;
278    }
279    result
280}
281
282/// Modular exponentiation for u128.
283fn mod_pow(mut base: u128, mut exp: u128, m: u128) -> u128 {
284    if m == 1 {
285        return 0;
286    }
287    let mut result: u128 = 1;
288    base %= m;
289    while exp > 0 {
290        if exp & 1 == 1 {
291            result = mod_mul(result, base, m);
292        }
293        exp >>= 1;
294        base = mod_mul(base, base, m);
295    }
296    result
297}
298
299/// Deterministic Miller-Rabin primality test for u128.
300fn is_prime_miller_rabin(n: u128) -> bool {
301    if n < 2 {
302        return false;
303    }
304    if n <= u64::MAX as u128 {
305        return is_prime_u64(n as u64);
306    }
307    if n.is_multiple_of(2) || n.is_multiple_of(3) {
308        return false;
309    }
310
311    for &p in &PRIMES_TO_997[3..] {
312        if n == p as u128 {
313            return true;
314        }
315        if n.is_multiple_of(p as u128) {
316            return false;
317        }
318    }
319
320    let mut d = n - 1;
321    let mut r = 0u32;
322    while d.is_multiple_of(2) {
323        d /= 2;
324        r += 1;
325    }
326
327    let witnesses: &[u128] = &[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37];
328
329    'witness: for &a in witnesses {
330        if a >= n {
331            continue;
332        }
333        let mut x = mod_pow(a, d, n);
334        if x == 1 || x == n - 1 {
335            continue;
336        }
337        for _ in 0..r - 1 {
338            x = mod_mul(x, x, n);
339            if x == n - 1 {
340                continue 'witness;
341            }
342        }
343        return false;
344    }
345    true
346}
347
348/// GCD for u128.
349fn gcd(mut a: u128, mut b: u128) -> u128 {
350    if a == 0 {
351        return b;
352    }
353    if b == 0 {
354        return a;
355    }
356    let shift = (a | b).trailing_zeros();
357    a >>= a.trailing_zeros();
358    loop {
359        b >>= b.trailing_zeros();
360        if a > b {
361            std::mem::swap(&mut a, &mut b);
362        }
363        b -= a;
364        if b == 0 {
365            break;
366        }
367    }
368    a << shift
369}
370
371/// Pollard's rho for u128.
372fn pollard_rho(n: u128) -> u128 {
373    if n.is_multiple_of(2) {
374        return 2;
375    }
376
377    for c_offset in 1u128..n {
378        let c = c_offset;
379        let mut x: u128 = c_offset.wrapping_mul(6364136223846793005).wrapping_add(1) % n;
380        let mut y = x;
381        let mut ys = x;
382        let mut q: u128 = 1;
383        let mut r: u128 = 1;
384        let mut d: u128 = 1;
385
386        while d == 1 {
387            x = y;
388            for _ in 0..r {
389                y = mod_mul(y, y, n).wrapping_add(c) % n;
390            }
391            let mut k: u128 = 0;
392            while k < r && d == 1 {
393                ys = y;
394                let m = (r - k).min(128);
395                for _ in 0..m {
396                    y = mod_mul(y, y, n).wrapping_add(c) % n;
397                    q = mod_mul(q, x.abs_diff(y), n);
398                }
399                d = gcd(q, n);
400                k += m;
401            }
402            r *= 2;
403        }
404
405        if d == n {
406            loop {
407                ys = mod_mul(ys, ys, n).wrapping_add(c) % n;
408                d = gcd(x.abs_diff(ys), n);
409                if d > 1 {
410                    break;
411                }
412            }
413        }
414
415        if d != n {
416            return d;
417        }
418    }
419    n
420}
421
422/// Recursively factor n (u128 path).
423fn factor_recursive(n: u128, factors: &mut Vec<u128>) {
424    if n <= 1 {
425        return;
426    }
427    if n <= u64::MAX as u128 {
428        factor_recursive_u64(n as u64, factors);
429        return;
430    }
431    if is_prime_miller_rabin(n) {
432        factors.push(n);
433        return;
434    }
435
436    let mut d = pollard_rho(n);
437    if d == n {
438        d = 2;
439        while d * d <= n {
440            if n.is_multiple_of(d) {
441                break;
442            }
443            d += 1;
444        }
445        if d * d > n {
446            factors.push(n);
447            return;
448        }
449    }
450    factor_recursive(d, factors);
451    factor_recursive(n / d, factors);
452}
453
454// ── Public API ───────────────────────────────────────────────────────────
455
456/// Return the sorted list of prime factors of n (with repetition).
457pub fn factorize(n: u128) -> Vec<u128> {
458    if n <= u64::MAX as u128 {
459        return factorize_u64(n as u64);
460    }
461
462    let mut factors = Vec::new();
463    let mut n = n;
464
465    // Trial division by precomputed primes
466    for &p in &PRIMES_TO_997 {
467        let p128 = p as u128;
468        if p128 * p128 > n {
469            break;
470        }
471        while n.is_multiple_of(p128) {
472            factors.push(p128);
473            n /= p128;
474        }
475    }
476
477    if n > 1 {
478        factor_recursive(n, &mut factors);
479        factors.sort();
480    }
481
482    factors
483}
484
485/// Format a factorization result as "NUMBER: FACTOR FACTOR ..." matching GNU factor output.
486/// Writes directly to a buffer to avoid per-number String allocation.
487pub fn format_factors(n: u128) -> String {
488    let factors = factorize(n);
489    let mut result = String::with_capacity(64);
490    if n <= u64::MAX as u128 {
491        let mut buf = itoa::Buffer::new();
492        result.push_str(buf.format(n as u64));
493    } else {
494        use std::fmt::Write;
495        let _ = write!(result, "{}", n);
496    }
497    result.push(':');
498    for f in &factors {
499        result.push(' ');
500        if *f <= u64::MAX as u128 {
501            let mut buf = itoa::Buffer::new();
502            result.push_str(buf.format(*f as u64));
503        } else {
504            use std::fmt::Write;
505            let _ = write!(result, "{}", f);
506        }
507    }
508    result
509}
510
511/// Write factorization of a u64 directly to a buffer.
512/// Zero-allocation hot path for the common case (numbers up to 2^64-1).
513pub fn write_factors_u64(n: u64, out: &mut Vec<u8>) {
514    let mut buf = itoa::Buffer::new();
515    out.extend_from_slice(buf.format(n).as_bytes());
516    out.push(b':');
517    if n <= 1 {
518        out.push(b'\n');
519        return;
520    }
521    write_factors_u64_inline(n, out);
522    out.push(b'\n');
523}
524
525/// Write factorization of a u128 to a buffer.
526/// Falls through to the u64 fast path when possible.
527pub fn write_factors(n: u128, out: &mut Vec<u8>) {
528    if n <= u64::MAX as u128 {
529        write_factors_u64(n as u64, out);
530        return;
531    }
532    let mut buf = itoa::Buffer::new();
533    {
534        use std::fmt::Write;
535        let mut s = String::new();
536        let _ = write!(s, "{}", n);
537        out.extend_from_slice(s.as_bytes());
538    }
539    out.push(b':');
540
541    let factors = factorize(n);
542    for f in &factors {
543        out.push(b' ');
544        if *f <= u64::MAX as u128 {
545            out.extend_from_slice(buf.format(*f as u64).as_bytes());
546        } else {
547            use std::fmt::Write;
548            let mut s = String::new();
549            let _ = write!(s, "{}", *f);
550            out.extend_from_slice(s.as_bytes());
551        }
552    }
553    out.push(b'\n');
554}
555
556/// Inline factoring + direct writing for u64 numbers.
557/// Uses extended primes table (to 997) so numbers up to ~994009 are fully
558/// factored by trial division alone, avoiding expensive Miller-Rabin/Pollard's rho.
559fn write_factors_u64_inline(mut n: u64, out: &mut Vec<u8>) {
560    let mut buf = itoa::Buffer::new();
561
562    // Special-case 2: bit shift is ~5x faster than hardware div
563    while n & 1 == 0 {
564        out.extend_from_slice(b" 2");
565        n >>= 1;
566    }
567
568    // Special-case 3: very common factor
569    while n.is_multiple_of(3) {
570        out.extend_from_slice(b" 3");
571        n /= 3;
572    }
573
574    // Trial division by primes from 5 to 997. Skip 2 and 3 (already done).
575    // The break condition p*p > n ensures we only test relevant primes.
576    for &p in &PRIMES_TO_997[2..] {
577        if p * p > n {
578            break;
579        }
580        while n.is_multiple_of(p) {
581            out.push(b' ');
582            out.extend_from_slice(buf.format(p).as_bytes());
583            n /= p;
584        }
585    }
586
587    if n <= 1 {
588        return;
589    }
590
591    // After trial division by primes to 997, if n ≤ 997² ≈ 994009 it must be prime.
592    if n <= 994009 || is_prime_u64(n) {
593        out.push(b' ');
594        out.extend_from_slice(buf.format(n).as_bytes());
595    } else {
596        // n has multiple large factors (all > 997) needing Pollard's rho.
597        let mut factors = Vec::new();
598        factor_recursive_u64(n, &mut factors);
599        factors.sort();
600        for f in &factors {
601            out.push(b' ');
602            out.extend_from_slice(buf.format(*f as u64).as_bytes());
603        }
604    }
605}