about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTrevor Gross <tmgross@umich.edu>2025-04-18 00:18:12 +0000
committerTrevor Gross <t.gross35@gmail.com>2025-04-17 22:00:42 -0500
commitf88b7c8a46c6c129696a6c42d126388ec02ed0bf (patch)
tree5df41353737bc4a0dbe2b10136bc7474e7370ec7
parente4d716c84801d1d91d473aaa28692f595f352b34 (diff)
downloadrust-f88b7c8a46c6c129696a6c42d126388ec02ed0bf.tar.gz
rust-f88b7c8a46c6c129696a6c42d126388ec02ed0bf.zip
Add `NEG_NAN` to `Float`
Introduce a constant representing NaN with a negative sign bit for use
with testing. There isn't really any guarantee that `F::NAN` is positive
but in practice it always is, which is good enough for testing purposes.
-rw-r--r--library/compiler-builtins/libm/crates/libm-test/src/f8_impl.rs1
-rw-r--r--library/compiler-builtins/libm/src/math/support/float_traits.rs25
2 files changed, 22 insertions, 4 deletions
diff --git a/library/compiler-builtins/libm/crates/libm-test/src/f8_impl.rs b/library/compiler-builtins/libm/crates/libm-test/src/f8_impl.rs
index 6772e092caa..ddb7bf90e7f 100644
--- a/library/compiler-builtins/libm/crates/libm-test/src/f8_impl.rs
+++ b/library/compiler-builtins/libm/crates/libm-test/src/f8_impl.rs
@@ -30,6 +30,7 @@ impl Float for f8 {
     const INFINITY: Self = Self(0b0_1111_000);
     const NEG_INFINITY: Self = Self(0b1_1111_000);
     const NAN: Self = Self(0b0_1111_100);
+    const NEG_NAN: Self = Self(0b1_1111_100);
     const MIN_POSITIVE_NORMAL: Self = Self(1 << Self::SIG_BITS);
     // FIXME: incorrect values
     const EPSILON: Self = Self::ZERO;
diff --git a/library/compiler-builtins/libm/src/math/support/float_traits.rs b/library/compiler-builtins/libm/src/math/support/float_traits.rs
index 96c209c852b..fac10483237 100644
--- a/library/compiler-builtins/libm/src/math/support/float_traits.rs
+++ b/library/compiler-builtins/libm/src/math/support/float_traits.rs
@@ -34,6 +34,7 @@ pub trait Float:
     const INFINITY: Self;
     const NEG_INFINITY: Self;
     const NAN: Self;
+    const NEG_NAN: Self;
     const MAX: Self;
     const MIN: Self;
     const EPSILON: Self;
@@ -187,6 +188,7 @@ macro_rules! float_impl {
         $bits:expr,
         $significand_bits:expr,
         $from_bits:path,
+        $to_bits:path,
         $fma_fn:ident,
         $fma_intrinsic:ident
     ) => {
@@ -201,6 +203,9 @@ macro_rules! float_impl {
             const INFINITY: Self = Self::INFINITY;
             const NEG_INFINITY: Self = Self::NEG_INFINITY;
             const NAN: Self = Self::NAN;
+            // NAN isn't guaranteed to be positive but it usually is. We only use this for
+            // tests.
+            const NEG_NAN: Self = $from_bits($to_bits(Self::NAN) | Self::SIGN_MASK);
             const MAX: Self = -Self::MIN;
             // Sign bit set, saturated mantissa, saturated exponent with last bit zeroed
             const MIN: Self = $from_bits(Self::Int::MAX & !(1 << Self::SIG_BITS));
@@ -275,11 +280,11 @@ macro_rules! float_impl {
 }
 
 #[cfg(f16_enabled)]
-float_impl!(f16, u16, i16, 16, 10, f16::from_bits, fmaf16, fmaf16);
-float_impl!(f32, u32, i32, 32, 23, f32_from_bits, fmaf, fmaf32);
-float_impl!(f64, u64, i64, 64, 52, f64_from_bits, fma, fmaf64);
+float_impl!(f16, u16, i16, 16, 10, f16::from_bits, f16::to_bits, fmaf16, fmaf16);
+float_impl!(f32, u32, i32, 32, 23, f32_from_bits, f32_to_bits, fmaf, fmaf32);
+float_impl!(f64, u64, i64, 64, 52, f64_from_bits, f64_to_bits, fma, fmaf64);
 #[cfg(f128_enabled)]
-float_impl!(f128, u128, i128, 128, 112, f128::from_bits, fmaf128, fmaf128);
+float_impl!(f128, u128, i128, 128, 112, f128::from_bits, f128::to_bits, fmaf128, fmaf128);
 
 /* FIXME(msrv): vendor some things that are not const stable at our MSRV */
 
@@ -289,12 +294,24 @@ pub const fn f32_from_bits(bits: u32) -> f32 {
     unsafe { mem::transmute::<u32, f32>(bits) }
 }
 
+/// `f32::to_bits`
+pub const fn f32_to_bits(x: f32) -> u32 {
+    // SAFETY: POD cast with no preconditions
+    unsafe { mem::transmute::<f32, u32>(x) }
+}
+
 /// `f64::from_bits`
 pub const fn f64_from_bits(bits: u64) -> f64 {
     // SAFETY: POD cast with no preconditions
     unsafe { mem::transmute::<u64, f64>(bits) }
 }
 
+/// `f64::to_bits`
+pub const fn f64_to_bits(x: f64) -> u64 {
+    // SAFETY: POD cast with no preconditions
+    unsafe { mem::transmute::<f64, u64>(x) }
+}
+
 /// Trait for floats twice the bit width of another integer.
 pub trait DFloat: Float {
     /// Float that is half the bit width of the floatthis trait is implemented for.