Skip to main content

malachite_nz/integer_vector/arithmetic/
sub.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_polynomial::arithmetic::coefficient::PolynomialCoefficient;
10use crate::integer_vector::IntegerVector;
11use core::ops::{Sub, SubAssign};
12
13// Subtracts each element of `ys` from the element of `xs` at the same index.
14//
15// This is equivalent to `_fmpz_vec_sub` from `fmpz_vec/sub.c`, FLINT 3.6.0, with the output the
16// same as the first input.
17pub(crate) fn vec_sub_assign<C: PolynomialCoefficient>(xs: &mut [C], ys: &[C]) {
18    for (x, y) in xs.iter_mut().zip(ys) {
19        *x -= y;
20    }
21}
22
23fn assert_same_dimension(v: &IntegerVector, w: &IntegerVector) {
24    assert_eq!(
25        v.elements.len(),
26        w.elements.len(),
27        "cannot subtract vectors of different dimensions"
28    );
29}
30
31impl Sub<Self> for IntegerVector {
32    type Output = Self;
33
34    /// Subtracts two [`IntegerVector`]s, taking both by value.
35    ///
36    /// The difference is taken element by element, so the result has the same dimension as the
37    /// operands.
38    ///
39    /// $$
40    /// f(v, w) = v - w.
41    /// $$
42    ///
43    /// # Worst-case complexity
44    /// $T(n) = O(n)$
45    ///
46    /// $M(n) = O(1)$
47    ///
48    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
49    /// elements of both vectors.
50    ///
51    /// # Panics
52    /// Panics if `self` and `other` have different dimensions.
53    ///
54    /// # Examples
55    /// ```
56    /// use core::str::FromStr;
57    /// use malachite_nz::integer_vector::IntegerVector;
58    ///
59    /// let v = IntegerVector::from_str("(1, -2, 3)").unwrap();
60    /// let w = IntegerVector::from_str("(-1, 5, 0)").unwrap();
61    /// assert_eq!((v - w).to_string(), "(2, -7, 3)");
62    /// ```
63    ///
64    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
65    #[inline]
66    fn sub(mut self, other: Self) -> Self {
67        self -= other;
68        self
69    }
70}
71
72impl Sub<&Self> for IntegerVector {
73    type Output = Self;
74
75    /// Subtracts two [`IntegerVector`]s, taking the first by value and the second by reference.
76    ///
77    /// The difference is taken element by element, so the result has the same dimension as the
78    /// operands.
79    ///
80    /// $$
81    /// f(v, w) = v - w.
82    /// $$
83    ///
84    /// # Worst-case complexity
85    /// $T(n) = O(n)$
86    ///
87    /// $M(n) = O(1)$
88    ///
89    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
90    /// elements of both vectors.
91    ///
92    /// # Panics
93    /// Panics if `self` and `other` have different dimensions.
94    ///
95    /// # Examples
96    /// ```
97    /// use core::str::FromStr;
98    /// use malachite_nz::integer_vector::IntegerVector;
99    ///
100    /// let v = IntegerVector::from_str("(1, -2, 3)").unwrap();
101    /// let w = IntegerVector::from_str("(-1, 5, 0)").unwrap();
102    /// assert_eq!((v - &w).to_string(), "(2, -7, 3)");
103    /// ```
104    ///
105    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
106    #[inline]
107    fn sub(mut self, other: &Self) -> Self {
108        self -= other;
109        self
110    }
111}
112
113impl Sub<IntegerVector> for &IntegerVector {
114    type Output = IntegerVector;
115
116    /// Subtracts two [`IntegerVector`]s, taking the first by reference and the second by value.
117    ///
118    /// The difference is taken element by element, so the result has the same dimension as the
119    /// operands.
120    ///
121    /// $$
122    /// f(v, w) = v - w.
123    /// $$
124    ///
125    /// # Worst-case complexity
126    /// $T(n) = O(n)$
127    ///
128    /// $M(n) = O(1)$
129    ///
130    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
131    /// elements of both vectors.
132    ///
133    /// # Panics
134    /// Panics if `self` and `other` have different dimensions.
135    ///
136    /// # Examples
137    /// ```
138    /// use core::str::FromStr;
139    /// use malachite_nz::integer_vector::IntegerVector;
140    ///
141    /// let v = IntegerVector::from_str("(1, -2, 3)").unwrap();
142    /// let w = IntegerVector::from_str("(-1, 5, 0)").unwrap();
143    /// assert_eq!((&v - w).to_string(), "(2, -7, 3)");
144    /// ```
145    ///
146    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
147    #[inline]
148    fn sub(self, mut other: IntegerVector) -> IntegerVector {
149        other -= self;
150        -other
151    }
152}
153
154impl Sub<&IntegerVector> for &IntegerVector {
155    type Output = IntegerVector;
156
157    /// Subtracts two [`IntegerVector`]s, taking both by reference.
158    ///
159    /// The difference is taken element by element, so the result has the same dimension as the
160    /// operands.
161    ///
162    /// $$
163    /// f(v, w) = v - w.
164    /// $$
165    ///
166    /// # Worst-case complexity
167    /// $T(n) = O(n)$
168    ///
169    /// $M(n) = O(n)$
170    ///
171    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
172    /// elements of both vectors.
173    ///
174    /// # Panics
175    /// Panics if `self` and `other` have different dimensions.
176    ///
177    /// # Examples
178    /// ```
179    /// use core::str::FromStr;
180    /// use malachite_nz::integer_vector::IntegerVector;
181    ///
182    /// let v = IntegerVector::from_str("(1, -2, 3)").unwrap();
183    /// let w = IntegerVector::from_str("(-1, 5, 0)").unwrap();
184    /// assert_eq!((&v - &w).to_string(), "(2, -7, 3)");
185    /// ```
186    ///
187    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
188    fn sub(self, other: &IntegerVector) -> IntegerVector {
189        assert_same_dimension(self, other);
190        IntegerVector {
191            elements: self
192                .elements
193                .iter()
194                .zip(&other.elements)
195                .map(|(x, y)| x - y)
196                .collect(),
197        }
198    }
199}
200
201impl SubAssign<Self> for IntegerVector {
202    /// Adds an [`IntegerVector`] to an [`IntegerVector`] in place, taking the [`IntegerVector`] on
203    /// the right-hand side by value.
204    ///
205    /// The difference is taken element by element, so the result has the same dimension as the
206    /// operands.
207    ///
208    /// $$
209    /// f(v, w) = v - w.
210    /// $$
211    ///
212    /// # Worst-case complexity
213    /// $T(n) = O(n)$
214    ///
215    /// $M(n) = O(1)$
216    ///
217    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
218    /// elements of both vectors.
219    ///
220    /// # Panics
221    /// Panics if `self` and `other` have different dimensions.
222    ///
223    /// # Examples
224    /// ```
225    /// use core::str::FromStr;
226    /// use malachite_nz::integer_vector::IntegerVector;
227    ///
228    /// let mut v = IntegerVector::from_str("(1, -2, 3)").unwrap();
229    /// v -= IntegerVector::from_str("(-1, 5, 0)").unwrap();
230    /// assert_eq!(v.to_string(), "(2, -7, 3)");
231    /// ```
232    ///
233    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
234    fn sub_assign(&mut self, other: Self) {
235        assert_same_dimension(self, &other);
236        for (x, y) in self.elements.iter_mut().zip(other.elements) {
237            *x -= y;
238        }
239    }
240}
241
242impl SubAssign<&Self> for IntegerVector {
243    /// Adds an [`IntegerVector`] to an [`IntegerVector`] in place, taking the [`IntegerVector`] on
244    /// the right-hand side by reference.
245    ///
246    /// The difference is taken element by element, so the result has the same dimension as the
247    /// operands.
248    ///
249    /// $$
250    /// f(v, w) = v - w.
251    /// $$
252    ///
253    /// # Worst-case complexity
254    /// $T(n) = O(n)$
255    ///
256    /// $M(n) = O(1)$
257    ///
258    /// where $T$ is time, $M$ is additional memory, and $n$ is the total number of bits of the
259    /// elements of both vectors.
260    ///
261    /// # Panics
262    /// Panics if `self` and `other` have different dimensions.
263    ///
264    /// # Examples
265    /// ```
266    /// use core::str::FromStr;
267    /// use malachite_nz::integer_vector::IntegerVector;
268    ///
269    /// let mut v = IntegerVector::from_str("(1, -2, 3)").unwrap();
270    /// v -= &IntegerVector::from_str("(-1, 5, 0)").unwrap();
271    /// assert_eq!(v.to_string(), "(2, -7, 3)");
272    /// ```
273    ///
274    /// This is equivalent to `_fmpz_vec_add` from `fmpz_vec/add.c`, FLINT 3.6.0.
275    fn sub_assign(&mut self, other: &Self) {
276        assert_same_dimension(self, other);
277        for (x, y) in self.elements.iter_mut().zip(&other.elements) {
278            *x -= y;
279        }
280    }
281}