about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTrevor Gross <tmgross@umich.edu>2024-06-16 03:09:58 -0500
committerTrevor Gross <tmgross@umich.edu>2024-06-24 00:42:21 -0500
commitfce07a82c632ec28ac02361b786e64bf56ec1739 (patch)
treeb83091f1165ea4e3b2e832e3d321014dd98c1c61
parentd49994b060684af423339b55769439b2f444a7b9 (diff)
downloadrust-fce07a82c632ec28ac02361b786e64bf56ec1739.tar.gz
rust-fce07a82c632ec28ac02361b786e64bf56ec1739.zip
Extract repeated constants from `f32` and `f64` source
This will make it easier to keep `f16` and `f128` consistent as their
implementations get added.
-rw-r--r--library/core/src/num/f32.rs45
-rw-r--r--library/core/src/num/f64.rs51
-rw-r--r--library/std/src/f32/tests.rs82
-rw-r--r--library/std/src/f64/tests.rs83
4 files changed, 160 insertions, 101 deletions
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 9d34d3da9e9..271965c2884 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -490,6 +490,21 @@ impl f32 {
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
 
+    /// Sign bit
+    const SIGN_MASK: u32 = 0x8000_0000;
+
+    /// Exponent mask
+    const EXP_MASK: u32 = 0x7f80_0000;
+
+    /// Mantissa mask
+    const MAN_MASK: u32 = 0x007f_ffff;
+
+    /// Minimum representable positive value (min subnormal)
+    const TINY_BITS: u32 = 0x1;
+
+    /// Minimum representable negative value (min negative subnormal)
+    const NEG_TINY_BITS: u32 = Self::TINY_BITS | Self::SIGN_MASK;
+
     /// Returns `true` if this value is NaN.
     ///
     /// ```
@@ -515,7 +530,7 @@ impl f32 {
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub(crate) const fn abs_private(self) -> f32 {
         // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
-        unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & 0x7fff_ffff) }
+        unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & !Self::SIGN_MASK) }
     }
 
     /// Returns `true` if this value is positive infinity or negative infinity, and
