Skip to main content

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}