algebraeon_rings/matrix/
primitive.rs

1use super::*;
2
3impl<RS: GreatestCommonDivisorSignature, RSB: BorrowedStructure<RS>> MatrixStructure<RS, RSB> {
4    pub fn factor_primitive(&self, mut mat: Matrix<RS::Set>) -> Option<(RS::Set, Matrix<RS::Set>)> {
5        let entries = mat.entries_list();
6        let g = self.ring().gcd_list(entries);
7        if self.ring().is_zero(&g) {
8            None
9        } else {
10            for r in 0..mat.rows() {
11                for c in 0..mat.cols() {
12                    *mat.at_mut(r, c).unwrap() =
13                        self.ring().try_divide(mat.at(r, c).unwrap(), &g).unwrap();
14                }
15            }
16            Some((g, mat))
17        }
18    }
19
20    pub fn primitive_part(&self, mat: Matrix<RS::Set>) -> Option<Matrix<RS::Set>> {
21        self.factor_primitive(mat).map(|(_unit, prim)| prim)
22    }
23}
24
25pub fn factor_primitive_fof<
26    Ring: GreatestCommonDivisorSignature,
27    Field: FieldSignature,
28    Fof: FieldOfFractionsInclusion<Ring, Field>,
29>(
30    fof_inclusion: &Fof,
31    mat: &Matrix<Field::Set>,
32) -> (Field::Set, Matrix<Ring::Set>) {
33    let ring = fof_inclusion.domain();
34    let field = fof_inclusion.range();
35    let mat_ring = MatrixStructure::new(ring.clone());
36
37    let div = ring.lcm_list(
38        mat.entries_list()
39            .into_iter()
40            .map(|c| fof_inclusion.denominator(c))
41            .collect(),
42    );
43
44    let (mul, prim) = mat_ring
45        .factor_primitive(mat.apply_map(|c| {
46            fof_inclusion
47                .try_preimage(&field.mul(&fof_inclusion.image(&div), c))
48                .unwrap()
49        }))
50        .unwrap();
51
52    (
53        field
54            .try_divide(&fof_inclusion.image(&mul), &fof_inclusion.image(&div))
55            .unwrap(),
56        prim,
57    )
58}
59
60impl<R: MetaType> Matrix<R>
61where
62    R::Signature: GreatestCommonDivisorSignature,
63{
64    pub fn factor_primitive(self) -> Option<(R, Matrix<R>)> {
65        Self::structure().factor_primitive(self)
66    }
67
68    pub fn primitive_part(self) -> Option<Matrix<R>> {
69        Self::structure().primitive_part(self)
70    }
71}
72
73impl<Field: MetaType> Matrix<Field>
74where
75    Field::Signature: FieldSignature,
76    PrincipalIntegerMap<Field::Signature, Field::Signature>:
77        FieldOfFractionsInclusion<IntegerCanonicalStructure, Field::Signature>,
78{
79    pub fn factor_primitive_fof(&self) -> (Field, Matrix<Integer>) {
80        factor_primitive_fof(&PrincipalIntegerMap::new(Field::structure()), self)
81    }
82}