Skip to main content

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}