Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions src/libstd/f32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1131,13 +1131,16 @@ impl f32 {
#[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) }
}
Expand Down Expand Up @@ -1732,8 +1735,15 @@ mod tests {
}
#[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();
Expand All @@ -1742,7 +1752,5 @@ mod tests {
// 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);
}
}
13 changes: 8 additions & 5 deletions src/libstd/f64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1046,13 +1046,16 @@ impl f64 {
#[inline]
pub fn from_bits(mut v: u64) -> Self {
const EXP_MASK: u64 = 0x7FF0000000000000;
const QNAN_MASK: u64 = 0x0001000000000000;
const FRACT_MASK: u64 = 0x000FFFFFFFFFFFFF;
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) }
}
Expand Down