qfall_math/utils/factorization/
refine.rs

1// Copyright © 2023 Marcel Luca Schmidt
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! Implementations for Factorizations of [`Z`](crate::integer::Z) values.
10
11use super::Factorization;
12use flint_sys::fmpz_factor::fmpz_factor_refine;
13
14impl Factorization {
15    /// Allows to refine a partial factorization of type [`Factorization`] to a more
16    /// complete one whose bases are pairwise relatively prime.
17    /// The bases of the factors are then in ascending order.
18    ///
19    /// For factorization `[(2, 2), (40, 1), (9, 2)]` the refinement looks like this
20    /// `[(2, 5), (5, 1), (9, 2)]`.
21    ///
22    /// # Examples
23    /// ```
24    /// use qfall_math::utils::Factorization;
25    /// use core::fmt;
26    ///
27    /// let mut fac = Factorization::from((1200, 20));
28    /// fac.refine();
29    ///
30    /// println!("{}", fac);
31    /// ```
32    pub fn refine(&mut self) {
33        unsafe { fmpz_factor_refine(&mut self.factors, &self.factors) }
34    }
35}
36
37#[cfg(test)]
38mod test_refine {
39    use super::Factorization;
40
41    /// Ensure that refinement works correctly.
42    #[test]
43    fn refine_correct() {
44        let mut fac = Factorization::from((3, 6));
45
46        fac.refine();
47
48        assert_eq!("[(2, 1), (3, 2)]", fac.to_string());
49    }
50
51    /// Ensure that refinement works correctly.
52    #[test]
53    fn refine_correct_large() {
54        let mut fac = Factorization::from((i64::MAX - 1, 2));
55
56        fac.refine();
57
58        assert_eq!(
59            format!("[(2, 2), ({}, 1)]", (i64::MAX - 1) / 2),
60            fac.to_string()
61        );
62    }
63
64    /// Ensure that refinement works correctly with negative numbers.
65    #[test]
66    fn refine_correct_negative() {
67        let mut fac = Factorization::from((-1200, 20));
68
69        fac.refine();
70
71        assert_eq!("[(-1, 1), (3, 1), (20, 3)]", fac.to_string());
72    }
73
74    /// Ensure that refinement orders the values correctly.
75    #[test]
76    fn refine_correct_order() {
77        let mut fac_1 = Factorization::from((8, 3));
78        let mut fac_2 = Factorization::from((i64::MAX - 1, 2));
79
80        fac_1.refine();
81        fac_2.refine();
82
83        assert_eq!("[(3, 1), (8, 1)]", fac_1.to_string());
84        assert_eq!(
85            format!("[(2, 2), ({}, 1)]", (i64::MAX - 1) / 2),
86            fac_2.to_string()
87        );
88    }
89
90    /// Ensure that refinement works for value 1.
91    #[test]
92    fn refine_correct_one() {
93        let mut fac = Factorization::from(1);
94
95        fac.refine();
96
97        assert_eq!("[(1, 1)]", fac.to_string());
98    }
99
100    /// Ensure that refinement works for value -1.
101    #[test]
102    fn refine_correct_minus_one() {
103        let mut fac = Factorization::from(-1);
104
105        fac.refine();
106
107        assert_eq!("[(-1, 1)]", fac.to_string());
108    }
109
110    /// Ensure that refinement works for value 0.
111    #[test]
112    fn refine_correct_zero() {
113        let mut fac = Factorization::from(0);
114
115        fac.refine();
116
117        assert_eq!("[]", fac.to_string());
118    }
119}