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}