feanor_math/algorithms/poly_factor/
mod.rs1use crate::field::*;
2use crate::homomorphism::*;
3use crate::integer::*;
4use crate::pid::*;
5use crate::ring::*;
6use crate::rings::finite::FiniteRing;
7use crate::rings::poly::*;
8use crate::rings::rational::*;
9use crate::rings::zn::zn_64::*;
10
11use finite::*;
12use rational::*;
13
14pub mod cantor_zassenhaus;
15pub mod extension;
16pub mod rational;
17pub mod finite;
18
19pub trait FactorPolyField: Field + PolyTFracGCDRing {
24
25 fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
73 where P: RingStore + Copy,
74 P::Type: PolyRing + EuclideanRing,
75 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>;
76
77 fn is_irred<P>(poly_ring: P, poly: &El<P>) -> bool
78 where P: RingStore + Copy,
79 P::Type: PolyRing + EuclideanRing,
80 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
81 {
82 let factorization = Self::factor_poly(poly_ring, poly).0;
83 return factorization.len() == 1 && factorization[0].1 == 1;
84 }
85}
86
87impl<R> FactorPolyField for R
88 where R: FiniteRing + Field + SelfIso
89{
90 fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
91 where P: RingStore,
92 P::Type: PolyRing + EuclideanRing,
93 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
94 {
95 poly_factor_finite_field(poly_ring, poly)
96 }
97}
98
99impl<I> FactorPolyField for RationalFieldBase<I>
100 where I: RingStore,
101 I::Type: IntegerRing,
102 ZnBase: CanHomFrom<I::Type>
103{
104 fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
105 where P: RingStore,
106 P::Type: PolyRing + EuclideanRing,
107 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
108 {
109 poly_factor_rational(poly_ring, poly)
110 }
111}
112
113#[cfg(test)]
114use crate::rings::poly::dense_poly::DensePolyRing;
115#[cfg(test)]
116use crate::rings::zn::*;
117
118use super::poly_gcd::PolyTFracGCDRing;
119
120#[test]
121fn test_factor_rational_poly() {
122 let QQ = RationalField::new(BigIntRing::RING);
123 let incl = QQ.int_hom();
124 let poly_ring = DensePolyRing::new(&QQ, "X");
125 let f = poly_ring.from_terms([(incl.map(2), 0), (incl.map(1), 3)].into_iter());
126 let g = poly_ring.from_terms([(incl.map(1), 0), (incl.map(2), 1), (incl.map(1), 2), (incl.map(1), 4)].into_iter());
127 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()));
128 assert_eq!(2, actual.len());
129 assert_el_eq!(poly_ring, f, actual[0].0);
130 assert_eq!(2, actual[0].1);
131 assert_el_eq!(poly_ring, g, actual[1].0);
132 assert_eq!(1, actual[1].1);
133 assert_el_eq!(QQ, QQ.one(), unit);
134
135 let f = poly_ring.from_terms([(incl.map(3), 0), (incl.map(1), 1)]);
136 let (actual, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &f);
137 assert_eq!(1, actual.len());
138 assert_eq!(1, actual[0].1);
139 assert_el_eq!(&poly_ring, f, &actual[0].0);
140 assert_el_eq!(QQ, QQ.one(), unit);
141
142 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)]);
143 poly_ring.inclusion().mul_assign_map(&mut f, QQ.div(&QQ.one(), &QQ.int_hom().map(121)));
144 let (actual, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &f);
145 assert_eq!(1, actual.len());
146 assert_eq!(2, actual[0].1);
147 assert_el_eq!(QQ, QQ.one(), unit);
148}
149
150#[test]
151fn test_factor_nonmonic_poly() {
152 let QQ = RationalField::new(BigIntRing::RING);
153 let incl = QQ.int_hom();
154 let poly_ring = DensePolyRing::new(&QQ, "X");
155 let f = poly_ring.from_terms([(QQ.div(&incl.map(3), &incl.map(5)), 0), (incl.map(1), 4)].into_iter());
156 let g = poly_ring.from_terms([(incl.map(1), 0), (incl.map(2), 1), (incl.map(1), 2), (incl.map(1), 4)].into_iter());
157 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()));
158 assert_eq!(2, actual.len());
159
160 assert_el_eq!(poly_ring, g, actual[0].0);
161 assert_eq!(1, actual[0].1);
162 assert_el_eq!(poly_ring, f, actual[1].0);
163 assert_eq!(2, actual[1].1);
164 assert_el_eq!(QQ, incl.map(100), unit);
165}
166
167#[test]
168fn test_factor_fp() {
169 let Fp = zn_static::Fp::<5>::RING;
170 let poly_ring = DensePolyRing::new(Fp, "X");
171 let f = poly_ring.from_terms([(1, 0), (2, 1), (1, 3)].into_iter());
172 let g = poly_ring.from_terms([(1, 0), (1, 1)].into_iter());
173 let h = poly_ring.from_terms([(2, 0), (1, 2)].into_iter());
174 let fgghhh = poly_ring.prod([&f, &g, &g, &h, &h, &h].iter().map(|poly| poly_ring.clone_el(poly)));
175 let (factorization, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &fgghhh);
176 assert_el_eq!(Fp, Fp.one(), unit);
177
178 assert_eq!(2, factorization[0].1);
179 assert_el_eq!(poly_ring, g, factorization[0].0);
180 assert_eq!(3, factorization[1].1);
181 assert_el_eq!(poly_ring, h, factorization[1].0);
182 assert_eq!(1, factorization[2].1);
183 assert_el_eq!(poly_ring, f, factorization[2].0);
184}