]> git.lizzy.rs Git - rust.git/blobdiff - src/libstd/f32.rs
Auto merge of #43270 - petrochenkov:fixstab, r=alexcrichton
[rust.git] / src / libstd / f32.rs
index 7d79fb078116f568cd6124af01b6beac93108c97..0135cd0a588cf09e530499f3e4c60b571cbf62b2 100644 (file)
@@ -1090,12 +1090,11 @@ pub fn atanh(self) -> f32 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_bits_conv)]
     /// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
     /// assert_eq!((12.5f32).to_bits(), 0x41480000);
     ///
     /// ```
-    #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")]
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[inline]
     pub fn to_bits(self) -> u32 {
         unsafe { ::mem::transmute(self) }
@@ -1118,7 +1117,6 @@ pub fn to_bits(self) -> u32 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(float_bits_conv)]
     /// use std::f32;
     /// let v = f32::from_bits(0x41480000);
     /// let difference = (v - 12.5).abs();
@@ -1127,17 +1125,20 @@ pub fn to_bits(self) -> u32 {
     /// let snan = 0x7F800001;
     /// assert_ne!(f32::from_bits(snan).to_bits(), snan);
     /// ```
-    #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")]
+    #[stable(feature = "float_bits_conv", since = "1.20.0")]
     #[inline]
     pub fn from_bits(mut v: u32) -> Self {
         const EXP_MASK: u32   = 0x7F800000;
-        const QNAN_MASK: u32  = 0x00400000;
         const FRACT_MASK: u32 = 0x007FFFFF;
         if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 {
-            // If we have a NaN value, we
-            // convert signaling NaN values to quiet NaN
-            // by setting the the highest bit of the fraction
-            v |= QNAN_MASK;
+            // While IEEE 754-2008 specifies encodings for quiet NaNs
+            // and signaling ones, certain MIPS and PA-RISC
+            // CPUs treat signaling NaNs differently.
+            // Therefore to be safe, we pass a known quiet NaN
+            // if v is any kind of NaN.
+            // The check above only assumes IEEE 754-1985 to be
+            // valid.
+            v = unsafe { ::mem::transmute(NAN) };
         }
         unsafe { ::mem::transmute(v) }
     }
@@ -1732,8 +1733,15 @@ fn test_float_bits_conv() {
     }
     #[test]
     fn test_snan_masking() {
+        // NOTE: this test assumes that our current platform
+        // implements IEEE 754-2008 that specifies the difference
+        // in encoding of quiet and signaling NaNs.
+        // If you are porting Rust to a platform that does not
+        // implement IEEE 754-2008 (but e.g. IEEE 754-1985, which
+        // only says that "Signaling NaNs shall be reserved operands"
+        // but doesn't specify the actual setup), feel free to
+        // cfg out this test.
         let snan: u32 = 0x7F801337;
-        const PAYLOAD_MASK: u32 = 0x003FFFFF;
         const QNAN_MASK: u32  = 0x00400000;
         let nan_masked_fl = f32::from_bits(snan);
         let nan_masked = nan_masked_fl.to_bits();
@@ -1742,7 +1750,5 @@ fn test_snan_masking() {
         // Ensure that we have a quiet NaN
         assert_ne!(nan_masked & QNAN_MASK, 0);
         assert!(nan_masked_fl.is_nan());
-        // Ensure the payload wasn't touched during conversion
-        assert_eq!(nan_masked & PAYLOAD_MASK, snan & PAYLOAD_MASK);
     }
 }