malachite_base/num/factorization/
factor.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// Uses code adopted from the FLINT Library.
4//
5//      Copyright © 2009 Tom Boothby
6//
7//      Copyright © 2008, 2009, 2012 William Hart
8//
9// This file is part of Malachite.
10//
11// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
12// Lesser General Public License (LGPL as published by the Free Software Foundation; either version
13// 3 of the License, or (at your option any later version. See <https://www.gnu.org/licenses/>.
14
15use crate::num::arithmetic::mod_pow::mul_mod_helper;
16use crate::num::arithmetic::sqrt::{sqrt_rem_2_newton, sqrt_rem_newton};
17use crate::num::arithmetic::traits::{
18    DivMod, FloorRoot, FloorSqrt, Gcd, ModMulPrecomputed, ModSub, ModSubAssign, Parity, PowerOf2,
19    SqrtRem, Square, WrappingAddAssign, WrappingMulAssign, WrappingSquare, WrappingSubAssign,
20    XMulYToZZ, XXDivModYToQR, XXSubYYToZZ,
21};
22use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32};
23use crate::num::basic::unsigneds::PrimitiveUnsigned;
24use crate::num::conversion::traits::{ExactFrom, WrappingFrom};
25use crate::num::factorization::primes::SMALL_PRIMES;
26use crate::num::factorization::traits::{Factor, IsPrime, IsSquare, Primes};
27use crate::num::logic::traits::{LeadingZeros, LowMask, SignificantBits};
28use core::mem::swap;
29
30pub(crate) const MAX_FACTORS_IN_U8: usize = 4;
31pub(crate) const MAX_FACTORS_IN_U16: usize = 6;
32pub(crate) const MAX_FACTORS_IN_U32: usize = 9;
33pub(crate) const MAX_FACTORS_IN_U64: usize = 15;
34pub(crate) const MAX_FACTORS_IN_USIZE: usize = 15;
35
36/// A struct that contains the prime factorization of an integer. See implementations of the
37/// [`Factor`] trait for more information.
38#[derive(Clone, Debug, Eq, PartialEq)]
39pub struct Factors<T: PrimitiveUnsigned, const N: usize> {
40    factors: [T; N],
41    exponents: [u8; N],
42}
43
44/// An iterator over [`Factors`].
45#[derive(Clone, Debug, Eq, PartialEq)]
46pub struct FactorsIterator<T: PrimitiveUnsigned, const N: usize> {
47    i: usize,
48    factors: Factors<T, N>,
49}
50
51impl<T: PrimitiveUnsigned, const N: usize> Iterator for FactorsIterator<T, N> {
52    type Item = (T, u8);
53
54    fn next(&mut self) -> Option<(T, u8)> {
55        let e = *self.factors.exponents.get(self.i)?;
56        if e == 0 {
57            return None;
58        }
59        let f = self.factors.factors[self.i];
60        self.i += 1;
61        Some((f, e))
62    }
63}
64
65impl<T: PrimitiveUnsigned, const N: usize> IntoIterator for Factors<T, N> {
66    type IntoIter = FactorsIterator<T, N>;
67    type Item = (T, u8);
68
69    fn into_iter(self) -> FactorsIterator<T, N> {
70        FactorsIterator {
71            i: 0,
72            factors: self,
73        }
74    }
75}
76
77impl<T: PrimitiveUnsigned, const N: usize> Factors<T, N> {
78    const fn new() -> Self {
79        Self {
80            factors: [T::ZERO; N],
81            exponents: [0; N],
82        }
83    }
84
85    // This takes linear time in the number of factors, but that's ok because the number of factors
86    // is small.
87    //
88    // This is n_factor_insert from ulong_extras/factor_insert.c, FLINT 3.1.2, but it also ensures
89    // that the factors are ordered least to greatest.
90    fn insert(&mut self, factor: T, exp: u8) {
91        let mut inserting = false;
92        let mut previous_f = T::ZERO;
93        let mut previous_e = 0;
94        for (f, e) in self.factors.iter_mut().zip(self.exponents.iter_mut()) {
95            if inserting {
96                swap(&mut previous_f, f);
97                swap(&mut previous_e, e);
98                if previous_e == 0 {
99                    break;
100                }
101            } else if *e == 0 {
102                *f = factor;
103                *e = exp;
104                break;
105            } else if *f == factor {
106                *e += exp;
107                break;
108            } else if *f > factor {
109                previous_f = *f;
110                previous_e = *e;
111                *f = factor;
112                *e = exp;
113                inserting = true;
114            }
115        }
116    }
117}
118
119type FactorsU8 = Factors<u8, MAX_FACTORS_IN_U8>;
120type FactorsU16 = Factors<u16, MAX_FACTORS_IN_U16>;
121type FactorsU32 = Factors<u32, MAX_FACTORS_IN_U32>;
122type FactorsU64 = Factors<u64, MAX_FACTORS_IN_U64>;
123type FactorsUsize = Factors<usize, MAX_FACTORS_IN_USIZE>;
124
125// This is n_divrem2_precomp when FLINT64 is false, from ulong_extras/divrem2_precomp.c, FLINT
126// 3.1.2, simplified to only include the branches used when factoring a `u32`.
127fn div_rem_precomputed_float_for_u32_factorization(a: u32, n: u32, inverse: f64) -> (u32, u32) {
128    let mut q = (f64::from(a) * inverse) as u32;
129    let r = a.wrapping_sub(q * n);
130    let ri = i32::wrapping_from(r);
131    if ri >= i32::wrapping_from(n) {
132        q += (f64::from(ri) * inverse) as u32;
133        (q + 1, a.wrapping_sub(q * n).wrapping_sub(n))
134    } else {
135        (q, r)
136    }
137}
138
139// This is n_divrem2_precomp when FLINT64 is true, from ulong_extras/divrem2_precomp.c, FLINT 3.1.2,
140// returning both q and r.
141fn div_rem_precomputed_float_u64(a: u64, n: u64, npre: f64) -> (u64, u64) {
142    if a < n {
143        return (0, a);
144    }
145    if n.get_highest_bit() {
146        return (1, a.wrapping_sub(n));
147    }
148    let (mut q, r) = if n == 1 {
149        (a, 0)
150    } else {
151        let q = ((a as f64) * npre) as u64;
152        (q, a.wrapping_sub(q.wrapping_mul(n)))
153    };
154    let ri = i64::wrapping_from(r);
155    let ni = i64::wrapping_from(n);
156    if ri < ni.wrapping_neg() {
157        q -= ((-(ri as f64)) * npre) as u64;
158    } else if ri >= ni {
159        q += ((ri as f64) * npre) as u64;
160    } else if ri < 0 {
161        return (q - 1, r.wrapping_add(n));
162    } else {
163        return (q, r);
164    }
165    let r = a.wrapping_sub(q.wrapping_mul(n));
166    let ri = i64::wrapping_from(r);
167    if ri >= ni {
168        (q + 1, r.wrapping_sub(n))
169    } else if ri < 0 {
170        (q - 1, r.wrapping_add(n))
171    } else {
172        (q, r)
173    }
174}
175
176// This is n_remove2_precomp when FLINT64 is false, from ulong_extras/remove2_precomp.c, FLINT
177// 3.1.2, returning n and exp.
178fn remove_factor_precomputed_float_u32(mut n: u32, p: u32, inverse: f64) -> (u32, u8) {
179    if p == 2 {
180        let exp = n.trailing_zeros();
181        if exp != 0 {
182            n >>= exp;
183        }
184        (n, u8::wrapping_from(exp))
185    } else {
186        let mut exp = 0;
187        while n >= p {
188            let (q, r) = div_rem_precomputed_float_for_u32_factorization(n, p, inverse);
189            if r != 0 {
190                break;
191            }
192            exp += 1;
193            n = q;
194        }
195        (n, exp)
196    }
197}
198
199// This is n_remove2_precomp when FLINT64 is true, from ulong_extras/remove2_precomp.c, FLINT 3.1.2,
200// returning n and exp.
201fn remove_factor_precomputed_float_u64(mut n: u64, p: u64, inverse: f64) -> (u64, u8) {
202    if p == 2 {
203        let exp = u64::from(n.trailing_zeros());
204        if exp != 0 {
205            n >>= exp;
206        }
207        (n, u8::wrapping_from(exp))
208    } else {
209        let mut exp = 0;
210        while n >= p {
211            let (q, r) = div_rem_precomputed_float_u64(n, p, inverse);
212            if r != 0 {
213                break;
214            }
215            exp += 1;
216            n = q;
217        }
218        (n, exp)
219    }
220}
221
222// This is n_factor_trial_range when FLINT64 is false, from ulong_extras/factor_trial.c, FLINT
223// 3.1.2, where start == 0.
224fn factor_trial_range_u32(factors: &mut FactorsU32, mut n: u32, num_primes: usize) -> u32 {
225    for p in u32::primes().take(num_primes) {
226        if p.square() > n {
227            break;
228        }
229        let exp;
230        (n, exp) = remove_factor_precomputed_float_u32(n, p, 1.0 / f64::from(p));
231        if exp != 0 {
232            factors.insert(p, exp);
233        }
234    }
235    n
236}
237
238// This is n_factor_trial_range when FLINT64 is true, from ulong_extras/factor_trial.c, FLINT 3.1.2.
239fn factor_trial_range_u64(factors: &mut FactorsU64, mut n: u64, num_primes: usize) -> u64 {
240    for p in u64::primes().take(num_primes) {
241        if p.square() > n {
242            break;
243        }
244        let exp;
245        (n, exp) = remove_factor_precomputed_float_u64(n, p, 1.0 / (p as f64));
246        if exp != 0 {
247            factors.insert(p, exp);
248        }
249    }
250    n
251}
252
253const POWER235_MOD63: [u8; 63] = [
254    7, 7, 4, 0, 5, 4, 0, 5, 6, 5, 4, 4, 0, 4, 4, 0, 5, 4, 5, 4, 4, 0, 5, 4, 0, 5, 4, 6, 7, 4, 0, 4,
255    4, 0, 4, 6, 7, 5, 4, 0, 4, 4, 0, 5, 4, 4, 5, 4, 0, 5, 4, 0, 4, 4, 4, 6, 4, 0, 5, 4, 0, 4, 6,
256];
257const POWER235_MOD61: [u8; 61] = [
258    7, 7, 0, 3, 1, 1, 0, 0, 2, 3, 0, 6, 1, 5, 5, 1, 1, 0, 0, 1, 3, 4, 1, 2, 2, 1, 0, 3, 2, 4, 0, 0,
259    4, 2, 3, 0, 1, 2, 2, 1, 4, 3, 1, 0, 0, 1, 1, 5, 5, 1, 6, 0, 3, 2, 0, 0, 1, 1, 3, 0, 7,
260];
261const POWER235_MOD44: [u8; 44] = [
262    7, 7, 0, 2, 3, 3, 0, 2, 2, 3, 0, 6, 7, 2, 0, 2, 3, 2, 0, 2, 3, 6, 0, 6, 2, 3, 0, 2, 2, 2, 0, 2,
263    6, 7, 0, 2, 3, 3, 0, 2, 2, 2, 0, 6,
264];
265const POWER235_MOD31: [u8; 31] =
266    [7, 7, 3, 0, 3, 5, 4, 1, 3, 1, 1, 0, 0, 0, 1, 2, 3, 0, 1, 1, 1, 0, 0, 2, 0, 5, 4, 2, 1, 2, 6];
267
268// This is n_factor_power235 when FLINT64 is false, from ulong_extras/factor_power235.c, FLINT
269// 3.1.2, returning y and exp, and simplified to only include the branches used when factoring a
270// `u32`. In particular, only perfect squares are checked for.
271fn factor_square_u32(n: u32) -> (u32, u8) {
272    let mut t = POWER235_MOD31[(n % 31) as usize];
273    if t == 0 {
274        return (0, 0);
275    };
276    t &= POWER235_MOD44[(n % 44) as usize];
277    if t == 0 {
278        return (0, 0);
279    };
280    t &= POWER235_MOD61[(n % 61) as usize];
281    if t == 0 {
282        return (0, 0);
283    };
284    t &= POWER235_MOD63[(n % 63) as usize];
285    if t.odd() {
286        let (y, r) = n.sqrt_rem();
287        if r == 0 {
288            return (y, 2);
289        }
290    }
291    (0, 0)
292}
293
294// This is n_factor_power235 when FLINT64 is true, from ulong_extras/factor_power235.c, FLINT 3.1.2,
295// returning y and exp. Fifth powers are not checked for, because this function is only called on
296// values with no prime factor less than 27449, and 27449^5 is greater than 2^64.
297fn factor_power23_u64(n: u64) -> (u64, u8) {
298    let mut t = POWER235_MOD31[(n % 31) as usize];
299    if t == 0 {
300        return (0, 0);
301    };
302    t &= POWER235_MOD44[(n % 44) as usize];
303    if t == 0 {
304        return (0, 0);
305    };
306    t &= POWER235_MOD61[(n % 61) as usize];
307    if t == 0 {
308        return (0, 0);
309    };
310    t &= POWER235_MOD63[(n % 63) as usize];
311    if t.odd() {
312        let (y, r) = n.sqrt_rem();
313        if r == 0 {
314            return (y, 2);
315        }
316    }
317    if t & 2 != 0 {
318        let y = n.floor_root(3);
319        if n == y.pow(3) {
320            return (y, 3);
321        }
322    }
323    (0, 0)
324}
325
326const FLINT_ONE_LINE_MULTIPLIER: u32 = 480;
327
328// This is n_factor_one_line when FLINT64 is true, from ulong_extras/factor_one_line.c, FLINT 3.1.2.
329fn factor_one_line_u64(mut n: u64, iters: usize) -> u64 {
330    let orig_n = n;
331    n.wrapping_mul_assign(u64::from(FLINT_ONE_LINE_MULTIPLIER));
332    let mut iin = 0;
333    let mut inn = n;
334    for _ in 0..iters {
335        if iin >= inn {
336            break;
337        }
338        let mut sqrti = inn.floor_sqrt() + 1;
339        let square = sqrti.square();
340        let mmod = square - inn;
341        if mmod.is_square() {
342            sqrti -= mmod.floor_sqrt();
343            let factor = orig_n.gcd(sqrti);
344            if factor != 1 {
345                return factor;
346            }
347        }
348        iin = inn;
349        inn.wrapping_add_assign(n);
350    }
351    0
352}
353
354fn wyhash64(seed: &mut u64) -> u64 {
355    seed.wrapping_add_assign(0x60bee2bee120fc15);
356    let tmp = u128::from(*seed) * 0xa3b195354a39b70d;
357    let tmp = ((tmp >> 64) ^ tmp).wrapping_mul(0x1b03738712fad5c9);
358    u64::wrapping_from((tmp >> 64) ^ tmp)
359}
360
361struct WyhashRandomU64s {
362    seed: u64,
363}
364
365impl WyhashRandomU64s {
366    const fn new() -> Self {
367        Self {
368            seed: 0x452aee49c457bbc3,
369        }
370    }
371}
372
373impl Iterator for WyhashRandomU64s {
374    type Item = u64;
375
376    fn next(&mut self) -> Option<u64> {
377        Some(wyhash64(&mut self.seed))
378    }
379}
380
381// This is n_factor_pp1_table from ulong_extras/factor_pp1.c, FLINT 3.1.2.
382const N_FACTOR_PP1_TABLE: [(u16, u8); 34] = [
383    (2784, 5),
384    (1208, 2),
385    (2924, 3),
386    (286, 5),
387    (58, 5),
388    (61, 4),
389    (815, 2),
390    (944, 2),
391    (61, 3),
392    (0, 0),
393    (0, 0),
394    (0, 0),
395    (0, 0),
396    (0, 0),
397    (0, 0),
398    (0, 0),
399    (0, 0),
400    (0, 0),
401    (0, 0),
402    (606, 1),
403    (2403, 1),
404    (2524, 1),
405    (2924, 1),
406    (3735, 2),
407    (669, 2),
408    (6092, 3),
409    (2179, 3),
410    (3922, 3),
411    (6717, 4),
412    (4119, 4),
413    (2288, 4),
414    (9004, 3),
415    (9004, 3),
416    (9004, 3),
417];
418
419// This is n_pp1_pow_ui when FLINT64 is true, from ulong_extras/factor_pp1.c, FLINT 3.1.2, returning
420// the new values of x and y. y is not passed in as its initial value is never used.
421fn pp1_pow_ui_u64(mut x: u64, exp: u64, n: u64, ninv: u64, norm: u64) -> (u64, u64) {
422    let x_orig = x;
423    let two = u64::power_of_2(norm + 1);
424    let mut y = mul_mod_helper::<u64, u128>(x, x, n, ninv, norm).mod_sub(two, n);
425    let mut bit = u64::power_of_2(exp.significant_bits() - 2);
426    while bit != 0 {
427        (x, y) = if exp & bit != 0 {
428            (
429                mul_mod_helper::<u64, u128>(x, y, n, ninv, norm).mod_sub(x_orig, n),
430                mul_mod_helper::<u64, u128>(y, y, n, ninv, norm).mod_sub(two, n),
431            )
432        } else {
433            (
434                mul_mod_helper::<u64, u128>(x, x, n, ninv, norm).mod_sub(two, n),
435                mul_mod_helper::<u64, u128>(y, x, n, ninv, norm).mod_sub(x_orig, n),
436            )
437        };
438        bit >>= 1;
439    }
440    (x, y)
441}
442
443// This is n_pp1_factor when FLINT64 is true, from ulong_extras/factor_pp1.c, FLINT 3.1.2.
444fn pp1_factor_u64(mut n: u64, mut x: u64, norm: u64) -> u64 {
445    if norm != 0 {
446        n >>= norm;
447        x >>= norm;
448    }
449    x.mod_sub_assign(2, n);
450    if x == 0 { 0 } else { n.gcd(x) }
451}
452
453// This is n_pp1_find_power when FLINT64 is true, from ulong_extras/factor_pp1.c, FLINT 3.1.2,
454// returning factor and the new values of x and y. y is not passed in as its initial value is never
455// used.
456fn pp1_find_power_u64(mut x: u64, p: u64, n: u64, ninv: u64, norm: u64) -> (u64, u64, u64) {
457    let mut factor = 1;
458    let mut y = 0;
459    while factor == 1 {
460        (x, y) = pp1_pow_ui_u64(x, p, n, ninv, norm);
461        factor = pp1_factor_u64(n, x, norm);
462    }
463    (factor, x, y)
464}
465
466// This is n_factor_pp1 when FLINT64 is false, from ulong_extras/factor_pp1.c, FLINT 3.1.2. It is
467// assumed that n is odd.
468fn factor_pp1_u64(mut n: u64, b1: u64, c: u64) -> u64 {
469    let mut primes = u64::primes();
470    let sqrt = b1.floor_sqrt();
471    let bits0 = b1.significant_bits();
472    let norm = LeadingZeros::leading_zeros(n);
473    n <<= norm;
474    let n_inverse = u64::precompute_mod_mul_data(&n);
475    let mut x = c << norm;
476    // mul by various prime powers
477    let mut p = 0;
478    let mut old_p = 0;
479    let mut i = 0;
480    let mut old_x = 0;
481    while p < b1 {
482        let j = i + 1024;
483        old_p = p;
484        old_x = x;
485        while i < j {
486            p = primes.next().unwrap();
487            x = if p < sqrt {
488                pp1_pow_ui_u64(
489                    x,
490                    p.pow(u32::wrapping_from(bits0 / p.significant_bits())),
491                    n,
492                    n_inverse,
493                    norm,
494                )
495                .0
496            } else {
497                pp1_pow_ui_u64(x, p, n, n_inverse, norm).0
498            };
499            i += 1;
500        }
501        let factor = pp1_factor_u64(n, x, norm);
502        if factor == 0 {
503            break;
504        }
505        if factor != 1 {
506            return factor;
507        }
508    }
509    if p < b1 {
510        // factor = 0
511        primes.jump_after(old_p);
512        x = old_x;
513        loop {
514            p = primes.next().unwrap();
515            old_x = x;
516            x = if p < sqrt {
517                pp1_pow_ui_u64(
518                    x,
519                    p.pow(u32::wrapping_from(bits0 / p.significant_bits())),
520                    n,
521                    n_inverse,
522                    norm,
523                )
524                .0
525            } else {
526                pp1_pow_ui_u64(x, p, n, n_inverse, norm).0
527            };
528            let factor = pp1_factor_u64(n, x, norm);
529            if factor == 0 {
530                break;
531            }
532            if factor != 1 {
533                return factor;
534            }
535        }
536    } else {
537        return 0;
538    }
539    // factor still 0
540    pp1_find_power_u64(old_x, p, n, n_inverse, norm).0
541}
542
543// This is n_factor_pp1_wrapper when FLINT64 is true, from ulong_extras/factor_pp1.c, FLINT 3.1.2.
544fn factor_pp1_wrapper_u64(n: u64) -> u64 {
545    let bits = n.significant_bits();
546    // silently fail if trial factoring would always succeed
547    if bits < 31 {
548        return 0;
549    }
550    let (b1, count) = N_FACTOR_PP1_TABLE[usize::wrapping_from(bits) - 31];
551    let b1 = u64::from(b1);
552    let mut state = WyhashRandomU64s::new();
553    let mask = u64::low_mask((n - 4).significant_bits());
554    let limit = n - 3;
555    for _ in 0..count {
556        let mut randint = u64::MAX;
557        while randint >= limit {
558            randint = state.next().unwrap() & mask;
559        }
560        let factor = factor_pp1_u64(n, b1, randint + 3);
561        if factor != 0 {
562            return factor;
563        }
564    }
565    0
566}
567
568// This is equivalent to `mpn_sqrtrem` from `mpn/generic/sqrtrem.c`, GMP 6.2.1, where `rp` is not
569// `NULL` and `Limb == u64`, and the input has two limbs. One limb of the square root and two limbs
570// of the remainder are returned.
571#[doc(hidden)]
572fn limbs_sqrt_rem_to_out_u64(xs_hi: u64, xs_lo: u64) -> (u64, u64, u64, usize) {
573    let high = if xs_hi == 0 { xs_lo } else { xs_hi };
574    assert_ne!(high, 0);
575    let shift = LeadingZeros::leading_zeros(high) >> 1;
576    let two_shift = shift << 1;
577    if xs_hi == 0 {
578        let (sqrt_lo, rem_lo) = if shift == 0 {
579            sqrt_rem_newton::<u64, i64>(high)
580        } else {
581            let sqrt = sqrt_rem_newton::<u64, i64>(high << two_shift).0 >> shift;
582            (sqrt, high - sqrt.square())
583        };
584        (sqrt_lo, 0, rem_lo, usize::from(rem_lo != 0))
585    } else if shift == 0 {
586        let (sqrt_lo, rem_hi, rem_lo) = sqrt_rem_2_newton::<u64, i64>(xs_hi, xs_lo);
587        if rem_hi {
588            (sqrt_lo, 1, rem_lo, 2)
589        } else {
590            (sqrt_lo, 0, rem_lo, usize::from(rem_lo != 0))
591        }
592    } else {
593        let mut lo = xs_lo;
594        let hi = (high << two_shift) | (lo >> (u64::WIDTH - two_shift));
595        let sqrt_lo = sqrt_rem_2_newton::<u64, i64>(hi, lo << two_shift).0 >> shift;
596        lo.wrapping_sub_assign(sqrt_lo.wrapping_square());
597        (sqrt_lo, 0, lo, usize::from(lo != 0))
598    }
599}
600
601const FACTOR_SQUFOF_ITERS: usize = 50_000;
602const FACTOR_ONE_LINE_ITERS: usize = 40_000;
603
604// This is _ll_factor_SQUFOF when FLINT64 is true, from ulong_extras/factor_SQUFOF.c, FLINT 3.1.2.
605fn ll_factor_squfof_u64(n_hi: u64, n_lo: u64, max_iters: usize) -> u64 {
606    let (mut sqrt_lo, mut rem_lo, num) = if n_hi != 0 {
607        let (sqrt_lo, _, rem_lo, size) = limbs_sqrt_rem_to_out_u64(n_hi, n_lo);
608        (sqrt_lo, rem_lo, size)
609    } else {
610        let (sqrt_lo, rem_lo) = n_lo.sqrt_rem();
611        (sqrt_lo, rem_lo, usize::from(sqrt_lo != 0))
612    };
613    let sqroot = sqrt_lo;
614    let mut p = sqroot;
615    let mut q = rem_lo;
616    if q == 0 || num == 0 {
617        return sqroot;
618    }
619    let l = 1 + ((p << 1).floor_sqrt() << 1);
620    let l2 = l >> 1;
621    let mut qupto = 0;
622    let mut qlast = 1u64;
623    let mut qarr = [0; 50];
624    let mut r = 0;
625    let mut finished_loop = true;
626    for i in 0..max_iters {
627        let iq = (sqroot + p) / q;
628        let pnext = iq * q - p;
629        if q <= l {
630            if q.even() {
631                qarr[qupto] = q >> 1;
632                qupto += 1;
633                if qupto >= 50 {
634                    return 0;
635                }
636            } else if q <= l2 {
637                qarr[qupto] = q;
638                qupto += 1;
639                if qupto >= 50 {
640                    return 0;
641                }
642            }
643        }
644        let t = qlast.wrapping_add(iq.wrapping_mul(p.wrapping_sub(pnext)));
645        qlast = q;
646        q = t;
647        p = pnext;
648        if i.odd() || !q.is_square() {
649            continue;
650        }
651        r = q.floor_sqrt();
652        if qupto == 0 {
653            finished_loop = false;
654            break;
655        }
656        let mut done = true;
657        for &q in &qarr[..qupto] {
658            if r == q {
659                done = false;
660                break;
661            }
662        }
663        if done {
664            finished_loop = false;
665            break;
666        }
667        if r == 1 {
668            return 0;
669        }
670    }
671    if finished_loop {
672        return 0;
673    }
674    qlast = r;
675    p = p + r * ((sqroot - p) / r);
676    let rem_hi;
677    (rem_hi, rem_lo) = u64::x_mul_y_to_zz(p, p);
678    let sqrt_hi;
679    (sqrt_hi, sqrt_lo) = u64::xx_sub_yy_to_zz(n_hi, n_lo, rem_hi, rem_lo);
680    q = if sqrt_hi != 0 {
681        let norm = LeadingZeros::leading_zeros(qlast);
682        u64::xx_div_mod_y_to_qr(
683            (sqrt_hi << norm) + (sqrt_lo >> (u64::WIDTH - norm)),
684            sqrt_lo << norm,
685            qlast << norm,
686        )
687        .0
688    } else {
689        sqrt_lo / qlast
690    };
691    let mut finished_loop = true;
692    for _ in 0..max_iters {
693        let iq = (sqroot + p) / q;
694        let pnext = iq * q - p;
695        if p == pnext {
696            finished_loop = false;
697            break;
698        }
699        let t = qlast.wrapping_add(iq.wrapping_mul(p.wrapping_sub(pnext)));
700        qlast = q;
701        q = t;
702        p = pnext;
703    }
704    if finished_loop {
705        0
706    } else if q.even() {
707        q >> 1
708    } else {
709        q
710    }
711}
712
713// This is n_factor_SQUFOF when FLINT64 is true, from ulong_extras/factor_SQUFOF.c, FLINT 3.1.2.
714fn factor_squfof_u64(n: u64, iters: usize) -> u64 {
715    let mut factor = ll_factor_squfof_u64(0, n, iters);
716    let mut finished_loop = true;
717    for &p in &SMALL_PRIMES[1..] {
718        if factor != 0 {
719            finished_loop = false;
720            break;
721        }
722        let multiplier = u64::from(p);
723        let (multn_1, multn_0) = u64::x_mul_y_to_zz(multiplier, n);
724        factor = ll_factor_squfof_u64(multn_1, multn_0, iters);
725        if factor != 0 {
726            let (quot, rem) = factor.div_mod(multiplier);
727            if rem == 0 {
728                factor = quot;
729            }
730            if factor == 1 || factor == n {
731                factor = 0;
732            }
733        }
734    }
735    if finished_loop { 0 } else { factor }
736}
737
738const FACTOR_TRIAL_PRIMES: usize = 3000;
739const FACTOR_TRIAL_CUTOFF: u32 = 27449 * 27449;
740
741impl Factor for u8 {
742    type FACTORS = FactorsU8;
743
744    /// Returns the prime factorization of a `u8`. The return value is iterable, and produces pairs
745    /// $(p,e)$ of type `(u8, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. The
746    /// primes are in ascending order.
747    ///
748    /// # Worst-case complexity
749    /// Constant time and additional memory.
750    ///
751    /// # Panics
752    /// Panics if `self` is 0.
753    ///
754    /// # Examples
755    /// ```
756    /// use itertools::Itertools;
757    /// use malachite_base::num::factorization::traits::Factor;
758    ///
759    /// assert_eq!(251u8.factor().into_iter().collect_vec(), &[(251, 1)]);
760    /// assert_eq!(
761    ///     120u8.factor().into_iter().collect_vec(),
762    ///     &[(2, 3), (3, 1), (5, 1)]
763    /// );
764    /// ```
765    fn factor(&self) -> FactorsU8 {
766        assert_ne!(*self, 0);
767        let mut n = *self;
768        let mut factors = FactorsU8::new();
769        if n == 1 {
770            return factors;
771        }
772        let zeros = n.trailing_zeros();
773        if zeros != 0 {
774            factors.insert(2, zeros as Self);
775            n >>= zeros;
776            if n == 1 {
777                return factors;
778            }
779        }
780        let mut e;
781        let (q, r) = n.div_mod(3);
782        if r == 0 {
783            e = 1;
784            n = q;
785            let (q, r) = n.div_mod(3);
786            if r == 0 {
787                e = 2;
788                n = q;
789                let (q, r) = n.div_mod(3);
790                if r == 0 {
791                    e = 3;
792                    n = q;
793                    let (q, r) = n.div_mod(3);
794                    if r == 0 {
795                        e = 4;
796                        n = q;
797                        if n == 3 {
798                            e = 5;
799                            n = 1;
800                        }
801                    }
802                }
803            }
804            factors.insert(3, e);
805            if n == 1 {
806                return factors;
807            }
808        }
809        let (q, r) = n.div_mod(5);
810        if r == 0 {
811            e = 1;
812            n = q;
813            let (q, r) = n.div_mod(5);
814            if r == 0 {
815                e = 2;
816                n = q;
817                if n == 5 {
818                    e = 3;
819                    n = 1;
820                }
821            }
822            factors.insert(5, e);
823            if n == 1 {
824                return factors;
825            }
826        }
827        let (q, r) = n.div_mod(7);
828        if r == 0 {
829            e = 1;
830            n = q;
831            if n == 7 {
832                e = 2;
833                n = 1;
834            }
835            factors.insert(7, e);
836            if n == 1 {
837                return factors;
838            }
839        }
840        match n {
841            121 => {
842                factors.insert(11, 2);
843            }
844            143 => {
845                factors.insert(11, 1);
846                factors.insert(13, 1);
847            }
848            169 => {
849                factors.insert(13, 2);
850            }
851            187 => {
852                factors.insert(11, 1);
853                factors.insert(17, 1);
854            }
855            209 => {
856                factors.insert(11, 1);
857                factors.insert(19, 1);
858            }
859            221 => {
860                factors.insert(13, 1);
861                factors.insert(17, 1);
862            }
863            247 => {
864                factors.insert(13, 1);
865                factors.insert(19, 1);
866            }
867            253 => {
868                factors.insert(11, 1);
869                factors.insert(23, 1);
870            }
871            _ => {
872                factors.insert(n, 1);
873            }
874        }
875        factors
876    }
877}
878
879impl Factor for u16 {
880    type FACTORS = FactorsU16;
881
882    /// Returns the prime factorization of a `u16`. The return value is iterable, and produces pairs
883    /// $(p,e)$ of type `(u16, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. The
884    /// primes are in ascending order.
885    ///
886    /// # Worst-case complexity
887    /// $T(n) = O(2^{n/4})$
888    ///
889    /// $M(n) = O(2^n)$
890    ///
891    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
892    ///
893    /// # Panics
894    /// Panics if `self` is 0.
895    ///
896    /// # Examples
897    /// ```
898    /// use itertools::Itertools;
899    /// use malachite_base::num::factorization::traits::Factor;
900    ///
901    /// assert_eq!(65521u16.factor().into_iter().collect_vec(), &[(65521, 1)]);
902    /// assert_eq!(
903    ///     40320u16.factor().into_iter().collect_vec(),
904    ///     &[(2, 7), (3, 2), (5, 1), (7, 1)]
905    /// );
906    /// ```
907    fn factor(&self) -> FactorsU16 {
908        let mut factors = FactorsU16::new();
909        for (f, e) in u32::from(*self).factor() {
910            factors.insert(f as Self, e);
911        }
912        factors
913    }
914}
915
916impl Factor for u32 {
917    type FACTORS = FactorsU32;
918
919    /// Returns the prime factorization of a `u32`. The return value is iterable, and produces pairs
920    /// $(p,e)$ of type `(u32, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. The
921    /// primes are in ascending order.
922    ///
923    /// # Worst-case complexity
924    /// $T(n) = O(2^{n/4})$
925    ///
926    /// $M(n) = O(2^n)$
927    ///
928    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
929    ///
930    /// # Panics
931    /// Panics if `self` is 0.
932    ///
933    /// # Examples
934    /// ```
935    /// use itertools::Itertools;
936    /// use malachite_base::num::factorization::traits::Factor;
937    ///
938    /// assert_eq!(
939    ///     4294967291u32.factor().into_iter().collect_vec(),
940    ///     &[(4294967291, 1)]
941    /// );
942    /// assert_eq!(
943    ///     479001600u32.factor().into_iter().collect_vec(),
944    ///     &[(2, 10), (3, 5), (5, 2), (7, 1), (11, 1)]
945    /// );
946    /// ```
947    ///
948    /// This is n_factor when FLINT64 is false, from ulong_extras/factor.c, FLINT 3.1.2.
949    fn factor(&self) -> FactorsU32 {
950        let n = *self;
951        assert_ne!(n, 0);
952        let mut factors = FactorsU32::new();
953        let cofactor = factor_trial_range_u32(&mut factors, n, FACTOR_TRIAL_PRIMES);
954        if cofactor == 1 {
955            return factors;
956        }
957        if cofactor.is_prime() {
958            factors.insert(cofactor, 1);
959            return factors;
960        }
961        let mut factor_arr = [0; MAX_FACTORS_IN_U32];
962        let mut exp_arr = [0; MAX_FACTORS_IN_U32];
963        factor_arr[0] = cofactor;
964        let mut factors_left = 1;
965        exp_arr[0] = 1;
966        let cutoff = FACTOR_TRIAL_CUTOFF;
967        while factors_left != 0 {
968            let mut factor = factor_arr[factors_left - 1];
969            if factor >= cutoff {
970                let (mut cofactor, exp) = factor_square_u32(factor);
971                if cofactor != 0 {
972                    exp_arr[factors_left - 1] *= exp;
973                    factor = cofactor;
974                    factor_arr[factors_left - 1] = factor;
975                }
976                if factor >= cutoff && !factor.is_prime() {
977                    cofactor = Self::exact_from(factor_one_line_u64(
978                        u64::from(factor),
979                        FACTOR_ONE_LINE_ITERS,
980                    ));
981                    exp_arr[factors_left] = exp_arr[factors_left - 1];
982                    factor_arr[factors_left] = cofactor;
983                    factor_arr[factors_left - 1] /= cofactor;
984                    factors_left += 1;
985                } else {
986                    factors.insert(factor, exp_arr[factors_left - 1]);
987                    factors_left -= 1;
988                }
989            } else {
990                factors.insert(factor, exp_arr[factors_left - 1]);
991                factors_left -= 1;
992            }
993        }
994        factors
995    }
996}
997
998const FACTOR_ONE_LINE_MAX: u64 = 1 << 39;
999
1000impl Factor for u64 {
1001    type FACTORS = FactorsU64;
1002
1003    /// Returns the prime factorization of a `u64`. The return value is iterable, and produces pairs
1004    /// $(p,e)$ of type `(u64, u8)`, where the $p$ is prime and $e$ is the exponent of $p$. The
1005    /// primes are in ascending order.
1006    ///
1007    /// # Worst-case complexity
1008    /// $T(n) = O(2^{n/4})$
1009    ///
1010    /// $M(n) = O(2^n)$
1011    ///
1012    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1013    ///
1014    /// # Panics
1015    /// Panics if `self` is 0.
1016    ///
1017    /// # Examples
1018    /// ```
1019    /// use itertools::Itertools;
1020    /// use malachite_base::num::factorization::traits::Factor;
1021    ///
1022    /// assert_eq!(
1023    ///     18446744073709551557u64.factor().into_iter().collect_vec(),
1024    ///     &[(18446744073709551557, 1)]
1025    /// );
1026    /// assert_eq!(
1027    ///     2432902008176640000u64.factor().into_iter().collect_vec(),
1028    ///     &[(2, 18), (3, 8), (5, 4), (7, 2), (11, 1), (13, 1), (17, 1), (19, 1)]
1029    /// );
1030    /// ```
1031    ///
1032    /// This is n_factor when FLINT64 is true, from ulong_extras/factor.c, FLINT 3.1.2.
1033    fn factor(&self) -> FactorsU64 {
1034        let n = *self;
1035        assert_ne!(n, 0);
1036        let mut factors = FactorsU64::new();
1037        let cofactor = factor_trial_range_u64(&mut factors, n, FACTOR_TRIAL_PRIMES);
1038        if cofactor == 1 {
1039            return factors;
1040        }
1041        if cofactor.is_prime() {
1042            factors.insert(cofactor, 1);
1043            return factors;
1044        }
1045        let mut factor_arr = [0; MAX_FACTORS_IN_U64];
1046        let mut exp_arr = [0; MAX_FACTORS_IN_U64];
1047        factor_arr[0] = cofactor;
1048        let mut factors_left = 1;
1049        exp_arr[0] = 1;
1050        const CUTOFF: u64 = FACTOR_TRIAL_CUTOFF as u64;
1051        while factors_left != 0 {
1052            let mut factor = factor_arr[factors_left - 1];
1053            if factor >= CUTOFF {
1054                let (mut cofactor, exp) = factor_power23_u64(factor);
1055                if cofactor != 0 {
1056                    exp_arr[factors_left - 1] *= exp;
1057                    factor = cofactor;
1058                    factor_arr[factors_left - 1] = factor;
1059                }
1060                if factor >= CUTOFF && !factor.is_prime() {
1061                    cofactor = 0;
1062                    if factor < FACTOR_ONE_LINE_MAX {
1063                        cofactor = factor_one_line_u64(factor, FACTOR_ONE_LINE_ITERS);
1064                    }
1065                    if cofactor == 0 {
1066                        cofactor = factor_pp1_wrapper_u64(factor);
1067                        if cofactor == 0 {
1068                            cofactor = factor_squfof_u64(factor, FACTOR_SQUFOF_ITERS);
1069                            assert_ne!(cofactor, 0);
1070                        }
1071                    }
1072                    exp_arr[factors_left] = exp_arr[factors_left - 1];
1073                    factor_arr[factors_left] = cofactor;
1074                    factor_arr[factors_left - 1] /= cofactor;
1075                    factors_left += 1;
1076                } else {
1077                    factors.insert(factor, exp_arr[factors_left - 1]);
1078                    factors_left -= 1;
1079                }
1080            } else {
1081                factors.insert(factor, exp_arr[factors_left - 1]);
1082                factors_left -= 1;
1083            }
1084        }
1085        factors
1086    }
1087}
1088
1089impl Factor for usize {
1090    type FACTORS = FactorsUsize;
1091
1092    /// Returns the prime factorization of a `usize`. The return value is iterable, and produces
1093    /// pairs $(p,e)$ of type `(usize, u8)`, where the $p$ is prime and $e$ is the exponent of $p$.
1094    /// The primes are in ascending order.
1095    ///
1096    /// # Worst-case complexity
1097    /// $T(n) = O(2^{n/4})$
1098    ///
1099    /// $M(n) = O(2^n)$
1100    ///
1101    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1102    ///
1103    /// # Panics
1104    /// Panics if `self` is 0.
1105    ///
1106    /// # Examples
1107    /// ```
1108    /// use itertools::Itertools;
1109    /// use malachite_base::num::factorization::traits::Factor;
1110    ///
1111    /// assert_eq!(
1112    ///     4294967291usize.factor().into_iter().collect_vec(),
1113    ///     &[(4294967291, 1)]
1114    /// );
1115    /// assert_eq!(
1116    ///     479001600usize.factor().into_iter().collect_vec(),
1117    ///     &[(2, 10), (3, 5), (5, 2), (7, 1), (11, 1)]
1118    /// );
1119    /// ```
1120    fn factor(&self) -> FactorsUsize {
1121        let mut factors = FactorsUsize::new();
1122        if USIZE_IS_U32 {
1123            for (f, e) in (*self as u32).factor() {
1124                factors.insert(f as Self, e);
1125            }
1126        } else {
1127            for (f, e) in (*self as u64).factor() {
1128                factors.insert(f as Self, e);
1129            }
1130        }
1131        factors
1132    }
1133}