malachite_float/arithmetic/
shl_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 crate::malachite_base::num::logic::traits::SignificantBits;
12use core::cmp::Ordering::{self, *};
13use malachite_base::num::arithmetic::traits::{IsPowerOf2, ShlRound, ShlRoundAssign};
14use malachite_base::num::basic::integers::PrimitiveInt;
15use malachite_base::num::basic::traits::{Infinity, NegativeInfinity, NegativeZero, Zero};
16use malachite_base::num::conversion::traits::SaturatingInto;
17use malachite_base::rounding_modes::RoundingMode::{self, *};
18
19impl Float {
20    pub(crate) fn shl_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_add(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 left-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    /// Left-shifts a [`Float`] (multiplies 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) = x2^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::shl_prec`] instead. If you
137    /// know that your target precision is the precision of the input, consider using
138    /// [`Float::shl_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::shl_prec_round#shl_prec_round).
154    pub fn shl_prec_round<T: PrimitiveInt>(
155        mut self,
156        bits: T,
157        prec: u64,
158        rm: RoundingMode,
159    ) -> (Self, Ordering) {
160        let o = self.shl_prec_round_assign(bits, prec, rm);
161        (self, o)
162    }
163
164    /// Left-shifts a [`Float`] (multiplies 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) = x2^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::shl_prec_ref`] instead. If
196    /// you know that your target precision is the precision of the input, consider using
197    /// [`Float::shl_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::shl_prec_round#shl_prec_round).
213    pub fn shl_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.shl_prec_round_assign(bits, prec, rm);
221        (x, o)
222    }
223
224    /// Left-shifts a [`Float`] (multiplies it by a power of 2) in place, rounding the result with
225    /// the 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 x2^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::shl_prec_assign`] instead. If
256    /// you know that your target precision is the precision of the input, consider using
257    /// [`Float::shl_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::shl_prec_round#shl_prec_round).
273    pub fn shl_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.shl_prec_round_assign_helper(
284                <T as SaturatingInto<i32>>::saturating_into(bits).saturating_add(old_exponent),
285                prec,
286                rm,
287                o,
288            )
289        } else {
290            Equal
291        }
292    }
293
294    /// Left-shifts a [`Float`] (multiplies 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) = x2^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::shl_prec#shl_prec).
322    #[inline]
323    pub fn shl_prec<T: PrimitiveInt>(self, bits: T, prec: u64) -> (Self, Ordering) {
324        self.shl_prec_round(bits, prec, Nearest)
325    }
326
327    /// Left-shifts a [`Float`] (multiplies 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) = x2^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::shl_prec#shl_prec).
355    #[inline]
356    pub fn shl_prec_ref<T: PrimitiveInt>(&self, bits: T, prec: u64) -> (Self, Ordering) {
357        self.shl_prec_round_ref(bits, prec, Nearest)
358    }
359
360    /// Left-shifts a [`Float`] (multiplies it by a power of 2) in place, rounding the result with
361    /// the specified precision.
362    ///
363    /// `NaN`, infinities, and zeros are unchanged. If the output has a precision, it is `prec`.
364    ///
365    /// $$
366    /// x \gets x2^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::shl_prec#shl_prec).
388    #[inline]
389    pub fn shl_prec_assign<T: PrimitiveInt>(&mut self, bits: T, prec: u64) -> Ordering {
390        self.shl_prec_round_assign(bits, prec, Nearest)
391    }
392}
393
394fn shl_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_add(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 left-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
459#[inline]
460fn shl_round_assign_primitive_int<T: PrimitiveInt>(
461    x: &mut Float,
462    bits: T,
463    rm: RoundingMode,
464) -> Ordering {
465    x.shl_prec_round_assign_helper(bits, x.significant_bits(), rm, Equal)
466}
467
468macro_rules! impl_natural_shl_round {
469    ($t:ident) => {
470        impl ShlRound<$t> for Float {
471            type Output = Float;
472
473            /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with
474            /// the specified rounding mode and taking the [`Float`] by value.
475            ///
476            /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
477            /// output has the same precision.
478            ///
479            /// $$
480            /// f(x,k,m) = x2^k.
481            /// $$
482            ///
483            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
484            ///   is returned instead.
485            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
486            ///   $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
487            ///   input.
488            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
489            ///   is returned instead.
490            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
491            ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
492            ///   input.
493            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
494            ///   instead.
495            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
496            ///   returned instead.
497            /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
498            /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
499            ///   returned instead.
500            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
501            ///   instead.
502            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
503            ///   returned instead.
504            /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
505            ///   instead.
506            /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
507            ///   returned instead.
508            ///
509            /// If you don't care about overflow or underflow behavior, or only want the behavior of
510            /// the `Nearest` rounding mode, you can just use `<<` instead.
511            ///
512            /// # Worst-case complexity
513            /// $T(n) = O(n)$
514            ///
515            /// $M(n) = O(n)$
516            ///
517            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
518            ///
519            /// # Panics
520            /// Panics if the result overflows or underflows and `rm` is `Exact`.
521            ///
522            /// # Examples
523            /// See [here](super::shl_round#shl_round).
524            #[inline]
525            fn shl_round(mut self, bits: $t, rm: RoundingMode) -> (Float, Ordering) {
526                let o = self.shl_round_assign(bits, rm);
527                (self, o)
528            }
529        }
530
531        impl ShlRound<$t> for &Float {
532            type Output = Float;
533
534            /// Left-shifts a [`Float`] (multiplies it by a power of 2), rounding the result with
535            /// the specified rounding mode and taking the [`Float`] by reference.
536            ///
537            /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
538            /// output has the same precision.
539            ///
540            /// $$
541            /// f(x,k,m) = x2^k.
542            /// $$
543            ///
544            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
545            ///   is returned instead.
546            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
547            ///   $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
548            ///   input.
549            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
550            ///   is returned instead.
551            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
552            ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
553            ///   input.
554            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
555            ///   instead.
556            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
557            ///   returned instead.
558            /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
559            /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
560            ///   returned instead.
561            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
562            ///   instead.
563            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
564            ///   returned instead.
565            /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
566            ///   instead.
567            /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
568            ///   returned instead.
569            ///
570            /// If you don't care about overflow or underflow behavior, or only want the behavior of
571            /// the `Nearest` rounding mode, you can just use `<<` instead.
572            ///
573            /// # Worst-case complexity
574            /// $T(n) = O(n)$
575            ///
576            /// $M(n) = O(n)$
577            ///
578            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
579            ///
580            /// # Panics
581            /// Panics if the result overflows or underflows and `rm` is `Exact`.
582            ///
583            /// # Examples
584            /// See [here](super::shl_round#shl_round).
585            #[inline]
586            fn shl_round(self, bits: $t, rm: RoundingMode) -> (Float, Ordering) {
587                shl_round_primitive_int_ref(self, bits, rm)
588            }
589        }
590
591        impl ShlRoundAssign<$t> for Float {
592            /// Left-shifts a [`Float`] (multiplies it by a power of 2), in place, rounding the
593            /// result with the specified rounding mode.
594            ///
595            /// `NaN`, infinities, and zeros are unchanged. If the [`Float`] has a precision, the
596            /// precision is unchanged.
597            ///
598            /// $$
599            /// x\gets x2^k.
600            /// $$
601            ///
602            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$
603            ///   is returned instead.
604            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`,
605            ///   $(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
606            ///   input.
607            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$
608            ///   is returned instead.
609            /// - If $f(x,k,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
610            ///   $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead, where `p` is the precision of the
611            ///   input.
612            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned
613            ///   instead.
614            /// - If $0<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is
615            ///   returned instead.
616            /// - If $0<f(x,k,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
617            /// - If $2^{-2^{30}-1}<f(x,k,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is
618            ///   returned instead.
619            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
620            ///   instead.
621            /// - If $-2^{-2^{30}}<f(x,k,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is
622            ///   returned instead.
623            /// - If $-2^{-2^{30}-1}\leq f(x,k,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned
624            ///   instead.
625            /// - If $-2^{-2^{30}}<f(x,k,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
626            ///   returned instead.
627            ///
628            /// If you don't care about overflow or underflow behavior, or only want the behavior of
629            /// the `Nearest` rounding mode, you can just use `<<=` instead.
630            ///
631            /// # Worst-case complexity
632            /// $T(n) = O(n)$
633            ///
634            /// $M(n) = O(n)$
635            ///
636            /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
637            ///
638            /// # Panics
639            /// Panics if the result overflows or underflows and `rm` is `Exact`.
640            ///
641            /// # Examples
642            /// See [here](super::shl_round#shl_round_assign).
643            #[inline]
644            fn shl_round_assign(&mut self, bits: $t, rm: RoundingMode) -> Ordering {
645                shl_round_assign_primitive_int(self, bits, rm)
646            }
647        }
648    };
649}
650apply_to_primitive_ints!(impl_natural_shl_round);