az/
int.rs

1// Copyright © 2019–2026 Trevor Spiteri
2
3// This library is free software: you can redistribute it and/or
4// modify it under the terms of either
5//
6//   * the Apache License, Version 2.0 or
7//   * the MIT License
8//
9// at your option.
10//
11// You should have recieved copies of the Apache License and the MIT
12// License along with the library. If not, see
13// <https://www.apache.org/licenses/LICENSE-2.0> and
14// <https://opensource.org/licenses/MIT>.
15
16use crate::{
17    Cast, CheckedCast, OverflowingCast, Round, SaturatingCast, StrictCast, UnwrappedCast,
18    WrappingCast, cast, checked_cast, overflowing_cast, saturating_cast, wrapping_cast,
19};
20use core::{mem, num::Wrapping};
21
22macro_rules! bool_to_int {
23    ($Dst:ty) => {
24        impl Cast<$Dst> for bool {
25            #[inline]
26            fn cast(self) -> $Dst {
27                self as $Dst
28            }
29        }
30
31        impl CheckedCast<$Dst> for bool {
32            #[inline]
33            fn checked_cast(self) -> Option<$Dst> {
34                Some(self as $Dst)
35            }
36        }
37
38        impl StrictCast<$Dst> for bool {
39            #[inline]
40            fn strict_cast(self) -> $Dst {
41                self as $Dst
42            }
43        }
44
45        impl SaturatingCast<$Dst> for bool {
46            #[inline]
47            fn saturating_cast(self) -> $Dst {
48                self as $Dst
49            }
50        }
51
52        impl WrappingCast<$Dst> for bool {
53            #[inline]
54            fn wrapping_cast(self) -> $Dst {
55                self as $Dst
56            }
57        }
58
59        impl OverflowingCast<$Dst> for bool {
60            #[inline]
61            fn overflowing_cast(self) -> ($Dst, bool) {
62                (self as $Dst, false)
63            }
64        }
65
66        impl UnwrappedCast<$Dst> for bool {
67            #[inline]
68            fn unwrapped_cast(self) -> $Dst {
69                StrictCast::<$Dst>::strict_cast(self)
70            }
71        }
72    };
73}
74
75macro_rules! common {
76    ($Src:ty => $Dst:ty) => {
77        impl Cast<$Dst> for $Src {
78            #[inline]
79            #[track_caller]
80            fn cast(self) -> $Dst {
81                let (wrapped, overflow) = overflowing_cast(self);
82                debug_assert!(!overflow, "{} overflows", self);
83                let _ = overflow;
84                wrapped
85            }
86        }
87
88        impl CheckedCast<$Dst> for $Src {
89            #[inline]
90            fn checked_cast(self) -> Option<$Dst> {
91                match overflowing_cast(self) {
92                    (value, false) => Some(value),
93                    (_, true) => None,
94                }
95            }
96        }
97
98        impl StrictCast<$Dst> for $Src {
99            #[inline]
100            fn strict_cast(self) -> $Dst {
101                match overflowing_cast(self) {
102                    (value, false) => value,
103                    (_, true) => panic!("overflow"),
104                }
105            }
106        }
107
108        impl SaturatingCast<$Dst> for $Src {
109            #[inline]
110            fn saturating_cast(self) -> $Dst {
111                match overflowing_cast(self) {
112                    (value, false) => value,
113                    (_, true) => {
114                        if self > 0 {
115                            <$Dst>::MAX
116                        } else {
117                            <$Dst>::MIN
118                        }
119                    }
120                }
121            }
122        }
123
124        impl WrappingCast<$Dst> for $Src {
125            #[inline]
126            fn wrapping_cast(self) -> $Dst {
127                overflowing_cast(self).0
128            }
129        }
130
131        impl UnwrappedCast<$Dst> for $Src {
132            #[inline]
133            fn unwrapped_cast(self) -> $Dst {
134                StrictCast::<$Dst>::strict_cast(self)
135            }
136        }
137    };
138}
139
140macro_rules! same_signedness {
141    ($($Src:ty),* => $Dst:ty) => { $(
142        common! { $Src => $Dst }
143
144        impl OverflowingCast<$Dst> for $Src {
145            #[inline]
146            fn overflowing_cast(self) -> ($Dst, bool) {
147                let wrapped = self as $Dst;
148                let overflow = self != wrapped as $Src;
149                (wrapped, overflow)
150            }
151        }
152    )* };
153}
154
155macro_rules! signed_to_unsigned {
156    ($($Src:ty),* => $Dst:ty) => { $(
157        common! { $Src => $Dst }
158
159        impl OverflowingCast<$Dst> for $Src {
160            #[inline]
161            fn overflowing_cast(self) -> ($Dst, bool) {
162                let wrapped = self as $Dst;
163                let overflow = self < 0 || self != wrapped as $Src;
164                (wrapped, overflow)
165            }
166        }
167    )* };
168}
169
170macro_rules! unsigned_to_signed {
171    ($($Src:ty),* => $Dst:ty) => { $(
172        common! { $Src => $Dst }
173
174        impl OverflowingCast<$Dst> for $Src {
175            #[inline]
176            fn overflowing_cast(self) -> ($Dst, bool) {
177                let wrapped = self as $Dst;
178                let overflow = wrapped < 0 || self != wrapped as $Src;
179                (wrapped, overflow)
180            }
181        }
182    )* };
183}
184
185macro_rules! wrapping_int {
186    ($($Src:ty),* => $Dst:ty) => { $(
187        impl Cast<Wrapping<$Dst>> for $Src {
188            #[inline]
189            fn cast(self) -> Wrapping<$Dst> {
190                Wrapping(wrapping_cast(self))
191            }
192        }
193
194        impl CheckedCast<Wrapping<$Dst>> for $Src {
195            #[inline]
196            fn checked_cast(self) -> Option<Wrapping<$Dst>> {
197                Some(cast(self))
198            }
199        }
200
201        impl StrictCast<Wrapping<$Dst>> for $Src {
202            #[inline]
203            fn strict_cast(self) -> Wrapping<$Dst> {
204                cast(self)
205            }
206        }
207
208        impl UnwrappedCast<Wrapping<$Dst>> for $Src {
209            #[inline]
210            fn unwrapped_cast(self) -> Wrapping<$Dst> {
211                StrictCast::<Wrapping<$Dst>>::strict_cast(self)
212            }
213        }
214    )* };
215}
216
217macro_rules! float_to_int_sat {
218    ($Src:ty, $ViaU:ty, $ViaI:ty, AsSaturates = True => $Dst:ty) => {
219        impl SaturatingCast<$Dst> for $Src {
220            #[track_caller]
221            fn saturating_cast(self) -> $Dst {
222                if self.is_nan() {
223                    panic!("NaN");
224                }
225                self as $Dst
226            }
227        }
228    };
229
230    ($Src:ty, $ViaU:ty, $ViaI:ty, AsSaturates = False => $Dst:ty) => {
231        impl SaturatingCast<$Dst> for $Src {
232            #[track_caller]
233            fn saturating_cast(self) -> $Dst {
234                let f: Float<$ViaU> = self.into();
235                let saturated = if f.neg { <$Dst>::MIN } else { <$Dst>::MAX };
236                match f.kind {
237                    FloatKind::Nan => panic!("NaN"),
238                    FloatKind::Infinite | FloatKind::Overflowing(_, true) => saturated,
239                    FloatKind::Overflowing(abs, false) => {
240                        if f.neg {
241                            let i = abs as $ViaI;
242                            if i == <$ViaI>::MIN {
243                                saturating_cast(i)
244                            } else if i < 0 {
245                                saturated
246                            } else {
247                                saturating_cast(-i)
248                            }
249                        } else {
250                            saturating_cast(abs)
251                        }
252                    }
253                }
254            }
255        }
256    };
257}
258
259macro_rules! float_to_int {
260    ($Src:ty, $ViaU:ty, $ViaI:ty, AsSaturates = $AsSat:tt => $($Dst:ty)*) => { $(
261        impl Cast<$Dst> for $Src {
262            #[inline]
263            #[track_caller]
264            fn cast(self) -> $Dst {
265                let (wrapped, overflow) = overflowing_cast(self);
266                debug_assert!(!overflow, "overflow");
267                let _ = overflow;
268                wrapped
269            }
270        }
271
272        impl CheckedCast<$Dst> for $Src {
273            fn checked_cast(self) -> Option<$Dst> {
274                let f: Float<$ViaU> = self.into();
275                match f.kind {
276                    FloatKind::Nan | FloatKind::Infinite | FloatKind::Overflowing(_, true) => None,
277                    FloatKind::Overflowing(abs, false) => {
278                        if f.neg {
279                            let i = abs as $ViaI;
280                            if i == <$ViaI>::MIN {
281                                checked_cast(i)
282                            } else if i < 0 {
283                                None
284                            } else {
285                                checked_cast(-i)
286                            }
287                        } else {
288                            checked_cast(abs)
289                        }
290                    }
291                }
292            }
293        }
294
295        impl StrictCast<$Dst> for $Src {
296            #[inline]
297            fn strict_cast(self) -> $Dst {
298                match overflowing_cast(self) {
299                    (val, false) => val,
300                    (_, true) => panic!("overflow"),
301                }
302            }
303        }
304
305        float_to_int_sat! { $Src, $ViaU, $ViaI, AsSaturates = $AsSat => $Dst }
306
307        impl WrappingCast<$Dst> for $Src {
308            #[inline]
309            #[track_caller]
310            fn wrapping_cast(self) -> $Dst {
311                overflowing_cast(self).0
312            }
313        }
314
315        impl OverflowingCast<$Dst> for $Src {
316            #[track_caller]
317            fn overflowing_cast(self) -> ($Dst, bool) {
318                let f: Float<$ViaU> = self.into();
319                match f.kind {
320                    FloatKind::Nan => panic!("NaN"),
321                    FloatKind::Infinite => panic!("infinite"),
322                    FloatKind::Overflowing(abs, overflow) => {
323                        if f.neg {
324                            let i = abs as $ViaI;
325                            let (wrapped, overflow2) = if i == <$ViaI>::MIN {
326                                overflowing_cast(i)
327                            } else if i < 0 {
328                                (wrapping_cast::<_, $Dst>(abs).wrapping_neg(), true)
329                            } else {
330                                overflowing_cast(-i)
331                            };
332                            (wrapped, overflow | overflow2)
333                        } else {
334                            let (wrapped, overflow2) = overflowing_cast(abs);
335                            (wrapped, overflow | overflow2)
336                        }
337                    }
338                }
339            }
340        }
341
342        impl UnwrappedCast<$Dst> for $Src {
343            #[inline]
344            fn unwrapped_cast(self) -> $Dst {
345                StrictCast::<$Dst>::strict_cast(self)
346            }
347        }
348
349        impl Cast<Wrapping<$Dst>> for $Src {
350            #[inline]
351            #[track_caller]
352            fn cast(self) -> Wrapping<$Dst> {
353                Wrapping(wrapping_cast(self))
354            }
355        }
356
357        impl CheckedCast<Wrapping<$Dst>> for $Src {
358            fn checked_cast(self) -> Option<Wrapping<$Dst>> {
359                let f: Float<$ViaU> = self.into();
360                match f.kind {
361                    FloatKind::Nan | FloatKind::Infinite => None,
362                    FloatKind::Overflowing(abs, _) => {
363                        let wrapped = if f.neg {
364                            let i = abs as $ViaI;
365                            if i == <$ViaI>::MIN {
366                                wrapping_cast(i)
367                            } else if i < 0 {
368                                wrapping_cast::<_, $Dst>(abs).wrapping_neg()
369                            } else {
370                                wrapping_cast(-i)
371                            }
372                        } else {
373                            wrapping_cast(abs)
374                        };
375                        Some(Wrapping(wrapped))
376                    }
377                }
378            }
379        }
380
381        impl StrictCast<Wrapping<$Dst>> for $Src {
382            #[inline]
383            fn strict_cast(self) -> Wrapping<$Dst> {
384                cast(self)
385            }
386        }
387
388        impl UnwrappedCast<Wrapping<$Dst>> for $Src {
389            #[inline]
390            fn unwrapped_cast(self) -> Wrapping<$Dst> {
391                StrictCast::<Wrapping<$Dst>>::strict_cast(self)
392            }
393        }
394    )* };
395}
396
397float_to_int! { f32, u32, i32, AsSaturates = True => i8 i16 i32 }
398float_to_int! { f32, u64, i64, AsSaturates = True => i64 }
399float_to_int! { f32, u128, i128, AsSaturates = True => i128 }
400#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
401float_to_int! { f32, u32, i32, AsSaturates = True => isize }
402#[cfg(target_pointer_width = "64")]
403float_to_int! { f32, u64, i64, AsSaturates = True => isize }
404float_to_int! { f32, u32, i32, AsSaturates = True => u8 u16 u32 }
405float_to_int! { f32, u64, i64, AsSaturates = True => u64 }
406float_to_int! { f32, u128, i128, AsSaturates = True => u128 }
407#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
408float_to_int! { f32, u32, i32, AsSaturates = True => usize }
409#[cfg(target_pointer_width = "64")]
410float_to_int! { f32, u64, i64, AsSaturates = True => usize }
411
412float_to_int! { f64, u64, i64, AsSaturates = True => i8 i16 i32 i64 }
413float_to_int! { f64, u128, i128, AsSaturates = True => i128 }
414float_to_int! { f64, u64, i64, AsSaturates = True => isize }
415float_to_int! { f64, u64, i64, AsSaturates = True => u8 u16 u32 u64 }
416float_to_int! { f64, u128, i128, AsSaturates = True => u128 }
417float_to_int! { f64, u64, i64, AsSaturates = True => usize }
418
419float_to_int! { Round<f32>, u32, i32, AsSaturates = False => i8 i16 i32 }
420float_to_int! { Round<f32>, u64, i64, AsSaturates = False => i64 }
421float_to_int! { Round<f32>, u128, i128, AsSaturates = False => i128 }
422#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
423float_to_int! { Round<f32>, u32, i32, AsSaturates = False => isize }
424#[cfg(target_pointer_width = "64")]
425float_to_int! { Round<f32>, u64, i64, AsSaturates = False => isize }
426float_to_int! { Round<f32>, u32, i32, AsSaturates = False => u8 u16 u32 }
427float_to_int! { Round<f32>, u64, i64, AsSaturates = False => u64 }
428float_to_int! { Round<f32>, u128, i128, AsSaturates = False => u128 }
429#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
430float_to_int! { Round<f32>, u32, i32, AsSaturates = False => usize }
431#[cfg(target_pointer_width = "64")]
432float_to_int! { Round<f32>, u64, i64, AsSaturates = False => usize }
433
434float_to_int! { Round<f64>, u64, i64, AsSaturates = False => i8 i16 i32 i64 }
435float_to_int! { Round<f64>, u128, i128, AsSaturates = False => i128 }
436float_to_int! { Round<f64>, u64, i64, AsSaturates = False => isize }
437float_to_int! { Round<f64>, u64, i64, AsSaturates = False => u8 u16 u32 u64 }
438float_to_int! { Round<f64>, u128, i128, AsSaturates = False => u128 }
439float_to_int! { Round<f64>, u64, i64, AsSaturates = False => usize }
440
441#[cfg(feature = "nightly-float")]
442mod impl_nightly_float {
443    use crate::int::{Float, FloatKind};
444    use crate::{
445        Cast, CheckedCast, OverflowingCast, Round, SaturatingCast, StrictCast, UnwrappedCast,
446        WrappingCast, cast, checked_cast, overflowing_cast, saturating_cast, wrapping_cast,
447    };
448    use core::num::Wrapping;
449
450    float_to_int! { f16, u32, i32, AsSaturates = True => i8 i16 i32 }
451    float_to_int! { f16, u64, i64, AsSaturates = True => i64 }
452    float_to_int! { f16, u128, i128, AsSaturates = True => i128 }
453    #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
454    float_to_int! { f16, u32, i32, AsSaturates = True => isize }
455    #[cfg(target_pointer_width = "64")]
456    float_to_int! { f16, u64, i64, AsSaturates = True => isize }
457    float_to_int! { f16, u32, i32, AsSaturates = True => u8 u16 u32 }
458    float_to_int! { f16, u64, i64, AsSaturates = True => u64 }
459    float_to_int! { f16, u128, i128, AsSaturates = True => u128 }
460    #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
461    float_to_int! { f16, u32, i32, AsSaturates = True => usize }
462    #[cfg(target_pointer_width = "64")]
463    float_to_int! { f16, u64, i64, AsSaturates = True => usize }
464
465    float_to_int! { f128, u128, i128, AsSaturates = True => i8 i16 i32 i64 i128 isize }
466    float_to_int! { f128, u128, i128, AsSaturates = True => u8 u16 u32 u64 u128 usize }
467
468    float_to_int! { Round<f16>, u32, i32, AsSaturates = False => i8 i16 i32 }
469    float_to_int! { Round<f16>, u64, i64, AsSaturates = False => i64 }
470    float_to_int! { Round<f16>, u128, i128, AsSaturates = False => i128 }
471    #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
472    float_to_int! { Round<f16>, u32, i32, AsSaturates = False => isize }
473    #[cfg(target_pointer_width = "64")]
474    float_to_int! { Round<f16>, u64, i64, AsSaturates = False => isize }
475    float_to_int! { Round<f16>, u32, i32, AsSaturates = False => u8 u16 u32 }
476    float_to_int! { Round<f16>, u64, i64, AsSaturates = False => u64 }
477    float_to_int! { Round<f16>, u128, i128, AsSaturates = False => u128 }
478    #[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))]
479    float_to_int! { Round<f16>, u32, i32, AsSaturates = False => usize }
480    #[cfg(target_pointer_width = "64")]
481    float_to_int! { Round<f16>, u64, i64, AsSaturates = False => usize }
482
483    float_to_int! { Round<f128>, u128, i128, AsSaturates = False => i8 i16 i32 i64 i128 isize }
484    float_to_int! { Round<f128>, u128, i128, AsSaturates = False => u8 u16 u32 u64 u128 usize }
485}
486
487macro_rules! signed {
488    ($($Dst:ty),*) => { $(
489        bool_to_int! { $Dst }
490        same_signedness! { i8, i16, i32, i64, i128, isize => $Dst }
491        unsigned_to_signed! { u8, u16, u32, u64, u128, usize => $Dst }
492        wrapping_int! {
493            bool, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize => $Dst
494        }
495    )* };
496}
497
498macro_rules! unsigned {
499    ($($Dst:ty),*) => { $(
500        bool_to_int! { $Dst }
501        signed_to_unsigned! { i8, i16, i32, i64, i128, isize => $Dst }
502        same_signedness! { u8, u16, u32, u64, u128, usize => $Dst }
503        wrapping_int! {
504            bool, i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize => $Dst
505        }
506    )* };
507}
508
509signed! { i8, i16, i32, i64, i128, isize }
510unsigned! { u8, u16, u32, u64, u128, usize }
511
512enum FloatKind<Uns> {
513    Nan,
514    Infinite,
515    Overflowing(Uns, bool),
516}
517struct Float<Uns> {
518    neg: bool,
519    kind: FloatKind<Uns>,
520}
521
522macro_rules! from_for_float {
523    ($Src:ty, $Uns:ty, $PREC:expr => $($Dst:ty),*) => { $(
524        impl From<$Src> for Float<$Dst> {
525            fn from(src: $Src) -> Self {
526                const SRC_NBITS: i32 = mem::size_of::<$Src>() as i32 * 8;
527                const DST_NBITS: i32 = mem::size_of::<$Dst>() as i32 * 8;
528                const MANT_NBITS: i32 = $PREC - 1;
529                const EXP_NBITS: i32 = SRC_NBITS - MANT_NBITS - 1;
530                const EXP_BIAS: i32 = (1 << (EXP_NBITS - 1)) - 1;
531                const SIGN_MASK: $Uns = !(!0 >> 1);
532                const MANT_MASK: $Uns = !(!0 << MANT_NBITS);
533                const EXP_MASK: $Uns = !(SIGN_MASK | MANT_MASK);
534
535                let u = src.to_bits();
536                let neg = (u & SIGN_MASK) != 0;
537                let biased_exp = u & EXP_MASK;
538                if biased_exp == EXP_MASK {
539                    let kind = if (u & MANT_MASK) == 0 {
540                        FloatKind::Infinite
541                    } else {
542                        FloatKind::Nan
543                    };
544                    return Float { neg, kind };
545                }
546                let shift = (biased_exp >> MANT_NBITS) as i32 - (EXP_BIAS + MANT_NBITS);
547
548                // Check if the magnitude is smaller than one. Do not return
549                // early if shift == -MANT_NBITS, as there is implicit one.
550                if shift < -MANT_NBITS {
551                    let kind = FloatKind::Overflowing(0, false);
552                    return Float { neg, kind };
553                }
554
555                // Check if the least significant bit will be in a $Dst.
556                if shift >= DST_NBITS {
557                    let kind = FloatKind::Overflowing(0, true);
558                    return Float { neg, kind };
559                }
560
561                let mut significand: $Dst = (u & MANT_MASK).into();
562                // Add implicit one.
563                significand |= 1 << MANT_NBITS;
564                let kind = if shift < 0 {
565                    FloatKind::Overflowing(significand >> -shift, false)
566                } else {
567                    let wrapped = significand << shift;
568                    let overflow = (wrapped >> shift) != significand;
569                    FloatKind::Overflowing(wrapped, overflow)
570                };
571                Float { neg, kind }
572            }
573        }
574
575        impl From<Round<$Src>> for Float<$Dst> {
576            fn from(src: Round<$Src>) -> Self {
577                const SRC_NBITS: i32 = mem::size_of::<$Src>() as i32 * 8;
578                const DST_NBITS: i32 = mem::size_of::<$Dst>() as i32 * 8;
579                const MANT_NBITS: i32 = $PREC - 1;
580                const EXP_NBITS: i32 = SRC_NBITS - MANT_NBITS - 1;
581                const EXP_BIAS: i32 = (1 << (EXP_NBITS - 1)) - 1;
582                const SIGN_MASK: $Uns = !(!0 >> 1);
583                const MANT_MASK: $Uns = !(!0 << MANT_NBITS);
584                const EXP_MASK: $Uns = !(SIGN_MASK | MANT_MASK);
585
586                let src = src.0;
587                let u = src.to_bits();
588                let neg = (u & SIGN_MASK) != 0;
589                let biased_exp = u & EXP_MASK;
590                if biased_exp == EXP_MASK {
591                    let kind = if (u & MANT_MASK) == 0 {
592                        FloatKind::Infinite
593                    } else {
594                        FloatKind::Nan
595                    };
596                    return Float { neg, kind };
597                }
598                let shift = (biased_exp >> MANT_NBITS) as i32 - (EXP_BIAS + MANT_NBITS);
599
600                // If shift = -MANT_BITS, then 1 ≤ x < 2.
601                // If shift = -MANT_BITS - 1, then 0.5 ≤ x < 1, which can be rounded up.
602                // If shift < -MANT_BITS - 1, then x < 0.5, which is rounded down.
603                ////                    || (shift == -MANT_NBITS - 1 && ((u & MANT_MASK) != 0 || x))
604                if shift < -MANT_NBITS - 1 {
605                    let kind = FloatKind::Overflowing(0, false);
606                    return Float { neg, kind };
607                }
608
609                // Check if the least significant bit will be in a $Dst.
610                if shift >= DST_NBITS {
611                    let kind = FloatKind::Overflowing(0, true);
612                    return Float { neg, kind };
613                }
614
615                let mut significand: $Dst = (u & MANT_MASK).into();
616                // Add implicit one.
617                significand |= 1 << MANT_NBITS;
618                let kind = if shift < 0 {
619                    let right = -shift;
620                    let round_bit = 1 << (right - 1);
621                    if (significand & round_bit) != 0 && (significand & (3 * round_bit - 1)) != 0 {
622                        significand += round_bit;
623                    }
624                    FloatKind::Overflowing(significand >> right, false)
625                } else {
626                    let wrapped = significand << shift;
627                    let overflow = (wrapped >> shift) != significand;
628                    FloatKind::Overflowing(wrapped, overflow)
629                };
630                Float { neg, kind }
631            }
632        }
633    )* };
634}
635
636#[cfg(feature = "nightly-float")]
637from_for_float! { f16, u16, 11 => u16, u32, u64, u128 }
638from_for_float! { f32, u32, 24 => u32, u64, u128 }
639from_for_float! { f64, u64, 53 => u64, u128 }
640#[cfg(feature = "nightly-float")]
641from_for_float! { f128, u128, 113 => u128 }