about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorSimonas Kazlauskas <git@kazlauskas.me>2017-06-04 21:44:57 +0300
committerSimonas Kazlauskas <git@kazlauskas.me>2017-06-22 23:12:01 +0300
commit3b9fe77bfcd4c800fab8afcdcc82d31facdc515b (patch)
tree464db7167313be8d61001eabd038521e9fcf0d0e /src/libcore
parent0da9721ab49d80bf74208e94a891b12c4a248507 (diff)
downloadrust-3b9fe77bfcd4c800fab8afcdcc82d31facdc515b.tar.gz
rust-3b9fe77bfcd4c800fab8afcdcc82d31facdc515b.zip
Fix NaN handling in is_sign_negative/positive
See #42425
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/num/f32.rs19
-rw-r--r--src/libcore/num/f64.rs17
2 files changed, 24 insertions, 12 deletions
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 91ca213e96e..aca37221f09 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -205,18 +205,25 @@ impl Float for f32 {
         }
     }
 
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > 0.0 || (1.0 / self) == INFINITY
+        !self.is_sign_negative()
     }
 
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < 0.0 || (1.0 / self) == NEG_INFINITY
+        // IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
+        // applies to zeros and NaNs as well.
+        #[repr(C)]
+        union F32Bytes {
+            f: f32,
+            b: u32
+        }
+        unsafe { F32Bytes { f: self }.b & 0x8000_0000 != 0 }
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 7d6d6cef049..ebe5daa67a7 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -205,18 +205,23 @@ impl Float for f64 {
         }
     }
 
-    /// Returns `true` if `self` is positive, including `+0.0` and
-    /// `Float::infinity()`.
+    /// Returns `true` if and only if `self` has a positive sign, including `+0.0`, `NaN`s with
+    /// positive sign bit and positive infinity.
     #[inline]
     fn is_sign_positive(self) -> bool {
-        self > 0.0 || (1.0 / self) == INFINITY
+        !self.is_sign_negative()
     }
 
-    /// Returns `true` if `self` is negative, including `-0.0` and
-    /// `Float::neg_infinity()`.
+    /// Returns `true` if and only if `self` has a negative sign, including `-0.0`, `NaN`s with
+    /// negative sign bit and negative infinity.
     #[inline]
     fn is_sign_negative(self) -> bool {
-        self < 0.0 || (1.0 / self) == NEG_INFINITY
+        #[repr(C)]
+        union F64Bytes {
+            f: f64,
+            b: u64
+        }
+        unsafe { F64Bytes { f: self }.b & 0x8000_0000_0000_0000 != 0 }
     }
 
     /// Returns the reciprocal (multiplicative inverse) of the number.