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}