Skip to main content

malachite_q/rational_vector/arithmetic/
add_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::{AddMul, AddMulAssign};
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 add-multiply vectors of different dimensions"
19    );
20}
21
22impl AddMul<Self, Rational> for RationalVector {
23    type Output = Self;
24
25    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`], taking
26    /// 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::add_mul#add_mul).
48    #[inline]
49    fn add_mul(mut self, w: Self, c: Rational) -> Self {
50        self.add_mul_assign(w, &c);
51        self
52    }
53}
54
55impl<'b> AddMul<Self, &'b Rational> for RationalVector {
56    type Output = Self;
57
58    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`], taking
59    /// the first vector by value, the second vector by value, and the scalar by reference.
60    ///
61    /// See the documentation for the [`AddMul`] 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::add_mul#add_mul).
77    #[inline]
78    fn add_mul(mut self, w: Self, c: &'b Rational) -> Self {
79        self.add_mul_assign(w, c);
80        self
81    }
82}
83
84impl<'a> AddMul<&'a Self, Rational> for RationalVector {
85    type Output = Self;
86
87    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`], taking
88    /// the first vector by value, the second vector by reference, and the scalar by value.
89    ///
90    /// See the documentation for the [`AddMul`] 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::add_mul#add_mul).
106    #[inline]
107    fn add_mul(mut self, w: &'a Self, c: Rational) -> Self {
108        self.add_mul_assign(w, &c);
109        self
110    }
111}
112
113impl<'a, 'b> AddMul<&'a Self, &'b Rational> for RationalVector {
114    type Output = Self;
115
116    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`], taking
117    /// the first vector by value, the second vector by reference, and the scalar by reference.
118    ///
119    /// See the documentation for the [`AddMul`] implementation that takes all three by value for
120    /// details.
121    ///
122    /// # Worst-case complexity
123    /// $T(n) = O(n (\log n)^2 \log\log n)$
124    ///
125    /// $M(n) = O(n \log n)$
126    ///
127    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
128    /// elements of both vectors and of `c`.
129    ///
130    /// # Panics
131    /// Panics if `self` and `w` have different dimensions.
132    ///
133    /// # Examples
134    /// See [here](super::add_mul#add_mul).
135    #[inline]
136    fn add_mul(mut self, w: &'a Self, c: &'b Rational) -> Self {
137        self.add_mul_assign(w, c);
138        self
139    }
140}
141
142impl AddMul<&RationalVector, &Rational> for &RationalVector {
143    type Output = RationalVector;
144
145    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`], taking
146    /// all three by reference.
147    ///
148    /// See the documentation for the [`AddMul`] implementation that takes all three by value for
149    /// details.
150    ///
151    /// # Worst-case complexity
152    /// $T(n) = O(n (\log n)^2 \log\log n)$
153    ///
154    /// $M(n) = O(n \log n)$
155    ///
156    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
157    /// elements of both vectors and of `c`.
158    ///
159    /// # Panics
160    /// Panics if `self` and `w` have different dimensions.
161    ///
162    /// # Examples
163    /// See [here](super::add_mul#add_mul).
164    fn add_mul(self, w: &RationalVector, c: &Rational) -> RationalVector {
165        assert_same_dimension(self, w);
166        match *c {
167            Rational::ZERO => self.clone(),
168            Rational::ONE => self + w,
169            Rational::NEGATIVE_ONE => self - w,
170            _ => RationalVector {
171                elements: self
172                    .elements
173                    .iter()
174                    .zip(&w.elements)
175                    .map(|(x, y)| x.add_mul(y, c))
176                    .collect(),
177            },
178        }
179    }
180}
181
182impl AddMulAssign<Self, Rational> for RationalVector {
183    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`] in
184    /// place, taking the vector and the scalar on the right-hand side by value.
185    ///
186    /// The operation is taken element by element. This special-cases multiplication by 0, 1, and
187    /// $-1$.
188    ///
189    /// $$
190    /// v \gets v + cw.
191    /// $$
192    ///
193    /// # Worst-case complexity
194    /// $T(n) = O(n (\log n)^2 \log\log n)$
195    ///
196    /// $M(n) = O(n \log n)$
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 and of `c`.
200    ///
201    /// # Panics
202    /// Panics if `self` and `w` have different dimensions.
203    ///
204    /// # Examples
205    /// See [here](super::add_mul#add_mul_assign).
206    #[inline]
207    fn add_mul_assign(&mut self, w: Self, c: Rational) {
208        self.add_mul_assign(w, &c);
209    }
210}
211
212impl<'b> AddMulAssign<Self, &'b Rational> for RationalVector {
213    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`] in
214    /// place, taking the vector on the right-hand side by value and the scalar by reference.
215    ///
216    /// See the documentation for the [`AddMulAssign`] implementation that takes both by value for
217    /// details.
218    ///
219    /// # Worst-case complexity
220    /// $T(n) = O(n (\log n)^2 \log\log n)$
221    ///
222    /// $M(n) = O(n \log n)$
223    ///
224    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
225    /// elements of both vectors and of `c`.
226    ///
227    /// # Panics
228    /// Panics if `self` and `w` have different dimensions.
229    ///
230    /// # Examples
231    /// See [here](super::add_mul#add_mul_assign).
232    fn add_mul_assign(&mut self, w: Self, c: &'b Rational) {
233        assert_same_dimension(self, &w);
234        match *c {
235            Rational::ZERO => {}
236            Rational::ONE => *self += w,
237            Rational::NEGATIVE_ONE => *self -= w,
238            _ => {
239                for (x, y) in self.elements.iter_mut().zip(w.elements) {
240                    x.add_mul_assign(y, c);
241                }
242            }
243        }
244    }
245}
246
247impl<'a> AddMulAssign<&'a Self, Rational> for RationalVector {
248    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`] in
249    /// place, taking the vector on the right-hand side by reference and the scalar by value.
250    ///
251    /// See the documentation for the [`AddMulAssign`] implementation that takes both by value for
252    /// details.
253    ///
254    /// # Worst-case complexity
255    /// $T(n) = O(n (\log n)^2 \log\log n)$
256    ///
257    /// $M(n) = O(n \log n)$
258    ///
259    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
260    /// elements of both vectors and of `c`.
261    ///
262    /// # Panics
263    /// Panics if `self` and `w` have different dimensions.
264    ///
265    /// # Examples
266    /// See [here](super::add_mul#add_mul_assign).
267    #[inline]
268    fn add_mul_assign(&mut self, w: &'a Self, c: Rational) {
269        self.add_mul_assign(w, &c);
270    }
271}
272
273impl<'a, 'b> AddMulAssign<&'a Self, &'b Rational> for RationalVector {
274    /// Adds the product of a [`RationalVector`] and a [`Rational`] to a [`RationalVector`] in
275    /// place, taking the vector and the scalar on the right-hand side by reference.
276    ///
277    /// See the documentation for the [`AddMulAssign`] implementation that takes both by value for
278    /// details.
279    ///
280    /// # Worst-case complexity
281    /// $T(n) = O(n (\log n)^2 \log\log n)$
282    ///
283    /// $M(n) = O(n \log n)$
284    ///
285    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
286    /// elements of both vectors and of `c`.
287    ///
288    /// # Panics
289    /// Panics if `self` and `w` have different dimensions.
290    ///
291    /// # Examples
292    /// See [here](super::add_mul#add_mul_assign).
293    fn add_mul_assign(&mut self, w: &'a Self, c: &'b Rational) {
294        assert_same_dimension(self, w);
295        match *c {
296            Rational::ZERO => {}
297            Rational::ONE => *self += w,
298            Rational::NEGATIVE_ONE => *self -= w,
299            _ => {
300                for (x, y) in self.elements.iter_mut().zip(&w.elements) {
301                    x.add_mul_assign(y, c);
302                }
303            }
304        }
305    }
306}