malachite_base/num/arithmetic/mod_power_of_2.rs
1// Copyright © 2025 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::{
10 CeilingModPowerOf2, CeilingModPowerOf2Assign, ModPowerOf2, ModPowerOf2Assign, NegModPowerOf2,
11 NegModPowerOf2Assign, RemPowerOf2, RemPowerOf2Assign,
12};
13use crate::num::basic::signeds::PrimitiveSigned;
14use crate::num::basic::unsigneds::PrimitiveUnsigned;
15use crate::num::conversion::traits::WrappingFrom;
16use core::fmt::Debug;
17
18const ERROR_MESSAGE: &str = "Result exceeds width of output type";
19
20fn mod_power_of_2_unsigned<T: PrimitiveUnsigned>(x: T, pow: u64) -> T {
21 if x == T::ZERO || pow >= T::WIDTH {
22 x
23 } else {
24 x & T::low_mask(pow)
25 }
26}
27
28fn mod_power_of_2_assign_unsigned<T: PrimitiveUnsigned>(x: &mut T, pow: u64) {
29 if *x != T::ZERO && pow < T::WIDTH {
30 *x &= T::low_mask(pow);
31 }
32}
33
34#[inline]
35fn neg_mod_power_of_2_unsigned<T: PrimitiveUnsigned>(x: T, pow: u64) -> T {
36 assert!(x == T::ZERO || pow <= T::WIDTH, "{ERROR_MESSAGE}");
37 x.wrapping_neg().mod_power_of_2(pow)
38}
39
40macro_rules! impl_mod_power_of_2_unsigned {
41 ($s:ident) => {
42 impl ModPowerOf2 for $s {
43 type Output = $s;
44
45 /// Divides a number by $2^k$, returning just the remainder.
46 ///
47 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k +
48 /// r$ and $0 \leq r < 2^k$.
49 ///
50 /// $$
51 /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
52 /// $$
53 ///
54 /// # Worst-case complexity
55 /// Constant time and additional memory.
56 ///
57 /// # Examples
58 /// See [here](super::mod_power_of_2#mod_power_of_2).
59 #[inline]
60 fn mod_power_of_2(self, pow: u64) -> $s {
61 mod_power_of_2_unsigned(self, pow)
62 }
63 }
64
65 impl ModPowerOf2Assign for $s {
66 /// Divides a number by $2^k$, replacing the first number by the remainder.
67 ///
68 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k +
69 /// r$ and $0 \leq r < 2^k$.
70 ///
71 /// $$
72 /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
73 /// $$
74 ///
75 /// # Worst-case complexity
76 /// Constant time and additional memory.
77 ///
78 /// # Examples
79 /// See [here](super::mod_power_of_2#mod_power_of_2_assign).
80 #[inline]
81 fn mod_power_of_2_assign(&mut self, pow: u64) {
82 mod_power_of_2_assign_unsigned(self, pow);
83 }
84 }
85
86 impl RemPowerOf2 for $s {
87 type Output = $s;
88
89 /// Divides a number by $2^k$, returning just the remainder. For unsigned integers,
90 /// `rem_power_of_2` is equivalent to [`mod_power_of_2`](super::traits::ModPowerOf2).
91 ///
92 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k +
93 /// r$ and $0 \leq r < 2^k$.
94 ///
95 /// $$
96 /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
97 /// $$
98 ///
99 /// # Worst-case complexity
100 /// Constant time and additional memory.
101 ///
102 /// # Examples
103 /// See [here](super::mod_power_of_2#rem_power_of_2).
104 #[inline]
105 fn rem_power_of_2(self, pow: u64) -> $s {
106 self.mod_power_of_2(pow)
107 }
108 }
109
110 impl RemPowerOf2Assign for $s {
111 /// Divides a number by $2^k$, replacing the first number by the remainder. For unsigned
112 /// integers, `rem_power_of_2_assign` is equivalent to
113 /// [`mod_power_of_2_assign`](super::traits::ModPowerOf2Assign).
114 ///
115 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k +
116 /// r$ and $0 \leq r < 2^k$.
117 ///
118 /// $$
119 /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
120 /// $$
121 ///
122 /// # Worst-case complexity
123 /// Constant time and additional memory.
124 ///
125 /// # Examples
126 /// See [here](super::mod_power_of_2#rem_power_of_2_assign).
127 #[inline]
128 fn rem_power_of_2_assign(&mut self, pow: u64) {
129 self.mod_power_of_2_assign(pow)
130 }
131 }
132
133 impl NegModPowerOf2 for $s {
134 type Output = $s;
135
136 /// Divides the negative of a number by a $2^k$, returning just the remainder.
137 ///
138 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k -
139 /// r$ and $0 \leq r < 2^k$.
140 ///
141 /// $$
142 /// f(x, k) = 2^k\left \lceil \frac{x}{2^k} \right \rceil - x.
143 /// $$
144 ///
145 /// # Worst-case complexity
146 /// Constant time and additional memory.
147 ///
148 /// # Panics
149 /// Panics if `self` is nonzero and `pow` is greater than `Self::WIDTH`.
150 ///
151 /// # Examples
152 /// See [here](super::mod_power_of_2#neg_mod_power_of_2).
153 #[inline]
154 fn neg_mod_power_of_2(self, pow: u64) -> $s {
155 neg_mod_power_of_2_unsigned(self, pow)
156 }
157 }
158
159 impl NegModPowerOf2Assign for $s {
160 /// Divides the negative of a number by $2^k$, returning just the remainder.
161 ///
162 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k -
163 /// r$ and $0 \leq r < 2^k$.
164 ///
165 /// $$
166 /// x \gets 2^k\left \lceil \frac{x}{2^k} \right \rceil - x.
167 /// $$
168 ///
169 /// # Worst-case complexity
170 /// Constant time and additional memory.
171 ///
172 /// # Panics
173 /// Panics if `self` is nonzero and `pow` is greater than `Self::WIDTH`.
174 ///
175 /// # Examples
176 /// See [here](super::mod_power_of_2#neg_mod_power_of_2_assign).
177 #[inline]
178 fn neg_mod_power_of_2_assign(&mut self, pow: u64) {
179 *self = self.neg_mod_power_of_2(pow)
180 }
181 }
182 };
183}
184apply_to_unsigneds!(impl_mod_power_of_2_unsigned);
185
186fn mod_power_of_2_signed<U: PrimitiveUnsigned + WrappingFrom<S>, S: PrimitiveSigned>(
187 x: S,
188 pow: u64,
189) -> U {
190 assert!(x >= S::ZERO || pow <= S::WIDTH, "{ERROR_MESSAGE}");
191 U::wrapping_from(x).mod_power_of_2(pow)
192}
193
194fn mod_power_of_2_assign_signed<U, S: TryFrom<U> + ModPowerOf2<Output = U> + PrimitiveSigned>(
195 x: &mut S,
196 pow: u64,
197) where
198 <S as TryFrom<U>>::Error: Debug,
199{
200 *x = S::try_from(x.mod_power_of_2(pow)).expect(ERROR_MESSAGE);
201}
202
203fn rem_power_of_2_signed<
204 U: PrimitiveUnsigned + WrappingFrom<S>,
205 S: PrimitiveSigned + WrappingFrom<U>,
206>(
207 x: S,
208 pow: u64,
209) -> S {
210 if x >= S::ZERO {
211 S::wrapping_from(U::wrapping_from(x).mod_power_of_2(pow))
212 } else {
213 S::wrapping_from(U::wrapping_from(x.wrapping_neg()).mod_power_of_2(pow)).wrapping_neg()
214 }
215}
216
217fn ceiling_mod_power_of_2_signed<
218 U: PrimitiveUnsigned + WrappingFrom<S>,
219 S: TryFrom<U> + PrimitiveSigned,
220>(
221 x: S,
222 pow: u64,
223) -> S
224where
225 <S as TryFrom<U>>::Error: Debug,
226{
227 let abs_result = if x >= S::ZERO {
228 U::wrapping_from(x).neg_mod_power_of_2(pow)
229 } else {
230 U::wrapping_from(x.wrapping_neg()).mod_power_of_2(pow)
231 };
232 S::try_from(abs_result)
233 .expect(ERROR_MESSAGE)
234 .checked_neg()
235 .expect(ERROR_MESSAGE)
236}
237
238macro_rules! impl_mod_power_of_2_signed {
239 ($u:ident, $s:ident) => {
240 impl ModPowerOf2 for $s {
241 type Output = $u;
242
243 /// Divides a number by $2^k$, returning just the remainder. The remainder is
244 /// non-negative.
245 ///
246 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k +
247 /// r$ and $0 \leq r < 2^k$.
248 ///
249 /// $$
250 /// f(x, k) = x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
251 /// $$
252 ///
253 /// # Worst-case complexity
254 /// Constant time and additional memory.
255 ///
256 /// # Panics
257 /// Panics if `self` is negative and `pow` is greater than `Self::WIDTH`.
258 ///
259 /// # Examples
260 /// See [here](super::mod_power_of_2#mod_power_of_2).
261 #[inline]
262 fn mod_power_of_2(self, pow: u64) -> $u {
263 mod_power_of_2_signed(self, pow)
264 }
265 }
266
267 impl ModPowerOf2Assign for $s {
268 /// Divides a number by $2^k$, replacing the first number by the remainder. The
269 /// remainder is non-negative.
270 ///
271 /// If the quotient were computed, he quotient and remainder would satisfy $x = q2^k +
272 /// r$ and $0 \leq r < 2^k$.
273 ///
274 /// $$
275 /// x \gets x - 2^k\left \lfloor \frac{x}{2^k} \right \rfloor.
276 /// $$
277 ///
278 /// # Worst-case complexity
279 /// Constant time and additional memory.
280 ///
281 /// # Panics
282 /// Panics if `self` is negative and `pow` is greater than or equal to `Self::WIDTH`.
283 ///
284 /// # Examples
285 /// See [here](super::mod_power_of_2#mod_power_of_2_assign).
286 #[inline]
287 fn mod_power_of_2_assign(&mut self, pow: u64) {
288 mod_power_of_2_assign_signed(self, pow);
289 }
290 }
291
292 impl RemPowerOf2 for $s {
293 type Output = $s;
294
295 /// Divides a number by $2^k$, returning just the remainder. The remainder has the same
296 /// sign as the first number.
297 ///
298 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k +
299 /// r$ and $0 \leq |r| < 2^k$.
300 ///
301 /// $$
302 /// f(x, k) = x - 2^k\operatorname{sgn}(x)\left \lfloor \frac{|x|}{2^k} \right \rfloor.
303 /// $$
304 ///
305 /// # Worst-case complexity
306 /// Constant time and additional memory.
307 ///
308 /// # Examples
309 /// See [here](super::mod_power_of_2#rem_power_of_2).
310 #[inline]
311 fn rem_power_of_2(self, pow: u64) -> $s {
312 rem_power_of_2_signed::<$u, $s>(self, pow)
313 }
314 }
315
316 impl RemPowerOf2Assign for $s {
317 /// Divides a number by $2^k$, replacing the first number by the remainder. The
318 /// remainder has the same sign as the first number.
319 ///
320 /// If the quotient were computed, he quotient and remainder would satisfy $x = q2^k +
321 /// r$ and $0 \leq r < 2^k$.
322 ///
323 /// $$
324 /// x \gets x - 2^k\operatorname{sgn}(x)\left \lfloor \frac{|x|}{2^k} \right \rfloor.
325 /// $$
326 ///
327 /// # Worst-case complexity
328 /// Constant time and additional memory.
329 ///
330 /// # Examples
331 /// See [here](super::mod_power_of_2#rem_power_of_2_assign).
332 #[inline]
333 fn rem_power_of_2_assign(&mut self, pow: u64) {
334 *self = self.rem_power_of_2(pow)
335 }
336 }
337
338 impl CeilingModPowerOf2 for $s {
339 type Output = $s;
340
341 /// Divides a number by $2^k$, returning just the remainder. The remainder is
342 /// non-positive.
343 ///
344 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k +
345 /// r$ and $0 \leq -r < 2^k$.
346 ///
347 /// $$
348 /// f(x, y) = x - 2^k\left \lceil \frac{x}{2^k} \right \rceil.
349 /// $$
350 ///
351 /// # Worst-case complexity
352 /// Constant time and additional memory.
353 ///
354 /// # Panics
355 /// Panics if `self` is positive or `Self::MIN`, and `pow` is greater than or equal to
356 /// `Self::WIDTH`.
357 ///
358 /// # Examples
359 /// See [here](super::mod_power_of_2#ceiling_mod_power_of_2).
360 #[inline]
361 fn ceiling_mod_power_of_2(self, pow: u64) -> $s {
362 ceiling_mod_power_of_2_signed::<$u, $s>(self, pow)
363 }
364 }
365
366 impl CeilingModPowerOf2Assign for $s {
367 /// Divides a number by $2^k$, replacing the first number by the remainder. The
368 /// remainder is non-positive.
369 ///
370 /// If the quotient were computed, the quotient and remainder would satisfy $x = q2^k +
371 /// r$ and $0 \leq -r < 2^k$.
372 ///
373 /// $$
374 /// x \gets x - 2^k\left \lceil\frac{x}{2^k} \right \rceil.
375 /// $$
376 ///
377 /// # Worst-case complexity
378 /// Constant time and additional memory.
379 ///
380 /// # Panics
381 /// Panics if `self` is positive or `Self::MIN`, and `pow` is greater than or equal to
382 /// `Self::WIDTH`.
383 ///
384 /// # Examples
385 /// See [here](super::mod_power_of_2#ceiling_mod_power_of_2_assign).
386 #[inline]
387 fn ceiling_mod_power_of_2_assign(&mut self, pow: u64) {
388 *self = self.ceiling_mod_power_of_2(pow)
389 }
390 }
391 };
392}
393apply_to_unsigned_signed_pairs!(impl_mod_power_of_2_signed);