Skip to main content

malachite_nz/integer_vector/arithmetic/
balanced_mod_power_of_2.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_vector::IntegerVector;
10use malachite_base::num::arithmetic::traits::{BalancedModPowerOf2, BalancedModPowerOf2Assign};
11
12impl BalancedModPowerOf2 for IntegerVector {
13    type Output = Self;
14
15    /// Reduces every element of an [`IntegerVector`] modulo $2^k$ to the representative closest to
16    /// zero, taking the vector by value.
17    ///
18    /// Each element $r_i$ of the result satisfies $-2^{k-1} < r_i \leq 2^{k-1}$ and is congruent to
19    /// the original element modulo $2^k$, which determine it uniquely, as with
20    /// [`BalancedModPowerOf2`] for [`Integer`](crate::integer::Integer)s; for $k = 0$ every element
21    /// is 0. A remainder of exactly $2^{k-1}$ is positive.
22    ///
23    /// The dimension is unchanged: unlike a polynomial, a vector keeps the elements that reduce to
24    /// zero.
25    ///
26    /// # Worst-case complexity
27    /// $T(n, m) = O(nm)$
28    ///
29    /// $M(n, m) = O(nm)$
30    ///
31    /// where $T$ is time, $M$ is additional memory, $n$ is the number of elements, and $m$ is
32    /// `pow`.
33    ///
34    /// # Examples
35    /// ```
36    /// use core::str::FromStr;
37    /// use malachite_base::num::arithmetic::traits::BalancedModPowerOf2;
38    /// use malachite_nz::integer_vector::IntegerVector;
39    ///
40    /// // Each element goes to its balanced remainder modulo 8, and half the modulus
41    /// // stays positive.
42    /// let v = IntegerVector::from_str("(-19, 23, -20)").unwrap();
43    /// assert_eq!(
44    ///     v.clone().balanced_mod_power_of_2(3).to_string(),
45    ///     "(-3, -1, 4)"
46    /// );
47    /// let v = IntegerVector::from_str("(-8, 7)").unwrap();
48    /// assert_eq!(v.clone().balanced_mod_power_of_2(3).to_string(), "(0, -1)");
49    /// ```
50    #[inline]
51    fn balanced_mod_power_of_2(mut self, pow: u64) -> Self {
52        self.balanced_mod_power_of_2_assign(pow);
53        self
54    }
55}
56
57impl BalancedModPowerOf2 for &IntegerVector {
58    type Output = IntegerVector;
59
60    /// Reduces every element of an [`IntegerVector`] modulo $2^k$ to the representative closest to
61    /// zero, taking the vector by reference.
62    ///
63    /// See the documentation for the [`BalancedModPowerOf2`] implementation on [`IntegerVector`]
64    /// that takes the vector by value for details.
65    ///
66    /// # Worst-case complexity
67    /// $T(n, m) = O(nm)$
68    ///
69    /// $M(n, m) = O(nm)$
70    ///
71    /// where $T$ is time, $M$ is additional memory, $n$ is the number of elements, and $m$ is
72    /// `pow`.
73    ///
74    /// # Examples
75    /// ```
76    /// use core::str::FromStr;
77    /// use malachite_base::num::arithmetic::traits::BalancedModPowerOf2;
78    /// use malachite_nz::integer_vector::IntegerVector;
79    ///
80    /// // Each element goes to its balanced remainder modulo 8, and half the modulus
81    /// // stays positive.
82    /// let v = IntegerVector::from_str("(-19, 23, -20)").unwrap();
83    /// assert_eq!((&v).balanced_mod_power_of_2(3).to_string(), "(-3, -1, 4)");
84    /// let v = IntegerVector::from_str("(-8, 7)").unwrap();
85    /// assert_eq!((&v).balanced_mod_power_of_2(3).to_string(), "(0, -1)");
86    /// ```
87    fn balanced_mod_power_of_2(self, pow: u64) -> IntegerVector {
88        IntegerVector {
89            elements: self
90                .elements
91                .iter()
92                .map(|x| x.balanced_mod_power_of_2(pow))
93                .collect(),
94        }
95    }
96}
97
98impl BalancedModPowerOf2Assign for IntegerVector {
99    /// Reduces every element of an [`IntegerVector`] modulo $2^k$ to the representative closest to
100    /// zero, in place.
101    ///
102    /// See the documentation for the [`BalancedModPowerOf2`] implementation on [`IntegerVector`]
103    /// that takes the vector by value for details.
104    ///
105    /// # Worst-case complexity
106    /// $T(n, m) = O(nm)$
107    ///
108    /// $M(n, m) = O(m)$
109    ///
110    /// where $T$ is time, $M$ is additional memory, $n$ is the number of elements, and $m$ is
111    /// `pow`.
112    ///
113    /// # Examples
114    /// ```
115    /// use core::str::FromStr;
116    /// use malachite_base::num::arithmetic::traits::BalancedModPowerOf2Assign;
117    /// use malachite_nz::integer_vector::IntegerVector;
118    ///
119    /// let mut v = IntegerVector::from_str("(-19, 23, -20)").unwrap();
120    /// v.balanced_mod_power_of_2_assign(3);
121    /// assert_eq!(v.to_string(), "(-3, -1, 4)");
122    /// ```
123    fn balanced_mod_power_of_2_assign(&mut self, pow: u64) {
124        for x in &mut self.elements {
125            x.balanced_mod_power_of_2_assign(pow);
126        }
127    }
128}