malachite_q/rational_vector/arithmetic/sub_mul.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;
10use crate::rational_vector::RationalVector;
11use malachite_base::num::arithmetic::traits::{SubMul, SubMulAssign};
12use malachite_base::num::basic::traits::{NegativeOne, One, Zero};
13
14fn assert_same_dimension(v: &RationalVector, w: &RationalVector) {
15 assert_eq!(
16 v.elements.len(),
17 w.elements.len(),
18 "cannot subtract-multiply vectors of different dimensions"
19 );
20}
21
22impl SubMul<Self, Rational> for RationalVector {
23 type Output = Self;
24
25 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`],
26 /// taking all three by value.
27 ///
28 /// The operation is taken element by element, so the result has the same dimension as the
29 /// vectors. This special-cases multiplication by 0, 1, and $-1$.
30 ///
31 /// $$
32 /// f(v, w, c) = v - cw = (v_0 - cw_0, v_1 - cw_1, \ldots, v_{n-1} - cw_{n-1}).
33 /// $$
34 ///
35 /// # Worst-case complexity
36 /// $T(n) = O(n (\log n)^2 \log\log n)$
37 ///
38 /// $M(n) = O(n \log n)$
39 ///
40 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
41 /// elements of both vectors and of `c`.
42 ///
43 /// # Panics
44 /// Panics if `self` and `w` have different dimensions.
45 ///
46 /// # Examples
47 /// See [here](super::sub_mul#sub_mul).
48 #[inline]
49 fn sub_mul(mut self, w: Self, c: Rational) -> Self {
50 self.sub_mul_assign(w, &c);
51 self
52 }
53}
54
55impl<'b> SubMul<Self, &'b Rational> for RationalVector {
56 type Output = Self;
57
58 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`],
59 /// taking the first vector by value, the second vector by value, and the scalar by reference.
60 ///
61 /// See the documentation for the [`SubMul`] implementation that takes all three by value for
62 /// details.
63 ///
64 /// # Worst-case complexity
65 /// $T(n) = O(n (\log n)^2 \log\log n)$
66 ///
67 /// $M(n) = O(n \log n)$
68 ///
69 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
70 /// elements of both vectors and of `c`.
71 ///
72 /// # Panics
73 /// Panics if `self` and `w` have different dimensions.
74 ///
75 /// # Examples
76 /// See [here](super::sub_mul#sub_mul).
77 #[inline]
78 fn sub_mul(mut self, w: Self, c: &'b Rational) -> Self {
79 self.sub_mul_assign(w, c);
80 self
81 }
82}
83
84impl<'a> SubMul<&'a Self, Rational> for RationalVector {
85 type Output = Self;
86
87 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`],
88 /// taking the first vector by value, the second vector by reference, and the scalar by value.
89 ///
90 /// See the documentation for the [`SubMul`] implementation that takes all three by value for
91 /// details.
92 ///
93 /// # Worst-case complexity
94 /// $T(n) = O(n (\log n)^2 \log\log n)$
95 ///
96 /// $M(n) = O(n \log n)$
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 and of `c`.
100 ///
101 /// # Panics
102 /// Panics if `self` and `w` have different dimensions.
103 ///
104 /// # Examples
105 /// See [here](super::sub_mul#sub_mul).
106 #[inline]
107 fn sub_mul(mut self, w: &'a Self, c: Rational) -> Self {
108 self.sub_mul_assign(w, &c);
109 self
110 }
111}
112
113impl<'a, 'b> SubMul<&'a Self, &'b Rational> for RationalVector {
114 type Output = Self;
115
116 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`],
117 /// taking the first vector by value, the second vector by reference, and the scalar by
118 /// reference.
119 ///
120 /// See the documentation for the [`SubMul`] implementation that takes all three by value for
121 /// details.
122 ///
123 /// # Worst-case complexity
124 /// $T(n) = O(n (\log n)^2 \log\log n)$
125 ///
126 /// $M(n) = O(n \log n)$
127 ///
128 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
129 /// elements of both vectors and of `c`.
130 ///
131 /// # Panics
132 /// Panics if `self` and `w` have different dimensions.
133 ///
134 /// # Examples
135 /// See [here](super::sub_mul#sub_mul).
136 #[inline]
137 fn sub_mul(mut self, w: &'a Self, c: &'b Rational) -> Self {
138 self.sub_mul_assign(w, c);
139 self
140 }
141}
142
143impl SubMul<&RationalVector, &Rational> for &RationalVector {
144 type Output = RationalVector;
145
146 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`],
147 /// taking all three by reference.
148 ///
149 /// See the documentation for the [`SubMul`] implementation that takes all three by value for
150 /// details.
151 ///
152 /// # Worst-case complexity
153 /// $T(n) = O(n (\log n)^2 \log\log n)$
154 ///
155 /// $M(n) = O(n \log n)$
156 ///
157 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
158 /// elements of both vectors and of `c`.
159 ///
160 /// # Panics
161 /// Panics if `self` and `w` have different dimensions.
162 ///
163 /// # Examples
164 /// See [here](super::sub_mul#sub_mul).
165 fn sub_mul(self, w: &RationalVector, c: &Rational) -> RationalVector {
166 assert_same_dimension(self, w);
167 match *c {
168 Rational::ZERO => self.clone(),
169 Rational::ONE => self - w,
170 Rational::NEGATIVE_ONE => self + w,
171 _ => RationalVector {
172 elements: self
173 .elements
174 .iter()
175 .zip(&w.elements)
176 .map(|(x, y)| x.sub_mul(y, c))
177 .collect(),
178 },
179 }
180 }
181}
182
183impl SubMulAssign<Self, Rational> for RationalVector {
184 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`]
185 /// in place, taking the vector and the scalar on the right-hand side by value.
186 ///
187 /// The operation is taken element by element. This special-cases multiplication by 0, 1, and
188 /// $-1$.
189 ///
190 /// $$
191 /// v \gets v - cw.
192 /// $$
193 ///
194 /// # Worst-case complexity
195 /// $T(n) = O(n (\log n)^2 \log\log n)$
196 ///
197 /// $M(n) = O(n \log n)$
198 ///
199 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
200 /// elements of both vectors and of `c`.
201 ///
202 /// # Panics
203 /// Panics if `self` and `w` have different dimensions.
204 ///
205 /// # Examples
206 /// See [here](super::sub_mul#sub_mul_assign).
207 #[inline]
208 fn sub_mul_assign(&mut self, w: Self, c: Rational) {
209 self.sub_mul_assign(w, &c);
210 }
211}
212
213impl<'b> SubMulAssign<Self, &'b Rational> for RationalVector {
214 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`]
215 /// in place, taking the vector on the right-hand side by value and the scalar by reference.
216 ///
217 /// See the documentation for the [`SubMulAssign`] implementation that takes both by value for
218 /// details.
219 ///
220 /// # Worst-case complexity
221 /// $T(n) = O(n (\log n)^2 \log\log n)$
222 ///
223 /// $M(n) = O(n \log n)$
224 ///
225 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
226 /// elements of both vectors and of `c`.
227 ///
228 /// # Panics
229 /// Panics if `self` and `w` have different dimensions.
230 ///
231 /// # Examples
232 /// See [here](super::sub_mul#sub_mul_assign).
233 fn sub_mul_assign(&mut self, w: Self, c: &'b Rational) {
234 assert_same_dimension(self, &w);
235 match *c {
236 Rational::ZERO => {}
237 Rational::ONE => *self -= w,
238 Rational::NEGATIVE_ONE => *self += w,
239 _ => {
240 for (x, y) in self.elements.iter_mut().zip(w.elements) {
241 x.sub_mul_assign(y, c);
242 }
243 }
244 }
245 }
246}
247
248impl<'a> SubMulAssign<&'a Self, Rational> for RationalVector {
249 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`]
250 /// in place, taking the vector on the right-hand side by reference and the scalar by value.
251 ///
252 /// See the documentation for the [`SubMulAssign`] implementation that takes both by value for
253 /// details.
254 ///
255 /// # Worst-case complexity
256 /// $T(n) = O(n (\log n)^2 \log\log n)$
257 ///
258 /// $M(n) = O(n \log n)$
259 ///
260 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
261 /// elements of both vectors and of `c`.
262 ///
263 /// # Panics
264 /// Panics if `self` and `w` have different dimensions.
265 ///
266 /// # Examples
267 /// See [here](super::sub_mul#sub_mul_assign).
268 #[inline]
269 fn sub_mul_assign(&mut self, w: &'a Self, c: Rational) {
270 self.sub_mul_assign(w, &c);
271 }
272}
273
274impl<'a, 'b> SubMulAssign<&'a Self, &'b Rational> for RationalVector {
275 /// Subtracts the product of a [`RationalVector`] and a [`Rational`] from a [`RationalVector`]
276 /// in place, taking the vector and the scalar on the right-hand side by reference.
277 ///
278 /// See the documentation for the [`SubMulAssign`] implementation that takes both by value for
279 /// details.
280 ///
281 /// # Worst-case complexity
282 /// $T(n) = O(n (\log n)^2 \log\log n)$
283 ///
284 /// $M(n) = O(n \log n)$
285 ///
286 /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
287 /// elements of both vectors and of `c`.
288 ///
289 /// # Panics
290 /// Panics if `self` and `w` have different dimensions.
291 ///
292 /// # Examples
293 /// See [here](super::sub_mul#sub_mul_assign).
294 fn sub_mul_assign(&mut self, w: &'a Self, c: &'b Rational) {
295 assert_same_dimension(self, w);
296 match *c {
297 Rational::ZERO => {}
298 Rational::ONE => *self -= w,
299 Rational::NEGATIVE_ONE => *self += w,
300 _ => {
301 for (x, y) in self.elements.iter_mut().zip(&w.elements) {
302 x.sub_mul_assign(y, c);
303 }
304 }
305 }
306 }
307}