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