qfall_math/utils/factorization/
from.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 a [`Factorization`] of [`Z`] values.
10
11use super::Factorization;
12use crate::integer::Z;
13use flint_sys::fmpz_factor::{_fmpz_factor_append, fmpz_factor_get_fmpz};
14
15impl<Integer: Into<Z>> From<Integer> for Factorization {
16    /// Convert an integer into a [`Factorization`].
17    ///
18    /// Parameters:
19    /// - `factor`: the integer we want as a [`Factorization`] object.
20    ///
21    /// Returns a new [`Factorization`] with `factor` as the only factor.
22    ///
23    /// # Examples
24    /// ```
25    /// use qfall_math::utils::Factorization;
26    ///
27    /// let fac = Factorization::from(10);
28    /// ```
29    fn from(factor: Integer) -> Self {
30        let factor = factor.into();
31        let mut out = Self::default();
32        unsafe { _fmpz_factor_append(&mut out.factors, &factor.value, 1) };
33        out
34    }
35}
36
37impl<Integer: Into<Z>> From<(Integer, Integer)> for Factorization {
38    /// Convert two integers into a [`Factorization`].
39    ///
40    /// Note that the order and occurrences of the factors are not altered by this method.
41    ///
42    /// Parameters:
43    /// - `factors`: a tuple with two integers we want in the [`Factorization`] object.
44    ///
45    /// Returns a new [`Factorization`] with `factors` as the only factors.
46    ///
47    /// # Examples
48    /// ```
49    /// use qfall_math::utils::Factorization;
50    ///
51    /// let fac = Factorization::from((10, 5));
52    /// ```
53    fn from(factors: (Integer, Integer)) -> Self {
54        let factor_1 = factors.0.into();
55        let factor_2 = factors.1.into();
56        let mut out = Self::default();
57        unsafe { _fmpz_factor_append(&mut out.factors, &factor_1.value, 1) };
58        unsafe { _fmpz_factor_append(&mut out.factors, &factor_2.value, 1) };
59        out
60    }
61}
62
63impl From<&Factorization> for Vec<(Z, u64)> {
64    /// Convert a [`Factorization`] into a [`Vec<(Z, u64)>`].
65    ///
66    /// Parameters:
67    /// - `factors`: the [`Factorization`] we want as a [`Vec<(Z, u64)>`] object.
68    ///
69    /// Returns a new [`Vec<(Z, u64)>`] with the factors from [`Factorization`]
70    /// represented as tuples with bases as [`Z`] and exponents as [`u64`] values.
71    ///
72    /// # Examples
73    /// ```
74    /// use qfall_math::utils::Factorization;
75    /// use qfall_math::integer::Z;
76    ///
77    /// let fac = Factorization::from(10);
78    ///
79    /// let vec = Vec::<(Z, u64)>::from(&fac);
80    /// ```
81    fn from(factors: &Factorization) -> Self {
82        let mut out = Vec::with_capacity(factors.factors.num as usize + 1);
83
84        if factors.factors.sign == -1 {
85            out.push((Z::MINUS_ONE, 1));
86        }
87
88        for i in 0..factors.factors.num {
89            let mut factor = Z::default();
90            unsafe { fmpz_factor_get_fmpz(&mut factor.value, &factors.factors, i) };
91
92            let exp = unsafe { *factors.factors.exp.offset(i.try_into().unwrap()) };
93            out.push((factor, exp));
94        }
95
96        if out.is_empty() && factors.factors.sign == 1 {
97            out.push((Z::ONE, 1));
98        }
99        out
100    }
101}
102
103impl From<&Vec<(Z, u64)>> for Factorization {
104    /// Convert a [`Vec<(Z, u64)>`] into a [`Factorization`].
105    ///
106    /// Note that the order and occurrences of the factors are not altered by this method
107    /// and an empty vector results in a factorization of 1.
108    ///
109    /// Parameters:
110    /// - `factors`: the [`Vec<(Z, u64)>`] we want as a [`Factorization`] object.
111    ///
112    /// Returns a new [`Factorization`] with the factors from [`Vec<(Z, u64)>`].
113    ///
114    /// # Examples
115    /// ```
116    /// use qfall_math::utils::Factorization;
117    /// use qfall_math::integer::Z;
118    ///
119    /// let vec: Vec<(Z, u64)>  = vec![(Z::from(3), 2), (Z::from(8), 2), (Z::from(4), 1)];
120    /// let fac = Factorization::from(&vec);
121    /// ```
122    fn from(factors: &Vec<(Z, u64)>) -> Self {
123        let mut out = Factorization::default();
124
125        for (factor, exponent) in factors {
126            unsafe { _fmpz_factor_append(&mut out.factors, &factor.value, *exponent) };
127        }
128        out
129    }
130}
131
132#[cfg(test)]
133mod tests_from_one {
134    use crate::utils::Factorization;
135
136    /// Ensure that a [`Factorization`] is correctly created from one value.
137    #[test]
138    fn from_one() {
139        let fac = Factorization::from(8);
140
141        assert_eq!("[(8, 1)]", fac.to_string());
142    }
143
144    /// Ensure that a [`Factorization`] is correctly created from a large value.
145    #[test]
146    fn from_one_large() {
147        let fac = Factorization::from(i64::MAX);
148
149        assert_eq!(format!("[({}, 1)]", i64::MAX), fac.to_string());
150    }
151
152    /// Ensure that a [`Factorization`] is correctly created from a negative value.
153    #[test]
154    fn from_one_negative() {
155        let fac = Factorization::from(-8);
156
157        assert_eq!("[(-8, 1)]", fac.to_string());
158    }
159
160    /// Ensure that a [`Factorization`] is correctly created from value 1.
161    #[test]
162    fn from_one_one() {
163        let fac = Factorization::from(1);
164
165        assert_eq!("[(1, 1)]", fac.to_string());
166    }
167
168    /// Ensure that a [`Factorization`] is correctly created from value 0.
169    #[test]
170    fn from_one_zero() {
171        let fac = Factorization::from(0);
172
173        assert_eq!("[(0, 1)]", fac.to_string());
174    }
175}
176
177#[cfg(test)]
178mod tests_from_two {
179    use crate::utils::Factorization;
180
181    /// Ensure that a [`Factorization`] is correctly created from two values
182    /// and the order is correct.
183    #[test]
184    fn from_two() {
185        let fac = Factorization::from((8, 3));
186
187        assert_eq!("[(8, 1), (3, 1)]", fac.to_string());
188    }
189
190    /// Ensure that a [`Factorization`] is correctly created from large values.
191    #[test]
192    fn from_two_large() {
193        let fac = Factorization::from((i64::MAX, 3));
194
195        assert_eq!(format!("[({}, 1), (3, 1)]", i64::MAX), fac.to_string());
196    }
197
198    /// Ensure that a [`Factorization`] is correctly created from two negative values.
199    #[test]
200    fn from_two_negative() {
201        let fac = Factorization::from((-8, -3));
202
203        assert_eq!("[(-8, 1), (-3, 1)]", fac.to_string());
204    }
205
206    /// Ensure that a [`Factorization`] is correctly created from value 1 and 0.
207    #[test]
208    fn from_two_zero_one() {
209        let fac = Factorization::from((0, 1));
210
211        assert_eq!("[(0, 1), (1, 1)]", fac.to_string());
212    }
213
214    /// Ensure that a [`Factorization`] is not refined in from.
215    #[test]
216    fn from_two_unrefined() {
217        let fac = Factorization::from((8, 8));
218
219        assert_eq!("[(8, 1), (8, 1)]", fac.to_string());
220    }
221}
222
223#[cfg(test)]
224mod tests_from_factorization_for_vector {
225    use crate::{integer::Z, utils::Factorization};
226
227    /// Ensure that a [`Vec`] is correctly created from a [`Factorization`].
228    #[test]
229    fn from_factorization() {
230        let fac = Factorization::from((4, 3));
231        let vec = Vec::<(Z, u64)>::from(&fac);
232
233        assert_eq!(Z::from(4), vec[0].0);
234        assert_eq!(Z::from(3), vec[1].0);
235
236        assert_eq!(1, vec[0].1);
237        assert_eq!(1, vec[1].1);
238    }
239
240    /// Ensure that a [`Vec`] is correctly created from a [`Factorization`]
241    /// with large values.
242    #[test]
243    fn from_factorization_large() {
244        let fac = Factorization::from((i64::MAX, 3));
245        let vec = Vec::<(Z, u64)>::from(&fac);
246
247        assert_eq!(Z::from(i64::MAX), vec[0].0);
248        assert_eq!(Z::from(3), vec[1].0);
249
250        assert_eq!(1, vec[0].1);
251        assert_eq!(1, vec[1].1);
252    }
253
254    /// Ensure that a [`Vec`] is correctly created from a [`Factorization`]
255    /// with negative values.
256    #[test]
257    fn from_factorization_negative() {
258        let fac = Factorization::from((-i64::MAX, 3));
259        let vec = Vec::<(Z, u64)>::from(&fac);
260
261        assert_eq!(Z::from(-i64::MAX), vec[0].0);
262        assert_eq!(Z::from(3), vec[1].0);
263
264        assert_eq!(1, vec[0].1);
265        assert_eq!(1, vec[1].1);
266    }
267
268    /// Ensure that a [`Vec`] is correctly created from a [`Factorization`].
269    #[test]
270    fn from_factorization_one_entry() {
271        let fac = Factorization::from(4);
272        let vec = Vec::<(Z, u64)>::from(&fac);
273
274        assert_eq!(Z::from(4), vec[0].0);
275
276        assert_eq!(1, vec[0].1);
277    }
278
279    /// Ensure that a [`Vec`] is correctly created from a refined [`Factorization`].
280    #[test]
281    fn from_factorization_refined() {
282        let mut fac = Factorization::from((-1200, 20));
283        fac.refine();
284
285        let vec = Vec::<(Z, u64)>::from(&fac);
286
287        assert_eq!(Z::MINUS_ONE, vec[0].0);
288        assert_eq!(Z::from(3), vec[1].0);
289        assert_eq!(Z::from(20), vec[2].0);
290
291        assert_eq!(1, vec[0].1);
292        assert_eq!(1, vec[1].1);
293        assert_eq!(3, vec[2].1);
294    }
295
296    /// Ensure that a [`Vec`] is correctly created from a refined [`Factorization`].
297    #[test]
298    fn from_factorization_one() {
299        let mut fac = Factorization::default();
300        fac.refine();
301
302        let vec = Vec::<(Z, u64)>::from(&fac);
303
304        assert_eq!(Z::ONE, vec[0].0);
305        assert_eq!(1, vec[0].1);
306    }
307
308    /// Ensure that a [`Vec`] is correctly created from a refined [`Factorization`].
309    #[test]
310    fn from_factorization_minus_one() {
311        let mut fac = Factorization::from(-1);
312        fac.refine();
313
314        let vec = Vec::<(Z, u64)>::from(&fac);
315
316        assert_eq!(Z::MINUS_ONE, vec[0].0);
317        assert_eq!(1, vec[0].1);
318    }
319
320    /// Ensure that a [`Vec`] is correctly created from a refined [`Factorization`].
321    #[test]
322    fn from_factorization_zero() {
323        let mut fac_1 = Factorization::from(0);
324        let mut fac_2 = Factorization::from((0, 1));
325        fac_1.refine();
326        fac_2.refine();
327
328        let vec_1 = Vec::<(Z, u64)>::from(&fac_1);
329        let vec_2 = Vec::<(Z, u64)>::from(&fac_2);
330
331        assert!(vec_1.is_empty());
332        assert!(vec_2.is_empty());
333    }
334
335    /// Ensure that the doc test works.
336    #[test]
337    fn doc_test() {
338        let fac = Factorization::from(10);
339        let _vec = Vec::<(Z, u64)>::from(&fac);
340    }
341}
342
343#[cfg(test)]
344mod tests_from_vector_for_factorization {
345    use crate::{integer::Z, utils::Factorization};
346
347    /// Ensure that a [`Factorization`] is correctly created from a [`Vec`].
348    #[test]
349    fn from_vector() {
350        let vec: Vec<(Z, u64)> = vec![(Z::from(3), 2), (Z::from(8), 2)];
351        let fac = Factorization::from(&vec);
352
353        assert_eq!("[(3, 2), (8, 2)]", fac.to_string());
354    }
355
356    /// Ensure that a [`Factorization`] is correctly created from a [`Vec`]
357    /// with large values.
358    #[test]
359    fn from_vector_large() {
360        let vec: Vec<(Z, u64)> = vec![(Z::from(i64::MAX), 2), (Z::from(8), 2)];
361        let fac = Factorization::from(&vec);
362
363        assert_eq!(format!("[({}, 2), (8, 2)]", i64::MAX), fac.to_string());
364    }
365
366    /// Ensure that a [`Factorization`] is correctly created from a [`Vec`]
367    /// with negative values.
368    #[test]
369    fn from_vector_negative() {
370        let vec: Vec<(Z, u64)> = vec![(Z::from(-i64::MAX), 2), (Z::from(-8), 2)];
371        let fac = Factorization::from(&vec);
372
373        assert_eq!(format!("[(-{}, 2), (-8, 2)]", i64::MAX), fac.to_string());
374    }
375
376    /// Ensure that a [`Vec`] is correctly created from one entry.
377    #[test]
378    fn from_vector_one_entry() {
379        let vec: Vec<(Z, u64)> = vec![(Z::from(3), 2)];
380        let fac = Factorization::from(&vec);
381
382        assert_eq!("[(3, 2)]", fac.to_string());
383    }
384
385    /// Ensure that a [`Vec`] is correctly created from no entry.
386    #[test]
387    fn from_vector_no_entry() {
388        let vec: Vec<(Z, u64)> = vec![];
389        let fac = Factorization::from(&vec);
390
391        assert_eq!("[(1, 1)]", fac.to_string());
392    }
393
394    /// Ensure that a [`Vec`] is correctly created from no entry.
395    #[test]
396    fn from_vector_zero() {
397        let vec: Vec<(Z, u64)> = vec![(Z::ZERO, 1)];
398        let fac = Factorization::from(&vec);
399
400        assert_eq!("[(0, 1)]", fac.to_string());
401    }
402}