use crate::num::arithmetic::mod_pow::mul_mod_helper;
use crate::num::arithmetic::sqrt::{sqrt_rem_2_newton, sqrt_rem_newton};
use crate::num::arithmetic::traits::{
DivMod, FloorRoot, FloorSqrt, Gcd, ModMulPrecomputed, ModSub, ModSubAssign, Parity, PowerOf2,
SqrtRem, Square, WrappingAddAssign, WrappingMulAssign, WrappingSquare, WrappingSubAssign,
XMulYToZZ, XXDivModYToQR, XXSubYYToZZ,
};
use crate::num::basic::integers::{PrimitiveInt, USIZE_IS_U32};
use crate::num::basic::unsigneds::PrimitiveUnsigned;
use crate::num::conversion::traits::{ExactFrom, WrappingFrom};
use crate::num::factorization::primes::SMALL_PRIMES;
use crate::num::factorization::traits::{Factor, IsPrime, IsSquare, Primes};
use crate::num::logic::traits::{LeadingZeros, LowMask, SignificantBits};
use core::mem::swap;
pub(crate) const MAX_FACTORS_IN_U8: usize = 4;
pub(crate) const MAX_FACTORS_IN_U16: usize = 6;
pub(crate) const MAX_FACTORS_IN_U32: usize = 9;
pub(crate) const MAX_FACTORS_IN_U64: usize = 15;
pub(crate) const MAX_FACTORS_IN_USIZE: usize = 15;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Factors<T: PrimitiveUnsigned, const N: usize> {
factors: [T; N],
exponents: [u8; N],
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FactorsIterator<T: PrimitiveUnsigned, const N: usize> {
i: usize,
factors: Factors<T, N>,
}
impl<T: PrimitiveUnsigned, const N: usize> Iterator for FactorsIterator<T, N> {
type Item = (T, u8);
fn next(&mut self) -> Option<(T, u8)> {
let e = *self.factors.exponents.get(self.i)?;
if e == 0 {
return None;
}
let f = self.factors.factors[self.i];
self.i += 1;
Some((f, e))
}
}
impl<T: PrimitiveUnsigned, const N: usize> IntoIterator for Factors<T, N> {
type IntoIter = FactorsIterator<T, N>;
type Item = (T, u8);
fn into_iter(self) -> FactorsIterator<T, N> {
FactorsIterator {
i: 0,
factors: self,
}
}
}
impl<T: PrimitiveUnsigned, const N: usize> Factors<T, N> {
const fn new() -> Self {
Self {
factors: [T::ZERO; N],
exponents: [0; N],
}
}
fn insert(&mut self, factor: T, exp: u8) {
let mut inserting = false;
let mut previous_f = T::ZERO;
let mut previous_e = 0;
for (f, e) in self.factors.iter_mut().zip(self.exponents.iter_mut()) {
if inserting {
swap(&mut previous_f, f);
swap(&mut previous_e, e);
if previous_e == 0 {
break;
}
} else if *e == 0 {
*f = factor;
*e = exp;
break;
} else if *f == factor {
*e += exp;
break;
} else if *f > factor {
previous_f = *f;
previous_e = *e;
*f = factor;
*e = exp;
inserting = true;
}
}
}
}
type FactorsU8 = Factors<u8, MAX_FACTORS_IN_U8>;
type FactorsU16 = Factors<u16, MAX_FACTORS_IN_U16>;
type FactorsU32 = Factors<u32, MAX_FACTORS_IN_U32>;
type FactorsU64 = Factors<u64, MAX_FACTORS_IN_U64>;
type FactorsUsize = Factors<usize, MAX_FACTORS_IN_USIZE>;
fn div_rem_precomputed_float_for_u32_factorization(a: u32, n: u32, inverse: f64) -> (u32, u32) {
let mut q = (f64::from(a) * inverse) as u32;
let r = a.wrapping_sub(q * n);
let ri = i32::wrapping_from(r);
if ri >= i32::wrapping_from(n) {
q += (f64::from(ri) * inverse) as u32;
(q + 1, a.wrapping_sub(q * n).wrapping_sub(n))
} else {
(q, r)
}
}
fn div_rem_precomputed_float_u64(a: u64, n: u64, npre: f64) -> (u64, u64) {
if a < n {
return (0, a);
}
if n.get_highest_bit() {
return (1, a.wrapping_sub(n));
}
let (mut q, r) = if n == 1 {
(a, 0)
} else {
let q = ((a as f64) * npre) as u64;
(q, a.wrapping_sub(q.wrapping_mul(n)))
};
let ri = i64::wrapping_from(r);
let ni = i64::wrapping_from(n);
if ri < ni.wrapping_neg() {
q -= ((-(ri as f64)) * npre) as u64;
} else if ri >= ni {
q += ((ri as f64) * npre) as u64;
} else if ri < 0 {
return (q - 1, r.wrapping_add(n));
} else {
return (q, r);
}
let r = a.wrapping_sub(q.wrapping_mul(n));
let ri = i64::wrapping_from(r);
if ri >= ni {
(q + 1, r.wrapping_sub(n))
} else if ri < 0 {
(q - 1, r.wrapping_add(n))
} else {
(q, r)
}
}
fn remove_factor_precomputed_float_u32(mut n: u32, p: u32, inverse: f64) -> (u32, u8) {
if p == 2 {
let exp = n.trailing_zeros();
if exp != 0 {
n >>= exp;
}
(n, u8::wrapping_from(exp))
} else {
let mut exp = 0;
while n >= p {
let (q, r) = div_rem_precomputed_float_for_u32_factorization(n, p, inverse);
if r != 0 {
break;
}
exp += 1;
n = q;
}
(n, exp)
}
}
fn remove_factor_precomputed_float_u64(mut n: u64, p: u64, inverse: f64) -> (u64, u8) {
if p == 2 {
let exp = u64::from(n.trailing_zeros());
if exp != 0 {
n >>= exp;
}
(n, u8::wrapping_from(exp))
} else {
let mut exp = 0;
while n >= p {
let (q, r) = div_rem_precomputed_float_u64(n, p, inverse);
if r != 0 {
break;
}
exp += 1;
n = q;
}
(n, exp)
}
}
fn factor_trial_range_u32(factors: &mut FactorsU32, mut n: u32, num_primes: usize) -> u32 {
for p in u32::primes().take(num_primes) {
if p.square() > n {
break;
}
let exp;
(n, exp) = remove_factor_precomputed_float_u32(n, p, 1.0 / f64::from(p));
if exp != 0 {
factors.insert(p, exp);
}
}
n
}
fn factor_trial_range_u64(factors: &mut FactorsU64, mut n: u64, num_primes: usize) -> u64 {
for p in u64::primes().take(num_primes) {
if p.square() > n {
break;
}
let exp;
(n, exp) = remove_factor_precomputed_float_u64(n, p, 1.0 / (p as f64));
if exp != 0 {
factors.insert(p, exp);
}
}
n
}
const POWER235_MOD63: [u8; 63] = [
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,
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,
];
const POWER235_MOD61: [u8; 61] = [
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,
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,
];
const POWER235_MOD44: [u8; 44] = [
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,
6, 7, 0, 2, 3, 3, 0, 2, 2, 2, 0, 6,
];
const POWER235_MOD31: [u8; 31] =
[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];
fn factor_square_u32(n: u32) -> (u32, u8) {
let mut t = POWER235_MOD31[(n % 31) as usize];
if t == 0 {
return (0, 0);
};
t &= POWER235_MOD44[(n % 44) as usize];
if t == 0 {
return (0, 0);
};
t &= POWER235_MOD61[(n % 61) as usize];
if t == 0 {
return (0, 0);
};
t &= POWER235_MOD63[(n % 63) as usize];
if t.odd() {
let (y, r) = n.sqrt_rem();
if r == 0 {
return (y, 2);
}
}
(0, 0)
}
fn factor_power23_u64(n: u64) -> (u64, u8) {
let mut t = POWER235_MOD31[(n % 31) as usize];
if t == 0 {
return (0, 0);
};
t &= POWER235_MOD44[(n % 44) as usize];
if t == 0 {
return (0, 0);
};
t &= POWER235_MOD61[(n % 61) as usize];
if t == 0 {
return (0, 0);
};
t &= POWER235_MOD63[(n % 63) as usize];
if t.odd() {
let (y, r) = n.sqrt_rem();
if r == 0 {
return (y, 2);
}
}
if t & 2 != 0 {
let y = n.floor_root(3);
if n == y.pow(3) {
return (y, 3);
}
}
(0, 0)
}
const FLINT_ONE_LINE_MULTIPLIER: u32 = 480;
fn factor_one_line_u64(mut n: u64, iters: usize) -> u64 {
let orig_n = n;
n.wrapping_mul_assign(u64::from(FLINT_ONE_LINE_MULTIPLIER));
let mut iin = 0;
let mut inn = n;
for _ in 0..iters {
if iin >= inn {
break;
}
let mut sqrti = inn.floor_sqrt() + 1;
let square = sqrti.square();
let mmod = square - inn;
if mmod.is_square() {
sqrti -= mmod.floor_sqrt();
let factor = orig_n.gcd(sqrti);
if factor != 1 {
return factor;
}
}
iin = inn;
inn.wrapping_add_assign(n);
}
0
}
fn wyhash64(seed: &mut u64) -> u64 {
seed.wrapping_add_assign(0x60bee2bee120fc15);
let tmp = u128::from(*seed) * 0xa3b195354a39b70d;
let tmp = ((tmp >> 64) ^ tmp).wrapping_mul(0x1b03738712fad5c9);
u64::wrapping_from((tmp >> 64) ^ tmp)
}
struct WyhashRandomU64s {
seed: u64,
}
impl WyhashRandomU64s {
const fn new() -> Self {
Self {
seed: 0x452aee49c457bbc3,
}
}
}
impl Iterator for WyhashRandomU64s {
type Item = u64;
fn next(&mut self) -> Option<u64> {
Some(wyhash64(&mut self.seed))
}
}
const N_FACTOR_PP1_TABLE: [(u16, u8); 34] = [
(2784, 5),
(1208, 2),
(2924, 3),
(286, 5),
(58, 5),
(61, 4),
(815, 2),
(944, 2),
(61, 3),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(0, 0),
(606, 1),
(2403, 1),
(2524, 1),
(2924, 1),
(3735, 2),
(669, 2),
(6092, 3),
(2179, 3),
(3922, 3),
(6717, 4),
(4119, 4),
(2288, 4),
(9004, 3),
(9004, 3),
(9004, 3),
];
fn pp1_pow_ui_u64(mut x: u64, exp: u64, n: u64, ninv: u64, norm: u64) -> (u64, u64) {
let x_orig = x;
let two = u64::power_of_2(norm + 1);
let mut y = mul_mod_helper::<u64, u128>(x, x, n, ninv, norm).mod_sub(two, n);
let mut bit = u64::power_of_2(exp.significant_bits() - 2);
while bit != 0 {
(x, y) = if exp & bit != 0 {
(
mul_mod_helper::<u64, u128>(x, y, n, ninv, norm).mod_sub(x_orig, n),
mul_mod_helper::<u64, u128>(y, y, n, ninv, norm).mod_sub(two, n),
)
} else {
(
mul_mod_helper::<u64, u128>(x, x, n, ninv, norm).mod_sub(two, n),
mul_mod_helper::<u64, u128>(y, x, n, ninv, norm).mod_sub(x_orig, n),
)
};
bit >>= 1;
}
(x, y)
}
fn pp1_factor_u64(mut n: u64, mut x: u64, norm: u64) -> u64 {
if norm != 0 {
n >>= norm;
x >>= norm;
}
x.mod_sub_assign(2, n);
if x == 0 { 0 } else { n.gcd(x) }
}
fn pp1_find_power_u64(mut x: u64, p: u64, n: u64, ninv: u64, norm: u64) -> (u64, u64, u64) {
let mut factor = 1;
let mut y = 0;
while factor == 1 {
(x, y) = pp1_pow_ui_u64(x, p, n, ninv, norm);
factor = pp1_factor_u64(n, x, norm);
}
(factor, x, y)
}
fn factor_pp1_u64(mut n: u64, b1: u64, c: u64) -> u64 {
let mut primes = u64::primes();
let sqrt = b1.floor_sqrt();
let bits0 = b1.significant_bits();
let norm = LeadingZeros::leading_zeros(n);
n <<= norm;
let n_inverse = u64::precompute_mod_mul_data(&n);
let mut x = c << norm;
let mut p = 0;
let mut old_p = 0;
let mut i = 0;
let mut old_x = 0;
while p < b1 {
let j = i + 1024;
old_p = p;
old_x = x;
while i < j {
p = primes.next().unwrap();
x = if p < sqrt {
pp1_pow_ui_u64(
x,
p.pow(u32::wrapping_from(bits0 / p.significant_bits())),
n,
n_inverse,
norm,
)
.0
} else {
pp1_pow_ui_u64(x, p, n, n_inverse, norm).0
};
i += 1;
}
let factor = pp1_factor_u64(n, x, norm);
if factor == 0 {
break;
}
if factor != 1 {
return factor;
}
}
if p < b1 {
primes.jump_after(old_p);
x = old_x;
loop {
p = primes.next().unwrap();
old_x = x;
x = if p < sqrt {
pp1_pow_ui_u64(
x,
p.pow(u32::wrapping_from(bits0 / p.significant_bits())),
n,
n_inverse,
norm,
)
.0
} else {
pp1_pow_ui_u64(x, p, n, n_inverse, norm).0
};
let factor = pp1_factor_u64(n, x, norm);
if factor == 0 {
break;
}
if factor != 1 {
return factor;
}
}
} else {
return 0;
}
pp1_find_power_u64(old_x, p, n, n_inverse, norm).0
}
fn factor_pp1_wrapper_u64(n: u64) -> u64 {
let bits = n.significant_bits();
if bits < 31 {
return 0;
}
let (b1, count) = N_FACTOR_PP1_TABLE[usize::wrapping_from(bits) - 31];
let b1 = u64::from(b1);
let mut state = WyhashRandomU64s::new();
let mask = u64::low_mask((n - 4).significant_bits());
let limit = n - 3;
for _ in 0..count {
let mut randint = u64::MAX;
while randint >= limit {
randint = state.next().unwrap() & mask;
}
let factor = factor_pp1_u64(n, b1, randint + 3);
if factor != 0 {
return factor;
}
}
0
}
#[doc(hidden)]
fn limbs_sqrt_rem_to_out_u64(xs_hi: u64, xs_lo: u64) -> (u64, u64, u64, usize) {
let high = if xs_hi == 0 { xs_lo } else { xs_hi };
assert_ne!(high, 0);
let shift = LeadingZeros::leading_zeros(high) >> 1;
let two_shift = shift << 1;
if xs_hi == 0 {
let (sqrt_lo, rem_lo) = if shift == 0 {
sqrt_rem_newton::<u64, i64>(high)
} else {
let sqrt = sqrt_rem_newton::<u64, i64>(high << two_shift).0 >> shift;
(sqrt, high - sqrt.square())
};
(sqrt_lo, 0, rem_lo, usize::from(rem_lo != 0))
} else if shift == 0 {
let (sqrt_lo, rem_hi, rem_lo) = sqrt_rem_2_newton::<u64, i64>(xs_hi, xs_lo);
if rem_hi {
(sqrt_lo, 1, rem_lo, 2)
} else {
(sqrt_lo, 0, rem_lo, usize::from(rem_lo != 0))
}
} else {
let mut lo = xs_lo;
let hi = (high << two_shift) | (lo >> (u64::WIDTH - two_shift));
let sqrt_lo = sqrt_rem_2_newton::<u64, i64>(hi, lo << two_shift).0 >> shift;
lo.wrapping_sub_assign(sqrt_lo.wrapping_square());
(sqrt_lo, 0, lo, usize::from(lo != 0))
}
}
const FACTOR_SQUFOF_ITERS: usize = 50_000;
const FACTOR_ONE_LINE_ITERS: usize = 40_000;
fn ll_factor_squfof_u64(n_hi: u64, n_lo: u64, max_iters: usize) -> u64 {
let (mut sqrt_lo, mut rem_lo, num) = if n_hi != 0 {
let (sqrt_lo, _, rem_lo, size) = limbs_sqrt_rem_to_out_u64(n_hi, n_lo);
(sqrt_lo, rem_lo, size)
} else {
let (sqrt_lo, rem_lo) = n_lo.sqrt_rem();
(sqrt_lo, rem_lo, usize::from(sqrt_lo != 0))
};
let sqroot = sqrt_lo;
let mut p = sqroot;
let mut q = rem_lo;
if q == 0 || num == 0 {
return sqroot;
}
let l = 1 + ((p << 1).floor_sqrt() << 1);
let l2 = l >> 1;
let mut qupto = 0;
let mut qlast = 1u64;
let mut qarr = [0; 50];
let mut r = 0;
let mut finished_loop = true;
for i in 0..max_iters {
let iq = (sqroot + p) / q;
let pnext = iq * q - p;
if q <= l {
if q.even() {
qarr[qupto] = q >> 1;
qupto += 1;
if qupto >= 50 {
return 0;
}
} else if q <= l2 {
qarr[qupto] = q;
qupto += 1;
if qupto >= 50 {
return 0;
}
}
}
let t = qlast.wrapping_add(iq.wrapping_mul(p.wrapping_sub(pnext)));
qlast = q;
q = t;
p = pnext;
if i.odd() || !q.is_square() {
continue;
}
r = q.floor_sqrt();
if qupto == 0 {
finished_loop = false;
break;
}
let mut done = true;
for &q in &qarr[..qupto] {
if r == q {
done = false;
break;
}
}
if done {
finished_loop = false;
break;
}
if r == 1 {
return 0;
}
}
if finished_loop {
return 0;
}
qlast = r;
p = p + r * ((sqroot - p) / r);
let rem_hi;
(rem_hi, rem_lo) = u64::x_mul_y_to_zz(p, p);
let sqrt_hi;
(sqrt_hi, sqrt_lo) = u64::xx_sub_yy_to_zz(n_hi, n_lo, rem_hi, rem_lo);
q = if sqrt_hi != 0 {
let norm = LeadingZeros::leading_zeros(qlast);
u64::xx_div_mod_y_to_qr(
(sqrt_hi << norm) + (sqrt_lo >> (u64::WIDTH - norm)),
sqrt_lo << norm,
qlast << norm,
)
.0
} else {
sqrt_lo / qlast
};
let mut finished_loop = true;
for _ in 0..max_iters {
let iq = (sqroot + p) / q;
let pnext = iq * q - p;
if p == pnext {
finished_loop = false;
break;
}
let t = qlast.wrapping_add(iq.wrapping_mul(p.wrapping_sub(pnext)));
qlast = q;
q = t;
p = pnext;
}
if finished_loop {
0
} else if q.even() {
q >> 1
} else {
q
}
}
fn factor_squfof_u64(n: u64, iters: usize) -> u64 {
let mut factor = ll_factor_squfof_u64(0, n, iters);
let mut finished_loop = true;
for &p in &SMALL_PRIMES[1..] {
if factor != 0 {
finished_loop = false;
break;
}
let multiplier = u64::from(p);
let (multn_1, multn_0) = u64::x_mul_y_to_zz(multiplier, n);
factor = ll_factor_squfof_u64(multn_1, multn_0, iters);
if factor != 0 {
let (quot, rem) = factor.div_mod(multiplier);
if rem == 0 {
factor = quot;
}
if factor == 1 || factor == n {
factor = 0;
}
}
}
if finished_loop { 0 } else { factor }
}
const FACTOR_TRIAL_PRIMES: usize = 3000;
const FACTOR_TRIAL_CUTOFF: u32 = 27449 * 27449;
impl Factor for u8 {
type FACTORS = FactorsU8;
fn factor(&self) -> FactorsU8 {
assert_ne!(*self, 0);
let mut n = *self;
let mut factors = FactorsU8::new();
if n == 1 {
return factors;
}
let zeros = n.trailing_zeros();
if zeros != 0 {
factors.insert(2, zeros as Self);
n >>= zeros;
if n == 1 {
return factors;
}
}
let mut e;
let (q, r) = n.div_mod(3);
if r == 0 {
e = 1;
n = q;
let (q, r) = n.div_mod(3);
if r == 0 {
e = 2;
n = q;
let (q, r) = n.div_mod(3);
if r == 0 {
e = 3;
n = q;
let (q, r) = n.div_mod(3);
if r == 0 {
e = 4;
n = q;
if n == 3 {
e = 5;
n = 1;
}
}
}
}
factors.insert(3, e);
if n == 1 {
return factors;
}
}
let (q, r) = n.div_mod(5);
if r == 0 {
e = 1;
n = q;
let (q, r) = n.div_mod(5);
if r == 0 {
e = 2;
n = q;
if n == 5 {
e = 3;
n = 1;
}
}
factors.insert(5, e);
if n == 1 {
return factors;
}
}
let (q, r) = n.div_mod(7);
if r == 0 {
e = 1;
n = q;
if n == 7 {
e = 2;
n = 1;
}
factors.insert(7, e);
if n == 1 {
return factors;
}
}
match n {
121 => {
factors.insert(11, 2);
}
143 => {
factors.insert(11, 1);
factors.insert(13, 1);
}
169 => {
factors.insert(13, 2);
}
187 => {
factors.insert(11, 1);
factors.insert(17, 1);
}
209 => {
factors.insert(11, 1);
factors.insert(19, 1);
}
221 => {
factors.insert(13, 1);
factors.insert(17, 1);
}
247 => {
factors.insert(13, 1);
factors.insert(19, 1);
}
253 => {
factors.insert(11, 1);
factors.insert(23, 1);
}
_ => {
factors.insert(n, 1);
}
}
factors
}
}
impl Factor for u16 {
type FACTORS = FactorsU16;
fn factor(&self) -> FactorsU16 {
let mut factors = FactorsU16::new();
for (f, e) in u32::from(*self).factor() {
factors.insert(f as Self, e);
}
factors
}
}
impl Factor for u32 {
type FACTORS = FactorsU32;
fn factor(&self) -> FactorsU32 {
let n = *self;
assert_ne!(n, 0);
let mut factors = FactorsU32::new();
let cofactor = factor_trial_range_u32(&mut factors, n, FACTOR_TRIAL_PRIMES);
if cofactor == 1 {
return factors;
}
if cofactor.is_prime() {
factors.insert(cofactor, 1);
return factors;
}
let mut factor_arr = [0; MAX_FACTORS_IN_U32];
let mut exp_arr = [0; MAX_FACTORS_IN_U32];
factor_arr[0] = cofactor;
let mut factors_left = 1;
exp_arr[0] = 1;
let cutoff = FACTOR_TRIAL_CUTOFF;
while factors_left != 0 {
let mut factor = factor_arr[factors_left - 1];
if factor >= cutoff {
let (mut cofactor, exp) = factor_square_u32(factor);
if cofactor != 0 {
exp_arr[factors_left - 1] *= exp;
factor = cofactor;
factor_arr[factors_left - 1] = factor;
}
if factor >= cutoff && !factor.is_prime() {
cofactor = Self::exact_from(factor_one_line_u64(
u64::from(factor),
FACTOR_ONE_LINE_ITERS,
));
exp_arr[factors_left] = exp_arr[factors_left - 1];
factor_arr[factors_left] = cofactor;
factor_arr[factors_left - 1] /= cofactor;
factors_left += 1;
} else {
factors.insert(factor, exp_arr[factors_left - 1]);
factors_left -= 1;
}
} else {
factors.insert(factor, exp_arr[factors_left - 1]);
factors_left -= 1;
}
}
factors
}
}
const FACTOR_ONE_LINE_MAX: u64 = 1 << 39;
impl Factor for u64 {
type FACTORS = FactorsU64;
fn factor(&self) -> FactorsU64 {
let n = *self;
assert_ne!(n, 0);
let mut factors = FactorsU64::new();
let cofactor = factor_trial_range_u64(&mut factors, n, FACTOR_TRIAL_PRIMES);
if cofactor == 1 {
return factors;
}
if cofactor.is_prime() {
factors.insert(cofactor, 1);
return factors;
}
let mut factor_arr = [0; MAX_FACTORS_IN_U64];
let mut exp_arr = [0; MAX_FACTORS_IN_U64];
factor_arr[0] = cofactor;
let mut factors_left = 1;
exp_arr[0] = 1;
const CUTOFF: u64 = FACTOR_TRIAL_CUTOFF as u64;
while factors_left != 0 {
let mut factor = factor_arr[factors_left - 1];
if factor >= CUTOFF {
let (mut cofactor, exp) = factor_power23_u64(factor);
if cofactor != 0 {
exp_arr[factors_left - 1] *= exp;
factor = cofactor;
factor_arr[factors_left - 1] = factor;
}
if factor >= CUTOFF && !factor.is_prime() {
cofactor = 0;
if factor < FACTOR_ONE_LINE_MAX {
cofactor = factor_one_line_u64(factor, FACTOR_ONE_LINE_ITERS);
}
if cofactor == 0 {
cofactor = factor_pp1_wrapper_u64(factor);
if cofactor == 0 {
cofactor = factor_squfof_u64(factor, FACTOR_SQUFOF_ITERS);
assert_ne!(cofactor, 0);
}
}
exp_arr[factors_left] = exp_arr[factors_left - 1];
factor_arr[factors_left] = cofactor;
factor_arr[factors_left - 1] /= cofactor;
factors_left += 1;
} else {
factors.insert(factor, exp_arr[factors_left - 1]);
factors_left -= 1;
}
} else {
factors.insert(factor, exp_arr[factors_left - 1]);
factors_left -= 1;
}
}
factors
}
}
impl Factor for usize {
type FACTORS = FactorsUsize;
fn factor(&self) -> FactorsUsize {
let mut factors = FactorsUsize::new();
if USIZE_IS_U32 {
for (f, e) in (*self as u32).factor() {
factors.insert(f as Self, e);
}
} else {
for (f, e) in (*self as u64).factor() {
factors.insert(f as Self, e);
}
}
factors
}
}