Skip to main content

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