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);