malachite_nz/integer/arithmetic/
shr_round.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::cmp::Ordering::{self, *};
12use core::ops::{Shl, ShlAssign};
13use malachite_base::num::arithmetic::traits::{ShrRound, ShrRoundAssign, UnsignedAbs};
14use malachite_base::num::basic::traits::Zero;
15use malachite_base::rounding_modes::RoundingMode;
16
17fn shr_round_unsigned_ref_i<'a, T>(x: &'a Integer, bits: T, rm: RoundingMode) -> (Integer, Ordering)
18where
19    &'a Natural: ShrRound<T, Output = Natural>,
20{
21    match *x {
22        Integer {
23            sign: true,
24            ref abs,
25        } => {
26            let (s, o) = abs.shr_round(bits, rm);
27            (Integer { sign: true, abs: s }, o)
28        }
29        Integer {
30            sign: false,
31            ref abs,
32        } => {
33            let (abs_shifted, o) = abs.shr_round(bits, -rm);
34            (
35                if abs_shifted == 0 {
36                    Integer::ZERO
37                } else {
38                    Integer {
39                        sign: false,
40                        abs: abs_shifted,
41                    }
42                },
43                o.reverse(),
44            )
45        }
46    }
47}
48
49fn shr_round_assign_unsigned_i<T>(x: &mut Integer, bits: T, rm: RoundingMode) -> Ordering
50where
51    Natural: ShrRoundAssign<T>,
52{
53    match *x {
54        Integer {
55            sign: true,
56            ref mut abs,
57        } => abs.shr_round_assign(bits, rm),
58        Integer {
59            sign: false,
60            ref mut abs,
61        } => {
62            let o = abs.shr_round_assign(bits, -rm);
63            if *abs == 0 {
64                x.sign = true;
65            }
66            o.reverse()
67        }
68    }
69}
70
71macro_rules! impl_shr_round_unsigned {
72    ($t:ident) => {
73        impl ShrRound<$t> for Integer {
74            type Output = Integer;
75
76            /// Shifts an [`Integer`] right (divides it by a power of 2), taking it by value, and
77            /// rounds according to the specified rounding mode. An [`Ordering`] is also returned,
78            /// indicating whether the returned value is less than, equal to, or greater than the
79            /// exact value.
80            ///
81            /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
82            /// use `self.divisible_by_power_of_2(bits)`.
83            ///
84            /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first
85            /// element of the pair, without the [`Ordering`]:
86            ///
87            /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$
88            ///
89            /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$
90            ///
91            /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$
92            ///
93            /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$
94            ///
95            /// $$
96            /// f(x, k, \mathrm{Nearest}) = \begin{cases}
97            ///     \lfloor q \rfloor & \text{if}
98            ///         \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\
99            ///     \lceil q \rceil & \text{if}
100            ///         \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\
101            ///     \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor =
102            ///         \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
103            ///     \\ \text{is even}, \\\\
104            ///     \lceil q \rceil &
105            ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and}
106            ///         \\ \lfloor q \rfloor \\ \text{is odd}.
107            /// \end{cases}
108            /// $$
109            ///
110            /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
111            ///
112            /// Then
113            ///
114            /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$.
115            ///
116            /// # Worst-case complexity
117            /// $T(n) = O(n)$
118            ///
119            /// $M(n) = O(1)$
120            ///
121            /// where $T$ is time, $M$ is additional memory and $n$ is `self.significant_bits()`.
122            ///
123            /// # Panics
124            /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$.
125            ///
126            /// # Examples
127            /// See [here](super::shr_round#shr_round).
128            #[inline]
129            fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) {
130                let o = self.shr_round_assign(bits, rm);
131                (self, o)
132            }
133        }
134
135        impl<'a> ShrRound<$t> for &Integer {
136            type Output = Integer;
137
138            /// Shifts an [`Integer`] right (divides it by a power of 2), taking it by reference,
139            /// and rounds according to the specified rounding mode. An [`Ordering`] is also
140            /// returned, indicating whether the returned value is less than, equal to, or greater
141            /// than the exact value.
142            ///
143            /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
144            /// use `self.divisible_by_power_of_2(bits)`.
145            ///
146            /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first
147            /// element of the pair, without the [`Ordering`]:
148            ///
149            /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$
150            ///
151            /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$
152            ///
153            /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$
154            ///
155            /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$
156            ///
157            /// $$
158            /// f(x, k, \mathrm{Nearest}) = \begin{cases}
159            ///     \lfloor q \rfloor & \text{if}
160            ///         \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\
161            ///     \lceil q \rceil & \text{if}
162            ///         \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\
163            ///     \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor =
164            ///         \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
165            ///     \\ \text{is even}, \\\\
166            ///     \lceil q \rceil &
167            ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and}
168            ///         \\ \lfloor q \rfloor \\ \text{is odd}.
169            /// \end{cases}
170            /// $$
171            ///
172            /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
173            ///
174            /// Then
175            ///
176            /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$.
177            ///
178            /// # Worst-case complexity
179            /// $T(n) = O(n)$
180            ///
181            /// $M(n) = O(1)$
182            ///
183            /// where $T$ is time, $M$ is additional memory and $n$ is `self.significant_bits()`.
184            ///
185            /// # Panics
186            /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$.
187            ///
188            /// # Examples
189            /// See [here](super::shr_round#shr_round).
190            #[inline]
191            fn shr_round(self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) {
192                shr_round_unsigned_ref_i(self, bits, rm)
193            }
194        }
195
196        impl ShrRoundAssign<$t> for Integer {
197            /// Shifts a [`Natural`] right (divides it by a power of 2) and rounds according to the
198            /// specified rounding mode, in place. Passing `Floor` is equivalent to using `>>=`. To
199            /// test whether `Exact` can be passed, use `self.divisible_by_power_of_2(bits)`. An
200            /// [`Ordering`] is returned, indicating whether the assigned value is less than, equal
201            /// to, or greater than the exact value.
202            ///
203            /// See the [`ShrRound`] documentation for details.
204            ///
205            /// # Worst-case complexity
206            /// $T(n) = O(n)$
207            ///
208            /// $M(n) = O(1)$
209            ///
210            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
211            ///
212            /// # Panics
213            /// Let $k$ be `bits`. Panics if `rm` is `Exact` but `self` is not divisible by $2^k$.
214            ///
215            /// # Examples
216            /// See [here](super::shr_round#shr_round_assign).
217            fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering {
218                shr_round_assign_unsigned_i(self, bits, rm)
219            }
220        }
221    };
222}
223apply_to_unsigneds!(impl_shr_round_unsigned);
224
225fn shr_round_signed_ref_i<'a, U, S: Copy + Ord + UnsignedAbs<Output = U> + Zero>(
226    x: &'a Integer,
227    bits: S,
228    rm: RoundingMode,
229) -> (Integer, Ordering)
230where
231    &'a Integer: Shl<U, Output = Integer> + ShrRound<U, Output = Integer>,
232{
233    if bits >= S::ZERO {
234        x.shr_round(bits.unsigned_abs(), rm)
235    } else {
236        (x << bits.unsigned_abs(), Equal)
237    }
238}
239
240fn shr_round_assign_signed_i<U, S: Copy + Ord + UnsignedAbs<Output = U> + Zero>(
241    x: &mut Integer,
242    bits: S,
243    rm: RoundingMode,
244) -> Ordering
245where
246    Integer: ShlAssign<U> + ShrRoundAssign<U>,
247{
248    if bits >= S::ZERO {
249        x.shr_round_assign(bits.unsigned_abs(), rm)
250    } else {
251        *x <<= bits.unsigned_abs();
252        Equal
253    }
254}
255
256macro_rules! impl_shr_round_signed {
257    ($t:ident) => {
258        impl ShrRound<$t> for Integer {
259            type Output = Integer;
260
261            /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2), taking it by
262            /// value, and rounds according to the specified rounding mode. An [`Ordering`] is also
263            /// returned, indicating whether the returned value is less than, equal to, or greater
264            /// than the exact value. If `bits` is negative, then the returned [`Ordering`] is
265            /// always `Equal`, even if the higher bits of the result are lost.
266            ///
267            /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
268            /// use `self.divisible_by_power_of_2(bits)`.
269            ///
270            /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first
271            /// element of the pair, without the [`Ordering`]:
272            ///
273            /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$
274            ///
275            /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$
276            ///
277            /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$
278            ///
279            /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$
280            ///
281            /// $$
282            /// f(x, k, \mathrm{Nearest}) = \begin{cases}
283            ///     \lfloor q \rfloor & \text{if}
284            ///         \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\
285            ///     \lceil q \rceil & \text{if}
286            ///         \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\
287            ///     \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor =
288            ///         \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
289            ///     \\ \text{is even}, \\\\
290            ///     \lceil q \rceil &
291            ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and}
292            ///         \\ \lfloor q \rfloor \\ \text{is odd}.
293            /// \end{cases}
294            /// $$
295            ///
296            /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
297            ///
298            /// Then
299            ///
300            /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$.
301            ///
302            /// # Worst-case complexity
303            /// $T(n, m) = O(n + m)$
304            ///
305            /// $M(n, m) = O(n + m)$
306            ///
307            /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and
308            /// $m$ is `max(-bits, 0)`.
309            ///
310            /// # Panics
311            /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not
312            /// divisible by $2^k$.
313            ///
314            /// # Examples
315            /// See [here](super::shr_round#shr_round).
316            #[inline]
317            fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) {
318                let o = self.shr_round_assign(bits, rm);
319                (self, o)
320            }
321        }
322
323        impl<'a> ShrRound<$t> for &Integer {
324            type Output = Integer;
325
326            /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2), taking it by
327            /// reference, and rounds according to the specified rounding mode. An [`Ordering`] is
328            /// also returned, indicating whether the returned value is less than, equal to, or
329            /// greater than the exact value. If `bits` is negative, then the returned [`Ordering`]
330            /// is always `Equal`, even if the higher bits of the result are lost.
331            ///
332            /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
333            /// use `self.divisible_by_power_of_2(bits)`.
334            ///
335            /// Let $q = \frac{x}{2^k}$, and let $g$ be the function that just returns the first
336            /// element of the pair, without the [`Ordering`]:
337            ///
338            /// $f(x, k, \mathrm{Down}) = \operatorname{sgn}(q) \lfloor |q| \rfloor.$
339            ///
340            /// $f(x, k, \mathrm{Up}) = \operatorname{sgn}(q) \lceil |q| \rceil.$
341            ///
342            /// $f(x, k, \mathrm{Floor}) = \lfloor q \rfloor.$
343            ///
344            /// $f(x, k, \mathrm{Ceiling}) = \lceil q \rceil.$
345            ///
346            /// $$
347            /// f(x, k, \mathrm{Nearest}) = \begin{cases}
348            ///     \lfloor q \rfloor & \text{if}
349            ///         \\quad q - \lfloor q \rfloor < \frac{1}{2}, \\\\
350            ///     \lceil q \rceil & \text{if}
351            ///         \\quad q - \lfloor q \rfloor > \frac{1}{2}, \\\\
352            ///     \lfloor q \rfloor & \text{if} \\quad q - \lfloor q \rfloor =
353            ///         \frac{1}{2} \\ \text{and} \\ \lfloor q \rfloor
354            ///     \\ \text{is even}, \\\\
355            ///     \lceil q \rceil &
356            ///     \text{if} \\quad q - \lfloor q \rfloor = \frac{1}{2} \\ \text{and}
357            ///         \\ \lfloor q \rfloor \\ \text{is odd}.
358            /// \end{cases}
359            /// $$
360            ///
361            /// $f(x, k, \mathrm{Exact}) = q$, but panics if $q \notin \Z$.
362            ///
363            /// Then
364            ///
365            /// $f(x, k, r) = (g(x, k, r), \operatorname{cmp}(g(x, k, r), q))$.
366            ///
367            /// # Worst-case complexity
368            /// $T(n, m) = O(n + m)$
369            ///
370            /// $M(n, m) = O(n + m)$
371            ///
372            /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and
373            /// $m$ is `max(-bits, 0)`.
374            ///
375            /// # Panics
376            /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not
377            /// divisible by $2^k$.
378            ///
379            /// # Examples
380            /// See [here](super::shr_round#shr_round).
381            #[inline]
382            fn shr_round(self, bits: $t, rm: RoundingMode) -> (Integer, Ordering) {
383                shr_round_signed_ref_i(self, bits, rm)
384            }
385        }
386
387        impl ShrRoundAssign<$t> for Integer {
388            /// Shifts an [`Integer`] right (divides or multiplies it by a power of 2) and rounds
389            /// according to the specified rounding mode, in place. An [`Ordering`] is returned,
390            /// indicating whether the assigned value is less than, equal to, or greater than the
391            /// exact value. If `bits` is negative, then the returned [`Ordering`] is always
392            /// `Equal`, even if the higher bits of the result are lost.
393            ///
394            /// Passing `Floor` is equivalent to using `>>`. To test whether `Exact` can be passed,
395            /// use `self.divisible_by_power_of_2(bits)`.
396            ///
397            /// See the [`ShrRound`] documentation for details.
398            ///
399            /// # Worst-case complexity
400            /// $T(n, m) = O(n + m)$
401            ///
402            /// $M(n, m) = O(n + m)$
403            ///
404            /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and
405            /// $m$ is `max(-bits, 0)`.
406            ///
407            /// # Panics
408            /// Let $k$ be `bits`. Panics if $k$ is positive and `rm` is `Exact` but `self` is not
409            /// divisible by $2^k$.
410            ///
411            /// # Examples
412            /// See [here](super::shr_round#shr_round_assign).
413            #[inline]
414            fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering {
415                shr_round_assign_signed_i(self, bits, rm)
416            }
417        }
418    };
419}
420apply_to_signeds!(impl_shr_round_signed);