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}