feanor_math/algorithms/poly_factor/
rational.rs1
2use crate::algorithms::poly_factor::factor_locally::poly_factor_integer;
3use crate::computation::*;
4use crate::rings::poly::dense_poly::DensePolyRing;
5use crate::ring::*;
6use crate::rings::poly::*;
7use crate::homomorphism::*;
8use crate::divisibility::*;
9use crate::rings::rational::RationalFieldBase;
10use crate::rings::zn::zn_64::*;
11use crate::algorithms::eea::signed_lcm;
12use crate::pid::EuclideanRing;
13
14use super::IntegerRing;
15
16#[stability::unstable(feature = "enable")]
17pub fn poly_factor_rational<'a, P, I, Controller>(poly_ring: P, poly: &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: RingStore<Type = RationalFieldBase<I>>,
21 I: RingStore,
22 I::Type: IntegerRing,
23 ZnBase: CanHomFrom<I::Type>,
24 Controller: ComputationController
25{
26 assert!(!poly_ring.is_zero(poly));
27 let QQX = &poly_ring;
28 let QQ = QQX.base_ring();
29 let ZZ = QQ.base_ring();
30
31 let den_lcm = QQX.terms(poly).map(|(c, _)| QQ.get_ring().den(c)).fold(ZZ.one(), |a, b| signed_lcm(a, ZZ.clone_el(b), ZZ));
32
33 let ZZX = DensePolyRing::new(ZZ, "X");
34 let f = ZZX.from_terms(QQX.terms(poly).map(|(c, i)| (ZZ.checked_div(&ZZ.mul_ref(&den_lcm, QQ.get_ring().num(c)), QQ.get_ring().den(c)).unwrap(), i)));
35 let mut factorization = poly_factor_integer(&ZZX, f, controller);
36 factorization.sort_unstable_by_key(|(factor, e)| (ZZX.degree(factor).unwrap(), *e));
37
38 let ZZX_to_QQX = QQX.lifted_hom(&ZZX, QQ.inclusion());
39 return (
40 factorization.into_iter().map(|(f, e)| (QQX.normalize(ZZX_to_QQX.map(f)), e)).collect(),
41 QQ.clone_el(QQX.lc(poly).unwrap())
42 );
43}