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}