From: est31 Date: Wed, 29 Mar 2017 00:39:59 +0000 (+0200) Subject: Convert sNaN to quiet NaN instead of returning errors X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=fc028b81803277f7552355052bb277b10a066249;p=rust.git Convert sNaN to quiet NaN instead of returning errors --- diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 76b629fb1d4..40bf7f17c3a 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -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 { + 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); } } diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index f553e580f0f..80bc149b1a4 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -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 { + 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); } }