feanor_math/algorithms/poly_factor/
finite.rs1use crate::algorithms::poly_gcd::finite::poly_squarefree_part_finite_field;
2use crate::computation::ComputationController;
3use crate::divisibility::*;
4use crate::field::*;
5use crate::integer::*;
6use crate::pid::*;
7use crate::ring::*;
8use crate::rings::finite::*;
9use crate::rings::poly::*;
10use crate::homomorphism::SelfIso;
11use super::cantor_zassenhaus;
12
13#[stability::unstable(feature = "enable")]
17pub fn poly_factor_finite_field<P, Controller>(poly_ring: P, f: &El<P>, controller: Controller) -> (Vec<(El<P>, usize)>, El<<P::Type as RingExtension>::BaseRing>)
18 where P: RingStore,
19 P::Type: PolyRing + EuclideanRing,
20 <<P::Type as RingExtension>::BaseRing as RingStore>::Type: FiniteRing + Field + SelfIso,
21 Controller: ComputationController
22{
23 assert!(!poly_ring.is_zero(&f));
24 let even_char = BigIntRing::RING.is_even(&poly_ring.base_ring().characteristic(&BigIntRing::RING).unwrap());
25
26 controller.run_computation(format_args!("factor_poly_GF(deg={})", poly_ring.degree(f).unwrap()), |controller| {
27
28 let mut result = Vec::new();
29 let mut unit = poly_ring.base_ring().one();
30 let mut el = poly_ring.clone_el(&f);
31
32 while !poly_ring.is_unit(&el) {
34
35 let sqrfree_part = poly_squarefree_part_finite_field(&poly_ring, &el, controller.clone());
36 assert!(!poly_ring.is_unit(&sqrfree_part));
37
38 let distinct_degree_factors = cantor_zassenhaus::distinct_degree_factorization(&poly_ring, poly_ring.clone_el(&sqrfree_part), controller.clone());
40 for (d, factor_d) in distinct_degree_factors.into_iter().enumerate() {
41 let mut stack = Vec::new();
42 stack.push(factor_d);
43
44 while let Some(mut current) = stack.pop() {
46 current = poly_ring.normalize(current);
47
48 if poly_ring.is_one(¤t) {
49 continue;
50 } else if poly_ring.degree(¤t) == Some(d) {
51 let mut found = false;
53 for (factor, power) in &mut result {
54 if poly_ring.eq_el(factor, ¤t) {
55 *power += 1;
56 found = true;
57 break;
58 }
59 }
60 if !found {
61 result.push((current, 1));
62 }
63 } else if even_char {
64 let factor = cantor_zassenhaus::cantor_zassenhaus_even(&poly_ring, poly_ring.clone_el(¤t), d, controller.clone());
65 stack.push(poly_ring.checked_div(¤t, &factor).unwrap());
66 stack.push(factor);
67 } else {
68 let factor = cantor_zassenhaus::cantor_zassenhaus(&poly_ring, poly_ring.clone_el(¤t), d, controller.clone());
69 stack.push(poly_ring.checked_div(¤t, &factor).unwrap());
70 stack.push(factor);
71 }
72 }
73 }
74 el = poly_ring.checked_div(&el, &sqrfree_part).unwrap();
75 }
76 poly_ring.base_ring().mul_assign_ref(&mut unit, poly_ring.coefficient_at(&el, 0));
77 debug_assert!(poly_ring.base_ring().is_unit(&unit));
78
79 return (result, unit);
80 })
81}