Skip to main content

malachite_nz/natural/arithmetic/
mod_power_of_2_shr.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::natural::Natural;
10use core::ops::{Shr, ShrAssign};
11use malachite_base::num::arithmetic::traits::{
12    ModPowerOf2Shl, ModPowerOf2ShlAssign, ModPowerOf2Shr, ModPowerOf2ShrAssign, UnsignedAbs,
13};
14use malachite_base::num::basic::signeds::PrimitiveSigned;
15use malachite_base::num::logic::traits::SignificantBits;
16
17fn mod_power_of_2_shr_ref<'a, U, S: PrimitiveSigned + UnsignedAbs<Output = U>>(
18    x: &'a Natural,
19    bits: S,
20    pow: u64,
21) -> Natural
22where
23    &'a Natural: ModPowerOf2Shl<U, Output = Natural> + Shr<U, Output = Natural>,
24{
25    assert!(
26        x.significant_bits() <= pow,
27        "x must be reduced mod 2^pow, but {x} >= 2^{pow}"
28    );
29    if bits >= S::ZERO {
30        x >> bits.unsigned_abs()
31    } else {
32        x.mod_power_of_2_shl(bits.unsigned_abs(), pow)
33    }
34}
35
36fn mod_power_of_2_shr_assign<U, S: PrimitiveSigned + UnsignedAbs<Output = U>>(
37    x: &mut Natural,
38    bits: S,
39    pow: u64,
40) where
41    Natural: ModPowerOf2ShlAssign<U> + ShrAssign<U>,
42{
43    assert!(
44        x.significant_bits() <= pow,
45        "x must be reduced mod 2^pow, but {x} >= 2^{pow}"
46    );
47    if bits >= S::ZERO {
48        *x >>= bits.unsigned_abs();
49    } else {
50        x.mod_power_of_2_shl_assign(bits.unsigned_abs(), pow);
51    }
52}
53
54macro_rules! impl_mod_power_of_2_shr_signed {
55    ($t:ident) => {
56        impl ModPowerOf2Shr<$t> for Natural {
57            type Output = Natural;
58
59            /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo $2^k$. The
60            /// [`Natural`] must be already reduced modulo $2^k$. The [`Natural`] is taken by value.
61            ///
62            /// $f(x, n, k) = y$, where $x, y < 2^k$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod
63            /// 2^k$.
64            ///
65            /// # Worst-case complexity
66            /// $T(n) = O(n)$
67            ///
68            /// $M(n) = O(n)$
69            ///
70            /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
71            ///
72            /// # Panics
73            /// Panics if `self` is greater than or equal to $2^k$.
74            ///
75            /// # Examples
76            /// See [here](super::mod_power_of_2_shr#mod_power_of_2_shr).
77            #[inline]
78            fn mod_power_of_2_shr(mut self, bits: $t, pow: u64) -> Natural {
79                self.mod_power_of_2_shr_assign(bits, pow);
80                self
81            }
82        }
83
84        impl ModPowerOf2Shr<$t> for &Natural {
85            type Output = Natural;
86
87            /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo $2^k$. The
88            /// [`Natural`] must be already reduced modulo $2^k$. The [`Natural`] is taken by
89            /// reference.
90            ///
91            /// $f(x, n, k) = y$, where $x, y < 2^k$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod
92            /// 2^k$.
93            ///
94            /// # Worst-case complexity
95            /// $T(n) = O(n)$
96            ///
97            /// $M(n) = O(n)$
98            ///
99            /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
100            ///
101            /// # Panics
102            /// Panics if `self` is greater than or equal to $2^k$.
103            ///
104            /// # Examples
105            /// See [here](super::mod_power_of_2_shr#mod_power_of_2_shr).
106            #[inline]
107            fn mod_power_of_2_shr(self, bits: $t, pow: u64) -> Natural {
108                mod_power_of_2_shr_ref(self, bits, pow)
109            }
110        }
111
112        impl ModPowerOf2ShrAssign<$t> for Natural {
113            /// Right-shifts a [`Natural`] (divides it by a power of 2) modulo $2^k$, in place. The
114            /// [`Natural`] must be already reduced modulo $2^k$.
115            ///
116            /// $x \gets y$, where $x, y < 2^k$ and $\lfloor 2^{-n}x \rfloor \equiv y \mod 2^k$.
117            ///
118            /// # Worst-case complexity
119            /// $T(n) = O(n)$
120            ///
121            /// $M(n) = O(n)$
122            ///
123            /// where $T$ is time, $M$ is additional memory, and $n$ is `pow`.
124            ///
125            /// # Panics
126            /// Panics if `self` is greater than or equal to $2^k$.
127            ///
128            /// # Examples
129            /// See [here](super::mod_power_of_2_shr#mod_power_of_2_shr_assign).
130            #[inline]
131            fn mod_power_of_2_shr_assign(&mut self, bits: $t, pow: u64) {
132                mod_power_of_2_shr_assign(self, bits, pow);
133            }
134        }
135    };
136}
137apply_to_signeds!(impl_mod_power_of_2_shr_signed);