malachite_nz/integer/arithmetic/shr.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::integer::Integer;
10use crate::natural::Natural;
11use core::ops::{Shl, ShlAssign, Shr, ShrAssign};
12use malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign, UnsignedAbs};
13use malachite_base::num::basic::traits::Zero;
14use malachite_base::rounding_modes::RoundingMode::*;
15
16fn shr_unsigned_ref<'a, T>(x: &'a Integer, bits: T) -> Integer
17where
18 &'a Natural: Shr<T, Output = Natural> + ShrRound<T, Output = Natural>,
19{
20 match *x {
21 Integer {
22 sign: true,
23 ref abs,
24 } => Integer {
25 sign: true,
26 abs: abs >> bits,
27 },
28 Integer {
29 sign: false,
30 ref abs,
31 } => {
32 let abs_shifted = abs.shr_round(bits, Ceiling).0;
33 if abs_shifted == 0 {
34 Integer::ZERO
35 } else {
36 Integer {
37 sign: false,
38 abs: abs_shifted,
39 }
40 }
41 }
42 }
43}
44
45fn shr_assign_unsigned<T>(x: &mut Integer, bits: T)
46where
47 Natural: ShrAssign<T> + ShrRoundAssign<T>,
48{
49 match *x {
50 Integer {
51 sign: true,
52 ref mut abs,
53 } => {
54 *abs >>= bits;
55 }
56 Integer {
57 sign: false,
58 ref mut abs,
59 } => {
60 abs.shr_round_assign(bits, Ceiling);
61 if *abs == 0 {
62 x.sign = true;
63 }
64 }
65 }
66}
67
68macro_rules! impl_shr_unsigned {
69 ($t:ident) => {
70 impl Shr<$t> for Integer {
71 type Output = Integer;
72
73 /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor), taking
74 /// it by value.
75 ///
76 /// $$
77 /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor.
78 /// $$
79 ///
80 /// # Worst-case complexity
81 /// $T(n) = O(n)$
82 ///
83 /// $M(n) = O(1)$
84 ///
85 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
86 /// self.significant_bits() - bits)`.
87 ///
88 /// # Examples
89 /// See [here](super::shr#shr).
90 #[inline]
91 fn shr(mut self, bits: $t) -> Integer {
92 self >>= bits;
93 self
94 }
95 }
96
97 impl<'a> Shr<$t> for &Integer {
98 type Output = Integer;
99
100 /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor), taking
101 /// it by reference.
102 ///
103 /// $$
104 /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor.
105 /// $$
106 ///
107 /// # Worst-case complexity
108 /// $T(n) = O(n)$
109 ///
110 /// $M(n) = O(1)$
111 ///
112 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
113 /// self.significant_bits() - bits)`.
114 ///
115 /// # Examples
116 /// See [here](super::shr#shr).
117 #[inline]
118 fn shr(self, bits: $t) -> Integer {
119 shr_unsigned_ref(self, bits)
120 }
121 }
122
123 impl ShrAssign<$t> for Integer {
124 /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor), in
125 /// place.
126 ///
127 /// $$
128 /// x \gets \left \lfloor \frac{x}{2^k} \right \rfloor.
129 /// $$
130 ///
131 /// # Worst-case complexity
132 /// $T(n) = O(n)$
133 ///
134 /// $M(n) = O(1)$
135 ///
136 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
137 /// self.significant_bits() - bits)`.
138 ///
139 /// # Examples
140 /// See [here](super::shr#shr_assign).
141 #[inline]
142 fn shr_assign(&mut self, bits: $t) {
143 shr_assign_unsigned(self, bits);
144 }
145 }
146 };
147}
148apply_to_unsigneds!(impl_shr_unsigned);
149
150fn shr_signed_ref<'a, U, S: Copy + Ord + UnsignedAbs<Output = U> + Zero>(
151 x: &'a Integer,
152 bits: S,
153) -> Integer
154where
155 &'a Integer: Shl<U, Output = Integer> + Shr<U, Output = Integer>,
156{
157 if bits >= S::ZERO {
158 x >> bits.unsigned_abs()
159 } else {
160 x << bits.unsigned_abs()
161 }
162}
163
164fn shr_assign_signed<U, S: Copy + Ord + UnsignedAbs<Output = U> + Zero>(x: &mut Integer, bits: S)
165where
166 Integer: ShlAssign<U> + ShrAssign<U>,
167{
168 if bits >= S::ZERO {
169 *x >>= bits.unsigned_abs();
170 } else {
171 *x <<= bits.unsigned_abs();
172 }
173}
174
175macro_rules! impl_shr_signed {
176 ($t:ident) => {
177 impl Shr<$t> for Integer {
178 type Output = Integer;
179
180 /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor or
181 /// multiplies it by a power of 2), taking it by value.
182 ///
183 /// $$
184 /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor.
185 /// $$
186 ///
187 /// # Worst-case complexity
188 /// $T(n) = O(n)$
189 ///
190 /// $M(n) = O(1)$
191 ///
192 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
193 /// self.significant_bits() - bits)`.
194 ///
195 /// # Examples
196 /// See [here](super::shr#shr).
197 #[inline]
198 fn shr(mut self, bits: $t) -> Integer {
199 self >>= bits;
200 self
201 }
202 }
203
204 impl<'a> Shr<$t> for &Integer {
205 type Output = Integer;
206
207 /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor or
208 /// multiplies it by a power of 2), taking it by reference.
209 ///
210 /// $$
211 /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor.
212 /// $$
213 ///
214 /// # Worst-case complexity
215 /// $T(n) = O(n)$
216 ///
217 /// $M(n) = O(1)$
218 ///
219 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
220 /// self.significant_bits() - bits)`.
221 ///
222 /// # Examples
223 /// See [here](super::shr#shr).
224 #[inline]
225 fn shr(self, bits: $t) -> Integer {
226 shr_signed_ref(self, bits)
227 }
228 }
229
230 impl ShrAssign<$t> for Integer {
231 /// Right-shifts an [`Integer`] (divides it by a power of 2 and takes the floor or
232 /// multiplies it by a power of 2), in place.
233 ///
234 /// $$
235 /// x \gets \left \lfloor \frac{x}{2^k} \right \rfloor.
236 /// $$
237 ///
238 /// # Worst-case complexity
239 /// $T(n) = O(n)$
240 ///
241 /// $M(n) = O(1)$
242 ///
243 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
244 /// self.significant_bits() - bits)`.
245 ///
246 /// # Examples
247 /// See [here](super::shr#shr_assign).
248 #[inline]
249 fn shr_assign(&mut self, bits: $t) {
250 shr_assign_signed(self, bits)
251 }
252 }
253 };
254}
255apply_to_signeds!(impl_shr_signed);