Skip to main content

malachite_nz/integer_vector/arithmetic/
add.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_polynomial::arithmetic::coefficient::PolynomialCoefficient;
10use crate::integer_vector::IntegerVector;
11use core::borrow::Borrow;
12use core::ops::{Add, AddAssign};
13
14// Sets each element of `out` to the sum of the elements of `xs` and `ys` at the same index.
15//
16// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0, with the output
17// separate from the inputs.
18pub(crate) fn vec_add<C: PolynomialCoefficient, T: Borrow<C>>(out: &mut [C], xs: &[T], ys: &[T]) {
19    for ((o, x), y) in out.iter_mut().zip(xs).zip(ys) {
20        *o = x.borrow().add_ref(y.borrow());
21    }
22}
23
24// Adds each element of `ys` to the element of `xs` at the same index.
25//
26// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0, with the output the
27// same as the first input.
28pub(crate) fn vec_add_assign<C: PolynomialCoefficient>(xs: &mut [C], ys: &[C]) {
29    for (x, y) in xs.iter_mut().zip(ys) {
30        *x += y;
31    }
32}
33
34fn assert_same_dimension(v: &IntegerVector, w: &IntegerVector) {
35    assert_eq!(
36        v.elements.len(),
37        w.elements.len(),
38        "cannot add vectors of different dimensions"
39    );
40}
41
42impl Add<Self> for IntegerVector {
43    type Output = Self;
44
45    /// Adds two [`IntegerVector`]s, taking both by value.
46    ///
47    /// The sum is taken element by element, so the result has the same dimension as the summands.
48    ///
49    /// $$
50    /// f(v, w) = v + w.
51    /// $$
52    ///
53    /// # Worst-case complexity
54    /// $T(n) = O(n)$
55    ///
56    /// $M(n) = O(1)$
57    ///
58    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
59    /// elements of both vectors.
60    ///
61    /// # Panics
62    /// Panics if `self` and `other` have different dimensions.
63    ///
64    /// # Examples
65    /// ```
66    /// use core::str::FromStr;
67    /// use malachite_nz::integer_vector::IntegerVector;
68    ///
69    /// let v = IntegerVector::from_str("(1, -2, 3)").unwrap();
70    /// let w = IntegerVector::from_str("(-1, 5, 0)").unwrap();
71    /// assert_eq!((v + w).to_string(), "(0, 3, 3)");
72    /// ```
73    ///
74    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
75    #[inline]
76    fn add(mut self, other: Self) -> Self {
77        self += other;
78        self
79    }
80}
81
82impl Add<&Self> for IntegerVector {
83    type Output = Self;
84
85    /// Adds two [`IntegerVector`]s, taking the first by value and the second by reference.
86    ///
87    /// The sum is taken element by element, so the result has the same dimension as the summands.
88    ///
89    /// $$
90    /// f(v, w) = v + w.
91    /// $$
92    ///
93    /// # Worst-case complexity
94    /// $T(n) = O(n)$
95    ///
96    /// $M(n) = O(1)$
97    ///
98    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
99    /// elements of both vectors.
100    ///
101    /// # Panics
102    /// Panics if `self` and `other` have different dimensions.
103    ///
104    /// # Examples
105    /// ```
106    /// use core::str::FromStr;
107    /// use malachite_nz::integer_vector::IntegerVector;
108    ///
109    /// let v = IntegerVector::from_str("(1, -2, 3)").unwrap();
110    /// let w = IntegerVector::from_str("(-1, 5, 0)").unwrap();
111    /// assert_eq!((v + &w).to_string(), "(0, 3, 3)");
112    /// ```
113    ///
114    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
115    #[inline]
116    fn add(mut self, other: &Self) -> Self {
117        self += other;
118        self
119    }
120}
121
122impl Add<IntegerVector> for &IntegerVector {
123    type Output = IntegerVector;
124
125    /// Adds two [`IntegerVector`]s, taking the first by reference and the second by value.
126    ///
127    /// The sum is taken element by element, so the result has the same dimension as the summands.
128    ///
129    /// $$
130    /// f(v, w) = v + w.
131    /// $$
132    ///
133    /// # Worst-case complexity
134    /// $T(n) = O(n)$
135    ///
136    /// $M(n) = O(1)$
137    ///
138    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
139    /// elements of both vectors.
140    ///
141    /// # Panics
142    /// Panics if `self` and `other` have different dimensions.
143    ///
144    /// # Examples
145    /// ```
146    /// use core::str::FromStr;
147    /// use malachite_nz::integer_vector::IntegerVector;
148    ///
149    /// let v = IntegerVector::from_str("(1, -2, 3)").unwrap();
150    /// let w = IntegerVector::from_str("(-1, 5, 0)").unwrap();
151    /// assert_eq!((&v + w).to_string(), "(0, 3, 3)");
152    /// ```
153    ///
154    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
155    #[inline]
156    fn add(self, mut other: IntegerVector) -> IntegerVector {
157        other += self;
158        other
159    }
160}
161
162impl Add<&IntegerVector> for &IntegerVector {
163    type Output = IntegerVector;
164
165    /// Adds two [`IntegerVector`]s, taking both by reference.
166    ///
167    /// The sum is taken element by element, so the result has the same dimension as the summands.
168    ///
169    /// $$
170    /// f(v, w) = v + w.
171    /// $$
172    ///
173    /// # Worst-case complexity
174    /// $T(n) = O(n)$
175    ///
176    /// $M(n) = O(n)$
177    ///
178    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
179    /// elements of both vectors.
180    ///
181    /// # Panics
182    /// Panics if `self` and `other` have different dimensions.
183    ///
184    /// # Examples
185    /// ```
186    /// use core::str::FromStr;
187    /// use malachite_nz::integer_vector::IntegerVector;
188    ///
189    /// let v = IntegerVector::from_str("(1, -2, 3)").unwrap();
190    /// let w = IntegerVector::from_str("(-1, 5, 0)").unwrap();
191    /// assert_eq!((&v + &w).to_string(), "(0, 3, 3)");
192    /// ```
193    ///
194    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
195    fn add(self, other: &IntegerVector) -> IntegerVector {
196        assert_same_dimension(self, other);
197        IntegerVector {
198            elements: self
199                .elements
200                .iter()
201                .zip(&other.elements)
202                .map(|(x, y)| x + y)
203                .collect(),
204        }
205    }
206}
207
208impl AddAssign<Self> for IntegerVector {
209    /// Adds an [`IntegerVector`] to an [`IntegerVector`] in place, taking the [`IntegerVector`] on
210    /// the right-hand side by value.
211    ///
212    /// The sum is taken element by element, so the result has the same dimension as the summands.
213    ///
214    /// $$
215    /// f(v, w) = v + w.
216    /// $$
217    ///
218    /// # Worst-case complexity
219    /// $T(n) = O(n)$
220    ///
221    /// $M(n) = O(1)$
222    ///
223    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
224    /// elements of both vectors.
225    ///
226    /// # Panics
227    /// Panics if `self` and `other` have different dimensions.
228    ///
229    /// # Examples
230    /// ```
231    /// use core::str::FromStr;
232    /// use malachite_nz::integer_vector::IntegerVector;
233    ///
234    /// let mut v = IntegerVector::from_str("(1, -2, 3)").unwrap();
235    /// v += IntegerVector::from_str("(-1, 5, 0)").unwrap();
236    /// assert_eq!(v.to_string(), "(0, 3, 3)");
237    /// ```
238    ///
239    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
240    fn add_assign(&mut self, other: Self) {
241        assert_same_dimension(self, &other);
242        for (x, y) in self.elements.iter_mut().zip(other.elements) {
243            *x += y;
244        }
245    }
246}
247
248impl AddAssign<&Self> for IntegerVector {
249    /// Adds an [`IntegerVector`] to an [`IntegerVector`] in place, taking the [`IntegerVector`] on
250    /// the right-hand side by reference.
251    ///
252    /// The sum is taken element by element, so the result has the same dimension as the summands.
253    ///
254    /// $$
255    /// f(v, w) = v + w.
256    /// $$
257    ///
258    /// # Worst-case complexity
259    /// $T(n) = O(n)$
260    ///
261    /// $M(n) = O(1)$
262    ///
263    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
264    /// elements of both vectors.
265    ///
266    /// # Panics
267    /// Panics if `self` and `other` have different dimensions.
268    ///
269    /// # Examples
270    /// ```
271    /// use core::str::FromStr;
272    /// use malachite_nz::integer_vector::IntegerVector;
273    ///
274    /// let mut v = IntegerVector::from_str("(1, -2, 3)").unwrap();
275    /// v += &IntegerVector::from_str("(-1, 5, 0)").unwrap();
276    /// assert_eq!(v.to_string(), "(0, 3, 3)");
277    /// ```
278    ///
279    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
280    fn add_assign(&mut self, other: &Self) {
281        assert_same_dimension(self, other);
282        for (x, y) in self.elements.iter_mut().zip(&other.elements) {
283            *x += y;
284        }
285    }
286}