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}