Skip to main content

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