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}