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