From 3cd450ec5d58e1cfebb7afe02bc2bb455dbb87a3 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 22 Aug 2020 12:24:35 -0700 Subject: [PATCH 1/4] Add `#![feature(const_float_bits_conv)]` for `f64::to_bits` and friends --- library/core/src/lib.rs | 1 + library/core/src/num/f32.rs | 24 ++++++++++++++++-------- library/core/src/num/f64.rs | 24 ++++++++++++++++-------- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 19cd05de2a758..7294adaccd3f6 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -73,6 +73,7 @@ #![feature(const_discriminant)] #![feature(const_checked_int_methods)] #![feature(const_euclidean_int_methods)] +#![feature(const_float_bits_conv)] #![feature(const_overflowing_int_methods)] #![feature(const_int_unchecked_arith)] #![feature(const_int_pow)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 9fb7296ce31cc..2d2d99ef6eeb7 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -652,8 +652,9 @@ impl f32 { /// /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn to_bits(self) -> u32 { + pub const fn to_bits(self) -> u32 { // SAFETY: `u32` is a plain old datatype so we can always transmute to it unsafe { mem::transmute(self) } } @@ -695,8 +696,9 @@ impl f32 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn from_bits(v: u32) -> Self { + pub const fn from_bits(v: u32) -> Self { // SAFETY: `u32` is a plain old datatype so we can always transmute from it // It turns out the safety issues with sNaN were overblown! Hooray! unsafe { mem::transmute(v) } @@ -712,8 +714,9 @@ impl f32 { /// assert_eq!(bytes, [0x41, 0x48, 0x00, 0x00]); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn to_be_bytes(self) -> [u8; 4] { + pub const fn to_be_bytes(self) -> [u8; 4] { self.to_bits().to_be_bytes() } @@ -727,8 +730,9 @@ impl f32 { /// assert_eq!(bytes, [0x00, 0x00, 0x48, 0x41]); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn to_le_bytes(self) -> [u8; 4] { + pub const fn to_le_bytes(self) -> [u8; 4] { self.to_bits().to_le_bytes() } @@ -755,8 +759,9 @@ impl f32 { /// ); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn to_ne_bytes(self) -> [u8; 4] { + pub const fn to_ne_bytes(self) -> [u8; 4] { self.to_bits().to_ne_bytes() } @@ -769,8 +774,9 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn from_be_bytes(bytes: [u8; 4]) -> Self { + pub const fn from_be_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_be_bytes(bytes)) } @@ -783,8 +789,9 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn from_le_bytes(bytes: [u8; 4]) -> Self { + pub const fn from_le_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_le_bytes(bytes)) } @@ -808,8 +815,9 @@ impl f32 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn from_ne_bytes(bytes: [u8; 4]) -> Self { + pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self { Self::from_bits(u32::from_ne_bytes(bytes)) } diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index a5b1eb3f1fd67..82ea82fe2be2b 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -666,8 +666,9 @@ impl f64 { /// /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn to_bits(self) -> u64 { + pub const fn to_bits(self) -> u64 { // SAFETY: `u64` is a plain old datatype so we can always transmute to it unsafe { mem::transmute(self) } } @@ -709,8 +710,9 @@ impl f64 { /// assert_eq!(v, 12.5); /// ``` #[stable(feature = "float_bits_conv", since = "1.20.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn from_bits(v: u64) -> Self { + pub const fn from_bits(v: u64) -> Self { // SAFETY: `u64` is a plain old datatype so we can always transmute from it // It turns out the safety issues with sNaN were overblown! Hooray! unsafe { mem::transmute(v) } @@ -726,8 +728,9 @@ impl f64 { /// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn to_be_bytes(self) -> [u8; 8] { + pub const fn to_be_bytes(self) -> [u8; 8] { self.to_bits().to_be_bytes() } @@ -741,8 +744,9 @@ impl f64 { /// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn to_le_bytes(self) -> [u8; 8] { + pub const fn to_le_bytes(self) -> [u8; 8] { self.to_bits().to_le_bytes() } @@ -769,8 +773,9 @@ impl f64 { /// ); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn to_ne_bytes(self) -> [u8; 8] { + pub const fn to_ne_bytes(self) -> [u8; 8] { self.to_bits().to_ne_bytes() } @@ -783,8 +788,9 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn from_be_bytes(bytes: [u8; 8]) -> Self { + pub const fn from_be_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_be_bytes(bytes)) } @@ -797,8 +803,9 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn from_le_bytes(bytes: [u8; 8]) -> Self { + pub const fn from_le_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_le_bytes(bytes)) } @@ -822,8 +829,9 @@ impl f64 { /// assert_eq!(value, 12.5); /// ``` #[stable(feature = "float_to_from_bytes", since = "1.40.0")] + #[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")] #[inline] - pub fn from_ne_bytes(bytes: [u8; 8]) -> Self { + pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self { Self::from_bits(u64::from_ne_bytes(bytes)) } From 23e08e223bb527eaef418a9fbc842471d555b3be Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 22 Aug 2020 12:25:39 -0700 Subject: [PATCH 2/4] Add `#![feature(const_float_classify)]` for `f64::classify` and friends --- library/core/src/lib.rs | 1 + library/core/src/num/f32.rs | 26 +++++++++++++++++--------- library/core/src/num/f64.rs | 26 +++++++++++++++++--------- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 7294adaccd3f6..99f8cc66638f3 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -73,6 +73,7 @@ #![feature(const_discriminant)] #![feature(const_checked_int_methods)] #![feature(const_euclidean_int_methods)] +#![feature(const_float_classify)] #![feature(const_float_bits_conv)] #![feature(const_overflowing_int_methods)] #![feature(const_int_unchecked_arith)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 2d2d99ef6eeb7..043f0b14f249f 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -381,8 +381,9 @@ impl f32 { /// assert!(!f.is_nan()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_nan(self) -> bool { + pub const fn is_nan(self) -> bool { self != self } @@ -390,7 +391,8 @@ impl f32 { // concerns about portability, so this implementation is for // private use internally. #[inline] - fn abs_private(self) -> f32 { + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + const fn abs_private(self) -> f32 { f32::from_bits(self.to_bits() & 0x7fff_ffff) } @@ -410,8 +412,9 @@ impl f32 { /// assert!(neg_inf.is_infinite()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_infinite(self) -> bool { + pub const fn is_infinite(self) -> bool { self.abs_private() == Self::INFINITY } @@ -430,8 +433,9 @@ impl f32 { /// assert!(!neg_inf.is_finite()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_finite(self) -> bool { + pub const fn is_finite(self) -> bool { // There's no need to handle NaN separately: if self is NaN, // the comparison is not true, exactly as desired. self.abs_private() < Self::INFINITY @@ -457,9 +461,10 @@ impl f32 { /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_normal(self) -> bool { - self.classify() == FpCategory::Normal + pub const fn is_normal(self) -> bool { + matches!(self.classify(), FpCategory::Normal) } /// Returns the floating point category of the number. If only one property @@ -476,7 +481,8 @@ impl f32 { /// assert_eq!(inf.classify(), FpCategory::Infinite); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn classify(self) -> FpCategory { + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + pub const fn classify(self) -> FpCategory { const EXP_MASK: u32 = 0x7f800000; const MAN_MASK: u32 = 0x007fffff; @@ -501,8 +507,9 @@ impl f32 { /// assert!(!g.is_sign_positive()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_sign_positive(self) -> bool { + pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() } @@ -517,8 +524,9 @@ impl f32 { /// assert!(g.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_sign_negative(self) -> bool { + pub const fn is_sign_negative(self) -> bool { // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus // applies to zeros and NaNs as well. self.to_bits() & 0x8000_0000 != 0 diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 82ea82fe2be2b..24624b88d59f6 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -380,8 +380,9 @@ impl f64 { /// assert!(!f.is_nan()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_nan(self) -> bool { + pub const fn is_nan(self) -> bool { self != self } @@ -389,7 +390,8 @@ impl f64 { // concerns about portability, so this implementation is for // private use internally. #[inline] - fn abs_private(self) -> f64 { + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + const fn abs_private(self) -> f64 { f64::from_bits(self.to_bits() & 0x7fff_ffff_ffff_ffff) } @@ -409,8 +411,9 @@ impl f64 { /// assert!(neg_inf.is_infinite()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_infinite(self) -> bool { + pub const fn is_infinite(self) -> bool { self.abs_private() == Self::INFINITY } @@ -429,8 +432,9 @@ impl f64 { /// assert!(!neg_inf.is_finite()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_finite(self) -> bool { + pub const fn is_finite(self) -> bool { // There's no need to handle NaN separately: if self is NaN, // the comparison is not true, exactly as desired. self.abs_private() < Self::INFINITY @@ -456,9 +460,10 @@ impl f64 { /// ``` /// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_normal(self) -> bool { - self.classify() == FpCategory::Normal + pub const fn is_normal(self) -> bool { + matches!(self.classify(), FpCategory::Normal) } /// Returns the floating point category of the number. If only one property @@ -475,7 +480,8 @@ impl f64 { /// assert_eq!(inf.classify(), FpCategory::Infinite); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn classify(self) -> FpCategory { + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] + pub const fn classify(self) -> FpCategory { const EXP_MASK: u64 = 0x7ff0000000000000; const MAN_MASK: u64 = 0x000fffffffffffff; @@ -500,8 +506,9 @@ impl f64 { /// assert!(!g.is_sign_positive()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_sign_positive(self) -> bool { + pub const fn is_sign_positive(self) -> bool { !self.is_sign_negative() } @@ -524,8 +531,9 @@ impl f64 { /// assert!(g.is_sign_negative()); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")] #[inline] - pub fn is_sign_negative(self) -> bool { + pub const fn is_sign_negative(self) -> bool { self.to_bits() & 0x8000_0000_0000_0000 != 0 } From b65daa7688e919d8cc991d9004d23f4235ee0482 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 21 May 2020 18:51:47 -0700 Subject: [PATCH 3/4] Test new floating point bit casts --- src/test/ui/consts/const-float-bits-conv.rs | 93 +++++++++++++++++++++ src/test/ui/consts/const-float-classify.rs | 77 +++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 src/test/ui/consts/const-float-bits-conv.rs create mode 100644 src/test/ui/consts/const-float-classify.rs diff --git a/src/test/ui/consts/const-float-bits-conv.rs b/src/test/ui/consts/const-float-bits-conv.rs new file mode 100644 index 0000000000000..ca5df9b0e97b5 --- /dev/null +++ b/src/test/ui/consts/const-float-bits-conv.rs @@ -0,0 +1,93 @@ +// -Zmir-opt-level=0 +// run-pass + +#![feature(const_panic)] +#![feature(const_float_bits_conv)] +#![feature(const_float_classify)] + +// Don't promote +const fn nop(x: T) -> T { x } + +macro_rules! const_assert { + ($a:expr) => { + { + const _: () = assert!($a); + assert!(nop($a)); + } + }; + ($a:expr, $b:expr) => { + { + const _: () = assert!($a == $b); + assert_eq!(nop($a), nop($b)); + } + }; +} + +fn f32() { + const_assert!((1f32).to_bits(), 0x3f800000); + const_assert!(u32::from_be_bytes(1f32.to_be_bytes()), 0x3f800000); + const_assert!((12.5f32).to_bits(), 0x41480000); + const_assert!(u32::from_le_bytes(12.5f32.to_le_bytes()), 0x41480000); + const_assert!((1337f32).to_bits(), 0x44a72000); + const_assert!(u32::from_ne_bytes(1337f32.to_ne_bytes()), 0x44a72000); + const_assert!((-14.25f32).to_bits(), 0xc1640000); + const_assert!(f32::from_bits(0x3f800000), 1.0); + const_assert!(f32::from_be_bytes(0x3f800000u32.to_be_bytes()), 1.0); + const_assert!(f32::from_bits(0x41480000), 12.5); + const_assert!(f32::from_le_bytes(0x41480000u32.to_le_bytes()), 12.5); + const_assert!(f32::from_bits(0x44a72000), 1337.0); + const_assert!(f32::from_ne_bytes(0x44a72000u32.to_ne_bytes()), 1337.0); + const_assert!(f32::from_bits(0xc1640000), -14.25); + + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA; + const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555; + + const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); + const_assert!(f32::from_bits(MASKED_NAN1).is_nan()); + + // LLVM does not guarantee that loads and stores of NaNs preserve their exact bit pattern. + // In practice, this seems to only cause a problem on x86, since the most widely used calling + // convention mandates that floating point values are returned on the x87 FPU stack. See #73328. + if !cfg!(target_arch = "x86") { + const_assert!(f32::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); + const_assert!(f32::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); + } +} + +fn f64() { + const_assert!((1f64).to_bits(), 0x3ff0000000000000); + const_assert!(u64::from_be_bytes(1f64.to_be_bytes()), 0x3ff0000000000000); + const_assert!((12.5f64).to_bits(), 0x4029000000000000); + const_assert!(u64::from_le_bytes(12.5f64.to_le_bytes()), 0x4029000000000000); + const_assert!((1337f64).to_bits(), 0x4094e40000000000); + const_assert!(u64::from_ne_bytes(1337f64.to_ne_bytes()), 0x4094e40000000000); + const_assert!((-14.25f64).to_bits(), 0xc02c800000000000); + const_assert!(f64::from_bits(0x3ff0000000000000), 1.0); + const_assert!(f64::from_be_bytes(0x3ff0000000000000u64.to_be_bytes()), 1.0); + const_assert!(f64::from_bits(0x4029000000000000), 12.5); + const_assert!(f64::from_le_bytes(0x4029000000000000u64.to_le_bytes()), 12.5); + const_assert!(f64::from_bits(0x4094e40000000000), 1337.0); + const_assert!(f64::from_ne_bytes(0x4094e40000000000u64.to_ne_bytes()), 1337.0); + const_assert!(f64::from_bits(0xc02c800000000000), -14.25); + + // Check that NaNs roundtrip their bits regardless of signalingness + // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits + const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA; + const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555; + + const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); + const_assert!(f64::from_bits(MASKED_NAN1).is_nan()); + + // See comment above. + if !cfg!(target_arch = "x86") { + const_assert!(f64::from_bits(MASKED_NAN1).to_bits(), MASKED_NAN1); + const_assert!(f64::from_bits(MASKED_NAN2).to_bits(), MASKED_NAN2); + } +} + +fn main() { + f32(); + f64(); +} diff --git a/src/test/ui/consts/const-float-classify.rs b/src/test/ui/consts/const-float-classify.rs new file mode 100644 index 0000000000000..539595db1137e --- /dev/null +++ b/src/test/ui/consts/const-float-classify.rs @@ -0,0 +1,77 @@ +// -Zmir-opt-level=0 +// run-pass + +#![feature(const_panic)] +#![feature(const_float_bits_conv)] +#![feature(const_float_classify)] +#![feature(const_trait_impl)] +#![allow(incomplete_features)] + +// Don't promote +const fn nop(x: T) -> T { x } + +macro_rules! const_assert { + ($a:expr, $b:expr) => { + { + const _: () = assert!($a == $b); + assert_eq!(nop($a), nop($b)); + } + }; +} + +macro_rules! suite { + ( $( $tt:tt )* ) => { + fn f32() { + suite_inner!(f32 $($tt)*); + } + + fn f64() { + suite_inner!(f64 $($tt)*); + } + } + +} + +macro_rules! suite_inner { + ( + $ty:ident [$( $fn:ident ),*] + $val:expr => [$($out:ident),*] + + $( $tail:tt )* + ) => { + $( const_assert!($ty::$fn($val), $out); )* + suite_inner!($ty [$($fn),*] $($tail)*) + }; + + ( $ty:ident [$( $fn:ident ),*]) => {}; +} + +#[derive(Debug)] +struct NonDet; + +impl const PartialEq for bool { + fn eq(&self, _: &NonDet) -> bool { + true + } +} + +// The result of the `is_sign` methods are not checked for correctness, since LLVM does not +// guarantee anything about the signedness of NaNs. See +// https://github.com/rust-lang/rust/issues/55131. + +suite! { + [is_nan, is_infinite, is_finite, is_normal, is_sign_positive, is_sign_negative] + -0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] + 0.0 / 0.0 => [ true, false, false, false, NonDet, NonDet] + 1.0 => [ false, false, true, true, true, false] + -1.0 => [ false, false, true, true, false, true] + 0.0 => [ false, false, true, false, true, false] + -0.0 => [ false, false, true, false, false, true] + 1.0 / 0.0 => [ false, true, false, false, true, false] + -1.0 / 0.0 => [ false, true, false, false, false, true] +} + +fn main() { + f32(); + f64(); +} From 130766c466de6cfdaff12c3444451c7d8847ff76 Mon Sep 17 00:00:00 2001 From: ecstatic-morse Date: Sun, 23 Aug 2020 10:45:26 -0700 Subject: [PATCH 4/4] Fix `compile-flags` directive Co-authored-by: Ralf Jung --- src/test/ui/consts/const-float-bits-conv.rs | 2 +- src/test/ui/consts/const-float-classify.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/const-float-bits-conv.rs b/src/test/ui/consts/const-float-bits-conv.rs index ca5df9b0e97b5..2dfc6de859783 100644 --- a/src/test/ui/consts/const-float-bits-conv.rs +++ b/src/test/ui/consts/const-float-bits-conv.rs @@ -1,4 +1,4 @@ -// -Zmir-opt-level=0 +// compile-flags: -Zmir-opt-level=0 // run-pass #![feature(const_panic)] diff --git a/src/test/ui/consts/const-float-classify.rs b/src/test/ui/consts/const-float-classify.rs index 539595db1137e..36fec9976be37 100644 --- a/src/test/ui/consts/const-float-classify.rs +++ b/src/test/ui/consts/const-float-classify.rs @@ -1,4 +1,4 @@ -// -Zmir-opt-level=0 +// compile-flags: -Zmir-opt-level=0 // run-pass #![feature(const_panic)]