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