feanor_math/algorithms/poly_factor/
mod.rsuse crate::field::*;
use crate::homomorphism::*;
use crate::integer::*;
use crate::pid::*;
use crate::ring::*;
use crate::rings::finite::FiniteRing;
use crate::rings::poly::*;
use crate::rings::rational::*;
use crate::rings::zn::zn_64::*;
use finite::*;
use rational::*;
pub mod cantor_zassenhaus;
pub mod extension;
pub mod rational;
pub mod finite;
pub trait FactorPolyField: Field + PolyTFracGCDRing {
fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
where P: RingStore + Copy,
P::Type: PolyRing + EuclideanRing,
<P::Type as RingExtension>::BaseRing: RingStore<Type = Self>;
fn is_irred<P>(poly_ring: P, poly: &El<P>) -> bool
where P: RingStore + Copy,
P::Type: PolyRing + EuclideanRing,
<P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
{
let factorization = Self::factor_poly(poly_ring, poly).0;
return factorization.len() == 1 && factorization[0].1 == 1;
}
}
impl<R> FactorPolyField for R
where R: FiniteRing + Field + SelfIso
{
fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
where P: RingStore,
P::Type: PolyRing + EuclideanRing,
<P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
{
poly_factor_finite_field(poly_ring, poly)
}
}
impl<I> FactorPolyField for RationalFieldBase<I>
where I: RingStore,
I::Type: IntegerRing,
ZnBase: CanHomFrom<I::Type>
{
fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
where P: RingStore,
P::Type: PolyRing + EuclideanRing,
<P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
{
poly_factor_rational(poly_ring, poly)
}
}
#[cfg(test)]
use crate::rings::poly::dense_poly::DensePolyRing;
#[cfg(test)]
use crate::rings::zn::*;
use super::poly_gcd::PolyTFracGCDRing;
#[test]
fn test_factor_rational_poly() {
let QQ = RationalField::new(BigIntRing::RING);
let incl = QQ.int_hom();
let poly_ring = DensePolyRing::new(&QQ, "X");
let f = poly_ring.from_terms([(incl.map(2), 0), (incl.map(1), 3)].into_iter());
let g = poly_ring.from_terms([(incl.map(1), 0), (incl.map(2), 1), (incl.map(1), 2), (incl.map(1), 4)].into_iter());
let (actual, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &poly_ring.prod([poly_ring.clone_el(&f), poly_ring.clone_el(&f), poly_ring.clone_el(&g)].into_iter()));
assert_eq!(2, actual.len());
assert_el_eq!(poly_ring, f, actual[0].0);
assert_eq!(2, actual[0].1);
assert_el_eq!(poly_ring, g, actual[1].0);
assert_eq!(1, actual[1].1);
assert_el_eq!(QQ, QQ.one(), unit);
let f = poly_ring.from_terms([(incl.map(3), 0), (incl.map(1), 1)]);
let (actual, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &f);
assert_eq!(1, actual.len());
assert_eq!(1, actual[0].1);
assert_el_eq!(&poly_ring, f, &actual[0].0);
assert_el_eq!(QQ, QQ.one(), unit);
let [mut f] = poly_ring.with_wrapped_indeterminate(|X| [16 - 32 * X + 104 * X.pow_ref(2) - 8 * 11 * X.pow_ref(3) + 121 * X.pow_ref(4)]);
poly_ring.inclusion().mul_assign_map(&mut f, QQ.div(&QQ.one(), &QQ.int_hom().map(121)));
let (actual, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &f);
assert_eq!(1, actual.len());
assert_eq!(2, actual[0].1);
assert_el_eq!(QQ, QQ.one(), unit);
}
#[test]
fn test_factor_nonmonic_poly() {
let QQ = RationalField::new(BigIntRing::RING);
let incl = QQ.int_hom();
let poly_ring = DensePolyRing::new(&QQ, "X");
let f = poly_ring.from_terms([(QQ.div(&incl.map(3), &incl.map(5)), 0), (incl.map(1), 4)].into_iter());
let g = poly_ring.from_terms([(incl.map(1), 0), (incl.map(2), 1), (incl.map(1), 2), (incl.map(1), 4)].into_iter());
let (actual, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &poly_ring.prod([poly_ring.clone_el(&f), poly_ring.clone_el(&f), poly_ring.clone_el(&g), poly_ring.int_hom().map(100)].into_iter()));
assert_eq!(2, actual.len());
assert_el_eq!(poly_ring, g, actual[0].0);
assert_eq!(1, actual[0].1);
assert_el_eq!(poly_ring, f, actual[1].0);
assert_eq!(2, actual[1].1);
assert_el_eq!(QQ, incl.map(100), unit);
}
#[test]
fn test_factor_fp() {
let Fp = zn_static::Fp::<5>::RING;
let poly_ring = DensePolyRing::new(Fp, "X");
let f = poly_ring.from_terms([(1, 0), (2, 1), (1, 3)].into_iter());
let g = poly_ring.from_terms([(1, 0), (1, 1)].into_iter());
let h = poly_ring.from_terms([(2, 0), (1, 2)].into_iter());
let fgghhh = poly_ring.prod([&f, &g, &g, &h, &h, &h].iter().map(|poly| poly_ring.clone_el(poly)));
let (factorization, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &fgghhh);
assert_el_eq!(Fp, Fp.one(), unit);
assert_eq!(2, factorization[0].1);
assert_el_eq!(poly_ring, g, factorization[0].0);
assert_eq!(3, factorization[1].1);
assert_el_eq!(poly_ring, h, factorization[1].0);
assert_eq!(1, factorization[2].1);
assert_el_eq!(poly_ring, f, factorization[2].0);
}