Skip to content

Commit fc028b8

Browse files
committed
Convert sNaN to quiet NaN instead of returning errors
1 parent bdab5cd commit fc028b8

File tree

2 files changed

+36
-24
lines changed

2 files changed

+36
-24
lines changed

src/libstd/f32.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -1254,29 +1254,35 @@ impl f32 {
12541254
/// representation into the `f32` type, similar to the
12551255
/// `transmute` function.
12561256
///
1257-
/// Note that this function is distinct from casting.
1257+
/// There is only one difference to a bare `transmute`:
1258+
/// Due to the implications onto Rust's safety promises being
1259+
/// uncertain, if the representation of a signaling NaN "sNaN" float
1260+
/// is passed to the function, a quiet NaN will be returned
1261+
/// instead.
12581262
///
1259-
/// Returns `Err(())` if the representation of a signaling NaN "sNaN"
1260-
/// float, is passed to the function.
1263+
/// Note that this function is distinct from casting.
12611264
///
12621265
/// # Examples
12631266
///
12641267
/// ```
12651268
/// #![feature(float_bits_conv)]
12661269
/// use std::f32;
1267-
/// let v = f32::from_bits(0x41480000).unwrap();
1270+
/// let v = f32::from_bits(0x41480000);
12681271
/// let difference = (v - 12.5).abs();
12691272
/// assert!(difference <= 1e-5);
12701273
/// // Example for a signaling NaN value:
1271-
/// assert_eq!(f32::from_bits(0x7F800001), Err(()));
1274+
/// let snan = 0x7F800001;
1275+
/// assert_ne!(f32::from_bits(snan).to_bits(), snan);
12721276
/// ```
12731277
#[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")]
12741278
#[inline]
1275-
pub fn from_bits(v: u32) -> Result<Self, ()> {
1279+
pub fn from_bits(v: u32) -> Self {
12761280
match v {
1281+
// sNaN limits source:
1282+
// https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html
12771283
0x7F800001 ... 0x7FBFFFFF |
1278-
0xFF800001 ... 0xFFBFFFFF => Err(()),
1279-
_ => Ok(unsafe { ::mem::transmute(v) }),
1284+
0xFF800001 ... 0xFFBFFFFF => ::f32::NAN,
1285+
_ => unsafe { ::mem::transmute(v) },
12801286
}
12811287
}
12821288
}
@@ -1930,9 +1936,9 @@ mod tests {
19301936
assert_eq!((12.5f32).to_bits(), 0x41480000);
19311937
assert_eq!((1337f32).to_bits(), 0x44a72000);
19321938
assert_eq!((-14.25f32).to_bits(), 0xc1640000);
1933-
assert_approx_eq!(f32::from_bits(0x3f800000).unwrap(), 1.0);
1934-
assert_approx_eq!(f32::from_bits(0x41480000).unwrap(), 12.5);
1935-
assert_approx_eq!(f32::from_bits(0x44a72000).unwrap(), 1337.0);
1936-
assert_approx_eq!(f32::from_bits(0xc1640000).unwrap(), -14.25);
1939+
assert_approx_eq!(f32::from_bits(0x3f800000), 1.0);
1940+
assert_approx_eq!(f32::from_bits(0x41480000), 12.5);
1941+
assert_approx_eq!(f32::from_bits(0x44a72000), 1337.0);
1942+
assert_approx_eq!(f32::from_bits(0xc1640000), -14.25);
19371943
}
19381944
}

src/libstd/f64.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -1146,29 +1146,35 @@ impl f64 {
11461146
/// representation into the `f64` type, similar to the
11471147
/// `transmute` function.
11481148
///
1149-
/// Note that this function is distinct from casting.
1149+
/// There is only one difference to a bare `transmute`:
1150+
/// Due to the implications onto Rust's safety promises being
1151+
/// uncertain, if the representation of a signaling NaN "sNaN" float
1152+
/// is passed to the function, a quiet NaN will be returned
1153+
/// instead.
11501154
///
1151-
/// Returns `Err(())` if the representation of a signaling NaN "sNaN"
1152-
/// float, is passed to the function.
1155+
/// Note that this function is distinct from casting.
11531156
///
11541157
/// # Examples
11551158
///
11561159
/// ```
11571160
/// #![feature(float_bits_conv)]
11581161
/// use std::f64;
1159-
/// let v = f64::from_bits(0x4029000000000000).unwrap();
1162+
/// let v = f64::from_bits(0x4029000000000000);
11601163
/// let difference = (v - 12.5).abs();
11611164
/// assert!(difference <= 1e-5);
11621165
/// // Example for a signaling NaN value:
1163-
/// assert_eq!(f64::from_bits(0x7FF0000000000001), Err(()));
1166+
/// let snan = 0x7FF0000000000001;
1167+
/// assert_ne!(f64::from_bits(snan).to_bits(), snan);
11641168
/// ```
11651169
#[unstable(feature = "float_bits_conv", reason = "recently added", issue = "40470")]
11661170
#[inline]
1167-
pub fn from_bits(v: u64) -> Result<Self, ()> {
1171+
pub fn from_bits(v: u64) -> Self {
11681172
match v {
1173+
// sNaN limits source:
1174+
// https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html
11691175
0x7FF0000000000001 ... 0x7FF7FFFFFFFFFFFF |
1170-
0xFFF0000000000001 ... 0xFFF7FFFFFFFFFFFF => Err(()),
1171-
_ => Ok(unsafe { ::mem::transmute(v) }),
1176+
0xFFF0000000000001 ... 0xFFF7FFFFFFFFFFFF => ::f64::NAN,
1177+
_ => unsafe { ::mem::transmute(v) },
11721178
}
11731179
}
11741180
}
@@ -1815,9 +1821,9 @@ mod tests {
18151821
assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
18161822
assert_eq!((1337f64).to_bits(), 0x4094e40000000000);
18171823
assert_eq!((-14.25f64).to_bits(), 0xc02c800000000000);
1818-
assert_approx_eq!(f64::from_bits(0x3ff0000000000000).unwrap(), 1.0);
1819-
assert_approx_eq!(f64::from_bits(0x4029000000000000).unwrap(), 12.5);
1820-
assert_approx_eq!(f64::from_bits(0x4094e40000000000).unwrap(), 1337.0);
1821-
assert_approx_eq!(f64::from_bits(0xc02c800000000000).unwrap(), -14.25);
1824+
assert_approx_eq!(f64::from_bits(0x3ff0000000000000), 1.0);
1825+
assert_approx_eq!(f64::from_bits(0x4029000000000000), 12.5);
1826+
assert_approx_eq!(f64::from_bits(0x4094e40000000000), 1337.0);
1827+
assert_approx_eq!(f64::from_bits(0xc02c800000000000), -14.25);
18221828
}
18231829
}

0 commit comments

Comments
 (0)