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