]> git.lizzy.rs Git - rust.git/commitdiff
Convert sNaN to quiet NaN instead of returning errors
authorest31 <MTest31@outlook.com>
Wed, 29 Mar 2017 00:39:59 +0000 (02:39 +0200)
committerest31 <MTest31@outlook.com>
Tue, 18 Apr 2017 00:43:16 +0000 (02:43 +0200)
src/libstd/f32.rs
src/libstd/f64.rs

index 76b629fb1d4cde88a7291a8ff2dc4ee93f5f77a9..40bf7f17c3aa6bd29036522935491b3c02504ec2 100644 (file)
@@ -1254,29 +1254,35 @@ pub fn to_bits(self) -> u32 {
     /// representation into the `f32` type, similar to the
     /// `transmute` function.
     ///
-    /// Note that this function is distinct from casting.
+    /// There is only one difference to a bare `transmute`:
+    /// Due to the implications onto Rust's safety promises being
+    /// uncertain, if the representation of a signaling NaN "sNaN" float
+    /// is passed to the function, a quiet NaN will be returned
+    /// instead.
     ///
-    /// Returns `Err(())` if the representation of a signaling NaN "sNaN"
-    /// float, is passed to the function.
+    /// Note that this function is distinct from casting.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(float_bits_conv)]
     /// use std::f32;
-    /// let v = f32::from_bits(0x41480000).unwrap();
+    /// let v = f32::from_bits(0x41480000);
     /// let difference = (v - 12.5).abs();
     /// assert!(difference <= 1e-5);
     /// // Example for a signaling NaN value:
-    /// assert_eq!(f32::from_bits(0x7F800001), Err(()));
+    /// let snan = 0x7F800001;
+    /// assert_ne!(f32::from_bits(snan).to_bits(), snan);
     /// ```
     #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")]
     #[inline]
-    pub fn from_bits(v: u32) -> Result<Self, ()> {
+    pub fn from_bits(v: u32) -> Self {
         match v {
+            // sNaN limits source:
+            // https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html
             0x7F800001 ... 0x7FBFFFFF |
-            0xFF800001 ... 0xFFBFFFFF => Err(()),
-            _ => Ok(unsafe { ::mem::transmute(v) }),
+            0xFF800001 ... 0xFFBFFFFF => ::f32::NAN,
+            _ => unsafe { ::mem::transmute(v) },
         }
     }
 }
@@ -1930,9 +1936,9 @@ fn test_float_bits_conv() {
         assert_eq!((12.5f32).to_bits(), 0x41480000);
         assert_eq!((1337f32).to_bits(), 0x44a72000);
         assert_eq!((-14.25f32).to_bits(), 0xc1640000);
-        assert_approx_eq!(f32::from_bits(0x3f800000).unwrap(), 1.0);
-        assert_approx_eq!(f32::from_bits(0x41480000).unwrap(), 12.5);
-        assert_approx_eq!(f32::from_bits(0x44a72000).unwrap(), 1337.0);
-        assert_approx_eq!(f32::from_bits(0xc1640000).unwrap(), -14.25);
+        assert_approx_eq!(f32::from_bits(0x3f800000), 1.0);
+        assert_approx_eq!(f32::from_bits(0x41480000), 12.5);
+        assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
+        assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
     }
 }
index f553e580f0fa9e63f9aea8a18541188dfa883ab2..80bc149b1a40a011dfcdcf5ccfc4247d0ad37164 100644 (file)
@@ -1146,29 +1146,35 @@ pub fn to_bits(self) -> u64 {
     /// representation into the `f64` type, similar to the
     /// `transmute` function.
     ///
-    /// Note that this function is distinct from casting.
+    /// There is only one difference to a bare `transmute`:
+    /// Due to the implications onto Rust's safety promises being
+    /// uncertain, if the representation of a signaling NaN "sNaN" float
+    /// is passed to the function, a quiet NaN will be returned
+    /// instead.
     ///
-    /// Returns `Err(())` if the representation of a signaling NaN "sNaN"
-    /// float, is passed to the function.
+    /// Note that this function is distinct from casting.
     ///
     /// # Examples
     ///
     /// ```
     /// #![feature(float_bits_conv)]
     /// use std::f64;
-    /// let v = f64::from_bits(0x4029000000000000).unwrap();
+    /// let v = f64::from_bits(0x4029000000000000);
     /// let difference = (v - 12.5).abs();
     /// assert!(difference <= 1e-5);
     /// // Example for a signaling NaN value:
-    /// assert_eq!(f64::from_bits(0x7FF0000000000001), Err(()));
+    /// let snan = 0x7FF0000000000001;
+    /// assert_ne!(f64::from_bits(snan).to_bits(), snan);
     /// ```
     #[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")]
     #[inline]
-    pub fn from_bits(v: u64) -> Result<Self, ()> {
+    pub fn from_bits(v: u64) -> Self {
         match v {
+            // sNaN limits source:
+            // https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html
             0x7FF0000000000001 ... 0x7FF7FFFFFFFFFFFF |
-            0xFFF0000000000001 ... 0xFFF7FFFFFFFFFFFF => Err(()),
-            _ => Ok(unsafe { ::mem::transmute(v) }),
+            0xFFF0000000000001 ... 0xFFF7FFFFFFFFFFFF => ::f64::NAN,
+            _ => unsafe { ::mem::transmute(v) },
         }
     }
 }
@@ -1815,9 +1821,9 @@ fn test_float_bits_conv() {
         assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
         assert_eq!((1337f64).to_bits(), 0x4094e40000000000);
         assert_eq!((-14.25f64).to_bits(), 0xc02c800000000000);
-        assert_approx_eq!(f64::from_bits(0x3ff0000000000000).unwrap(), 1.0);
-        assert_approx_eq!(f64::from_bits(0x4029000000000000).unwrap(), 12.5);
-        assert_approx_eq!(f64::from_bits(0x4094e40000000000).unwrap(), 1337.0);
-        assert_approx_eq!(f64::from_bits(0xc02c800000000000).unwrap(), -14.25);
+        assert_approx_eq!(f64::from_bits(0x3ff0000000000000), 1.0);
+        assert_approx_eq!(f64::from_bits(0x4029000000000000), 12.5);
+        assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
+        assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
     }
 }