Skip to main content

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}