Skip to main content

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