feanor_math/algorithms/poly_factor/
mod.rs1use crate::computation::*;
2use super::poly_gcd::PolyTFracGCDRing;
3use crate::field::*;
4use crate::homomorphism::*;
5use crate::integer::*;
6use crate::pid::*;
7use crate::ring::*;
8use crate::rings::finite::FiniteRing;
9use crate::rings::poly::*;
10use crate::rings::rational::*;
11use crate::rings::zn::zn_64::*;
12
13use finite::*;
14use rational::*;
15
16pub mod factor_locally;
22pub mod cantor_zassenhaus;
30
31pub mod extension;
36
37pub mod rational;
42
43pub mod finite;
48
49pub trait FactorPolyField: Field + PolyTFracGCDRing {
54
55 fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
103 where P: RingStore + Copy,
104 P::Type: PolyRing + EuclideanRing,
105 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>;
106
107 fn factor_poly_with_controller<P, Controller>(poly_ring: P, poly: &El<P>, _: Controller) -> (Vec<(El<P>, usize)>, Self::Element)
113 where P: RingStore + Copy,
114 P::Type: PolyRing + EuclideanRing,
115 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>,
116 Controller: ComputationController
117 {
118 Self::factor_poly(poly_ring, poly)
119 }
120
121 fn is_irred<P>(poly_ring: P, poly: &El<P>) -> bool
128 where P: RingStore + Copy,
129 P::Type: PolyRing + EuclideanRing,
130 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
131 {
132 let factorization = Self::factor_poly(poly_ring, poly).0;
133 return factorization.len() == 1 && factorization[0].1 == 1;
134 }
135}
136
137impl<R: ?Sized> FactorPolyField for R
138 where R: FiniteRing + Field + SelfIso
139{
140 fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
141 where P: RingStore + Copy,
142 P::Type: PolyRing + EuclideanRing,
143 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
144 {
145 Self::factor_poly_with_controller(poly_ring, poly, DontObserve)
146 }
147
148 fn factor_poly_with_controller<P, Controller>(poly_ring: P, poly: &El<P>, controller: Controller) -> (Vec<(El<P>, usize)>, Self::Element)
149 where P: RingStore,
150 P::Type: PolyRing + EuclideanRing,
151 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>,
152 Controller: ComputationController
153 {
154 poly_factor_finite_field(poly_ring, poly, controller)
155 }
156}
157
158impl<I> FactorPolyField for RationalFieldBase<I>
159 where I: RingStore,
160 I::Type: IntegerRing,
161 ZnBase: CanHomFrom<I::Type>
162{
163 fn factor_poly<P>(poly_ring: P, poly: &El<P>) -> (Vec<(El<P>, usize)>, Self::Element)
164 where P: RingStore + Copy,
165 P::Type: PolyRing + EuclideanRing,
166 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>
167 {
168 Self::factor_poly_with_controller(poly_ring, poly, DontObserve)
169 }
170
171 fn factor_poly_with_controller<P, Controller>(poly_ring: P, poly: &El<P>, controller: Controller) -> (Vec<(El<P>, usize)>, Self::Element)
172 where P: RingStore + Copy,
173 P::Type: PolyRing + EuclideanRing,
174 <P::Type as RingExtension>::BaseRing: RingStore<Type = Self>,
175 Controller: ComputationController
176 {
177 poly_factor_rational(poly_ring, poly, controller)
178 }
179}
180
181#[cfg(test)]
182use crate::rings::poly::dense_poly::DensePolyRing;
183#[cfg(test)]
184use crate::rings::zn::*;
185
186#[test]
187fn test_factor_rational_poly() {
188 let QQ = RationalField::new(BigIntRing::RING);
189 let incl = QQ.int_hom();
190 let poly_ring = DensePolyRing::new(&QQ, "X");
191 let f = poly_ring.from_terms([(incl.map(2), 0), (incl.map(1), 3)].into_iter());
192 let g = poly_ring.from_terms([(incl.map(1), 0), (incl.map(2), 1), (incl.map(1), 2), (incl.map(1), 4)].into_iter());
193 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()));
194 assert_eq!(2, actual.len());
195 assert_el_eq!(poly_ring, f, actual[0].0);
196 assert_eq!(2, actual[0].1);
197 assert_el_eq!(poly_ring, g, actual[1].0);
198 assert_eq!(1, actual[1].1);
199 assert_el_eq!(QQ, QQ.one(), unit);
200
201 let f = poly_ring.from_terms([(incl.map(3), 0), (incl.map(1), 1)]);
202 let (actual, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &f);
203 assert_eq!(1, actual.len());
204 assert_eq!(1, actual[0].1);
205 assert_el_eq!(&poly_ring, f, &actual[0].0);
206 assert_el_eq!(QQ, QQ.one(), unit);
207
208 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)]);
209 poly_ring.inclusion().mul_assign_map(&mut f, QQ.div(&QQ.one(), &QQ.int_hom().map(121)));
210 let (actual, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &f);
211 assert_eq!(1, actual.len());
212 assert_eq!(2, actual[0].1);
213 assert_el_eq!(QQ, QQ.one(), unit);
214}
215
216#[test]
217fn test_factor_nonmonic_poly() {
218 let QQ = RationalField::new(BigIntRing::RING);
219 let incl = QQ.int_hom();
220 let poly_ring = DensePolyRing::new(&QQ, "X");
221 let f = poly_ring.from_terms([(QQ.div(&incl.map(3), &incl.map(5)), 0), (incl.map(1), 4)].into_iter());
222 let g = poly_ring.from_terms([(incl.map(1), 0), (incl.map(2), 1), (incl.map(1), 2), (incl.map(1), 4)].into_iter());
223 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()));
224 assert_eq!(2, actual.len());
225
226 assert_el_eq!(poly_ring, g, actual[0].0);
227 assert_eq!(1, actual[0].1);
228 assert_el_eq!(poly_ring, f, actual[1].0);
229 assert_eq!(2, actual[1].1);
230 assert_el_eq!(QQ, incl.map(100), unit);
231}
232
233#[test]
234fn test_factor_fp() {
235 let Fp = zn_static::Fp::<5>::RING;
236 let poly_ring = DensePolyRing::new(Fp, "X");
237 let f = poly_ring.from_terms([(1, 0), (2, 1), (1, 3)].into_iter());
238 let g = poly_ring.from_terms([(1, 0), (1, 1)].into_iter());
239 let h = poly_ring.from_terms([(2, 0), (1, 2)].into_iter());
240 let fgghhh = poly_ring.prod([&f, &g, &g, &h, &h, &h].iter().map(|poly| poly_ring.clone_el(poly)));
241 let (factorization, unit) = <_ as FactorPolyField>::factor_poly(&poly_ring, &fgghhh);
242 assert_el_eq!(Fp, Fp.one(), unit);
243
244 assert_eq!(2, factorization[0].1);
245 assert_el_eq!(poly_ring, g, factorization[0].0);
246 assert_eq!(3, factorization[1].1);
247 assert_el_eq!(poly_ring, h, factorization[1].0);
248 assert_eq!(1, factorization[2].1);
249 assert_el_eq!(poly_ring, f, factorization[2].0);
250}