malachite_nz/integer/arithmetic/balanced_mod.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::Integer;
10use crate::natural::Natural;
11use core::cmp::Ordering::Less;
12use malachite_base::num::arithmetic::traits::{BalancedMod, BalancedModAssign, ModEuclidean};
13use malachite_base::num::comparison::traits::OrdDouble;
14
15// The Euclidean remainder already lies in [0, |m|), so the balanced one is that remainder when it
16// is at most half the modulus, and that remainder less the modulus otherwise. A remainder of
17// exactly half the modulus stays positive, which puts the endpoint at the top of the range.
18fn balanced_mod_helper(x: &Integer, m: &Integer) -> Integer {
19 let r: Natural = x.mod_euclidean(m);
20 let abs_m = m.unsigned_abs_ref();
21 // `r <= abs_m >> 1` is exactly `2r <= abs_m`: for an integer `r`, `r <= floor(x)` iff `r <= x`.
22 // Phrasing it as the latter lets `cmp_double` answer it without building either value.
23 if abs_m.cmp_double(&r) == Less {
24 Integer::from(r) - Integer::from(abs_m)
25 } else {
26 Integer::from(r)
27 }
28}
29
30impl BalancedMod<Self> for Integer {
31 type Output = Self;
32
33 /// Divides an [`Integer`] by another [`Integer`], returning the balanced remainder: the
34 /// representative of `self` modulo `other` that is closest to zero, taking both [`Integer`]s by
35 /// value.
36 ///
37 /// The remainder $r$ satisfies $-|y|/2 < r \leq |y|/2$ and $r \equiv x \bmod y$, which
38 /// determine it uniquely. A remainder of exactly $|y|/2$ is positive. Only the magnitude of
39 /// `other` matters, so negating it leaves the result unchanged.
40 ///
41 /// # Worst-case complexity
42 /// $T(n) = O(n \log n \log \log n)$
43 ///
44 /// $M(n) = O(n \log n)$
45 ///
46 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
47 ///
48 /// # Panics
49 /// Panics if `other` is zero.
50 ///
51 /// # Examples
52 /// ```
53 /// use malachite_base::num::arithmetic::traits::BalancedMod;
54 /// use malachite_nz::integer::Integer;
55 ///
56 /// assert_eq!(Integer::from(23).balanced_mod(Integer::from(10)), 3);
57 /// // 7 is more than half of 10, so the representative closest to zero is negative
58 /// assert_eq!(Integer::from(27).balanced_mod(Integer::from(10)), -3);
59 /// // only the magnitude of the modulus matters
60 /// assert_eq!(Integer::from(27).balanced_mod(Integer::from(-10)), -3);
61 /// ```
62 #[inline]
63 fn balanced_mod(self, other: Self) -> Self {
64 balanced_mod_helper(&self, &other)
65 }
66}
67
68impl BalancedMod<&Self> for Integer {
69 type Output = Self;
70
71 /// Divides an [`Integer`] by another [`Integer`], returning the balanced remainder: the
72 /// representative of `self` modulo `other` that is closest to zero, taking the first
73 /// [`Integer`] by value and the second by reference.
74 ///
75 /// The remainder $r$ satisfies $-|y|/2 < r \leq |y|/2$ and $r \equiv x \bmod y$, which
76 /// determine it uniquely. A remainder of exactly $|y|/2$ is positive. Only the magnitude of
77 /// `other` matters, so negating it leaves the result unchanged.
78 ///
79 /// # Worst-case complexity
80 /// $T(n) = O(n \log n \log \log n)$
81 ///
82 /// $M(n) = O(n \log n)$
83 ///
84 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
85 ///
86 /// # Panics
87 /// Panics if `other` is zero.
88 ///
89 /// # Examples
90 /// ```
91 /// use malachite_base::num::arithmetic::traits::BalancedMod;
92 /// use malachite_nz::integer::Integer;
93 ///
94 /// assert_eq!(Integer::from(23).balanced_mod(&Integer::from(10)), 3);
95 /// // 7 is more than half of 10, so the representative closest to zero is negative
96 /// assert_eq!(Integer::from(27).balanced_mod(&Integer::from(10)), -3);
97 /// // only the magnitude of the modulus matters
98 /// assert_eq!(Integer::from(27).balanced_mod(&Integer::from(-10)), -3);
99 /// ```
100 #[inline]
101 fn balanced_mod(self, other: &Self) -> Self {
102 balanced_mod_helper(&self, other)
103 }
104}
105
106impl BalancedMod<Integer> for &Integer {
107 type Output = Integer;
108
109 /// Divides an [`Integer`] by another [`Integer`], returning the balanced remainder: the
110 /// representative of `self` modulo `other` that is closest to zero, taking the first
111 /// [`Integer`] by reference and the second by value.
112 ///
113 /// The remainder $r$ satisfies $-|y|/2 < r \leq |y|/2$ and $r \equiv x \bmod y$, which
114 /// determine it uniquely. A remainder of exactly $|y|/2$ is positive. Only the magnitude of
115 /// `other` matters, so negating it leaves the result unchanged.
116 ///
117 /// # Worst-case complexity
118 /// $T(n) = O(n \log n \log \log n)$
119 ///
120 /// $M(n) = O(n \log n)$
121 ///
122 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
123 ///
124 /// # Panics
125 /// Panics if `other` is zero.
126 ///
127 /// # Examples
128 /// ```
129 /// use malachite_base::num::arithmetic::traits::BalancedMod;
130 /// use malachite_nz::integer::Integer;
131 ///
132 /// assert_eq!((&Integer::from(23)).balanced_mod(Integer::from(10)), 3);
133 /// // 7 is more than half of 10, so the representative closest to zero is negative
134 /// assert_eq!((&Integer::from(27)).balanced_mod(Integer::from(10)), -3);
135 /// // only the magnitude of the modulus matters
136 /// assert_eq!((&Integer::from(27)).balanced_mod(Integer::from(-10)), -3);
137 /// ```
138 #[inline]
139 fn balanced_mod(self, other: Integer) -> Integer {
140 balanced_mod_helper(self, &other)
141 }
142}
143
144impl BalancedMod<&Integer> for &Integer {
145 type Output = Integer;
146
147 /// Divides an [`Integer`] by another [`Integer`], returning the balanced remainder: the
148 /// representative of `self` modulo `other` that is closest to zero, taking both [`Integer`]s by
149 /// reference.
150 ///
151 /// The remainder $r$ satisfies $-|y|/2 < r \leq |y|/2$ and $r \equiv x \bmod y$, which
152 /// determine it uniquely. A remainder of exactly $|y|/2$ is positive. Only the magnitude of
153 /// `other` matters, so negating it leaves the result unchanged.
154 ///
155 /// # Worst-case complexity
156 /// $T(n) = O(n \log n \log \log n)$
157 ///
158 /// $M(n) = O(n \log n)$
159 ///
160 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
161 ///
162 /// # Panics
163 /// Panics if `other` is zero.
164 ///
165 /// # Examples
166 /// ```
167 /// use malachite_base::num::arithmetic::traits::BalancedMod;
168 /// use malachite_nz::integer::Integer;
169 ///
170 /// assert_eq!((&Integer::from(23)).balanced_mod(&Integer::from(10)), 3);
171 /// // 7 is more than half of 10, so the representative closest to zero is negative
172 /// assert_eq!((&Integer::from(27)).balanced_mod(&Integer::from(10)), -3);
173 /// // only the magnitude of the modulus matters
174 /// assert_eq!((&Integer::from(27)).balanced_mod(&Integer::from(-10)), -3);
175 /// ```
176 #[inline]
177 fn balanced_mod(self, other: &Integer) -> Integer {
178 balanced_mod_helper(self, other)
179 }
180}
181
182impl BalancedModAssign<Self> for Integer {
183 /// Divides an [`Integer`] by another [`Integer`], replacing the first [`Integer`] by the
184 /// balanced remainder: the representative of `self` modulo `other` that is closest to zero. The
185 /// [`Integer`] on the right-hand side is taken by value.
186 ///
187 /// The remainder $r$ satisfies $-|y|/2 < r \leq |y|/2$; a remainder of exactly $|y|/2$ is
188 /// positive.
189 ///
190 /// # Worst-case complexity
191 /// $T(n) = O(n \log n \log \log n)$
192 ///
193 /// $M(n) = O(n \log n)$
194 ///
195 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
196 ///
197 /// # Panics
198 /// Panics if `other` is zero.
199 ///
200 /// # Examples
201 /// ```
202 /// use malachite_base::num::arithmetic::traits::BalancedModAssign;
203 /// use malachite_nz::integer::Integer;
204 ///
205 /// let mut x = Integer::from(27);
206 /// x.balanced_mod_assign(Integer::from(10));
207 /// assert_eq!(x, -3);
208 /// ```
209 #[inline]
210 fn balanced_mod_assign(&mut self, other: Self) {
211 *self = balanced_mod_helper(self, &other);
212 }
213}
214
215impl BalancedModAssign<&Self> for Integer {
216 /// Divides an [`Integer`] by another [`Integer`], replacing the first [`Integer`] by the
217 /// balanced remainder: the representative of `self` modulo `other` that is closest to zero. The
218 /// [`Integer`] on the right-hand side is taken by reference.
219 ///
220 /// The remainder $r$ satisfies $-|y|/2 < r \leq |y|/2$; a remainder of exactly $|y|/2$ is
221 /// positive.
222 ///
223 /// # Worst-case complexity
224 /// $T(n) = O(n \log n \log \log n)$
225 ///
226 /// $M(n) = O(n \log n)$
227 ///
228 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
229 ///
230 /// # Panics
231 /// Panics if `other` is zero.
232 ///
233 /// # Examples
234 /// ```
235 /// use malachite_base::num::arithmetic::traits::BalancedModAssign;
236 /// use malachite_nz::integer::Integer;
237 ///
238 /// let mut x = Integer::from(27);
239 /// x.balanced_mod_assign(&Integer::from(10));
240 /// assert_eq!(x, -3);
241 /// ```
242 #[inline]
243 fn balanced_mod_assign(&mut self, other: &Self) {
244 *self = balanced_mod_helper(self, other);
245 }
246}