malachite_nz/natural/arithmetic/shr.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MP Library.
4//
5// Copyright © 1991, 1993, 1994, 1996, 2000-2002 Free Software Foundation, Inc.
6//
7// This file is part of Malachite.
8//
9// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
10// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
11// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
12
13use crate::natural::InnerNatural::{Large, Small};
14use crate::natural::{Natural, bit_to_limb_count_floor};
15use crate::platform::Limb;
16use alloc::vec::Vec;
17use core::ops::{Shl, ShlAssign, Shr, ShrAssign};
18use malachite_base::num::arithmetic::traits::UnsignedAbs;
19use malachite_base::num::basic::integers::PrimitiveInt;
20use malachite_base::num::basic::signeds::PrimitiveSigned;
21use malachite_base::num::basic::traits::Zero;
22use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
23use malachite_base::num::conversion::traits::{ExactFrom, WrappingFrom};
24use malachite_base::vecs::vec_delete_left;
25
26// Interpreting a slice of `Limb`s as the limbs (in ascending order) of a `Natural`, returns the
27// limbs of the `Natural` right-shifted by a `Limb`, rounding down.
28//
29// # Worst-case complexity
30// $T(n) = O(n)$
31//
32// $M(n) = O(n)$
33//
34// where $T$ is time, $M$ is additional memory and $n$ is `max(1, xs.len() - bits / Limb::WIDTH)`.
35//
36// This is equivalent to `mpn_rshift` from `mpn/generic/rshift.c`, GMP 6.2.1, where the result is
37// returned.
38pub_crate_test! {limbs_shr(xs: &[Limb], bits: u64) -> Vec<Limb> {
39 let delete_count = bit_to_limb_count_floor(bits);
40 if delete_count >= xs.len() {
41 Vec::new()
42 } else {
43 let mut out = xs[delete_count..].to_vec();
44 let small_bits = bits & Limb::WIDTH_MASK;
45 if small_bits != 0 {
46 limbs_slice_shr_in_place(&mut out, small_bits);
47 }
48 out
49 }
50}}
51
52// Interpreting a nonempty slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes
53// the limbs of the `Natural` right-shifted by a `Limb` to an output slice. The output slice must be
54// at least as long as the input slice. The `Limb` must be between 1 and `Limb::WIDTH` - 1,
55// inclusive. The carry, or the bits that are shifted past the width of the input slice, is
56// returned. The input slice should not only contain zeros.
57//
58// # Worst-case complexity
59// $T(n) = O(n)$
60//
61// $M(n) = O(1)$
62//
63// where $T$ is time, $M$ is additional memory and $n$ is `xs.len()`.
64//
65// # Panics
66// Panics if `xs` is empty, `out` is shorter than `xs`, `bits` is 0, or `bits` is greater than or
67// equal to `Limb::WIDTH`.
68//
69// This is equivalent to `mpn_rshift` from `mpn/generic/rshift.c`, GMP 6.2.1.
70pub_crate_test! {limbs_shr_to_out(out: &mut [Limb], xs: &[Limb], bits: u64) -> Limb {
71 let len = xs.len();
72 assert_ne!(len, 0);
73 assert_ne!(bits, 0);
74 assert!(bits < Limb::WIDTH);
75 assert!(out.len() >= len);
76 let cobits = Limb::WIDTH - bits;
77 let (xs_head, xs_tail) = xs.split_first().unwrap();
78 let remaining_bits = xs_head << cobits;
79 let mut previous_x = xs_head >> bits;
80 let (out_last, out_init) = out[..len].split_last_mut().unwrap();
81 for (out, x) in out_init.iter_mut().zip(xs_tail.iter()) {
82 *out = previous_x | (x << cobits);
83 previous_x = x >> bits;
84 }
85 *out_last = previous_x;
86 remaining_bits
87}}
88
89// Interpreting a nonempty slice of `Limb`s as the limbs (in ascending order) of a `Natural`, writes
90// the limbs of the `Natural` right-shifted by a `Limb` to the input slice. The `Limb` must be
91// between 1 and `Limb::WIDTH` - 1, inclusive. The carry, or the bits that are shifted past the
92// width of the input slice, is returned.
93//
94// # Worst-case complexity
95// $T(n) = O(n)$
96//
97// $M(n) = O(1)$
98//
99// where $T$ is time, $M$ is additional memory and $n$ is `xs.len()`.
100//
101// # Panics
102// Panics if `xs` is empty, `bits` is 0, or `bits` is greater than or equal to `Limb::WIDTH`.
103//
104// This is equivalent to `mpn_rshift` from `mpn/generic/rshift.c`, GMP 6.2.1, where `rp == up`.
105pub_crate_test! {limbs_slice_shr_in_place<T: PrimitiveUnsigned>(xs: &mut [T], bits: u64) -> T {
106 assert_ne!(bits, 0);
107 assert!(bits < T::WIDTH);
108 let len = xs.len();
109 assert_ne!(len, 0);
110 let cobits = T::WIDTH - bits;
111 let mut x = xs[0];
112 let remaining_bits = x << cobits;
113 let mut previous_x = x >> bits;
114 for i in 1..len {
115 x = xs[i];
116 xs[i - 1] = previous_x | (x << cobits);
117 previous_x = x >> bits;
118 }
119 *xs.last_mut().unwrap() = previous_x;
120 remaining_bits
121}}
122
123// Interpreting a `Vec` of `Limb`s as the limbs (in ascending order) of a `Natural`, writes the
124// limbs of the `Natural` right-shifted by a `Limb` to the input `Vec`.
125//
126// # Worst-case complexity
127// $T(n) = O(n)$
128//
129// $M(n) = O(1)$
130//
131// where $T$ is time, $M$ is additional memory and $n$ is `max(1, xs.len() - bits / Limb::WIDTH)`.
132//
133// This is equivalent to `mpn_rshift` from `mpn/generic/rshift.c`, GMP 6.2.1, where `rp == up` and
134// if `cnt` is sufficiently large, limbs are removed from `rp`.
135pub_crate_test! {limbs_vec_shr_in_place(xs: &mut Vec<Limb>, bits: u64) {
136 let delete_count = bit_to_limb_count_floor(bits);
137 if delete_count >= xs.len() {
138 xs.clear();
139 } else {
140 let small_shift = bits & Limb::WIDTH_MASK;
141 vec_delete_left(xs, delete_count);
142 if small_shift != 0 {
143 limbs_slice_shr_in_place(xs, small_shift);
144 }
145 }
146}}
147
148fn shr_unsigned_ref<T: Copy + Eq + Ord + WrappingFrom<u64> + Zero>(x: &Natural, bits: T) -> Natural
149where
150 u64: ExactFrom<T>,
151 Limb: Shr<T, Output = Limb>,
152{
153 match (x, bits) {
154 (&Natural::ZERO, _) => x.clone(),
155 (_, bits) if bits == T::ZERO => x.clone(),
156 (Natural(Small(_)), bits) if bits >= T::wrapping_from(Limb::WIDTH) => Natural::ZERO,
157 (Natural(Small(small)), bits) => Natural(Small(*small >> bits)),
158 (Natural(Large(limbs)), bits) => {
159 Natural::from_owned_limbs_asc(limbs_shr(limbs, u64::exact_from(bits)))
160 }
161 }
162}
163
164fn shr_assign_unsigned<T: PrimitiveUnsigned>(x: &mut Natural, bits: T)
165where
166 u64: ExactFrom<T>,
167 Limb: ShrAssign<T>,
168{
169 match (&mut *x, bits) {
170 (&mut Natural::ZERO, _) => {}
171 (_, bits) if bits == T::ZERO => {}
172 (Natural(Small(small)), bits) if bits >= T::wrapping_from(Limb::WIDTH) => {
173 *small = 0;
174 }
175 (Natural(Small(small)), bits) => {
176 *small >>= bits;
177 }
178 (Natural(Large(limbs)), bits) => {
179 limbs_vec_shr_in_place(limbs, u64::exact_from(bits));
180 x.trim();
181 }
182 }
183}
184
185macro_rules! impl_natural_shr_unsigned {
186 ($t:ident) => {
187 impl Shr<$t> for Natural {
188 type Output = Natural;
189
190 /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor), taking
191 /// it by value.
192 ///
193 /// $$
194 /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor.
195 /// $$
196 ///
197 /// # Worst-case complexity
198 /// $T(n) = O(n)$
199 ///
200 /// $M(n) = O(1)$
201 ///
202 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
203 /// self.significant_bits() - bits)`.
204 ///
205 /// # Examples
206 /// See [here](super::shr#shr).
207 #[inline]
208 fn shr(mut self, bits: $t) -> Natural {
209 self >>= bits;
210 self
211 }
212 }
213
214 impl<'a> Shr<$t> for &Natural {
215 type Output = Natural;
216
217 /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor), taking
218 /// it by reference.
219 ///
220 /// $$
221 /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor.
222 /// $$
223 ///
224 /// # Worst-case complexity
225 /// $T(n) = O(n)$
226 ///
227 /// $M(n) = O(n)$
228 ///
229 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
230 /// self.significant_bits() - bits)`.
231 ///
232 /// # Examples
233 /// See [here](super::shr#shr).
234 #[inline]
235 fn shr(self, bits: $t) -> Natural {
236 shr_unsigned_ref(self, bits)
237 }
238 }
239
240 impl ShrAssign<$t> for Natural {
241 /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor), in
242 /// place.
243 ///
244 /// $$
245 /// x \gets \left \lfloor \frac{x}{2^k} \right \rfloor.
246 /// $$
247 ///
248 /// # Worst-case complexity
249 /// $T(n) = O(n)$
250 ///
251 /// $M(n) = O(1)$
252 ///
253 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
254 /// self.significant_bits() - bits)`.
255 ///
256 /// # Examples
257 /// See [here](super::shr#shr_assign).
258 #[inline]
259 fn shr_assign(&mut self, bits: $t) {
260 shr_assign_unsigned(self, bits);
261 }
262 }
263 };
264}
265apply_to_unsigneds!(impl_natural_shr_unsigned);
266
267fn shr_signed_ref<'a, U, S: PrimitiveSigned + UnsignedAbs<Output = U>>(
268 x: &'a Natural,
269 bits: S,
270) -> Natural
271where
272 &'a Natural: Shl<U, Output = Natural> + Shr<U, Output = Natural>,
273{
274 if bits >= S::ZERO {
275 x >> bits.unsigned_abs()
276 } else {
277 x << bits.unsigned_abs()
278 }
279}
280
281fn shr_assign_signed<U, S: PrimitiveSigned + UnsignedAbs<Output = U>>(x: &mut Natural, bits: S)
282where
283 Natural: ShlAssign<U> + ShrAssign<U>,
284{
285 if bits >= S::ZERO {
286 *x >>= bits.unsigned_abs();
287 } else {
288 *x <<= bits.unsigned_abs();
289 }
290}
291
292macro_rules! impl_natural_shr_signed {
293 ($t:ident) => {
294 impl Shr<$t> for Natural {
295 type Output = Natural;
296
297 /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor or
298 /// multiplies it by a power of 2), taking it by value.
299 ///
300 /// $$
301 /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor.
302 /// $$
303 ///
304 /// # Worst-case complexity
305 /// $T(n) = O(n)$
306 ///
307 /// $M(n) = O(1)$
308 ///
309 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
310 /// self.significant_bits() - bits)`.
311 ///
312 /// # Examples
313 /// See [here](super::shr#shr).
314 #[inline]
315 fn shr(mut self, bits: $t) -> Natural {
316 self >>= bits;
317 self
318 }
319 }
320
321 impl<'a> Shr<$t> for &Natural {
322 type Output = Natural;
323
324 /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor or
325 /// multiplies it by a power of 2), taking it by reference.
326 ///
327 /// $$
328 /// f(x, k) = \left \lfloor \frac{x}{2^k} \right \rfloor.
329 /// $$
330 ///
331 /// # Worst-case complexity
332 /// $T(n) = O(n)$
333 ///
334 /// $M(n) = O(n)$
335 ///
336 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
337 /// self.significant_bits() - bits)`.
338 ///
339 /// # Examples
340 /// See [here](super::shr#shr).
341 #[inline]
342 fn shr(self, bits: $t) -> Natural {
343 shr_signed_ref(self, bits)
344 }
345 }
346
347 impl ShrAssign<$t> for Natural {
348 /// Right-shifts a [`Natural`] (divides it by a power of 2 and takes the floor or
349 /// multiplies it by a power of 2), in place.
350 ///
351 /// $$
352 /// x \gets \left \lfloor \frac{x}{2^k} \right \rfloor.
353 /// $$
354 ///
355 /// # Worst-case complexity
356 /// $T(n) = O(n)$
357 ///
358 /// $M(n) = O(1)$
359 ///
360 /// where $T$ is time, $M$ is additional memory and $n$ is `max(1,
361 /// self.significant_bits() - bits)`.
362 ///
363 /// # Examples
364 /// See [here](super::shr#shr_assign).
365 #[inline]
366 fn shr_assign(&mut self, bits: $t) {
367 shr_assign_signed(self, bits);
368 }
369 }
370 };
371}
372apply_to_signeds!(impl_natural_shr_signed);