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}