Skip to main content

malachite_float/float/conversion/
primitive_int_from_float.rs

1// Copyright © 2026 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::InnerFloat::{Finite, Infinity, NaN, Zero};
10use crate::float::arithmetic::is_power_of_2::float_is_signed_min;
11use crate::{Float, significand_bits};
12use core::cmp::Ordering::{self, *};
13use malachite_base::num::arithmetic::traits::{DivisibleByPowerOf2, ShrRound};
14use malachite_base::num::basic::signeds::PrimitiveSigned;
15use malachite_base::num::basic::unsigneds::PrimitiveUnsigned;
16use malachite_base::num::conversion::from::{SignedFromFloatError, UnsignedFromFloatError};
17use malachite_base::num::conversion::traits::{ConvertibleFrom, RoundingFrom, WrappingFrom};
18use malachite_base::rounding_modes::RoundingMode::{self, *};
19use malachite_nz::integer::Integer;
20use malachite_nz::natural::Natural;
21
22#[allow(clippy::type_repetition_in_bounds)]
23fn unsigned_rounding_from_float<T: PrimitiveUnsigned>(f: Float, rm: RoundingMode) -> (T, Ordering)
24where
25    for<'a> T: TryFrom<&'a Natural>,
26{
27    match f {
28        float_nan!() => panic!("Can't convert NaN to {}", T::NAME),
29        float_infinity!() => match rm {
30            Floor | Down | Nearest => (T::MAX, Less),
31            _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm),
32        },
33        float_negative_infinity!() => match rm {
34            Ceiling | Down | Nearest => (T::ZERO, Greater),
35            _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm),
36        },
37        float_either_zero!() => (T::ZERO, Equal),
38        Float(Finite {
39            sign,
40            exponent,
41            significand,
42            ..
43        }) => {
44            let exponent = i64::from(exponent);
45            if !sign {
46                match rm {
47                    Ceiling | Down | Nearest => (T::ZERO, Greater),
48                    _ => panic!("Cannot convert negative Float to {} using {}", T::NAME, rm),
49                }
50            } else if exponent < 0 {
51                match rm {
52                    Floor | Down | Nearest => (T::ZERO, Less),
53                    Ceiling | Up => (T::ONE, Greater),
54                    Exact => {
55                        panic!("Cannot convert Float to {} using {}", T::NAME, rm)
56                    }
57                }
58            } else if exponent > i64::wrapping_from(T::WIDTH) {
59                match rm {
60                    Floor | Down | Nearest => (T::MAX, Less),
61                    _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm),
62                }
63            } else {
64                let sb = significand_bits(&significand);
65                let eb = exponent.unsigned_abs();
66                let (n, o) = if sb >= eb {
67                    significand.shr_round(sb - eb, rm)
68                } else {
69                    (significand << (eb - sb), Equal)
70                };
71                if let Ok(n) = T::try_from(&n) {
72                    (n, o)
73                } else {
74                    match rm {
75                        Floor | Down | Nearest => (T::MAX, Less),
76                        _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm),
77                    }
78                }
79            }
80        }
81    }
82}
83
84#[allow(clippy::type_repetition_in_bounds)]
85fn unsigned_rounding_from_float_ref<T: PrimitiveUnsigned>(
86    f: &Float,
87    rm: RoundingMode,
88) -> (T, Ordering)
89where
90    for<'a> T: TryFrom<&'a Natural>,
91{
92    match f {
93        float_nan!() => panic!("Can't convert NaN to {}", T::NAME),
94        float_infinity!() => match rm {
95            Floor | Down | Nearest => (T::MAX, Less),
96            _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm),
97        },
98        float_negative_infinity!() => match rm {
99            Ceiling | Down | Nearest => (T::ZERO, Greater),
100            _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm),
101        },
102        float_either_zero!() => (T::ZERO, Equal),
103        Float(Finite {
104            sign,
105            exponent,
106            significand,
107            ..
108        }) => {
109            let exponent = i64::from(*exponent);
110            if !sign {
111                match rm {
112                    Ceiling | Down | Nearest => (T::ZERO, Greater),
113                    _ => panic!("Cannot convert negative Float to {} using {}", T::NAME, rm),
114                }
115            } else if exponent < 0 {
116                match rm {
117                    Floor | Down | Nearest => (T::ZERO, Less),
118                    Ceiling | Up => (T::ONE, Greater),
119                    Exact => {
120                        panic!("Cannot convert Float to {} using {}", T::NAME, rm)
121                    }
122                }
123            } else if exponent > i64::wrapping_from(T::WIDTH) {
124                match rm {
125                    Floor | Down | Nearest => (T::MAX, Less),
126                    _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm),
127                }
128            } else {
129                let sb = significand_bits(significand);
130                let eb = exponent.unsigned_abs();
131                let (n, o) = if sb >= eb {
132                    significand.shr_round(sb - eb, rm)
133                } else {
134                    (significand << (eb - sb), Equal)
135                };
136                if let Ok(n) = T::try_from(&n) {
137                    (n, o)
138                } else {
139                    match rm {
140                        Floor | Down | Nearest => (T::MAX, Less),
141                        _ => panic!("Cannot convert large Float to {} using {}", T::NAME, rm),
142                    }
143                }
144            }
145        }
146    }
147}
148
149#[allow(clippy::type_repetition_in_bounds)]
150fn unsigned_try_from_float<T: PrimitiveUnsigned>(f: Float) -> Result<T, UnsignedFromFloatError>
151where
152    for<'a> T: WrappingFrom<&'a Natural>,
153{
154    match f {
155        float_either_zero!() => Ok(T::ZERO),
156        Float(Finite {
157            sign,
158            exponent,
159            significand,
160            ..
161        }) => {
162            let exponent = i64::from(exponent);
163            if !sign {
164                Err(UnsignedFromFloatError::FloatNegative)
165            } else if exponent <= 0 || exponent > i64::wrapping_from(T::WIDTH) {
166                Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
167            } else {
168                let sb = significand_bits(&significand);
169                let eb = exponent.unsigned_abs();
170                let n = if sb >= eb {
171                    let bits = sb - eb;
172                    if significand.divisible_by_power_of_2(bits) {
173                        Ok(significand >> bits)
174                    } else {
175                        Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
176                    }
177                } else {
178                    Ok(significand << (eb - sb))
179                };
180                n.map(|n| T::wrapping_from(&n))
181            }
182        }
183        _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan),
184    }
185}
186
187#[allow(clippy::type_repetition_in_bounds)]
188fn unsigned_try_from_float_ref<T: PrimitiveUnsigned>(f: &Float) -> Result<T, UnsignedFromFloatError>
189where
190    for<'a> T: WrappingFrom<&'a Natural>,
191{
192    match f {
193        float_either_zero!() => Ok(T::ZERO),
194        Float(Finite {
195            sign,
196            exponent,
197            significand,
198            ..
199        }) => {
200            let exponent = i64::from(*exponent);
201            if !sign {
202                Err(UnsignedFromFloatError::FloatNegative)
203            } else if exponent <= 0 || exponent > i64::wrapping_from(T::WIDTH) {
204                Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
205            } else {
206                let sb = significand_bits(significand);
207                let eb = exponent.unsigned_abs();
208                let n = if sb >= eb {
209                    let bits = sb - eb;
210                    if significand.divisible_by_power_of_2(bits) {
211                        Ok(significand >> bits)
212                    } else {
213                        Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
214                    }
215                } else {
216                    Ok(significand << (eb - sb))
217                };
218                n.map(|n| T::wrapping_from(&n))
219            }
220        }
221        _ => Err(UnsignedFromFloatError::FloatInfiniteOrNan),
222    }
223}
224
225fn unsigned_convertible_from_float<T: PrimitiveUnsigned>(f: &Float) -> bool {
226    match f {
227        float_either_zero!() => true,
228        Float(Finite {
229            sign,
230            exponent,
231            significand,
232            ..
233        }) => {
234            let exponent = i64::from(*exponent);
235            *sign && exponent > 0 && exponent <= i64::wrapping_from(T::WIDTH) && {
236                let sb = significand_bits(significand);
237                let eb = exponent.unsigned_abs();
238                sb < eb || significand.divisible_by_power_of_2(sb - eb)
239            }
240        }
241        _ => false,
242    }
243}
244
245macro_rules! impl_unsigned_from {
246    ($t: ident) => {
247        impl RoundingFrom<Float> for $t {
248            /// Converts a [`Float`] to an unsigned primitive integer, using a specified
249            /// [`RoundingMode`] and taking the [`Float`] by value. An [`Ordering`] is also
250            /// returned, indicating whether the returned value is less than, equal to, or greater
251            /// than the original value.
252            ///
253            /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero
254            /// when the [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this
255            /// function will panic.
256            ///
257            /// If the [`Float`] is greater than the maximum representable value of the unsigned
258            /// type (including $\infty$), then it will be rounded to the maximum value when the
259            /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will
260            /// panic.
261            ///
262            /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode.
263            ///
264            /// # Worst-case complexity
265            /// $T(n) = O(n)$
266            ///
267            /// $M(n) = O(1)$
268            ///
269            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
270            /// rounding must examine the bits that are discarded.
271            ///
272            /// # Panics
273            /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`]
274            /// is less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, if the [`Float`]
275            /// is greater than the maximum representable value of the unsigned type and `rm` is not
276            /// `Down`, `Floor`, or `Nearest`, or if the [`Float`] is NaN.
277            ///
278            /// # Examples
279            /// See [here](super::primitive_int_from_float#rounding_from).
280            #[inline]
281            fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) {
282                unsigned_rounding_from_float(f, rm)
283            }
284        }
285
286        impl RoundingFrom<&Float> for $t {
287            /// Converts a [`Float`] to an unsigned primitive integer, using a specified
288            /// [`RoundingMode`] and taking the [`Float`] by reference. An [`Ordering`] is also
289            /// returned, indicating whether the returned value is less than, equal to, or greater
290            /// than the original value.
291            ///
292            /// If the [`Float`] is negative (including $-\infty$), then it will be rounded to zero
293            /// when the [`RoundingMode`] is `Ceiling`, `Down`, or `Nearest`. Otherwise, this
294            /// function will panic.
295            ///
296            /// If the [`Float`] is greater than the maximum representable value of the unsigned
297            /// type (including $\infty$), then it will be rounded to the maximum value when the
298            /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will
299            /// panic.
300            ///
301            /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode.
302            ///
303            /// # Worst-case complexity
304            /// $T(n) = O(n)$
305            ///
306            /// $M(n) = O(1)$
307            ///
308            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
309            /// rounding must examine the bits that are discarded.
310            ///
311            /// # Panics
312            /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`]
313            /// is less than zero and `rm` is not `Down`, `Ceiling`, or `Nearest`, if the [`Float`]
314            /// is greater than the maximum representable value of the unsigned type and `rm` is not
315            /// `Down`, `Floor`, or `Nearest`, or if the [`Float`] is NaN.
316            ///
317            /// # Examples
318            /// See [here](super::primitive_int_from_float#rounding_from).
319            #[inline]
320            fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) {
321                unsigned_rounding_from_float_ref(f, rm)
322            }
323        }
324
325        impl TryFrom<Float> for $t {
326            type Error = UnsignedFromFloatError;
327
328            /// Converts a [`Float`] to a primitive unsigned integer, taking the [`Float`] by value.
329            /// If the [`Float`] is not equal to an unsigned primitive integer of the given type, an
330            /// error is returned.
331            ///
332            /// Both positive and negative zero convert to a primitive unsigned integer zero.
333            ///
334            /// # Worst-case complexity
335            /// $T(n) = O(n)$
336            ///
337            /// $M(n) = O(1)$
338            ///
339            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
340            /// rounding must examine the bits that are discarded.
341            ///
342            /// # Examples
343            /// See [here](super::primitive_int_from_float#try_from).
344            #[inline]
345            fn try_from(f: Float) -> Result<$t, Self::Error> {
346                unsigned_try_from_float(f)
347            }
348        }
349
350        impl TryFrom<&Float> for $t {
351            type Error = UnsignedFromFloatError;
352
353            /// Converts a [`Float`] to a primitive unsigned integer, taking the [`Float`] by
354            /// reference. If the [`Float`] is not equal to an unsigned primitive integer of the
355            /// given type, an error is returned.
356            ///
357            /// Both positive and negative zero convert to a primitive unsigned integer zero.
358            ///
359            /// # Worst-case complexity
360            /// $T(n) = O(n)$
361            ///
362            /// $M(n) = O(1)$
363            ///
364            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
365            /// rounding must examine the bits that are discarded.
366            ///
367            /// # Examples
368            /// See [here](super::primitive_int_from_float#try_from).
369            #[inline]
370            fn try_from(f: &Float) -> Result<$t, Self::Error> {
371                unsigned_try_from_float_ref(f)
372            }
373        }
374
375        impl ConvertibleFrom<&Float> for $t {
376            /// Determines whether a [`Float`] can be converted to an unsigned primitive integer,
377            /// taking the [`Float`] by reference.
378            ///
379            /// Both positive and negative zero are convertible to any unsigned primitive integer.
380            /// (Although negative zero is nominally negative, the real number it represents is
381            /// zero, which is not negative.)
382            ///
383            /// # Worst-case complexity
384            /// $T(n) = O(n)$
385            ///
386            /// $M(n) = O(1)$
387            ///
388            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
389            /// rounding must examine the bits that are discarded.
390            ///
391            /// # Examples
392            /// See [here](super::primitive_int_from_float#convertible_from).
393            #[inline]
394            fn convertible_from(f: &Float) -> bool {
395                unsigned_convertible_from_float::<$t>(f)
396            }
397        }
398    };
399}
400apply_to_unsigneds!(impl_unsigned_from);
401
402#[allow(clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds)]
403fn signed_rounding_from_float<T: PrimitiveSigned>(f: Float, rm: RoundingMode) -> (T, Ordering)
404where
405    for<'a> T: TryFrom<&'a Natural> + TryFrom<&'a Integer>,
406{
407    match f {
408        float_nan!() => panic!("Can't convert NaN to {}", T::NAME),
409        float_infinity!() => match rm {
410            Floor | Down | Nearest => (T::MAX, Less),
411            _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm),
412        },
413        float_negative_infinity!() => match rm {
414            Ceiling | Down | Nearest => (T::MIN, Greater),
415            _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm),
416        },
417        float_either_zero!() => (T::ZERO, Equal),
418        Float(Finite {
419            sign,
420            exponent,
421            significand,
422            ..
423        }) => {
424            let exponent = i64::from(exponent);
425            if sign {
426                if exponent < 0 {
427                    match rm {
428                        Floor | Down | Nearest => (T::ZERO, Less),
429                        Ceiling | Up => (T::ONE, Greater),
430                        Exact => {
431                            panic!("Cannot convert Float to Integer using {rm}")
432                        }
433                    }
434                } else if exponent >= i64::wrapping_from(T::WIDTH) {
435                    match rm {
436                        Floor | Down | Nearest => (T::MAX, Less),
437                        _ => {
438                            panic!("Cannot convert Float to Integer using {rm}")
439                        }
440                    }
441                } else {
442                    let sb = significand_bits(&significand);
443                    let eb = exponent.unsigned_abs();
444                    let (n, o) = if sb >= eb {
445                        significand.shr_round(sb - eb, rm)
446                    } else {
447                        (significand << (eb - sb), Equal)
448                    };
449                    if let Ok(n) = T::try_from(&n) {
450                        (n, o)
451                    } else {
452                        match rm {
453                            Floor | Down | Nearest => (T::MAX, Less),
454                            _ => {
455                                panic!("Cannot convert large Float to {} using {}", T::NAME, rm)
456                            }
457                        }
458                    }
459                }
460            } else if exponent < 0 {
461                match rm {
462                    Ceiling | Down | Nearest => (T::ZERO, Greater),
463                    Floor | Up => (T::NEGATIVE_ONE, Less),
464                    Exact => {
465                        panic!("Cannot convert Float to Integer using {rm}")
466                    }
467                }
468            } else if exponent > i64::wrapping_from(T::WIDTH) {
469                // This doesn't catch the case where -2^(W+1) < x < -2^W, but that's ok because the
470                // next else block handles it.
471                match rm {
472                    Ceiling | Down | Nearest => (T::MIN, Greater),
473                    _ => {
474                        panic!("Cannot convert Float to Integer using {rm}")
475                    }
476                }
477            } else {
478                let sb = significand_bits(&significand);
479                let eb = exponent.unsigned_abs();
480                let (n, o) = if sb >= eb {
481                    significand.shr_round(sb - eb, -rm)
482                } else {
483                    (significand << (eb - sb), Equal)
484                };
485                if let Ok(n) = T::try_from(&-n) {
486                    (n, o.reverse())
487                } else {
488                    match rm {
489                        Ceiling | Down | Nearest => (T::MIN, Greater),
490                        _ => panic!(
491                            "Cannot convert large negative Float to {} using {}",
492                            T::NAME,
493                            rm
494                        ),
495                    }
496                }
497            }
498        }
499    }
500}
501
502#[allow(clippy::trait_duplication_in_bounds, clippy::type_repetition_in_bounds)]
503fn signed_rounding_from_float_ref<T: PrimitiveSigned>(f: &Float, rm: RoundingMode) -> (T, Ordering)
504where
505    for<'a> T: TryFrom<&'a Natural> + TryFrom<&'a Integer>,
506{
507    match f {
508        float_nan!() => panic!("Can't convert NaN to {}", T::NAME),
509        float_infinity!() => match rm {
510            Floor | Down | Nearest => (T::MAX, Less),
511            _ => panic!("Can't convert Infinity to {} using {}", T::NAME, rm),
512        },
513        float_negative_infinity!() => match rm {
514            Ceiling | Down | Nearest => (T::MIN, Greater),
515            _ => panic!("Can't convert -Infinity to {} using {}", T::NAME, rm),
516        },
517        float_either_zero!() => (T::ZERO, Equal),
518        Float(Finite {
519            sign,
520            exponent,
521            significand,
522            ..
523        }) => {
524            let exponent = i64::from(*exponent);
525            if *sign {
526                if exponent < 0 {
527                    match rm {
528                        Floor | Down | Nearest => (T::ZERO, Less),
529                        Ceiling | Up => (T::ONE, Greater),
530                        Exact => {
531                            panic!("Cannot convert Float to Integer using {rm}")
532                        }
533                    }
534                } else if exponent >= i64::wrapping_from(T::WIDTH) {
535                    match rm {
536                        Floor | Down | Nearest => (T::MAX, Less),
537                        _ => {
538                            panic!("Cannot convert Float to Integer using {rm}")
539                        }
540                    }
541                } else {
542                    let sb = significand_bits(significand);
543                    let eb = exponent.unsigned_abs();
544                    let (n, o) = if sb >= eb {
545                        significand.shr_round(sb - eb, rm)
546                    } else {
547                        (significand << (eb - sb), Equal)
548                    };
549                    if let Ok(n) = T::try_from(&n) {
550                        (n, o)
551                    } else {
552                        match rm {
553                            Floor | Down | Nearest => (T::MAX, Less),
554                            _ => {
555                                panic!("Cannot convert large Float to {} using {}", T::NAME, rm)
556                            }
557                        }
558                    }
559                }
560            } else if exponent < 0 {
561                match rm {
562                    Ceiling | Down | Nearest => (T::ZERO, Greater),
563                    Floor | Up => (T::NEGATIVE_ONE, Less),
564                    Exact => {
565                        panic!("Cannot convert Float to Integer using {rm}")
566                    }
567                }
568            } else if exponent > i64::wrapping_from(T::WIDTH) {
569                // This doesn't catch the case where -2^(W+1) < x < -2^W, but that's ok because the
570                // next else block handles it.
571                match rm {
572                    Ceiling | Down | Nearest => (T::MIN, Greater),
573                    _ => {
574                        panic!("Cannot convert Float to Integer using {rm}")
575                    }
576                }
577            } else {
578                let sb = significand_bits(significand);
579                let eb = exponent.unsigned_abs();
580                let (n, o) = if sb >= eb {
581                    significand.shr_round(sb - eb, -rm)
582                } else {
583                    (significand << (eb - sb), Equal)
584                };
585                if let Ok(n) = T::try_from(&-n) {
586                    (n, o.reverse())
587                } else {
588                    match rm {
589                        Ceiling | Down | Nearest => (T::MIN, Greater),
590                        _ => panic!(
591                            "Cannot convert large negative Float to {} using {}",
592                            T::NAME,
593                            rm
594                        ),
595                    }
596                }
597            }
598        }
599    }
600}
601
602#[allow(clippy::type_repetition_in_bounds)]
603fn signed_try_from_float<T: PrimitiveSigned>(f: Float) -> Result<T, SignedFromFloatError>
604where
605    for<'a> T: TryFrom<&'a Integer>,
606{
607    match f {
608        float_either_zero!() => Ok(T::ZERO),
609        Float(Finite {
610            sign,
611            exponent,
612            significand,
613            ..
614        }) => {
615            let exponent = i64::from(exponent);
616            if exponent <= 0
617                || (sign && exponent >= i64::wrapping_from(T::WIDTH)
618                    || !sign && exponent > i64::wrapping_from(T::WIDTH))
619            {
620                Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)
621            } else {
622                let sb = significand_bits(&significand);
623                let eb = exponent.unsigned_abs();
624                let i = Integer::from_sign_and_abs(
625                    sign,
626                    if sb >= eb {
627                        let bits = sb - eb;
628                        if significand.divisible_by_power_of_2(bits) {
629                            significand >> bits
630                        } else {
631                            return Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange);
632                        }
633                    } else {
634                        significand << (eb - sb)
635                    },
636                );
637                T::try_from(&i).map_err(|_| SignedFromFloatError::FloatNonIntegerOrOutOfRange)
638            }
639        }
640        _ => Err(SignedFromFloatError::FloatInfiniteOrNan),
641    }
642}
643
644#[allow(clippy::type_repetition_in_bounds)]
645fn signed_try_from_float_ref<T: PrimitiveSigned>(f: &Float) -> Result<T, SignedFromFloatError>
646where
647    for<'a> T: TryFrom<&'a Integer>,
648{
649    match f {
650        float_either_zero!() => Ok(T::ZERO),
651        Float(Finite {
652            sign,
653            exponent,
654            significand,
655            ..
656        }) => {
657            let exponent = i64::from(*exponent);
658            if exponent <= 0
659                || (*sign && exponent >= i64::wrapping_from(T::WIDTH)
660                    || !*sign && exponent > i64::wrapping_from(T::WIDTH))
661            {
662                Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange)
663            } else {
664                let sb = significand_bits(significand);
665                let eb = exponent.unsigned_abs();
666                let i = Integer::from_sign_and_abs(
667                    *sign,
668                    if sb >= eb {
669                        let bits = sb - eb;
670                        if significand.divisible_by_power_of_2(bits) {
671                            significand >> bits
672                        } else {
673                            return Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange);
674                        }
675                    } else {
676                        significand << (eb - sb)
677                    },
678                );
679                T::try_from(&i).map_err(|_| SignedFromFloatError::FloatNonIntegerOrOutOfRange)
680            }
681        }
682        _ => Err(SignedFromFloatError::FloatInfiniteOrNan),
683    }
684}
685
686fn signed_convertible_from_float<T: PrimitiveSigned>(f: &Float) -> bool {
687    match f {
688        float_either_zero!() => true,
689        Float(Finite {
690            exponent,
691            significand,
692            ..
693        }) => {
694            let exponent = i64::from(*exponent);
695            if exponent <= 0 {
696                return false;
697            }
698            if exponent >= i64::wrapping_from(T::WIDTH) {
699                float_is_signed_min::<T>(f)
700            } else {
701                let sb = significand_bits(significand);
702                let eb = exponent.unsigned_abs();
703                sb < eb || significand.divisible_by_power_of_2(sb - eb)
704            }
705        }
706        _ => false,
707    }
708}
709
710macro_rules! impl_signed_from {
711    ($t: ident) => {
712        impl RoundingFrom<Float> for $t {
713            /// Converts a [`Float`] to a signed primitive integer, using a specified
714            /// [`RoundingMode`] and taking the [`Float`] by value. An [`Ordering`] is also
715            /// returned, indicating whether the returned value is less than, equal to, or greater
716            /// than the original value.
717            ///
718            /// If the [`Float`] is less than the minimum representable value of the signed type
719            /// (including $-\infty$), then it will be rounded to zero when the [`RoundingMode`] is
720            /// `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic.
721            ///
722            /// If the [`Float`] is greater than the maximum representable value of the signed type
723            /// (including $\infty$), then it will be rounded to the maximum value when the
724            /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will
725            /// panic.
726            ///
727            /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode.
728            ///
729            /// # Worst-case complexity
730            /// $T(n) = O(n)$
731            ///
732            /// $M(n) = O(1)$
733            ///
734            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
735            /// rounding must examine the bits that are discarded.
736            ///
737            /// # Panics
738            /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`]
739            /// is smaller than the minimum representable value of the signed type and `rm` is not
740            /// `Down`, `Ceiling`, or `Nearest`, if the [`Float`] is greater than the maximum
741            /// representable value of the signed type and `rm` is not `Down`, `Floor`, or
742            /// `Nearest`, or if the [`Float`] is NaN.
743            ///
744            /// # Examples
745            /// See [here](super::primitive_int_from_float#rounding_from).
746            #[inline]
747            fn rounding_from(f: Float, rm: RoundingMode) -> ($t, Ordering) {
748                signed_rounding_from_float(f, rm)
749            }
750        }
751
752        impl RoundingFrom<&Float> for $t {
753            /// Converts a [`Float`] to a signed primitive integer, using a specified
754            /// [`RoundingMode`] and taking the [`Float`] by reference. An [`Ordering`] is also
755            /// returned, indicating whether the returned value is less than, equal to, or greater
756            /// than the original value.
757            ///
758            /// If the [`Float`] is less than the minimum representable value of the signed type
759            /// (including $-\infty$), then it will be rounded to zero when the [`RoundingMode`] is
760            /// `Ceiling`, `Down`, or `Nearest`. Otherwise, this function will panic.
761            ///
762            /// If the [`Float`] is greater than the maximum representable value of the signed type
763            /// (including $\infty$), then it will be rounded to the maximum value when the
764            /// [`RoundingMode`] is `Floor`, `Down`, or `Nearest`. Otherwise, this function will
765            /// panic.
766            ///
767            /// If the [`Float`] is NaN, the function will panic regardless of the rounding mode.
768            ///
769            /// # Worst-case complexity
770            /// $T(n) = O(n)$
771            ///
772            /// $M(n) = O(1)$
773            ///
774            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
775            /// rounding must examine the bits that are discarded.
776            ///
777            /// # Panics
778            /// Panics if the [`Float`] is not an integer and `rm` is `Exact`, or if the [`Float`]
779            /// is smaller than the minimum representable value of the signed type and `rm` is not
780            /// `Down`, `Ceiling`, or `Nearest`, if the [`Float`] is greater than the maximum
781            /// representable value of the signed type and `rm` is not `Down`, `Floor`, or
782            /// `Nearest`, or if the [`Float`] is NaN.
783            ///
784            /// # Examples
785            /// See [here](super::primitive_int_from_float#rounding_from).
786            #[inline]
787            fn rounding_from(f: &Float, rm: RoundingMode) -> ($t, Ordering) {
788                signed_rounding_from_float_ref(f, rm)
789            }
790        }
791
792        impl TryFrom<Float> for $t {
793            type Error = SignedFromFloatError;
794
795            /// Converts a [`Float`] to a primitive signed integer, taking the [`Float`] by value.
796            /// If the [`Float`] is not equal to a signed primitive integer of the given type, an
797            /// error is returned.
798            ///
799            /// # Worst-case complexity
800            /// $T(n) = O(n)$
801            ///
802            /// $M(n) = O(1)$
803            ///
804            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
805            /// rounding must examine the bits that are discarded.
806            ///
807            /// # Examples
808            /// See [here](super::primitive_int_from_float#try_from).
809            #[inline]
810            fn try_from(f: Float) -> Result<$t, Self::Error> {
811                signed_try_from_float(f)
812            }
813        }
814
815        impl TryFrom<&Float> for $t {
816            type Error = SignedFromFloatError;
817
818            /// Converts a [`Float`] to a primitive signed integer, taking the [`Float`] by
819            /// reference. If the [`Float`] is not equal to a signed primitive integer of the given
820            /// type, an error is returned.
821            ///
822            /// # Worst-case complexity
823            /// $T(n) = O(n)$
824            ///
825            /// $M(n) = O(1)$
826            ///
827            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
828            /// rounding must examine the bits that are discarded.
829            ///
830            /// # Examples
831            /// See [here](super::primitive_int_from_float#try_from).
832            #[inline]
833            fn try_from(f: &Float) -> Result<$t, Self::Error> {
834                signed_try_from_float_ref(f)
835            }
836        }
837
838        impl ConvertibleFrom<&Float> for $t {
839            /// Determines whether a [`Float`] can be converted to a signed primitive integer,
840            /// taking the [`Float`] by reference.
841            ///
842            /// # Worst-case complexity
843            /// $T(n) = O(n)$
844            ///
845            /// $M(n) = O(1)$
846            ///
847            /// where $T$ is time, $M$ is additional memory, and $n$ is `f.significant_bits()`:
848            /// rounding must examine the bits that are discarded.
849            ///
850            /// # Examples
851            /// See [here](super::primitive_int_from_float#convertible_from).
852            #[inline]
853            fn convertible_from(f: &Float) -> bool {
854                signed_convertible_from_float::<$t>(f)
855            }
856        }
857    };
858}
859apply_to_signeds!(impl_signed_from);