| // Tests for the `float_conversions` methods (ACP rust-lang/libs-team#810): | |
| // `cast`, `to_int_saturating`, `to_int_checked`, and `to_int_strict`. | |
| #[test] | |
| fn cast_widen_narrow() { | |
| assert_eq!(1.5_f32.cast::<f64>(), 1.5_f64); | |
| assert_eq!(0.5_f64.cast::<f32>(), 0.5_f32); | |
| // Narrowing a value out of the target range produces an infinity. | |
| assert_eq!(1e300_f64.cast::<f32>(), f32::INFINITY); | |
| assert_eq!((-1e300_f64).cast::<f32>(), f32::NEG_INFINITY); | |
| // Same-type cast is the identity. | |
| assert_eq!(3.25_f64.cast::<f64>(), 3.25_f64); | |
| // Narrowing rounds to the nearest representable value. | |
| assert_eq!(0.1_f64.cast::<f32>(), 0.1_f32); | |
| } | |
| #[test] | |
| fn saturating_basics() { | |
| assert_eq!(255.9_f32.to_int_saturating::<u8>(), 255); | |
| assert_eq!(300.0_f32.to_int_saturating::<u8>(), 255); | |
| assert_eq!((-1.0_f32).to_int_saturating::<u8>(), 0); | |
| assert_eq!(f32::NAN.to_int_saturating::<u8>(), 0); | |
| assert_eq!(f32::INFINITY.to_int_saturating::<u8>(), 255); | |
| assert_eq!(f32::NEG_INFINITY.to_int_saturating::<i8>(), i8::MIN); | |
| assert_eq!(f64::NAN.to_int_saturating::<i32>(), 0); | |
| // Large finite values saturate at the target boundary. | |
| assert_eq!(1e18_f64.to_int_saturating::<i32>(), i32::MAX); | |
| assert_eq!((-1e18_f64).to_int_saturating::<i32>(), i32::MIN); | |
| } | |
| #[test] | |
| fn checked_truncates_then_bounds() { | |
| // Truncation toward zero happens before the bounds check. | |
| assert_eq!(255.5_f64.to_int_checked::<u8>(), Some(255)); | |
| assert_eq!(255.9_f64.to_int_checked::<u8>(), Some(255)); | |
| assert_eq!(256.0_f64.to_int_checked::<u8>(), None); | |
| // A negative fraction truncates toward zero and fits. | |
| assert_eq!((-0.5_f64).to_int_checked::<u8>(), Some(0)); | |
| assert_eq!((-1.0_f64).to_int_checked::<u8>(), None); | |
| // Non-finite is always None. | |
| assert_eq!(f64::NAN.to_int_checked::<u8>(), None); | |
| assert_eq!(f64::INFINITY.to_int_checked::<u8>(), None); | |
| assert_eq!(f64::NEG_INFINITY.to_int_checked::<i32>(), None); | |
| } | |
| #[test] | |
| fn checked_signed_boundaries() { | |
| assert_eq!((-128.0_f64).to_int_checked::<i8>(), Some(-128)); | |
| assert_eq!((-128.9_f64).to_int_checked::<i8>(), Some(-128)); | |
| assert_eq!((-129.0_f64).to_int_checked::<i8>(), None); | |
| assert_eq!(127.0_f64.to_int_checked::<i8>(), Some(127)); | |
| assert_eq!(127.9_f64.to_int_checked::<i8>(), Some(127)); | |
| assert_eq!(128.0_f64.to_int_checked::<i8>(), None); | |
| } | |
| #[test] | |
| fn checked_exact_power_of_two_bounds() { | |
| // i32::MIN is exactly representable and must be accepted. | |
| assert_eq!((i32::MIN as f64).to_int_checked::<i32>(), Some(i32::MIN)); | |
| // 2^31 as f32 is exact and one past i32::MAX, so it is rejected... | |
| assert_eq!((2147483648.0_f32).to_int_checked::<i32>(), None); | |
| // ...while the largest f32 below 2^31 is accepted. | |
| assert_eq!((2147483520.0_f32).to_int_checked::<i32>(), Some(2147483520)); | |
| } | |
| #[test] | |
| fn strict_matches_checked() { | |
| assert_eq!(255.5_f64.to_int_strict::<u8>(), 255); | |
| assert_eq!((-128.0_f64).to_int_strict::<i8>(), -128); | |
| } | |
| #[test] | |
| #[should_panic] | |
| fn strict_panics_on_nan() { | |
| let _ = f64::NAN.to_int_strict::<u8>(); | |
| } | |
| #[test] | |
| #[should_panic] | |
| fn strict_panics_on_overflow() { | |
| let _ = 256.0_f64.to_int_strict::<u8>(); | |
| } | |
| #[cfg(target_has_reliable_f16)] | |
| #[test] | |
| fn f16_into_wide_int_accepts_all_finite() { | |
| // Every finite f16 fits in i128, so the bounds are +/-inf and accept all | |
| // finite values; only non-finite is rejected. | |
| assert_eq!(f16::MAX.to_int_checked::<i128>(), Some(f16::MAX as i128)); | |
| assert_eq!((-f16::MAX).to_int_checked::<i128>(), Some(-f16::MAX as i128)); | |
| assert_eq!(f16::INFINITY.to_int_checked::<u128>(), None); | |
| assert_eq!(f16::NAN.to_int_checked::<u128>(), None); | |
| assert_eq!(4.6_f16.to_int_saturating::<u8>(), 4); | |
| assert_eq!(1.5_f16.cast::<f32>(), 1.5_f32); | |
| } | |
| // Truncation-then-check must not depend on a libm `trunc`, which is unreliable | |
| // for f16/f128 on some targets. These exercise the fractional checked path. | |
| #[cfg(target_has_reliable_f16)] | |
| #[test] | |
| fn f16_checked_fractional() { | |
| assert_eq!(4.6_f16.to_int_checked::<u8>(), Some(4)); | |
| assert_eq!(255.5_f16.to_int_checked::<u8>(), Some(255)); | |
| assert_eq!(256.0_f16.to_int_checked::<u8>(), None); | |
| assert_eq!((-0.5_f16).to_int_checked::<u8>(), Some(0)); | |
| assert_eq!(4.6_f16.to_int_strict::<u8>(), 4); | |
| } | |
| #[cfg(target_has_reliable_f128)] | |
| #[test] | |
| fn f128_checked_fractional() { | |
| assert_eq!(4.6_f128.to_int_checked::<u8>(), Some(4)); | |
| assert_eq!(255.5_f128.to_int_checked::<u8>(), Some(255)); | |
| assert_eq!(256.0_f128.to_int_checked::<u8>(), None); | |
| assert_eq!((-0.5_f128).to_int_checked::<u8>(), Some(0)); | |
| assert_eq!(4.6_f128.to_int_strict::<u8>(), 4); | |
| } |