rug/integer/
casts.rs

1// Copyright © 2016–2025 Trevor Spiteri
2
3// This program is free software: you can redistribute it and/or modify it under
4// the terms of the GNU Lesser General Public License as published by the Free
5// Software Foundation, either version 3 of the License, or (at your option) any
6// later version.
7//
8// This program is distributed in the hope that it will be useful, but WITHOUT
9// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11// details.
12//
13// You should have received a copy of the GNU Lesser General Public License and
14// a copy of the GNU General Public License along with this program. If not, see
15// <https://www.gnu.org/licenses/>.
16
17use crate::Integer;
18use crate::ext::xmpz;
19use crate::misc;
20use crate::ops::NegAssign;
21use az::{
22    Az, Cast, CheckedCast, OverflowingCast, Round, SaturatingCast, UnwrappedCast, WrappingCast,
23};
24
25macro_rules! cast_int {
26    ($Prim:ty, $fits:path, $get_abs:path) => {
27        impl Cast<Integer> for $Prim {
28            #[inline]
29            fn cast(self) -> Integer {
30                Integer::from(self)
31            }
32        }
33
34        impl Cast<$Prim> for Integer {
35            #[inline]
36            fn cast(self) -> $Prim {
37                (&self).cast()
38            }
39        }
40        impl Cast<$Prim> for &'_ Integer {
41            #[inline]
42            fn cast(self) -> $Prim {
43                let (wrapped, overflow) = self.overflowing_cast();
44                debug_assert!(!overflow, "overflow");
45                wrapped
46            }
47        }
48        impl CheckedCast<$Prim> for Integer {
49            #[inline]
50            fn checked_cast(self) -> Option<$Prim> {
51                (&self).checked_cast()
52            }
53        }
54        impl CheckedCast<$Prim> for &'_ Integer {
55            #[inline]
56            fn checked_cast(self) -> Option<$Prim> {
57                if $fits(self) {
58                    Some(self.wrapping_cast())
59                } else {
60                    None
61                }
62            }
63        }
64        impl SaturatingCast<$Prim> for Integer {
65            #[inline]
66            fn saturating_cast(self) -> $Prim {
67                (&self).saturating_cast()
68            }
69        }
70        impl SaturatingCast<$Prim> for &'_ Integer {
71            #[inline]
72            fn saturating_cast(self) -> $Prim {
73                if $fits(self) {
74                    self.wrapping_cast()
75                } else if self.is_negative() {
76                    <$Prim>::MIN
77                } else {
78                    <$Prim>::MAX
79                }
80            }
81        }
82        impl WrappingCast<$Prim> for Integer {
83            #[inline]
84            fn wrapping_cast(self) -> $Prim {
85                (&self).wrapping_cast()
86            }
87        }
88        impl WrappingCast<$Prim> for &'_ Integer {
89            #[inline]
90            fn wrapping_cast(self) -> $Prim {
91                let val = $get_abs(self);
92                if self.is_negative() {
93                    val.wrapping_neg()
94                } else {
95                    val
96                }
97                .wrapping_cast()
98            }
99        }
100        impl OverflowingCast<$Prim> for Integer {
101            #[inline]
102            fn overflowing_cast(self) -> ($Prim, bool) {
103                (&self).overflowing_cast()
104            }
105        }
106        impl OverflowingCast<$Prim> for &'_ Integer {
107            #[inline]
108            fn overflowing_cast(self) -> ($Prim, bool) {
109                (self.wrapping_cast(), !$fits(self))
110            }
111        }
112        impl UnwrappedCast<$Prim> for Integer {
113            #[inline]
114            fn unwrapped_cast(self) -> $Prim {
115                (&self).unwrapped_cast()
116            }
117        }
118        impl UnwrappedCast<$Prim> for &'_ Integer {
119            #[inline]
120            fn unwrapped_cast(self) -> $Prim {
121                if $fits(self) {
122                    self.wrapping_cast()
123                } else {
124                    panic!("overflow")
125                }
126            }
127        }
128    };
129}
130
131impl Cast<Integer> for bool {
132    #[inline]
133    fn cast(self) -> Integer {
134        if self {
135            Integer::from(1u32)
136        } else {
137            Integer::new()
138        }
139    }
140}
141
142cast_int! { i8, xmpz::fits_i8, xmpz::get_abs_u8 }
143cast_int! { i16, xmpz::fits_i16, xmpz::get_abs_u16 }
144cast_int! { i32, xmpz::fits_i32, xmpz::get_abs_u32 }
145cast_int! { i64, xmpz::fits_i64, xmpz::get_abs_u64 }
146cast_int! { i128, xmpz::fits_i128, xmpz::get_abs_u128 }
147#[cfg(target_pointer_width = "32")]
148cast_int! { isize, xmpz::fits_i32, xmpz::get_abs_u32 }
149#[cfg(target_pointer_width = "64")]
150cast_int! { isize, xmpz::fits_i64, xmpz::get_abs_u64 }
151cast_int! { u8, xmpz::fits_u8, xmpz::get_abs_u8 }
152cast_int! { u16, xmpz::fits_u16, xmpz::get_abs_u16 }
153cast_int! { u32, xmpz::fits_u32, xmpz::get_abs_u32 }
154cast_int! { u64, xmpz::fits_u64, xmpz::get_abs_u64 }
155cast_int! { u128, xmpz::fits_u128, xmpz::get_abs_u128 }
156#[cfg(target_pointer_width = "32")]
157cast_int! { usize, xmpz::fits_u32, xmpz::get_abs_u32 }
158#[cfg(target_pointer_width = "64")]
159cast_int! { usize, xmpz::fits_u64, xmpz::get_abs_u64 }
160
161impl Cast<Integer> for f32 {
162    #[inline]
163    fn cast(self) -> Integer {
164        self.checked_cast().expect("not finite")
165    }
166}
167
168impl CheckedCast<Integer> for f32 {
169    #[inline]
170    fn checked_cast(self) -> Option<Integer> {
171        let bits = self.to_bits();
172        let biased_exp = (bits >> 23) & 0xFF;
173        // biased_exp:
174        //     0x00 => subnormal, 1
175        //     0x01..=0x7E => finite < 1.0
176        //     0x7F..=0xFE finite >= 1.0
177        //     0xFF => not finite 1
178        if biased_exp < 0x7F {
179            Some(Integer::new())
180        } else if biased_exp == 0xFF {
181            None
182        } else {
183            // 1.0 has biased_exp == 127 and would need >> 23.
184            // 2.0 has biased_exp == 128 and would need >> 22.
185            // 2.0^23 has biased_exp == 150 and would need >> 0.
186            // So, we need >> 150 - biased_exp
187            let mantissa_with_one = 0x0080_0000 | (bits & 0x007F_FFFF);
188            let mut val = if biased_exp <= 150 {
189                Integer::from(mantissa_with_one >> (150 - biased_exp))
190            } else {
191                Integer::from(mantissa_with_one) << (biased_exp - 150)
192            };
193            if bits & 0x8000_0000 != 0 {
194                val.neg_assign();
195            }
196            Some(val)
197        }
198    }
199}
200
201impl UnwrappedCast<Integer> for f32 {
202    #[inline]
203    fn unwrapped_cast(self) -> Integer {
204        self.checked_cast().expect("not finite")
205    }
206}
207
208impl Cast<f32> for Integer {
209    #[inline]
210    fn cast(self) -> f32 {
211        (&self).cast()
212    }
213}
214
215impl Cast<f32> for &'_ Integer {
216    #[inline]
217    fn cast(self) -> f32 {
218        misc::trunc_f64_to_f32(self.cast())
219    }
220}
221
222impl Cast<Integer> for f64 {
223    #[inline]
224    fn cast(self) -> Integer {
225        self.checked_cast().expect("not finite")
226    }
227}
228
229impl CheckedCast<Integer> for f64 {
230    #[inline]
231    fn checked_cast(self) -> Option<Integer> {
232        let bits = self.to_bits();
233        let biased_exp = (bits >> 52) & 0x7FF;
234        // biased_exp:
235        //     0x000 => subnormal,
236        //     0x001..=0x3FE => finite < 1.0,
237        //     0x3FF..=0x7FE finite >= 1.0,
238        //     0x7FF => not finite
239        if biased_exp < 0x3FF {
240            Some(Integer::new())
241        } else if biased_exp == 0x7FF {
242            None
243        } else {
244            // 1.0 has biased_exp == 1023 and would need >> 52.
245            // 2.0 has biased_exp == 1024 and would need >> 51.
246            // 2.0^52 has biased_exp == 1075 and would need >> 0.
247            // So, we need >> 1075 - biased_exp
248            let mantissa_with_one = 0x0010_0000_0000_0000 | (bits & 0x000F_FFFF_FFFF_FFFF);
249            let mut val = if biased_exp <= 1075 {
250                Integer::from(mantissa_with_one >> (1075 - biased_exp).az::<u32>())
251            } else {
252                Integer::from(mantissa_with_one) << (biased_exp - 1075).az::<u32>()
253            };
254            if bits & 0x8000_0000_0000_0000 != 0 {
255                val.neg_assign();
256            }
257            Some(val)
258        }
259    }
260}
261
262impl UnwrappedCast<Integer> for f64 {
263    #[inline]
264    fn unwrapped_cast(self) -> Integer {
265        self.checked_cast().expect("not finite")
266    }
267}
268
269impl Cast<f64> for Integer {
270    #[inline]
271    fn cast(self) -> f64 {
272        (&self).cast()
273    }
274}
275
276impl Cast<f64> for &'_ Integer {
277    #[inline]
278    fn cast(self) -> f64 {
279        xmpz::get_f64(self)
280    }
281}
282
283impl Cast<Integer> for Round<f32> {
284    #[inline]
285    fn cast(self) -> Integer {
286        self.checked_cast().expect("not finite")
287    }
288}
289
290impl CheckedCast<Integer> for Round<f32> {
291    #[inline]
292    fn checked_cast(self) -> Option<Integer> {
293        let bits = self.0.to_bits();
294        let biased_exp = (bits >> 23) & 0xFF;
295        // biased_exp:
296        //     0x00 => subnormal, 1
297        //     0x01..=0x7E => finite < 1.0
298        //     0x7F..=0xFE finite >= 1.0
299        //     0xFF => not finite 1
300        if biased_exp < 0x7F {
301            Some(Integer::new())
302        } else if biased_exp == 0xFF {
303            None
304        } else {
305            // 1.0 has biased_exp == 127 and would need >> 23.
306            // 2.0 has biased_exp == 128 and would need >> 22.
307            // 2.0^23 has biased_exp == 150 and would need >> 0.
308            // So, we need >> 150 - biased_exp
309            let mantissa_with_one = 0x0080_0000 | (bits & 0x007F_FFFF);
310            let mut val = if biased_exp <= 150 {
311                let mut round = 1u32 << (150 - biased_exp) >> 1;
312                // Round away from zero if val & round != 0 and either
313                //   * odd, that is val & (round << 1) != 0
314                //   * greater than tie, that is val & (round - 1) != 0
315                // The two conditions can be simplified to
316                //     val & ((2 * round) | (round - 1))
317                //   = val & (3 * round - 1)
318                if mantissa_with_one & round == 0 || mantissa_with_one & (3 * round - 1) == 0 {
319                    round = 0;
320                }
321                Integer::from((mantissa_with_one + round) >> (150 - biased_exp))
322            } else {
323                Integer::from(mantissa_with_one) << (biased_exp - 150)
324            };
325            if bits & 0x8000_0000 != 0 {
326                val.neg_assign();
327            }
328            Some(val)
329        }
330    }
331}
332
333impl UnwrappedCast<Integer> for Round<f32> {
334    #[inline]
335    fn unwrapped_cast(self) -> Integer {
336        self.checked_cast().expect("not finite")
337    }
338}
339
340impl Cast<Integer> for Round<f64> {
341    #[inline]
342    fn cast(self) -> Integer {
343        self.checked_cast().expect("not finite")
344    }
345}
346
347impl CheckedCast<Integer> for Round<f64> {
348    #[inline]
349    fn checked_cast(self) -> Option<Integer> {
350        let bits = self.0.to_bits();
351        let biased_exp = (bits >> 52) & 0x7FF;
352        // biased_exp:
353        //     0x000 => subnormal,
354        //     0x001..=0x3FE => finite < 1.0,
355        //     0x3FF..=0x7FE finite >= 1.0,
356        //     0x7FF => not finite
357        if biased_exp < 0x3FF {
358            Some(Integer::new())
359        } else if biased_exp == 0x7FF {
360            None
361        } else {
362            // 1.0 has biased_exp == 1023 and would need >> 52.
363            // 2.0 has biased_exp == 1024 and would need >> 51.
364            // 2.0^52 has biased_exp == 1075 and would need >> 0.
365            // So, we need >> 1075 - biased_exp
366            let mantissa_with_one = 0x0010_0000_0000_0000 | (bits & 0x000F_FFFF_FFFF_FFFF);
367            let mut val = if biased_exp <= 1075 {
368                let mut round = 1u64 << (1075 - biased_exp) >> 1;
369                // Round away from zero if val & round != 0 and either
370                //   * odd, that is val & (round << 1) != 0
371                //   * greater than tie, that is val & (round - 1) != 0
372                // The two conditions can be simplified to
373                //     val & ((2 * round) | (round - 1))
374                //   = val & (3 * round - 1)
375                if mantissa_with_one & round == 0 || mantissa_with_one & (3 * round - 1) == 0 {
376                    round = 0;
377                }
378                Integer::from((mantissa_with_one + round) >> (1075 - biased_exp).az::<u32>())
379            } else {
380                Integer::from(mantissa_with_one) << (biased_exp - 1075).az::<u32>()
381            };
382            if bits & 0x8000_0000_0000_0000 != 0 {
383                val.neg_assign();
384            }
385            Some(val)
386        }
387    }
388}
389
390impl UnwrappedCast<Integer> for Round<f64> {
391    #[inline]
392    fn unwrapped_cast(self) -> Integer {
393        self.checked_cast().expect("not finite")
394    }
395}
396
397#[cfg(test)]
398#[allow(clippy::float_cmp)]
399mod tests {
400    use crate::Integer;
401    use az::{
402        Az, Cast, CheckedAs, CheckedCast, OverflowingAs, OverflowingCast, Round, SaturatingAs,
403        SaturatingCast, UnwrappedAs, UnwrappedCast, WrappingAs, WrappingCast,
404    };
405    use core::borrow::Borrow;
406    use core::fmt::Debug;
407    use std::panic;
408
409    #[test]
410    fn check_bool() {
411        let zero = Integer::new();
412        let one = Integer::from(1);
413        assert_eq!(false.az::<Integer>(), zero);
414        assert_eq!(true.az::<Integer>(), one);
415    }
416
417    fn check_there_and_back<T>(min: T, max: T)
418    where
419        T: Copy + Debug + Eq + Cast<Integer>,
420        for<'a> &'a Integer: Cast<T>
421            + CheckedCast<T>
422            + SaturatingCast<T>
423            + WrappingCast<T>
424            + OverflowingCast<T>
425            + UnwrappedCast<T>,
426    {
427        let min_int: Integer = min.az::<Integer>();
428        let max_int: Integer = max.az::<Integer>();
429        assert_eq!(min_int.borrow().az::<T>(), min);
430        assert_eq!(max_int.borrow().az::<T>(), max);
431        assert_eq!(min_int.borrow().checked_as::<T>(), Some(min));
432        assert_eq!(max_int.borrow().checked_as::<T>(), Some(max));
433        assert_eq!(min_int.borrow().saturating_as::<T>(), min);
434        assert_eq!(max_int.borrow().saturating_as::<T>(), max);
435        assert_eq!(min_int.borrow().wrapping_as::<T>(), min);
436        assert_eq!(max_int.borrow().wrapping_as::<T>(), max);
437        assert_eq!(min_int.borrow().overflowing_as::<T>(), (min, false));
438        assert_eq!(max_int.borrow().overflowing_as::<T>(), (max, false));
439        assert_eq!(min_int.borrow().unwrapped_as::<T>(), min);
440        assert_eq!(max_int.borrow().unwrapped_as::<T>(), max);
441
442        let too_small: Integer = min_int - 1;
443        let too_large: Integer = max_int + 1;
444        assert_eq!(too_small.borrow().checked_as::<T>(), None);
445        assert_eq!(too_large.borrow().checked_as::<T>(), None);
446        assert_eq!(too_small.borrow().saturating_as::<T>(), min);
447        assert_eq!(too_large.borrow().saturating_as::<T>(), max);
448        assert_eq!(too_small.borrow().wrapping_as::<T>(), max);
449        assert_eq!(too_large.borrow().wrapping_as::<T>(), min);
450        assert_eq!(too_small.borrow().overflowing_as::<T>(), (max, true));
451        assert_eq!(too_large.borrow().overflowing_as::<T>(), (min, true));
452        assert!(panic::catch_unwind(|| too_small.borrow().unwrapped_as::<T>()).is_err());
453        assert!(panic::catch_unwind(|| too_large.borrow().unwrapped_as::<T>()).is_err());
454    }
455
456    #[test]
457    fn check_integers() {
458        check_there_and_back(i8::MIN, i8::MAX);
459        check_there_and_back(i16::MIN, i16::MAX);
460        check_there_and_back(i32::MIN, i32::MAX);
461        check_there_and_back(i64::MIN, i64::MAX);
462        check_there_and_back(i128::MIN, i128::MAX);
463        check_there_and_back(isize::MIN, isize::MAX);
464        check_there_and_back(u8::MIN, u8::MAX);
465        check_there_and_back(u16::MIN, u16::MAX);
466        check_there_and_back(u32::MIN, u32::MAX);
467        check_there_and_back(u64::MIN, u64::MAX);
468        check_there_and_back(u128::MIN, u128::MAX);
469        check_there_and_back(usize::MIN, usize::MAX);
470    }
471
472    #[test]
473    fn check_floats() {
474        let f32_max: Integer = Integer::from((1u32 << 24) - 1) << (127 - 23);
475        let f64_max: Integer = Integer::from((1u64 << 53) - 1) << (1023 - 52);
476
477        assert_eq!(f32::NAN.checked_as::<Integer>(), None);
478        assert!(panic::catch_unwind(|| f32::NAN.unwrapped_as::<Integer>()).is_err());
479        assert_eq!(f32::NEG_INFINITY.checked_as::<Integer>(), None);
480        assert!(panic::catch_unwind(|| f32::NEG_INFINITY.unwrapped_as::<Integer>()).is_err());
481        assert_eq!((-f32::MAX).az::<Integer>(), *f32_max.as_neg());
482        assert_eq!((-2f32).az::<Integer>(), -2);
483        assert_eq!((-1.99f32).az::<Integer>(), -1);
484        assert_eq!((-1f32).az::<Integer>(), -1);
485        assert_eq!((-0.99f32).az::<Integer>(), 0);
486        assert_eq!(0.99f32.az::<Integer>(), 0);
487        assert_eq!(1f32.az::<Integer>(), 1);
488        assert_eq!(1.99f32.az::<Integer>(), 1);
489        assert_eq!(2f32.az::<Integer>(), 2);
490        assert_eq!(f32::MAX.az::<Integer>(), f32_max);
491        assert_eq!(f32::INFINITY.checked_as::<Integer>(), None);
492        assert!(panic::catch_unwind(|| f32::INFINITY.unwrapped_as::<Integer>()).is_err());
493
494        assert_eq!(f64::NAN.checked_as::<Integer>(), None);
495        assert!(panic::catch_unwind(|| f64::NAN.unwrapped_as::<Integer>()).is_err());
496        assert_eq!(f64::NEG_INFINITY.checked_as::<Integer>(), None);
497        assert!(panic::catch_unwind(|| f64::NEG_INFINITY.unwrapped_as::<Integer>()).is_err());
498        assert_eq!((-f64::MAX).az::<Integer>(), *f64_max.as_neg());
499        assert_eq!((-2f64).az::<Integer>(), -2);
500        assert_eq!((-1.99f64).az::<Integer>(), -1);
501        assert_eq!((-1f64).az::<Integer>(), -1);
502        assert_eq!((-0.99f64).az::<Integer>(), 0);
503        assert_eq!(0.99f64.az::<Integer>(), 0);
504        assert_eq!(1f64.az::<Integer>(), 1);
505        assert_eq!(1.99f64.az::<Integer>(), 1);
506        assert_eq!(2f64.az::<Integer>(), 2);
507        assert_eq!(f64::MAX.az::<Integer>(), f64_max);
508        assert_eq!(f64::INFINITY.checked_as::<Integer>(), None);
509        assert!(panic::catch_unwind(|| f64::INFINITY.unwrapped_as::<Integer>()).is_err());
510
511        let zero: Integer = Integer::new();
512        let one: Integer = Integer::from(1);
513        let two: Integer = Integer::from(2);
514        let f32_overflow: Integer = Integer::from(1) << 128;
515        let f64_overflow: Integer = Integer::from(1) << 1024;
516        let still_f32_max: Integer = f32_overflow.clone() - 1;
517        let still_f64_max: Integer = f64_overflow.clone() - 1;
518
519        assert_eq!(
520            (*f32_overflow.as_neg()).borrow().az::<f32>(),
521            f32::NEG_INFINITY
522        );
523        assert_eq!((*still_f32_max.as_neg()).borrow().az::<f32>(), -f32::MAX);
524        assert_eq!((*f32_max.as_neg()).borrow().az::<f32>(), -f32::MAX);
525        assert_eq!((*two.as_neg()).borrow().az::<f32>(), -2f32);
526        assert_eq!((*one.as_neg()).borrow().az::<f32>(), -1f32);
527        assert_eq!(zero.borrow().az::<f32>(), 0f32);
528        assert_eq!(one.borrow().az::<f32>(), 1f32);
529        assert_eq!(two.borrow().az::<f32>(), 2f32);
530        assert_eq!(f32_max.borrow().az::<f32>(), f32::MAX);
531        assert_eq!(still_f32_max.borrow().az::<f32>(), f32::MAX);
532        assert_eq!(f32_overflow.borrow().az::<f32>(), f32::INFINITY);
533
534        assert_eq!(
535            (*f64_overflow.as_neg()).borrow().az::<f64>(),
536            f64::NEG_INFINITY
537        );
538        assert_eq!((*still_f64_max.as_neg()).borrow().az::<f64>(), -f64::MAX);
539        assert_eq!((*f64_max.as_neg()).borrow().az::<f64>(), -f64::MAX);
540        assert_eq!((*two.as_neg()).borrow().az::<f64>(), -2f64);
541        assert_eq!((*one.as_neg()).borrow().az::<f64>(), -1f64);
542        assert_eq!(zero.borrow().az::<f64>(), 0f64);
543        assert_eq!(one.borrow().az::<f64>(), 1f64);
544        assert_eq!(two.borrow().az::<f64>(), 2f64);
545        assert_eq!(f64_max.borrow().az::<f64>(), f64::MAX);
546        assert_eq!(f64_overflow.borrow().az::<f64>(), f64::INFINITY);
547    }
548
549    #[test]
550    fn check_round_floats() {
551        let f32_max: Integer = Integer::from((1u32 << 24) - 1) << (127 - 23);
552        let f64_max: Integer = Integer::from((1u64 << 53) - 1) << (1023 - 52);
553
554        assert_eq!(Round(f32::NAN).checked_as::<Integer>(), None);
555        assert!(panic::catch_unwind(|| Round(f32::NAN).unwrapped_as::<Integer>()).is_err());
556        assert_eq!(Round(f32::NEG_INFINITY).checked_as::<Integer>(), None);
557        assert!(
558            panic::catch_unwind(|| Round(f32::NEG_INFINITY).unwrapped_as::<Integer>()).is_err()
559        );
560        assert_eq!(Round(-f32::MAX).az::<Integer>(), *f32_max.as_neg());
561        assert_eq!(Round(-4f32).az::<Integer>(), -4);
562        assert_eq!(Round(-3.5f32).az::<Integer>(), -4);
563        assert_eq!(Round(-3.49f32).az::<Integer>(), -3);
564        assert_eq!(Round(-2.51f32).az::<Integer>(), -3);
565        assert_eq!(Round(-2.5f32).az::<Integer>(), -2);
566        assert_eq!(Round(-2f32).az::<Integer>(), -2);
567        assert_eq!(Round(-1.5f32).az::<Integer>(), -2);
568        assert_eq!(Round(-1.49f32).az::<Integer>(), -1);
569        assert_eq!(Round(-1f32).az::<Integer>(), -1);
570        assert_eq!(Round(-0.5f32).az::<Integer>(), 0);
571        assert_eq!(Round(0.5f32).az::<Integer>(), 0);
572        assert_eq!(Round(1f32).az::<Integer>(), 1);
573        assert_eq!(Round(1.49f32).az::<Integer>(), 1);
574        assert_eq!(Round(1.5f32).az::<Integer>(), 2);
575        assert_eq!(Round(2f32).az::<Integer>(), 2);
576        assert_eq!(Round(2.5f32).az::<Integer>(), 2);
577        assert_eq!(Round(2.51f32).az::<Integer>(), 3);
578        assert_eq!(Round(3.49f32).az::<Integer>(), 3);
579        assert_eq!(Round(3.5f32).az::<Integer>(), 4);
580        assert_eq!(Round(4f32).az::<Integer>(), 4);
581        assert_eq!(Round(f32::MAX).az::<Integer>(), f32_max);
582        assert_eq!(Round(f32::INFINITY).checked_as::<Integer>(), None);
583        assert!(panic::catch_unwind(|| Round(f32::INFINITY).unwrapped_as::<Integer>()).is_err());
584
585        assert_eq!(Round(f64::NAN).checked_as::<Integer>(), None);
586        assert!(panic::catch_unwind(|| Round(f64::NAN).unwrapped_as::<Integer>()).is_err());
587        assert_eq!(Round(f64::NEG_INFINITY).checked_as::<Integer>(), None);
588        assert!(
589            panic::catch_unwind(|| Round(f64::NEG_INFINITY).unwrapped_as::<Integer>()).is_err()
590        );
591        assert_eq!(Round(-f64::MAX).az::<Integer>(), *f64_max.as_neg());
592        assert_eq!(Round(-4f64).az::<Integer>(), -4);
593        assert_eq!(Round(-3.5f64).az::<Integer>(), -4);
594        assert_eq!(Round(-3.49f64).az::<Integer>(), -3);
595        assert_eq!(Round(-2.51f64).az::<Integer>(), -3);
596        assert_eq!(Round(-2.5f64).az::<Integer>(), -2);
597        assert_eq!(Round(-2f64).az::<Integer>(), -2);
598        assert_eq!(Round(-1.5f64).az::<Integer>(), -2);
599        assert_eq!(Round(-1.49f64).az::<Integer>(), -1);
600        assert_eq!(Round(-1f64).az::<Integer>(), -1);
601        assert_eq!(Round(-0.5f64).az::<Integer>(), 0);
602        assert_eq!(Round(0.5f64).az::<Integer>(), 0);
603        assert_eq!(Round(1f64).az::<Integer>(), 1);
604        assert_eq!(Round(1.49f64).az::<Integer>(), 1);
605        assert_eq!(Round(1.5f64).az::<Integer>(), 2);
606        assert_eq!(Round(2f64).az::<Integer>(), 2);
607        assert_eq!(Round(2.5f64).az::<Integer>(), 2);
608        assert_eq!(Round(2.51f64).az::<Integer>(), 3);
609        assert_eq!(Round(3.49f64).az::<Integer>(), 3);
610        assert_eq!(Round(3.5f64).az::<Integer>(), 4);
611        assert_eq!(Round(4f64).az::<Integer>(), 4);
612        assert_eq!(Round(f64::MAX).az::<Integer>(), f64_max);
613        assert_eq!(Round(f64::INFINITY).checked_as::<Integer>(), None);
614        assert!(panic::catch_unwind(|| Round(f64::INFINITY).unwrapped_as::<Integer>()).is_err());
615    }
616}