malachite_base/num/conversion/
from.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::num::arithmetic::traits::{ShrRoundAssign, UnsignedAbs};
10use crate::num::basic::floats::PrimitiveFloat;
11use crate::num::basic::integers::PrimitiveInt;
12use crate::num::basic::signeds::PrimitiveSigned;
13use crate::num::basic::unsigneds::PrimitiveUnsigned;
14use crate::num::conversion::mantissa_and_exponent::sci_mantissa_and_exponent_round;
15use crate::num::conversion::traits::{
16    ConvertibleFrom, OverflowingFrom, RoundingFrom, SaturatingFrom, SciMantissaAndExponent,
17    WrappingFrom,
18};
19use crate::num::float::NiceFloat;
20use crate::rounding_modes::RoundingMode::{self, *};
21use core::cmp::Ordering::{self, *};
22use core::ops::Neg;
23
24// This macro defines conversions from a type to itself.
25macro_rules! identity_conversion {
26    ($t:ty) => {
27        impl WrappingFrom<$t> for $t {
28            /// Converts a value to its own type. This conversion is always valid and always leaves
29            /// the value unchanged.
30            ///
31            /// # Worst-case complexity
32            /// Constant time and additional memory.
33            ///
34            /// # Examples
35            /// See [here](super::from#wrapping_from).
36            #[inline]
37            fn wrapping_from(value: $t) -> $t {
38                value
39            }
40        }
41
42        impl SaturatingFrom<$t> for $t {
43            /// Converts a value to its own type. This conversion is always valid and always leaves
44            /// the value unchanged.
45            ///
46            /// # Worst-case complexity
47            /// Constant time and additional memory.
48            ///
49            /// # Examples
50            /// See [here](super::from#saturating_from).
51            #[inline]
52            fn saturating_from(value: $t) -> $t {
53                value
54            }
55        }
56
57        impl OverflowingFrom<$t> for $t {
58            /// Converts a value to its own type. Since this conversion is always valid and always
59            /// leaves the value unchanged, the second component of the result is always false (no
60            /// overflow).
61            ///
62            /// # Worst-case complexity
63            /// Constant time and additional memory.
64            ///
65            /// # Examples
66            /// See [here](super::from#overflowing_from).
67            #[inline]
68            fn overflowing_from(value: $t) -> ($t, bool) {
69                (value, false)
70            }
71        }
72
73        impl ConvertibleFrom<$t> for $t {
74            /// Checks whether a value is convertible to its own type. The result is always `true`.
75            ///
76            /// # Worst-case complexity
77            /// Constant time and additional memory.
78            ///
79            /// # Examples
80            /// See [here](super::from#convertible_from).
81            #[inline]
82            fn convertible_from(_: $t) -> bool {
83                true
84            }
85        }
86    };
87}
88
89// This macro defines conversions from type $a to type $b, where every value of type $a is
90// representable by a value of type $b.
91macro_rules! lossless_conversion {
92    ($a:ty, $b:ident) => {
93        impl WrappingFrom<$a> for $b {
94            /// Converts a value to another type. This conversion is always valid and always leaves
95            /// the value unchanged.
96            ///
97            /// # Worst-case complexity
98            /// Constant time and additional memory.
99            ///
100            /// # Examples
101            /// See [here](super::from#wrapping_from).
102            #[inline]
103            fn wrapping_from(value: $a) -> $b {
104                $b::from(value)
105            }
106        }
107
108        impl SaturatingFrom<$a> for $b {
109            /// Converts a value to another type. This conversion is always valid and always leaves
110            /// the value unchanged.
111            ///
112            /// # Worst-case complexity
113            /// Constant time and additional memory.
114            ///
115            /// # Examples
116            /// See [here](super::from#saturating_from).
117            #[inline]
118            fn saturating_from(value: $a) -> $b {
119                $b::from(value)
120            }
121        }
122
123        impl OverflowingFrom<$a> for $b {
124            /// Converts a value to the value's type. Since this conversion is always valid and
125            /// always leaves the value unchanged, the second component of the result is always
126            /// false (no overflow).
127            ///
128            /// # Worst-case complexity
129            /// Constant time and additional memory.
130            ///
131            /// # Examples
132            /// See [here](super::from#overflowing_from).
133            #[inline]
134            fn overflowing_from(value: $a) -> ($b, bool) {
135                ($b::from(value), false)
136            }
137        }
138
139        impl ConvertibleFrom<$a> for $b {
140            /// Checks whether a value is convertible to a different type. The result is always
141            /// `true`.
142            ///
143            /// # Worst-case complexity
144            /// Constant time and additional memory.
145            ///
146            /// # Examples
147            /// See [here](super::from#convertible_from).
148            #[inline]
149            fn convertible_from(_: $a) -> bool {
150                true
151            }
152        }
153    };
154}
155
156fn saturating_from_lossy<A: TryFrom<B> + PrimitiveInt, B: PrimitiveInt + WrappingFrom<A>>(
157    value: A,
158) -> B {
159    if let Ok(b_max) = A::try_from(B::MAX) {
160        if value >= b_max {
161            return B::MAX;
162        }
163    }
164    if let Ok(b_min) = A::try_from(B::MIN) {
165        if value <= b_min {
166            return B::MIN;
167        }
168    }
169    B::wrapping_from(value)
170}
171
172fn overflowing_from_lossy<A: PrimitiveInt + WrappingFrom<B>, B: PrimitiveInt + WrappingFrom<A>>(
173    value: A,
174) -> (B, bool) {
175    let result = B::wrapping_from(value);
176    (
177        result,
178        (result >= B::ZERO) != (value >= A::ZERO) || A::wrapping_from(result) != value,
179    )
180}
181
182fn convertible_from_lossy<A: PrimitiveInt + WrappingFrom<B>, B: PrimitiveInt + WrappingFrom<A>>(
183    value: A,
184) -> bool {
185    let result = B::wrapping_from(value);
186    (result >= B::ZERO) == (value >= A::ZERO) && A::wrapping_from(result) == value
187}
188
189// This macro defines conversions from type $a to type $b, where not every value of type $a is
190// representable by a value of type $b.
191macro_rules! lossy_conversion {
192    ($a:ident, $b:ident) => {
193        #[allow(clippy::cast_lossless)]
194        impl WrappingFrom<$a> for $b {
195            /// Converts a value to another type. If the value cannot be represented in the new
196            /// type, it is wrapped.
197            ///
198            /// Let $W$ be the width of the target type.
199            ///
200            /// If the target type is unsigned, then $f_W(n) = m$, where $m < 2^W$ and $n + 2^W k =
201            /// m$ for some $k \in \Z$.
202            ///
203            /// If the target type is signed, then $f_W(n) = m$, where $-2^{W-1} \leq m < 2^{W-1}$
204            /// and $n + 2^W k = m$ for some $k \in \Z$.
205            ///
206            /// # Worst-case complexity
207            /// Constant time and additional memory.
208            ///
209            /// # Examples
210            /// See [here](super::from#wrapping_from).
211            #[inline]
212            fn wrapping_from(value: $a) -> $b {
213                value as $b
214            }
215        }
216
217        impl SaturatingFrom<$a> for $b {
218            /// Converts a value to another type. If the value cannot be represented in the new
219            /// type, the maximum or minimum value of the new type, whichever is closer, is
220            /// returned.
221            ///
222            /// Let $W$ be the width of the target type.
223            ///
224            /// If the target type is unsigned, then
225            /// $$
226            /// f_W(n) = \\begin{cases}
227            ///     0 & n < 0 \\\\
228            ///     2^W-1 & \text{if} \\quad n \geq 2^W, \\\\
229            ///     n & \\text{otherwise}.
230            /// \\end{cases}
231            /// $$
232            ///
233            /// If the target type is signed, then
234            /// $$
235            /// f_W(n) = \\begin{cases}
236            ///     -2^{W-1} & \text{if} \\quad n < -2^{W-1}, \\\\
237            ///     2^{W-1}-1 & \text{if} \\quad n \geq 2^{W-1}, \\\\
238            ///     n & \\text{otherwise}.
239            /// \\end{cases}
240            /// $$
241            ///
242            /// # Worst-case complexity
243            /// Constant time and additional memory.
244            ///
245            /// # Examples
246            /// See [here](super::from#saturating_from).
247            #[inline]
248            fn saturating_from(value: $a) -> $b {
249                saturating_from_lossy(value)
250            }
251        }
252
253        impl OverflowingFrom<$a> for $b {
254            /// Converts a value to another type. If the value cannot be represented in the new
255            /// type, it is wrapped. The second component of the result indicates whether overflow
256            /// occurred.
257            ///
258            /// Let $W$ be the width of the target type.
259            ///
260            /// If the target type is unsigned, then $f_W(n) = (m, k \neq 0)$, where $m < 2^W$ and
261            /// $n + 2^W k = m$ for some $k \in \Z$.
262            ///
263            /// If the target type is signed, then $f_W(n) = (m, k \neq 0)$, where $-2^{W-1} \leq m
264            /// < 2^{W-1}$ and $n + 2^W k = m$ for some $k \in \Z$.
265            ///
266            /// # Worst-case complexity
267            /// Constant time and additional memory.
268            ///
269            /// # Examples
270            /// See [here](super::from#overflowing_from).
271            #[inline]
272            fn overflowing_from(value: $a) -> ($b, bool) {
273                overflowing_from_lossy(value)
274            }
275        }
276
277        impl ConvertibleFrom<$a> for $b {
278            /// Determines whether a value is convertible to a different type.
279            ///
280            /// Let $W$ be the width of the target type.
281            ///
282            /// If the target type is unsigned then,
283            /// $$
284            /// f_W(n) = (0 \leq n < 2^W).
285            /// $$
286            ///
287            /// If the target type is signed then,
288            /// $$
289            /// f_W(n) = (-2^{W-1} \leq n < 2^{W-1}-1).
290            /// $$
291            ///
292            /// # Worst-case complexity
293            /// Constant time and additional memory.
294            ///
295            /// # Examples
296            /// See [here](super::from#convertible_from).
297            #[inline]
298            fn convertible_from(value: $a) -> bool {
299                convertible_from_lossy::<$a, $b>(value)
300            }
301        }
302    };
303}
304
305// This macro defines conversions from type $a to type $b, where the set of values representable by
306// type $a is a proper subset of the set of values representable by type $b.
307macro_rules! proper_subset_conversion {
308    ($a:ident, $b:ident) => {
309        lossless_conversion!($a, $b);
310        lossy_conversion!($b, $a);
311    };
312}
313
314// This macro defines conversions from type $a to type $b, where the set of values representable by
315// type $a is neither a subset nor a superset of the set of values representable by type $b.
316macro_rules! no_containment_conversion {
317    ($a:ident, $b:ident) => {
318        lossy_conversion!($a, $b);
319        lossy_conversion!($b, $a);
320    };
321}
322
323apply_to_primitive_ints!(identity_conversion);
324
325proper_subset_conversion!(u8, u16);
326proper_subset_conversion!(u8, u32);
327proper_subset_conversion!(u8, u64);
328proper_subset_conversion!(u8, u128);
329proper_subset_conversion!(u8, usize);
330proper_subset_conversion!(u8, i16);
331proper_subset_conversion!(u8, i32);
332proper_subset_conversion!(u8, i64);
333proper_subset_conversion!(u8, i128);
334proper_subset_conversion!(u8, isize);
335proper_subset_conversion!(u16, u32);
336proper_subset_conversion!(u16, u64);
337proper_subset_conversion!(u16, u128);
338proper_subset_conversion!(u16, usize);
339proper_subset_conversion!(u16, i32);
340proper_subset_conversion!(u16, i64);
341proper_subset_conversion!(u16, i128);
342proper_subset_conversion!(u32, u64);
343proper_subset_conversion!(u32, u128);
344proper_subset_conversion!(u32, i64);
345proper_subset_conversion!(u32, i128);
346proper_subset_conversion!(u64, u128);
347proper_subset_conversion!(u64, i128);
348proper_subset_conversion!(i8, i16);
349proper_subset_conversion!(i8, i32);
350proper_subset_conversion!(i8, i64);
351proper_subset_conversion!(i8, i128);
352proper_subset_conversion!(i8, isize);
353proper_subset_conversion!(i16, i32);
354proper_subset_conversion!(i16, i64);
355proper_subset_conversion!(i16, i128);
356proper_subset_conversion!(i16, isize);
357proper_subset_conversion!(i32, i64);
358proper_subset_conversion!(i32, i128);
359proper_subset_conversion!(i64, i128);
360
361no_containment_conversion!(u8, i8);
362no_containment_conversion!(u16, i8);
363no_containment_conversion!(u16, i16);
364no_containment_conversion!(u16, isize);
365no_containment_conversion!(u32, usize);
366no_containment_conversion!(u32, i8);
367no_containment_conversion!(u32, i16);
368no_containment_conversion!(u32, i32);
369no_containment_conversion!(u32, isize);
370no_containment_conversion!(u64, usize);
371no_containment_conversion!(u64, i8);
372no_containment_conversion!(u64, i16);
373no_containment_conversion!(u64, i32);
374no_containment_conversion!(u64, i64);
375no_containment_conversion!(u64, isize);
376no_containment_conversion!(u128, usize);
377no_containment_conversion!(u128, i8);
378no_containment_conversion!(u128, i16);
379no_containment_conversion!(u128, i32);
380no_containment_conversion!(u128, i64);
381no_containment_conversion!(u128, i128);
382no_containment_conversion!(u128, isize);
383no_containment_conversion!(usize, i8);
384no_containment_conversion!(usize, i16);
385no_containment_conversion!(usize, i32);
386no_containment_conversion!(usize, i64);
387no_containment_conversion!(usize, i128);
388no_containment_conversion!(usize, isize);
389no_containment_conversion!(i32, isize);
390no_containment_conversion!(i64, isize);
391no_containment_conversion!(i128, isize);
392
393fn primitive_float_rounding_from_unsigned<T: PrimitiveFloat, U: PrimitiveUnsigned>(
394    value: U,
395    rm: RoundingMode,
396) -> (T, Ordering) {
397    if value == U::ZERO {
398        return (T::ZERO, Equal);
399    }
400    let (mantissa, exponent, o) = sci_mantissa_and_exponent_round(value, rm).unwrap();
401    if let Some(f) = T::from_sci_mantissa_and_exponent(mantissa, i64::wrapping_from(exponent)) {
402        (f, o)
403    } else {
404        match rm {
405            Exact => {
406                panic!("Value cannot be represented exactly as an {}", T::NAME)
407            }
408            Floor | Down | Nearest => (T::MAX_FINITE, Less),
409            _ => (T::INFINITY, Greater),
410        }
411    }
412}
413
414fn unsigned_rounding_from_primitive_float<T: PrimitiveUnsigned, U: PrimitiveFloat>(
415    value: U,
416    rm: RoundingMode,
417) -> (T, Ordering) {
418    assert!(!value.is_nan());
419    if value.is_infinite() {
420        return if value.is_sign_positive() {
421            match rm {
422                Exact => {
423                    panic!("Value cannot be represented exactly as a {}", T::NAME)
424                }
425                Down | Floor | Nearest => (T::MAX, Less),
426                _ => panic!("Cannot round away from positive infinity"),
427            }
428        } else {
429            match rm {
430                Exact => {
431                    panic!("Value cannot be represented exactly as a {}", T::NAME)
432                }
433                Down | Ceiling | Nearest => (T::ZERO, Greater),
434                _ => panic!("Cannot round away from negative infinity"),
435            }
436        };
437    }
438    if value == U::ZERO {
439        return (T::ZERO, Equal);
440    }
441    if value.is_sign_negative() {
442        return match rm {
443            Exact => {
444                panic!("Value cannot be represented exactly as a {}", T::NAME)
445            }
446            Ceiling | Down | Nearest => (T::ZERO, Greater),
447            _ => panic!("Value is less than 0 and rounding mode is {rm}"),
448        };
449    }
450    let (mut mantissa, exponent) = value.integer_mantissa_and_exponent();
451    let (result, o) = if exponent <= 0 {
452        let o = mantissa.shr_round_assign(-exponent, rm);
453        (T::try_from(mantissa).ok(), o)
454    } else {
455        (
456            T::try_from(mantissa)
457                .ok()
458                .and_then(|n| n.arithmetic_checked_shl(exponent)),
459            Equal,
460        )
461    };
462    if let Some(n) = result {
463        (n, o)
464    } else {
465        match rm {
466            Exact => {
467                panic!("Value cannot be represented exactly as a {}", T::NAME)
468            }
469            Floor | Down | Nearest => (T::MAX, Less),
470            _ => panic!(
471                "Value is greater than {}::MAX and rounding mode is {}",
472                T::NAME,
473                rm
474            ),
475        }
476    }
477}
478
479#[derive(Clone, Copy, Debug, Eq, PartialEq)]
480pub struct PrimitiveFloatFromUnsignedError;
481
482fn primitive_float_try_from_unsigned<T: PrimitiveFloat, U: PrimitiveUnsigned>(
483    value: U,
484) -> Result<T, PrimitiveFloatFromUnsignedError> {
485    if value == U::ZERO {
486        return Ok(T::ZERO);
487    }
488    let (mantissa, exponent, _) =
489        sci_mantissa_and_exponent_round(value, Exact).ok_or(PrimitiveFloatFromUnsignedError)?;
490    T::from_sci_mantissa_and_exponent(mantissa, i64::wrapping_from(exponent))
491        .ok_or(PrimitiveFloatFromUnsignedError)
492}
493
494#[derive(Clone, Copy, Debug, Eq, PartialEq)]
495pub enum UnsignedFromFloatError {
496    FloatInfiniteOrNan,
497    FloatNegative,
498    FloatNonIntegerOrOutOfRange,
499}
500
501fn unsigned_try_from_primitive_float<T: PrimitiveUnsigned, U: PrimitiveFloat>(
502    value: U,
503) -> Result<T, UnsignedFromFloatError> {
504    if !value.is_finite() {
505        Err(UnsignedFromFloatError::FloatInfiniteOrNan)
506    } else if value == U::ZERO {
507        Ok(T::ZERO)
508    } else if value < U::ZERO {
509        Err(UnsignedFromFloatError::FloatNegative)
510    } else {
511        let (mantissa, exponent) = value.integer_mantissa_and_exponent();
512        if exponent < 0 {
513            Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
514        } else {
515            T::try_from(mantissa)
516                .or(Err(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange))
517                .and_then(|n| {
518                    n.arithmetic_checked_shl(exponent)
519                        .ok_or(UnsignedFromFloatError::FloatNonIntegerOrOutOfRange)
520                })
521        }
522    }
523}
524
525fn primitive_float_convertible_from_unsigned<
526    T: PrimitiveFloat,
527    U: PrimitiveUnsigned + SciMantissaAndExponent<T, u64>,
528>(
529    value: U,
530) -> bool {
531    if value == U::ZERO {
532        return true;
533    }
534    let precision = (value >> value.trailing_zeros()).significant_bits();
535    precision <= T::MANTISSA_WIDTH + 1
536        && i64::wrapping_from(SciMantissaAndExponent::<T, u64>::sci_exponent(value))
537            <= T::MAX_EXPONENT
538}
539
540#[inline]
541fn unsigned_convertible_from_primitive_float<T: PrimitiveUnsigned, U: PrimitiveFloat>(
542    value: U,
543) -> bool {
544    value >= U::ZERO
545        && value.is_integer()
546        && (value == U::ZERO || value.sci_exponent() < i64::wrapping_from(T::WIDTH))
547}
548
549macro_rules! impl_from_float_unsigned {
550    ($u:ident) => {
551        macro_rules! impl_from_float_unsigned_inner {
552            ($f:ident) => {
553                impl RoundingFrom<$u> for $f {
554                    /// Converts a value of an unsigned type to a value of a floating point type
555                    /// according to a specified [`RoundingMode`]. An [`Ordering`] is also returned,
556                    /// indicating whether the returned value is less than, equal to, or greater
557                    /// than the original value.
558                    ///
559                    /// - If the rounding mode is `Floor` or `Down`, the largest float less than or
560                    ///   equal to the value is returned.
561                    /// - If the rounding mode is `Ceiling` or `Up`, the smallest float greater than
562                    ///   or equal to the value is returned.
563                    /// - If the rounding mode is `Nearest`, then the nearest float is returned. If
564                    ///   the value is exactly between two floats, the float with the zero
565                    ///   least-significant bit in its representation is selected. If the value is
566                    ///   larger than the maximum finite float (which can only happen when
567                    ///   converting a `u128` to an `f32`), the maximum finite float is returned.
568                    ///
569                    /// # Worst-case complexity
570                    /// Constant time and additional memory.
571                    ///
572                    /// # Panics
573                    /// Panics if `rm` is `Exact` but `value` is not exactly equal to any value of
574                    /// the primitive float type.
575                    ///
576                    /// # Examples
577                    /// See [here](super::from#rounding_from).
578                    #[inline]
579                    fn rounding_from(value: $u, rm: RoundingMode) -> ($f, Ordering) {
580                        primitive_float_rounding_from_unsigned(value, rm)
581                    }
582                }
583
584                impl RoundingFrom<$f> for $u {
585                    /// Converts a value of a floating point type to a value of an unsigned type
586                    /// according to a specified [`RoundingMode`]. An [`Ordering`] is also returned,
587                    /// indicating whether the returned value is less than, equal to, or greater
588                    /// than the original value.
589                    ///
590                    /// - If the rounding mode is `Floor`, the largest number less than or equal to
591                    ///   the value is returned. If the float is greater than the maximum
592                    ///   representable unsigned value, the maximum unsigned value is returned. If
593                    ///   the float is negative, the function panics.
594                    /// - If the rounding mode is `Ceiling`, the smallest number greater than or
595                    ///   equal to the value is returned. If the float is negative, zero is
596                    ///   returned. If the float is greater than the maximum representable unsigned
597                    ///   value, the function panics.
598                    /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor`
599                    ///   if the float is non-negative and as with `Ceiling` if the value is
600                    ///   negative.
601                    /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling`
602                    ///   if the value is non-negative and as with `Floor` if the value is negative.
603                    /// - If the rounding mode is `Nearest`, then the nearest value is returned. If
604                    ///   the value is exactly between two numbers, the even one is selected. If the
605                    ///   float is greater than the maximum representable unsigned value, the
606                    ///   maximum unsigned value is returned. If the float is negative, zero is
607                    ///   returned.
608                    ///
609                    /// # Worst-case complexity
610                    /// Constant time and additional memory.
611                    ///
612                    /// # Panics
613                    /// - If `value` is `NaN`.
614                    /// - If `rm` is `Exact` but `value` is not exactly equal to any value of the
615                    ///   unsigned type.
616                    /// - If `value` is greater than the maximum value of the unsigned type and `rm`
617                    ///   is `Ceiling` or `Up`.
618                    /// - If `value` is negative and `rm` is `Floor` or `Up`.
619                    ///
620                    /// # Examples
621                    /// See [here](super::from#rounding_from).
622                    #[inline]
623                    fn rounding_from(value: $f, rm: RoundingMode) -> ($u, Ordering) {
624                        unsigned_rounding_from_primitive_float(value, rm)
625                    }
626                }
627
628                impl TryFrom<$u> for NiceFloat<$f> {
629                    type Error = PrimitiveFloatFromUnsignedError;
630
631                    /// Converts a value of an unsigned type to a value of a floating point type,
632                    /// returning an error if an exact conversion is not possible.
633                    ///
634                    /// The conversion succeeds if the unsigned value is not too large to represent
635                    /// (which can only happen when converting a [`u128`] to an [`f32`]) and the
636                    /// precision of the unsigned value is not too high.
637                    ///
638                    /// # Worst-case complexity
639                    /// Constant time and additional memory.
640                    ///
641                    /// # Examples
642                    /// See [here](super::from#try_from).
643                    #[inline]
644                    fn try_from(value: $u) -> Result<NiceFloat<$f>, Self::Error> {
645                        primitive_float_try_from_unsigned(value).map(NiceFloat)
646                    }
647                }
648
649                impl TryFrom<NiceFloat<$f>> for $u {
650                    type Error = UnsignedFromFloatError;
651
652                    /// Converts a value of a floating point type to a value of an unsigned type,
653                    /// returning an error if an exact conversion is not possible.
654                    ///
655                    /// The conversion succeeds if the floating point value is an integer, not
656                    /// negative (negative zero is ok), and not too large.
657                    ///
658                    /// # Worst-case complexity
659                    /// Constant time and additional memory.
660                    ///
661                    /// # Examples
662                    /// See [here](super::from#try_from).
663                    #[inline]
664                    fn try_from(value: NiceFloat<$f>) -> Result<$u, Self::Error> {
665                        unsigned_try_from_primitive_float(value.0)
666                    }
667                }
668
669                impl ConvertibleFrom<$u> for $f {
670                    /// Checks whether a value of an unsigned type is convertible to a floating
671                    /// point type.
672                    ///
673                    /// An exact conversion is possible if the unsigned value is not too large to
674                    /// represent (which can only happen when converting a [`u128`] to an [`f32`])
675                    /// and the precision of the unsigned value is not too high.
676                    ///
677                    /// # Worst-case complexity
678                    /// Constant time and additional memory.
679                    ///
680                    /// # Examples
681                    /// See [here](super::from#convertible_from).
682                    #[inline]
683                    fn convertible_from(value: $u) -> bool {
684                        primitive_float_convertible_from_unsigned::<$f, $u>(value)
685                    }
686                }
687
688                impl ConvertibleFrom<$f> for $u {
689                    /// Checks whether a value of a floating point type is convertible to an
690                    /// unsigned type.
691                    ///
692                    /// An exact conversion is possible if the floating point value is an integer,
693                    /// not negative (negative zero is ok), and not too large.
694                    ///
695                    /// # Worst-case complexity
696                    /// Constant time and additional memory.
697                    ///
698                    /// # Examples
699                    /// See [here](super::from#convertible_from).
700                    #[inline]
701                    fn convertible_from(value: $f) -> bool {
702                        unsigned_convertible_from_primitive_float::<$u, $f>(value)
703                    }
704                }
705            };
706        }
707        apply_to_primitive_floats!(impl_from_float_unsigned_inner);
708    };
709}
710apply_to_unsigneds!(impl_from_float_unsigned);
711
712#[inline]
713fn primitive_float_rounding_from_signed<
714    U: PrimitiveUnsigned,
715    S: PrimitiveSigned + UnsignedAbs<Output = U>,
716    F: PrimitiveFloat + RoundingFrom<U>,
717>(
718    value: S,
719    rm: RoundingMode,
720) -> (F, Ordering) {
721    let abs = value.unsigned_abs();
722    if value >= S::ZERO {
723        F::rounding_from(abs, rm)
724    } else {
725        let (x, o) = F::rounding_from(abs, -rm);
726        (-x, o.reverse())
727    }
728}
729
730fn signed_rounding_from_primitive_float<
731    U: PrimitiveUnsigned + RoundingFrom<F>,
732    S: TryFrom<U> + PrimitiveSigned + UnsignedAbs<Output = U>,
733    F: PrimitiveFloat,
734>(
735    value: F,
736    rm: RoundingMode,
737) -> (S, Ordering) {
738    if value.is_infinite() {
739        return if value.is_sign_positive() {
740            match rm {
741                Exact => {
742                    panic!("Value cannot be represented exactly as a {}", S::NAME)
743                }
744                Down | Floor | Nearest => (S::MAX, Less),
745                _ => panic!("Cannot round away from extreme value"),
746            }
747        } else {
748            match rm {
749                Exact => {
750                    panic!("Value cannot be represented exactly as a {}", S::NAME)
751                }
752                Down | Nearest | Ceiling => (S::MIN, Greater),
753                _ => panic!("Cannot round away from extreme value"),
754            }
755        };
756    }
757    if value == F::ZERO {
758        return (S::ZERO, Equal);
759    }
760    if value.is_sign_positive() {
761        let (abs, o) = U::rounding_from(value, rm);
762        if let Ok(n) = S::try_from(abs) {
763            (n, o)
764        } else {
765            match rm {
766                Exact => {
767                    panic!("Value cannot be represented exactly as an {}", S::NAME)
768                }
769                Floor | Down | Nearest => (S::MAX, Less),
770                _ => panic!(
771                    "Value is greater than {}::MAX and rounding mode is {}",
772                    S::NAME,
773                    rm
774                ),
775            }
776        }
777    } else {
778        let (abs, o) = U::rounding_from(-value, -rm);
779        let n = if abs == S::MIN.unsigned_abs() {
780            Some(S::MIN)
781        } else {
782            S::try_from(abs).ok().map(Neg::neg)
783        };
784        if let Some(n) = n {
785            (n, o.reverse())
786        } else {
787            match rm {
788                Exact => {
789                    panic!("Value cannot be represented exactly as an {}", S::NAME)
790                }
791                Ceiling | Down | Nearest => (S::MIN, Greater),
792                _ => panic!(
793                    "Value is smaller than {}::MIN and rounding mode is {}",
794                    S::NAME,
795                    rm
796                ),
797            }
798        }
799    }
800}
801
802#[derive(Clone, Copy, Debug, Eq, PartialEq)]
803pub struct PrimitiveFloatFromSignedError;
804
805#[inline]
806fn primitive_float_try_from_signed<
807    U: PrimitiveUnsigned,
808    S: PrimitiveSigned + UnsignedAbs<Output = U>,
809    F: PrimitiveFloat,
810>(
811    value: S,
812) -> Result<F, PrimitiveFloatFromSignedError>
813where
814    NiceFloat<F>: TryFrom<U>,
815{
816    let abs = value.unsigned_abs();
817    if value >= S::ZERO {
818        NiceFloat::<F>::try_from(abs)
819            .map(|f| f.0)
820            .map_err(|_| PrimitiveFloatFromSignedError)
821    } else {
822        NiceFloat::<F>::try_from(abs)
823            .map(|f| -f.0)
824            .map_err(|_| PrimitiveFloatFromSignedError)
825    }
826}
827
828#[derive(Clone, Copy, Debug, Eq, PartialEq)]
829pub enum SignedFromFloatError {
830    FloatInfiniteOrNan,
831    FloatNonIntegerOrOutOfRange,
832}
833
834fn signed_try_from_primitive_float<
835    U: TryFrom<NiceFloat<F>> + PrimitiveUnsigned,
836    S: TryFrom<U> + PrimitiveSigned + UnsignedAbs<Output = U>,
837    F: PrimitiveFloat,
838>(
839    value: F,
840) -> Result<S, SignedFromFloatError> {
841    if !value.is_finite() {
842        return Err(SignedFromFloatError::FloatInfiniteOrNan);
843    }
844    if value >= F::ZERO {
845        S::try_from(
846            U::try_from(NiceFloat(value))
847                .or(Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange))?,
848        )
849        .or(Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange))
850    } else {
851        let abs = U::try_from(NiceFloat(-value))
852            .or(Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange))?;
853        if abs == S::MIN.unsigned_abs() {
854            Ok(S::MIN)
855        } else {
856            S::try_from(abs)
857                .map(Neg::neg)
858                .or(Err(SignedFromFloatError::FloatNonIntegerOrOutOfRange))
859        }
860    }
861}
862
863#[inline]
864fn primitive_float_convertible_from_signed<
865    U: PrimitiveUnsigned,
866    S: PrimitiveSigned + UnsignedAbs<Output = U>,
867    F: ConvertibleFrom<U> + PrimitiveFloat,
868>(
869    value: S,
870) -> bool {
871    F::convertible_from(value.unsigned_abs())
872}
873
874fn signed_convertible_from_primitive_float<U: PrimitiveUnsigned, F: PrimitiveFloat>(
875    value: F,
876) -> bool {
877    if !value.is_integer() {
878        return false;
879    }
880    if value >= F::ZERO {
881        value == F::ZERO || value.sci_exponent() < i64::wrapping_from(U::WIDTH) - 1
882    } else {
883        let exponent = value.sci_exponent();
884        let limit = i64::wrapping_from(U::WIDTH) - 1;
885        value == F::ZERO
886            || exponent < limit
887            || exponent == limit
888                && value == -F::from_sci_mantissa_and_exponent(F::ONE, exponent).unwrap()
889    }
890}
891
892macro_rules! impl_from_float_signed {
893    ($u:ident, $i:ident) => {
894        macro_rules! impl_from_float_signed_inner {
895            ($f:ident) => {
896                impl RoundingFrom<$i> for $f {
897                    /// Converts a value of a signed type to a value of a floating point type
898                    /// according to a specified [`RoundingMode`]. An [`Ordering`] is also returned,
899                    /// indicating whether the returned value is less than, equal to, or greater
900                    /// than the original value.
901                    ///
902                    /// - If the rounding mode is `Floor`, the largest float less than or equal to
903                    ///   the value is returned.
904                    /// - If the rounding mode is `Ceiling`, the smallest float greater than or
905                    ///   equal to the value is returned.
906                    /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor`
907                    ///   if the value is non-negative and as with `Ceiling` if the value is
908                    ///   negative.
909                    /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling`
910                    ///   if the value is non-negative and as with `Floor` if the value is negative.
911                    /// - If the rounding mode is `Nearest`, then the nearest float is returned. If
912                    ///   the value is exactly between two floats, the float with the zero
913                    ///   least-significant bit in its representation is selected.
914                    ///
915                    /// # Worst-case complexity
916                    /// Constant time and additional memory.
917                    ///
918                    /// # Panics
919                    /// Panics if `rm` is `Exact` but `value` is not exactly equal to any value of
920                    /// the primitive float type.
921                    ///
922                    /// # Examples
923                    /// See [here](super::from#rounding_from).
924                    #[inline]
925                    fn rounding_from(value: $i, rm: RoundingMode) -> ($f, Ordering) {
926                        primitive_float_rounding_from_signed::<$u, $i, $f>(value, rm)
927                    }
928                }
929
930                impl RoundingFrom<$f> for $i {
931                    /// Converts a value of a floating point type to a value of a signed type
932                    /// according to a specified [`RoundingMode`]. An [`Ordering`] is also returned,
933                    /// indicating whether the returned value is less than, equal to, or greater
934                    /// than the original value.
935                    ///
936                    /// - If the rounding mode is `Floor`, the largest number less than or equal to
937                    ///   the value is returned. If the float is greater than the maximum
938                    ///   representable signed value, the maximum signed value is returned. If the
939                    ///   float is smaller than the minimum representable signed value, the function
940                    ///   panics.
941                    /// - If the rounding mode is `Ceiling`, the smallest number greater than or
942                    ///   equal to the value is returned. If the float is smaller than the minimum
943                    ///   representable signed value, the minimum signed value is returned. If the
944                    ///   float is greater than the maximum representable signed value, the function
945                    ///   panics.
946                    /// - If the rounding mode is `Down`, then the rounding proceeds as with `Floor`
947                    ///   if the float is non-negative and as with `Ceiling` if the value is
948                    ///   negative.
949                    /// - If the rounding mode is `Up`, then the rounding proceeds as with `Ceiling`
950                    ///   if the value is non-negative and as with `Floor` if the value is negative.
951                    /// - If the rounding mode is `Nearest`, then the nearest value is returned. If
952                    ///   the value is exactly between two numbers, the even one is selected. If the
953                    ///   float is greater than the maximum representable signed value, the maximum
954                    ///   signed value is returned. If the float is smaller than the minimum
955                    ///   representable signed value, the minimum signed value is returned.
956                    ///
957                    /// # Worst-case complexity
958                    /// Constant time and additional memory.
959                    ///
960                    /// # Panics
961                    /// - If `value` is `NaN`.
962                    /// - If `rm` is `Exact` but `value` is not exactly equal to any value of the
963                    ///   unsigned type.
964                    /// - If `value` is greater than the maximum value of the signed type and `rm`
965                    ///   is `Ceiling` or `Up`.
966                    /// - If `value` is smaller than the minimum value of the signed type and `rm`
967                    ///   is `Floor` or `Up`.
968                    ///
969                    /// # Examples
970                    /// See [here](super::from#rounding_from).
971                    #[inline]
972                    fn rounding_from(value: $f, rm: RoundingMode) -> ($i, Ordering) {
973                        signed_rounding_from_primitive_float::<$u, $i, $f>(value, rm)
974                    }
975                }
976
977                impl TryFrom<$i> for NiceFloat<$f> {
978                    type Error = PrimitiveFloatFromSignedError;
979
980                    /// Converts a value of a signed type to a value of a floating point type,
981                    /// returning an error if an exact conversion is not possible.
982                    ///
983                    /// The conversion succeeds if the precision of the signed value is not too
984                    /// high.
985                    ///
986                    /// # Worst-case complexity
987                    /// Constant time and additional memory.
988                    ///
989                    /// # Examples
990                    /// See [here](super::from#try_from).
991                    #[inline]
992                    fn try_from(value: $i) -> Result<NiceFloat<$f>, Self::Error> {
993                        primitive_float_try_from_signed(value).map(NiceFloat)
994                    }
995                }
996
997                impl TryFrom<NiceFloat<$f>> for $i {
998                    type Error = SignedFromFloatError;
999
1000                    /// Converts a value of a floating point type to a value of a signed type,
1001                    /// returning an error if an exact conversion is not possible.
1002                    ///
1003                    /// The conversion succeeds if the floating point value is an integer and not
1004                    /// too large or too small.
1005                    ///
1006                    /// # Worst-case complexity
1007                    /// Constant time and additional memory.
1008                    ///
1009                    /// # Examples
1010                    /// See [here](super::from#try_from).
1011                    #[inline]
1012                    fn try_from(value: NiceFloat<$f>) -> Result<$i, Self::Error> {
1013                        signed_try_from_primitive_float::<$u, $i, $f>(value.0)
1014                    }
1015                }
1016
1017                impl ConvertibleFrom<$i> for $f {
1018                    /// Checks whether a value of a signed type is convertible to a floating point
1019                    /// type.
1020                    ///
1021                    /// An exact conversion is possible if the precision of the signed value is not
1022                    /// too high.
1023                    ///
1024                    /// # Worst-case complexity
1025                    /// Constant time and additional memory.
1026                    ///
1027                    /// # Examples
1028                    /// See [here](super::from#convertible_from).
1029                    #[inline]
1030                    fn convertible_from(value: $i) -> bool {
1031                        primitive_float_convertible_from_signed::<$u, $i, $f>(value)
1032                    }
1033                }
1034
1035                impl ConvertibleFrom<$f> for $i {
1036                    /// Checks whether a value of a floating point type is convertible to a signed
1037                    /// type.
1038                    ///
1039                    /// An exact conversion is possible if the floating point value is an integer
1040                    /// and not too large or too small.
1041                    ///
1042                    /// # Worst-case complexity
1043                    /// Constant time and additional memory.
1044                    ///
1045                    /// # Examples
1046                    /// See [here](super::from#convertible_from).
1047                    #[inline]
1048                    fn convertible_from(value: $f) -> bool {
1049                        signed_convertible_from_primitive_float::<$u, $f>(value)
1050                    }
1051                }
1052            };
1053        }
1054        apply_to_primitive_floats!(impl_from_float_signed_inner);
1055    };
1056}
1057apply_to_unsigned_signed_pairs!(impl_from_float_signed);