#![cfg(all(feature = "poly", feature = "rational"))]
use puremp::{Int, Poly, Rational};
fn rp(coeffs: &[i64]) -> Poly<Rational> {
Poly::new(
coeffs
.iter()
.map(|&c| Rational::from_integer(Int::from_i64(c)))
.collect(),
)
}
fn reconstruct(factors: &[(Poly<Rational>, usize)]) -> Poly<Rational> {
let mut prod = Poly::constant(Rational::ONE);
for (f, m) in factors {
for _ in 0..*m {
prod = prod.mul(f);
}
}
prod
}
#[test]
fn factors_reconstruct_and_are_monic() {
let cases: Vec<Vec<i64>> = vec![
vec![-1, 0, 1], vec![-2, 0, 1], vec![-1, 0, 0, 0, 1], vec![0, -1, 0, 1], vec![1, 2, 1], vec![1, 1, 2, 1, 1], vec![1, 5, 6], vec![1, 0, -10, 0, 1], vec![-6, 11, -6, 1], vec![2, 3, 1], ];
for c in &cases {
let f = rp(c);
let facs = f.factor();
assert_eq!(
reconstruct(&facs),
f.monic(),
"reconstruction failed for {c:?}"
);
for (g, m) in &facs {
assert!(*m >= 1 && g.degree().unwrap() >= 1);
assert_eq!(
g.leading().unwrap(),
&Rational::ONE,
"factor not monic for {c:?}"
);
}
}
}
#[test]
fn known_factorizations() {
let f = rp(&[-1, 0, 1]).factor();
assert_eq!(f.len(), 2);
assert!(f.iter().all(|(g, m)| g.degree() == Some(1) && *m == 1));
let f = rp(&[1, 2, 1]).factor();
assert_eq!(f.len(), 1);
assert_eq!(f[0].1, 2);
assert_eq!(f[0].0, rp(&[1, 1]));
let f = rp(&[-2, 0, 1]).factor();
assert_eq!(f.len(), 1);
assert_eq!(f[0].0.degree(), Some(2));
let f = rp(&[-1, 0, 0, 0, 1]).factor();
assert_eq!(f.len(), 3);
assert_eq!(f.iter().filter(|(g, _)| g.degree() == Some(2)).count(), 1);
let f = rp(&[1, 5, 6]).factor();
assert_eq!(f.len(), 2);
assert!(f.iter().all(|(g, m)| g.degree() == Some(1) && *m == 1));
}
#[test]
fn stress_random_products() {
let mut seed = 0x00C0_FFEE_1234u64;
let rnd = |lo: i64, hi: i64, s: &mut u64| {
*s = s.wrapping_mul(6364136223846793005).wrapping_add(1);
lo + ((*s >> 33) as i64).rem_euclid(hi - lo + 1)
};
for _ in 0..60 {
let k = 2 + (rnd(0, 2, &mut seed) as usize);
let mut f = rp(&[1]);
for _ in 0..k {
let g = if rnd(0, 1, &mut seed) == 0 {
rp(&[rnd(-5, 5, &mut seed), rnd(1, 4, &mut seed)]) } else {
rp(&[
rnd(-3, 3, &mut seed),
rnd(-3, 3, &mut seed),
rnd(1, 3, &mut seed),
]) };
f = f.mul(&g);
}
if f.degree().unwrap_or(0) == 0 {
continue;
}
let facs = f.factor();
assert_eq!(reconstruct(&facs), f.monic(), "reconstruction failed");
for (g, _) in &facs {
let refac = g.factor();
assert_eq!(refac.len(), 1, "factor not irreducible: {:?}", g.coeffs());
assert_eq!(refac[0].1, 1);
}
}
}