@@ -682,12 +697,9 @@ impl f32 {
     // runtime-deviating logic which may or may not be acceptable.
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     const unsafe fn partial_classify(self) -> FpCategory {
-        const EXP_MASK: u32 = 0x7f800000;
-        const MAN_MASK: u32 = 0x007fffff;
-
         // SAFETY: The caller is not asking questions for which this will tell lies.
         let b = unsafe { mem::transmute::<f32, u32>(self) };
-        match (b & MAN_MASK, b & EXP_MASK) {
+        match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
             (0, 0) => FpCategory::Zero,
             (_, 0) => FpCategory::Subnormal,
             _ => FpCategory::Normal,
@@ -699,12 +711,9 @@ impl f32 {
     // plus a transmute. We do not live in a just world, but we can make it more so.
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     const fn classify_bits(b: u32) -> FpCategory {
-        const EXP_MASK: u32 = 0x7f800000;
-        const MAN_MASK: u32 = 0x007fffff;
-
-        match (b & MAN_MASK, b & EXP_MASK) {
-            (0, EXP_MASK) => FpCategory::Infinite,
-            (_, EXP_MASK) => FpCategory::Nan,
+        match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
+            (0, Self::EXP_MASK) => FpCategory::Infinite,
+            (_, Self::EXP_MASK) => FpCategory::Nan,
             (0, 0) => FpCategory::Zero,
             (_, 0) => FpCategory::Subnormal,
             _ => FpCategory::Normal,
@@ -789,17 +798,14 @@ impl f32 {
     pub const fn next_up(self) -> Self {
         // We must use strictly integer arithmetic to prevent denormals from
         // flushing to zero after an arithmetic operation on some platforms.
-        const TINY_BITS: u32 = 0x1; // Smallest positive f32.
-        const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff;
-
         let bits = self.to_bits();
         if self.is_nan() || bits == Self::INFINITY.to_bits() {
             return self;
         }
 
-        let abs = bits & CLEAR_SIGN_MASK;
+        let abs = bits & !Self::SIGN_MASK;
         let next_bits = if abs == 0 {
-            TINY_BITS
+            Self::TINY_BITS
         } else if bits == abs {
             bits + 1
         } else {
@@ -839,17 +845,14 @@ impl f32 {
     pub const fn next_down(self) -> Self {
         // We must use strictly integer arithmetic to prevent denormals from
         // flushing to zero after an arithmetic operation on some platforms.
-        const NEG_TINY_BITS: u32 = 0x8000_0001; // Smallest (in magnitude) negative f32.
-        const CLEAR_SIGN_MASK: u32 = 0x7fff_ffff;
-
         let bits = self.to_bits();
         if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() {
             return self;
         }
 
-        let abs = bits & CLEAR_SIGN_MASK;
+        let abs = bits & !Self::SIGN_MASK;
         let next_bits = if abs == 0 {
-            NEG_TINY_BITS
+            Self::NEG_TINY_BITS
         } else if bits == abs {
             bits - 1
         } else {
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 95f021b2541..bccd39f6059 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -489,6 +489,21 @@ impl f64 {
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
     pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
 
+    /// Sign bit
+    const SIGN_MASK: u64 = 0x8000_0000_0000_0000;
+
+    /// Exponent mask
+    const EXP_MASK: u64 = 0x7ff0_0000_0000_0000;
+
+    /// Mantissa mask
+    const MAN_MASK: u64 = 0x000f_ffff_ffff_ffff;
+
+    /// Minimum representable positive value (min subnormal)
+    const TINY_BITS: u64 = 0x1;
+
+    /// Minimum representable negative value (min negative subnormal)
+    const NEG_TINY_BITS: u64 = Self::TINY_BITS | Self::SIGN_MASK;
+
     /// Returns `true` if this value is NaN.
     ///
     /// ```
@@ -514,9 +529,7 @@ impl f64 {
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     pub(crate) const fn abs_private(self) -> f64 {
         // SAFETY: This transmutation is fine. Probably. For the reasons std is using it.
-        unsafe {
-            mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & 0x7fff_ffff_ffff_ffff)
-        }
+        unsafe { mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & !Self::SIGN_MASK) }
     }
 
     /// Returns `true` if this value is positive infinity or negative infinity, and
@@ -673,13 +686,10 @@ impl f64 {
     // and some normal floating point numbers truncated from an x87 FPU.
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     const unsafe fn partial_classify(self) -> FpCategory {
-        const EXP_MASK: u64 = 0x7ff0000000000000;
-        const MAN_MASK: u64 = 0x000fffffffffffff;
-
         // SAFETY: The caller is not asking questions for which this will tell lies.
         let b = unsafe { mem::transmute::<f64, u64>(self) };
-        match (b & MAN_MASK, b & EXP_MASK) {
-            (0, EXP_MASK) => FpCategory::Infinite,
+        match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
+            (0, Self::EXP_MASK) => FpCategory::Infinite,
             (0, 0) => FpCategory::Zero,
             (_, 0) => FpCategory::Subnormal,
             _ => FpCategory::Normal,
@@ -691,12 +701,9 @@ impl f64 {
     // plus a transmute. We do not live in a just world, but we can make it more so.
     #[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
     const fn classify_bits(b: u64) -> FpCategory {
-        const EXP_MASK: u64 = 0x7ff0000000000000;
-        const MAN_MASK: u64 = 0x000fffffffffffff;
-
-        match (b & MAN_MASK, b & EXP_MASK) {
-            (0, EXP_MASK) => FpCategory::Infinite,
-            (_, EXP_MASK) => FpCategory::Nan,
+        match (b & Self::MAN_MASK, b & Self::EXP_MASK) {
+            (0, Self::EXP_MASK) => FpCategory::Infinite,
+            (_, Self::EXP_MASK) => FpCategory::Nan,
             (0, 0) => FpCategory::Zero,
             (_, 0) => FpCategory::Subnormal,
             _ => FpCategory::Normal,
@@ -756,7 +763,7 @@ impl f64 {
         // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
         // applies to zeros and NaNs as well.
         // SAFETY: This is just transmuting to get the sign bit, it's fine.
-        unsafe { mem::transmute::<f64, u64>(self) & 0x8000_0000_0000_0000 != 0 }
+        unsafe { mem::transmute::<f64, u64>(self) & Self::SIGN_MASK != 0 }
     }
 
     #[must_use]
@@ -799,17 +806,14 @@ impl f64 {
     pub const fn next_up(self) -> Self {
         // We must use strictly integer arithmetic to prevent denormals from
         // flushing to zero after an arithmetic operation on some platforms.
-        const TINY_BITS: u64 = 0x1; // Smallest positive f64.
-        const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff;
-
         let bits = self.to_bits();
         if self.is_nan() || bits == Self::INFINITY.to_bits() {
             return self;
         }
 
-        let abs = bits & CLEAR_SIGN_MASK;
+        let abs = bits & !Self::SIGN_MASK;
         let next_bits = if abs == 0 {
-            TINY_BITS
+            Self::TINY_BITS
         } else if bits == abs {
             bits + 1
         } else {
@@ -849,17 +853,14 @@ impl f64 {
     pub const fn next_down(self) -> Self {
         // We must use strictly integer arithmetic to prevent denormals from
         // flushing to zero after an arithmetic operation on some platforms.
-        const NEG_TINY_BITS: u64 = 0x8000_0000_0000_0001; // Smallest (in magnitude) negative f64.
-        const CLEAR_SIGN_MASK: u64 = 0x7fff_ffff_ffff_ffff;
-
         let bits = self.to_bits();
         if self.is_nan() || bits == Self::NEG_INFINITY.to_bits() {
             return self;
         }
 
-        let abs = bits & CLEAR_SIGN_MASK;
+        let abs = bits & !Self::SIGN_MASK;
         let next_bits = if abs == 0 {
-            NEG_TINY_BITS
+            Self::NEG_TINY_BITS
         } else if bits == abs {
             bits - 1
         } else {
diff --git a/library/std/src/f32/tests.rs b/library/std/src/f32/tests.rs
index 9ca4e8f2f45..63e65698374 100644
--- a/library/std/src/f32/tests.rs
+++ b/library/std/src/f32/tests.rs
@@ -2,6 +2,45 @@ use crate::f32::consts;
 use crate::num::FpCategory as Fp;
 use crate::num::*;
 
+/// Smallest number
+#[allow(dead_code)] // unused on x86
+const TINY_BITS: u32 = 0x1;
+
+/// Next smallest number
+#[allow(dead_code)] // unused on x86
+const TINY_UP_BITS: u32 = 0x2;
+
+/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
+#[allow(dead_code)] // unused on x86
+const MAX_DOWN_BITS: u32 = 0x7f7f_fffe;
+
+/// Zeroed exponent, full significant
+#[allow(dead_code)] // unused on x86
+const LARGEST_SUBNORMAL_BITS: u32 = 0x007f_ffff;
+
+/// Exponent = 0b1, zeroed significand
+#[allow(dead_code)] // unused on x86
+const SMALLEST_NORMAL_BITS: u32 = 0x0080_0000;
+
+/// First pattern over the mantissa
+#[allow(dead_code)] // unused on x86
+const NAN_MASK1: u32 = 0x002a_aaaa;
+
+/// Second pattern over the mantissa
+#[allow(dead_code)] // unused on x86
+const NAN_MASK2: u32 = 0x0055_5555;
+
+#[allow(unused_macros)]
+macro_rules! assert_f32_biteq {
+    ($left : expr, $right : expr) => {
+        let l: &f32 = &$left;
+        let r: &f32 = &$right;
+        let lb = l.to_bits();
+        let rb = r.to_bits();
+        assert_eq!(lb, rb, "float {l} ({lb:#010x}) is not bitequal to {r} ({rb:#010x})");
+    };
+}
+
 #[test]
 fn test_num_f32() {
     test_num(10f32, 2f32);
@@ -315,27 +354,16 @@ fn test_is_sign_negative() {
     assert!((-f32::NAN).is_sign_negative());
 }
 
-#[allow(unused_macros)]
-macro_rules! assert_f32_biteq {
-    ($left : expr, $right : expr) => {
-        let l: &f32 = &$left;
-        let r: &f32 = &$right;
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {} ({:#x}) is not equal to {} ({:#x})", *l, lb, *r, rb);
-    };
-}
-
 // Ignore test on x87 floating point, these platforms do not guarantee NaN
 // payloads are preserved and flush denormals to zero, failing the tests.
 #[cfg(not(target_arch = "x86"))]
 #[test]
 fn test_next_up() {
-    let tiny = f32::from_bits(1);
-    let tiny_up = f32::from_bits(2);
-    let max_down = f32::from_bits(0x7f7f_fffe);
-    let largest_subnormal = f32::from_bits(0x007f_ffff);
-    let smallest_normal = f32::from_bits(0x0080_0000);
+    let tiny = f32::from_bits(TINY_BITS);
+    let tiny_up = f32::from_bits(TINY_UP_BITS);
+    let max_down = f32::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
     assert_f32_biteq!(f32::NEG_INFINITY.next_up(), f32::MIN);
     assert_f32_biteq!(f32::MIN.next_up(), -max_down);
     assert_f32_biteq!((-1.0 - f32::EPSILON).next_up(), -1.0);
@@ -352,8 +380,8 @@ fn test_next_up() {
 
     // Check that NaNs roundtrip.
     let nan0 = f32::NAN;
-    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa);
-    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555);
+    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
     assert_f32_biteq!(nan0.next_up(), nan0);
     assert_f32_biteq!(nan1.next_up(), nan1);
     assert_f32_biteq!(nan2.next_up(), nan2);
@@ -364,11 +392,11 @@ fn test_next_up() {
 #[cfg(not(target_arch = "x86"))]
 #[test]
 fn test_next_down() {
-    let tiny = f32::from_bits(1);
-    let tiny_up = f32::from_bits(2);
-    let max_down = f32::from_bits(0x7f7f_fffe);
-    let largest_subnormal = f32::from_bits(0x007f_ffff);
-    let smallest_normal = f32::from_bits(0x0080_0000);
+    let tiny = f32::from_bits(TINY_BITS);
+    let tiny_up = f32::from_bits(TINY_UP_BITS);
+    let max_down = f32::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f32::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f32::from_bits(SMALLEST_NORMAL_BITS);
     assert_f32_biteq!(f32::NEG_INFINITY.next_down(), f32::NEG_INFINITY);
     assert_f32_biteq!(f32::MIN.next_down(), f32::NEG_INFINITY);
     assert_f32_biteq!((-max_down).next_down(), f32::MIN);
@@ -386,8 +414,8 @@ fn test_next_down() {
 
     // Check that NaNs roundtrip.
     let nan0 = f32::NAN;
-    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ 0x002a_aaaa);
-    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ 0x0055_5555);
+    let nan1 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f32::from_bits(f32::NAN.to_bits() ^ NAN_MASK2);
     assert_f32_biteq!(nan0.next_down(), nan0);
     assert_f32_biteq!(nan1.next_down(), nan1);
     assert_f32_biteq!(nan2.next_down(), nan2);
@@ -734,8 +762,8 @@ fn test_float_bits_conv() {
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
     // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
-    let masked_nan1 = f32::NAN.to_bits() ^ 0x002A_AAAA;
-    let masked_nan2 = f32::NAN.to_bits() ^ 0x0055_5555;
+    let masked_nan1 = f32::NAN.to_bits() ^ NAN_MASK1;
+    let masked_nan2 = f32::NAN.to_bits() ^ NAN_MASK2;
     assert!(f32::from_bits(masked_nan1).is_nan());
     assert!(f32::from_bits(masked_nan2).is_nan());
 
diff --git a/library/std/src/f64/tests.rs b/library/std/src/f64/tests.rs
index f88d01593b5..d9e17fd601d 100644
--- a/library/std/src/f64/tests.rs
+++ b/library/std/src/f64/tests.rs
@@ -2,6 +2,45 @@ use crate::f64::consts;
 use crate::num::FpCategory as Fp;
 use crate::num::*;
 
+/// Smallest number
+#[allow(dead_code)] // unused on x86
+const TINY_BITS: u64 = 0x1;
+
+/// Next smallest number
+#[allow(dead_code)] // unused on x86
+const TINY_UP_BITS: u64 = 0x2;
+
+/// Exponent = 0b11...10, Sifnificand 0b1111..10. Min val > 0
+#[allow(dead_code)] // unused on x86
+const MAX_DOWN_BITS: u64 = 0x7fef_ffff_ffff_fffe;
+
+/// Zeroed exponent, full significant
+#[allow(dead_code)] // unused on x86
+const LARGEST_SUBNORMAL_BITS: u64 = 0x000f_ffff_ffff_ffff;
+
+/// Exponent = 0b1, zeroed significand
+#[allow(dead_code)] // unused on x86
+const SMALLEST_NORMAL_BITS: u64 = 0x0010_0000_0000_0000;
+
+/// First pattern over the mantissa
+#[allow(dead_code)] // unused on x86
+const NAN_MASK1: u64 = 0x000a_aaaa_aaaa_aaaa;
+
+/// Second pattern over the mantissa
+#[allow(dead_code)] // unused on x86
+const NAN_MASK2: u64 = 0x0005_5555_5555_5555;
+
+#[allow(unused_macros)]
+macro_rules! assert_f64_biteq {
+    ($left : expr, $right : expr) => {
+        let l: &f64 = &$left;
+        let r: &f64 = &$right;
+        let lb = l.to_bits();
+        let rb = r.to_bits();
+        assert_eq!(lb, rb, "float {l} ({lb:#018x}) is not bitequal to {r} ({rb:#018x})");
+    };
+}
+
 #[test]
 fn test_num_f64() {
     test_num(10f64, 2f64);
@@ -305,27 +344,16 @@ fn test_is_sign_negative() {
     assert!((-f64::NAN).is_sign_negative());
 }
 
-#[allow(unused_macros)]
-macro_rules! assert_f64_biteq {
-    ($left : expr, $right : expr) => {
-        let l: &f64 = &$left;
-        let r: &f64 = &$right;
-        let lb = l.to_bits();
-        let rb = r.to_bits();
-        assert_eq!(lb, rb, "float {} ({:#x}) is not equal to {} ({:#x})", *l, lb, *r, rb);
-    };
-}
-
 // Ignore test on x87 floating point, these platforms do not guarantee NaN
 // payloads are preserved and flush denormals to zero, failing the tests.
 #[cfg(not(target_arch = "x86"))]
 #[test]
 fn test_next_up() {
-    let tiny = f64::from_bits(1);
-    let tiny_up = f64::from_bits(2);
-    let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe);
-    let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff);
-    let smallest_normal = f64::from_bits(0x0010_0000_0000_0000);
+    let tiny = f64::from_bits(TINY_BITS);
+    let tiny_up = f64::from_bits(TINY_UP_BITS);
+    let max_down = f64::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
     assert_f64_biteq!(f64::NEG_INFINITY.next_up(), f64::MIN);
     assert_f64_biteq!(f64::MIN.next_up(), -max_down);
     assert_f64_biteq!((-1.0 - f64::EPSILON).next_up(), -1.0);
@@ -341,8 +369,8 @@ fn test_next_up() {
     assert_f64_biteq!(f64::INFINITY.next_up(), f64::INFINITY);
 
     let nan0 = f64::NAN;
-    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa);
-    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555);
+    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
     assert_f64_biteq!(nan0.next_up(), nan0);
     assert_f64_biteq!(nan1.next_up(), nan1);
     assert_f64_biteq!(nan2.next_up(), nan2);
@@ -353,11 +381,11 @@ fn test_next_up() {
 #[cfg(not(target_arch = "x86"))]
 #[test]
 fn test_next_down() {
-    let tiny = f64::from_bits(1);
-    let tiny_up = f64::from_bits(2);
-    let max_down = f64::from_bits(0x7fef_ffff_ffff_fffe);
-    let largest_subnormal = f64::from_bits(0x000f_ffff_ffff_ffff);
-    let smallest_normal = f64::from_bits(0x0010_0000_0000_0000);
+    let tiny = f64::from_bits(TINY_BITS);
+    let tiny_up = f64::from_bits(TINY_UP_BITS);
+    let max_down = f64::from_bits(MAX_DOWN_BITS);
+    let largest_subnormal = f64::from_bits(LARGEST_SUBNORMAL_BITS);
+    let smallest_normal = f64::from_bits(SMALLEST_NORMAL_BITS);
     assert_f64_biteq!(f64::NEG_INFINITY.next_down(), f64::NEG_INFINITY);
     assert_f64_biteq!(f64::MIN.next_down(), f64::NEG_INFINITY);
     assert_f64_biteq!((-max_down).next_down(), f64::MIN);
@@ -374,8 +402,8 @@ fn test_next_down() {
     assert_f64_biteq!(f64::INFINITY.next_down(), f64::MAX);
 
     let nan0 = f64::NAN;
-    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ 0x000a_aaaa_aaaa_aaaa);
-    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ 0x0005_5555_5555_5555);
+    let nan1 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK1);
+    let nan2 = f64::from_bits(f64::NAN.to_bits() ^ NAN_MASK2);
     assert_f64_biteq!(nan0.next_down(), nan0);
     assert_f64_biteq!(nan1.next_down(), nan1);
     assert_f64_biteq!(nan2.next_down(), nan2);
@@ -715,9 +743,8 @@ fn test_float_bits_conv() {
     assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
 
     // Check that NaNs roundtrip their bits regardless of signaling-ness
-    // 0xA is 0b1010; 0x5 is 0b0101 -- so these two together clobbers all the mantissa bits
-    let masked_nan1 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
-    let masked_nan2 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
+    let masked_nan1 = f64::NAN.to_bits() ^ NAN_MASK1;
+    let masked_nan2 = f64::NAN.to_bits() ^ NAN_MASK2;
     assert!(f64::from_bits(masked_nan1).is_nan());
     assert!(f64::from_bits(masked_nan2).is_nan());