malachite_float/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::Float;
10use crate::InnerFloat::Finite;
11use core::cmp::Ordering::{self, *};
12use malachite_base::num::arithmetic::traits::{IsPowerOf2, ShrRound, ShrRoundAssign};
13use malachite_base::num::basic::integers::PrimitiveInt;
14use malachite_base::num::basic::traits::{Infinity, NegativeInfinity, NegativeZero, Zero};
15use malachite_base::num::conversion::traits::SaturatingInto;
16use malachite_base::num::logic::traits::SignificantBits;
17use malachite_base::rounding_modes::RoundingMode::{self, *};
18
19impl Float {
20    pub(crate) fn shr_prec_round_assign_helper<T: PrimitiveInt>(
21        &mut self,
22        bits: T,
23        prec: u64,
24        rm: RoundingMode,
25        previous_o: Ordering,
26    ) -> Ordering {
27        if let Self(Finite {
28            significand,
29            exponent,
30            sign,
31            precision,
32        }) = self
33        {
34            let mut possibly_just_under_min = false;
35            if let Ok(bits) = bits.try_into()
36                && let Some(new_exponent) = exponent.checked_sub(bits)
37            {
38                possibly_just_under_min = true;
39                if (Self::MIN_EXPONENT..=Self::MAX_EXPONENT).contains(&new_exponent) {
40                    *exponent = new_exponent;
41                    return previous_o;
42                }
43            }
44            assert!(rm != Exact, "Inexact Float right-shift");
45            if bits < T::ZERO {
46                match (*sign, rm) {
47                    (true, Up | Ceiling | Nearest) => {
48                        *self = Self::INFINITY;
49                        Greater
50                    }
51                    (true, Floor | Down) => {
52                        *self = Self::max_finite_value_with_prec(prec);
53                        Less
54                    }
55                    (false, Up | Floor | Nearest) => {
56                        *self = Self::NEGATIVE_INFINITY;
57                        Less
58                    }
59                    (false, Ceiling | Down) => {
60                        *self = -Self::max_finite_value_with_prec(prec);
61                        Greater
62                    }
63                    (_, Exact) => unreachable!(),
64                }
65            } else if rm == Nearest
66                && possibly_just_under_min
67                && *exponent - <T as SaturatingInto<i32>>::saturating_into(bits)
68                    == Self::MIN_EXPONENT - 1
69                && (previous_o == if *sign { Less } else { Greater }
70                    || !significand.is_power_of_2())
71            {
72                if *sign {
73                    *self = Self::min_positive_value_prec(*precision);
74                    Greater
75                } else {
76                    *self = -Self::min_positive_value_prec(*precision);
77                    Less
78                }
79            } else {
80                match (*sign, rm) {
81                    (true, Up | Ceiling) => {
82                        *self = Self::min_positive_value_prec(prec);
83                        Greater
84                    }
85                    (true, Floor | Down | Nearest) => {
86                        *self = Self::ZERO;
87                        Less
88                    }
89                    (false, Up | Floor) => {
90                        *self = -Self::min_positive_value_prec(prec);
91                        Less
92                    }
93                    (false, Ceiling | Down | Nearest) => {
94                        *self = Self::NEGATIVE_ZERO;
95                        Greater
96                    }
97                    (_, Exact) => unreachable!(),
98                }
99            }
100        } else {
101            Equal
102        }
103    }
104
105    /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
106    /// specified rounding mode and precision, and taking the [`Float`] by value.
107    ///
108    /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
109    ///
110    /// $$
111    /// f(x,k,p,m) = x/2^k.
112    /// $$
113    ///
114    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
115    ///   returned instead.
116    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
117    ///   is returned instead, where `p` is the precision of the input.
118    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
119    ///   returned instead.
120    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
121    ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`.
122    /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
123    /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
124    ///   instead.
125    /// - If $0<f(x,k,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
126    /// - If $2^{-2^{30}-1}<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
127    ///   instead.
128    /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
129    ///   instead.
130    /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
131    ///   instead.
132    /// - If $-2^{-2^{30}-1}\leq f(x,k,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
133    /// - If $-2^{-2^{30}}<f(x,k,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
134    ///   returned instead.
135    ///
136    /// If you know you'll be using `Nearest`, consider using [`Float::shr_prec`] instead. If you
137    /// know that your target precision is the precision of the input, consider using
138    /// [`Float::shr_round`] instead. If both of these things are true, or you don't care about
139    /// overflow or underflow behavior, consider using `>>` instead.
140    ///
141    /// # Worst-case complexity
142    /// $T(n) = O(n)$
143    ///
144    /// $M(n) = O(n)$
145    ///
146    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
147    ///
148    /// # Panics
149    /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed
150    /// exactly with the specified precision.
151    ///
152    /// # Examples
153    /// See [here](super::shr_prec_round#shr_prec_round).
154    pub fn shr_prec_round<T: PrimitiveInt>(
155        mut self,
156        bits: T,
157        prec: u64,
158        rm: RoundingMode,
159    ) -> (Self, Ordering) {
160        let o = self.shr_prec_round_assign(bits, prec, rm);
161        (self, o)
162    }
163
164    /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
165    /// specified rounding mode and precision, and taking the [`Float`] by reference.
166    ///
167    /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
168    ///
169    /// $$
170    /// f(x,k,p,m) = x/2^k.
171    /// $$
172    ///
173    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
174    ///   returned instead.
175    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
176    ///   is returned instead, where `p` is the precision of the input.
177    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
178    ///   returned instead.
179    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
180    ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`.
181    /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
182    /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
183    ///   instead.
184    /// - If $0<f(x,k,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
185    /// - If $2^{-2^{30}-1}<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
186    ///   instead.
187    /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
188    ///   instead.
189    /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
190    ///   instead.
191    /// - If $-2^{-2^{30}-1}\leq f(x,k,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
192    /// - If $-2^{-2^{30}}<f(x,k,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
193    ///   returned instead.
194    ///
195    /// If you know you'll be using `Nearest`, consider using [`Float::shr_prec_ref`] instead. If
196    /// you know that your target precision is the precision of the input, consider using
197    /// [`Float::shr_round_ref`] instead. If both of these things are true, or you don't care about
198    /// overflow or underflow behavior, consider using `>>` instead.
199    ///
200    /// # Worst-case complexity
201    /// $T(n) = O(n)$
202    ///
203    /// $M(n) = O(n)$
204    ///
205    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
206    ///
207    /// # Panics
208    /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed
209    /// exactly with the specified precision.
210    ///
211    /// # Examples
212    /// See [here](super::shr_prec_round#shr_prec_round).
213    pub fn shr_prec_round_ref<T: PrimitiveInt>(
214        &self,
215        bits: T,
216        prec: u64,
217        rm: RoundingMode,
218    ) -> (Self, Ordering) {
219        let mut x = self.clone();
220        let o = x.shr_prec_round_assign(bits, prec, rm);
221        (x, o)
222    }
223
224    /// Right-shifts a [`Float`] (divides it by a power of 2) in place, rounding the result with the
225    /// specified rounding mode and precision.
226    ///
227    /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
228    ///
229    /// $$
230    /// x \gets x/2^k.
231    /// $$
232    ///
233    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
234    ///   returned instead.
235    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
236    ///   is returned instead, where `p` is the precision of the input.
237    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
238    ///   returned instead.
239    /// - If $f(x,k,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
240    ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is `prec`.
241    /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
242    /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
243    ///   instead.
244    /// - If $0<f(x,k,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
245    /// - If $2^{-2^{30}-1}<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
246    ///   instead.
247    /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
248    ///   instead.
249    /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
250    ///   instead.
251    /// - If $-2^{-2^{30}-1}\leq f(x,k,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
252    /// - If $-2^{-2^{30}}<f(x,k,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
253    ///   returned instead.
254    ///
255    /// If you know you'll be using `Nearest`, consider using [`Float::shr_prec_assign`] instead. If
256    /// you know that your target precision is the precision of the input, consider using
257    /// [`Float::shr_round_assign`] instead. If both of these things are true, or you don't care
258    /// about overflow or underflow behavior, consider using `>>=` instead.
259    ///
260    /// # Worst-case complexity
261    /// $T(n) = O(n)$
262    ///
263    /// $M(n) = O(n)$
264    ///
265    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
266    ///
267    /// # Panics
268    /// Panics if `rm` is `Exact` and the result overflows or underflows, or cannot be expressed
269    /// exactly with the specified precision.
270    ///
271    /// # Examples
272    /// See [here](super::shr_prec_round#shr_prec_round).
273    pub fn shr_prec_round_assign<T: PrimitiveInt>(
274        &mut self,
275        bits: T,
276        prec: u64,
277        rm: RoundingMode,
278    ) -> Ordering {
279        if let Self(Finite { exponent, .. }) = self {
280            let old_exponent = *exponent;
281            *exponent = 0;
282            let o = self.set_prec_round(prec, rm);
283            self.shr_prec_round_assign_helper(
284                <T as SaturatingInto<i32>>::saturating_into(bits).saturating_sub(old_exponent),
285                prec,
286                rm,
287                o,
288            )
289        } else {
290            Equal
291        }
292    }
293
294    /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
295    /// specified precision, and taking the [`Float`] by value.
296    ///
297    /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
298    ///
299    /// $$
300    /// f(x,k,p) = x/2^k.
301    /// $$
302    ///
303    /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
304    /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
305    /// - If $0<f(x,k,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
306    /// - If $2^{-2^{30}-1}<f(x,k,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
307    /// - If $-2^{-2^{30}-1}\leq f(x,k,p)<0$, $-0.0$ is returned instead.
308    /// - If $-2^{-2^{30}}<f(x,k,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
309    ///
310    /// If you know that your target precision is the precision of the input, or you don't care
311    /// about overflow or underflow behavior, consider using `>>` instead.
312    ///
313    /// # Worst-case complexity
314    /// $T(n) = O(n)$
315    ///
316    /// $M(n) = O(n)$
317    ///
318    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
319    ///
320    /// # Examples
321    /// See [here](super::shr_prec#shr_prec).
322    #[inline]
323    pub fn shr_prec<T: PrimitiveInt>(self, bits: T, prec: u64) -> (Self, Ordering) {
324        self.shr_prec_round(bits, prec, Nearest)
325    }
326
327    /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
328    /// specified precision, and taking the [`Float`] by reference.
329    ///
330    /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
331    ///
332    /// $$
333    /// f(x,k,p) = x/2^k.
334    /// $$
335    ///
336    /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
337    /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
338    /// - If $0<f(x,k,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
339    /// - If $2^{-2^{30}-1}<f(x,k,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
340    /// - If $-2^{-2^{30}-1}\leq f(x,k,p)<0$, $-0.0$ is returned instead.
341    /// - If $-2^{-2^{30}}<f(x,k,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
342    ///
343    /// If you know that your target precision is the precision of the input, or you don't care
344    /// about overflow or underflow behavior, consider using `>>` instead.
345    ///
346    /// # Worst-case complexity
347    /// $T(n) = O(n)$
348    ///
349    /// $M(n) = O(n)$
350    ///
351    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
352    ///
353    /// # Examples
354    /// See [here](super::shr_prec#shr_prec).
355    #[inline]
356    pub fn shr_prec_ref<T: PrimitiveInt>(&self, bits: T, prec: u64) -> (Self, Ordering) {
357        self.shr_prec_round_ref(bits, prec, Nearest)
358    }
359
360    /// Right-shifts a [`Float`] (divides it by a power of 2) in place, rounding the result with the
361    /// specified precision.
362    ///
363    /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
364    ///
365    /// $$
366    /// x \gets x/2^k.
367    /// $$
368    ///
369    /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
370    /// - If $f(x,k,p)\geq 2^{2^{30}-1}$, $-\infty$ is returned instead.
371    /// - If $0<f(x,k,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
372    /// - If $2^{-2^{30}-1}<f(x,k,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
373    /// - If $-2^{-2^{30}-1}\leq f(x,k,p)<0$, $-0.0$ is returned instead.
374    /// - If $-2^{-2^{30}}<f(x,k,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
375    ///
376    /// If you know that your target precision is the precision of the input, or you don't care
377    /// about overflow or underflow behavior, consider using `>>=` instead.
378    ///
379    /// # Worst-case complexity
380    /// $T(n) = O(n)$
381    ///
382    /// $M(n) = O(n)$
383    ///
384    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
385    ///
386    /// # Examples
387    /// See [here](super::shr_prec#shr_prec).
388    #[inline]
389    pub fn shr_prec_assign<T: PrimitiveInt>(&mut self, bits: T, prec: u64) -> Ordering {
390        self.shr_prec_round_assign(bits, prec, Nearest)
391    }
392}
393
394fn shr_round_primitive_int_ref<T: PrimitiveInt>(
395    x: &Float,
396    bits: T,
397    rm: RoundingMode,
398) -> (Float, Ordering) {
399    if let Float(Finite {
400        significand,
401        exponent,
402        sign,
403        precision,
404    }) = x
405    {
406        let mut possibly_just_under_min = false;
407        if let Ok(bits) = bits.try_into()
408            && let Some(new_exponent) = exponent.checked_sub(bits)
409        {
410            possibly_just_under_min = true;
411            if (Float::MIN_EXPONENT..=Float::MAX_EXPONENT).contains(&new_exponent) {
412                return (
413                    Float(Finite {
414                        significand: significand.clone(),
415                        exponent: new_exponent,
416                        sign: *sign,
417                        precision: *precision,
418                    }),
419                    Equal,
420                );
421            }
422        }
423        assert!(rm != Exact, "Inexact Float right-shift");
424        if bits < T::ZERO {
425            match (*sign, rm) {
426                (true, Up | Ceiling | Nearest) => (Float::INFINITY, Greater),
427                (true, Floor | Down) => (Float::max_finite_value_with_prec(*precision), Less),
428                (false, Up | Floor | Nearest) => (Float::NEGATIVE_INFINITY, Less),
429                (false, Ceiling | Down) => {
430                    (-Float::max_finite_value_with_prec(*precision), Greater)
431                }
432                (_, Exact) => unreachable!(),
433            }
434        } else if rm == Nearest
435            && possibly_just_under_min
436            && *exponent - <T as SaturatingInto<i32>>::saturating_into(bits)
437                == Float::MIN_EXPONENT - 1
438            && !significand.is_power_of_2()
439        {
440            if *sign {
441                (Float::min_positive_value_prec(*precision), Greater)
442            } else {
443                (-Float::min_positive_value_prec(*precision), Less)
444            }
445        } else {
446            match (*sign, rm) {
447                (true, Up | Ceiling) => (Float::min_positive_value_prec(*precision), Greater),
448                (true, Floor | Down | Nearest) => (Float::ZERO, Less),
449                (false, Up | Floor) => (-Float::min_positive_value_prec(*precision), Less),
450                (false, Ceiling | Down | Nearest) => (Float::NEGATIVE_ZERO, Greater),
451                (_, Exact) => unreachable!(),
452            }
453        }
454    } else {
455        (x.clone(), Equal)
456    }
457}
458
459fn shr_round_assign_primitive_int<T: PrimitiveInt>(
460    x: &mut Float,
461    bits: T,
462    rm: RoundingMode,
463) -> Ordering {
464    x.shr_prec_round_assign_helper(bits, x.significant_bits(), rm, Equal)
465}
466
467macro_rules! impl_natural_shr_round {
468    ($t:ident) => {
469        impl ShrRound<$t> for Float {
470            type Output = Float;
471
472            /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
473            /// specified rounding mode and taking the [`Float`] by value.
474            ///
475            /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
476            /// output has the same precision.
477            ///
478            /// $$
479            /// f(x,k,m) = x/2^k.
480            /// $$
481            ///
482            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
483            ///   is returned instead.
484            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
485            ///   $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
486            ///   input.
487            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
488            ///   is returned instead.
489            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
490            ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
491            ///   input.
492            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
493            ///   instead.
494            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
495            ///   returned instead.
496            /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
497            /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
498            ///   returned instead.
499            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
500            ///   instead.
501            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
502            ///   returned instead.
503            /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
504            ///   instead.
505            /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
506            ///   returned instead.
507            ///
508            /// If you don't care about overflow or underflow behavior, or only want the behavior of
509            /// the `Nearest` rounding mode, you can just use `>>` instead.
510            ///
511            /// # Worst-case complexity
512            /// $T(n) = O(n)$
513            ///
514            /// $M(n) = O(n)$
515            ///
516            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
517            ///
518            /// # Panics
519            /// Panics if the result overflows or underflows and `rm` is `Exact`.
520            ///
521            /// # Examples
522            /// See [here](super::shr_round#shr_round).
523            #[inline]
524            fn shr_round(mut self, bits: $t, rm: RoundingMode) -> (Float, Ordering) {
525                let o = self.shr_round_assign(bits, rm);
526                (self, o)
527            }
528        }
529
530        impl ShrRound<$t> for &Float {
531            type Output = Float;
532
533            /// Right-shifts a [`Float`] (divides it by a power of 2), rounding the result with the
534            /// specified rounding mode and taking the [`Float`] by reference.
535            ///
536            /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
537            /// output has the same precision.
538            ///
539            /// $$
540            /// f(x,k,m) = x/2^k.
541            /// $$
542            ///
543            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
544            ///   is returned instead.
545            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
546            ///   $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
547            ///   input.
548            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
549            ///   is returned instead.
550            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
551            ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
552            ///   input.
553            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
554            ///   instead.
555            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
556            ///   returned instead.
557            /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
558            /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
559            ///   returned instead.
560            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
561            ///   instead.
562            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
563            ///   returned instead.
564            /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
565            ///   instead.
566            /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
567            ///   returned instead.
568            ///
569            /// If you don't care about overflow or underflow behavior, or only want the behavior of
570            /// the `Nearest` rounding mode, you can just use `>>` instead.
571            ///
572            /// # Worst-case complexity
573            /// $T(n) = O(n)$
574            ///
575            /// $M(n) = O(n)$
576            ///
577            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
578            ///
579            /// # Panics
580            /// Panics if the result overflows or underflows and `rm` is `Exact`.
581            ///
582            /// # Examples
583            /// See [here](super::shr_round#shr_round).
584            #[inline]
585            fn shr_round(self, bits: $t, rm: RoundingMode) -> (Float, Ordering) {
586                shr_round_primitive_int_ref(self, bits, rm)
587            }
588        }
589
590        impl ShrRoundAssign<$t> for Float {
591            /// Right-shifts a [`Float`] (divides it by a power of 2), in place, rounding the result
592            /// with the specified rounding mode.
593            ///
594            /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
595            /// precision is unchanged.
596            ///
597            /// $$
598            /// x\gets x/2^k.
599            /// $$
600            ///
601            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
602            ///   is returned instead.
603            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
604            ///   $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
605            ///   input.
606            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
607            ///   is returned instead.
608            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
609            ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
610            ///   input.
611            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
612            ///   instead.
613            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
614            ///   returned instead.
615            /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
616            /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
617            ///   returned instead.
618            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
619            ///   instead.
620            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
621            ///   returned instead.
622            /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
623            ///   instead.
624            /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
625            ///   returned instead.
626            ///
627            /// If you don't care about overflow or underflow behavior, or only want the behavior of
628            /// the `Nearest` rounding mode, you can just use `>>=` instead.
629            ///
630            /// # Worst-case complexity
631            /// $T(n) = O(n)$
632            ///
633            /// $M(n) = O(n)$
634            ///
635            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
636            ///
637            /// # Panics
638            /// Panics if the result overflows or underflows and `rm` is `Exact`.
639            ///
640            /// # Examples
641            /// See [here](super::shr_round#shr_round_assign).
642            #[inline]
643            fn shr_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering {
644                shr_round_assign_primitive_int(self, bits, rm)
645            }
646        }
647    };
648}
649apply_to_primitive_ints!(impl_natural_shr_round);