/// # 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) }
/// # Examples
///
/// ```
- /// #![feature(float_bits_conv)]
/// use std::f32;
/// let v = f32::from_bits(0x41480000);
/// let difference = (v - 12.5).abs();
/// 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) }
}
}
#[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();
// 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);
}
}