Skip to main content

malachite_nz/integer_vector/arithmetic/
element_lcm.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::integer_vector::IntegerVector;
10use crate::natural::Natural;
11use malachite_base::num::arithmetic::traits::{ElementLcm, LcmAssign};
12use malachite_base::num::basic::traits::One;
13
14impl ElementLcm for IntegerVector {
15    type Output = Natural;
16
17    /// Returns the LCM of the elements of a [`IntegerVector`], taking the vector by reference.
18    ///
19    /// The LCM of the elements of the 0-dimensional vector is 1. If an element is 0 the LCM is 0,
20    /// and the elements after it are not examined. The LCM is the LCM of the absolute values, so it
21    /// is non-negative.
22    ///
23    /// $$
24    /// f(v) = \operatorname{lcm}(v_0, v_1, \ldots, v_{n-1}),
25    /// $$
26    ///
27    /// where $n$ is the dimension of $v$.
28    ///
29    /// # Worst-case complexity
30    /// $T(n, m) = O(mn (\log n)^2 \log\log n)$
31    ///
32    /// $M(n) = O(n)$
33    ///
34    /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
35    /// elements, and $m$ is the dimension of the vector.
36    ///
37    /// # Examples
38    /// ```
39    /// use core::str::FromStr;
40    /// use malachite_base::num::arithmetic::traits::ElementLcm;
41    /// use malachite_nz::integer_vector::IntegerVector;
42    ///
43    /// assert_eq!(
44    ///     IntegerVector::from_str("(-4, 6, -10)")
45    ///         .unwrap()
46    ///         .to_element_lcm(),
47    ///     60
48    /// );
49    /// assert_eq!(
50    ///     IntegerVector::from_str("(-4, 0, 6)")
51    ///         .unwrap()
52    ///         .to_element_lcm(),
53    ///     0
54    /// );
55    /// assert_eq!(IntegerVector::from_str("()").unwrap().to_element_lcm(), 1);
56    /// ```
57    ///
58    /// This is equivalent to `_fmpz_vec_lcm` from `fmpz_vec/lcm.c`, FLINT 3.6.0.
59    fn to_element_lcm(&self) -> Natural {
60        let mut lcm = Natural::ONE;
61        for c in &self.elements {
62            lcm.lcm_assign(&c.abs);
63            if lcm == 0u32 {
64                break;
65            }
66        }
67        lcm
68    }
69
70    /// Returns the LCM of the elements of a [`IntegerVector`], taking the vector by value.
71    ///
72    /// The LCM of the elements of the 0-dimensional vector is 1. If an element is 0 the LCM is 0,
73    /// and the elements after it are not examined. The LCM is the LCM of the absolute values, so it
74    /// is non-negative.
75    ///
76    /// $$
77    /// f(v) = \operatorname{lcm}(v_0, v_1, \ldots, v_{n-1}),
78    /// $$
79    ///
80    /// where $n$ is the dimension of $v$.
81    ///
82    /// # Worst-case complexity
83    /// $T(n, m) = O(mn (\log n)^2 \log\log n)$
84    ///
85    /// $M(n) = O(n)$
86    ///
87    /// where $T$ is time, $M$ is additional memory, $n$ is the total number of bits of the
88    /// elements, and $m$ is the dimension of the vector.
89    ///
90    /// # Examples
91    /// ```
92    /// use core::str::FromStr;
93    /// use malachite_base::num::arithmetic::traits::ElementLcm;
94    /// use malachite_nz::integer_vector::IntegerVector;
95    ///
96    /// assert_eq!(
97    ///     IntegerVector::from_str("(-4, 6, -10)")
98    ///         .unwrap()
99    ///         .into_element_lcm(),
100    ///     60
101    /// );
102    /// assert_eq!(
103    ///     IntegerVector::from_str("(-4, 0, 6)")
104    ///         .unwrap()
105    ///         .into_element_lcm(),
106    ///     0
107    /// );
108    /// assert_eq!(IntegerVector::from_str("()").unwrap().into_element_lcm(), 1);
109    /// ```
110    ///
111    /// This is equivalent to `_fmpz_vec_lcm` from `fmpz_vec/lcm.c`, FLINT 3.6.0.
112    fn into_element_lcm(self) -> Natural {
113        let mut lcm = Natural::ONE;
114        for c in self.elements {
115            lcm.lcm_assign(c.abs);
116            if lcm == 0u32 {
117                break;
118            }
119        }
120        lcm
121    }
122}