@@ -1276,14 +1276,17 @@ impl f32 {
1276
1276
/// ```
1277
1277
#[ unstable( feature = "float_bits_conv" , reason = "recently added" , issue = "40470" ) ]
1278
1278
#[ inline]
1279
- pub fn from_bits ( v : u32 ) -> Self {
1280
- match v {
1281
- // sNaN limits source:
1282
- // https://www.doc.ic.ac.uk/~eedwards/compsys/float/nan.html
1283
- 0x7F800001 ... 0x7FBFFFFF |
1284
- 0xFF800001 ... 0xFFBFFFFF => :: f32:: NAN ,
1285
- _ => unsafe { :: mem:: transmute ( v) } ,
1279
+ pub fn from_bits ( mut v : u32 ) -> Self {
1280
+ const EXP_MASK : u32 = 0x7F800000 ;
1281
+ const QNAN_MASK : u32 = 0x00400000 ;
1282
+ const FRACT_MASK : u32 = 0x007FFFFF ;
1283
+ if v & EXP_MASK == EXP_MASK && v & FRACT_MASK != 0 {
1284
+ // If we have a NaN value, we
1285
+ // convert signaling NaN values to quiet NaN
1286
+ // by setting the the highest bit of the fraction
1287
+ v |= QNAN_MASK ;
1286
1288
}
1289
+ unsafe { :: mem:: transmute ( v) }
1287
1290
}
1288
1291
}
1289
1292
@@ -1941,4 +1944,19 @@ mod tests {
1941
1944
assert_approx_eq ! ( f32 :: from_bits( 0x44a72000 ) , 1337.0 ) ;
1942
1945
assert_approx_eq ! ( f32 :: from_bits( 0xc1640000 ) , -14.25 ) ;
1943
1946
}
1947
+ #[ test]
1948
+ fn test_snan_masking ( ) {
1949
+ let snan: u32 = 0x7F801337 ;
1950
+ const PAYLOAD_MASK : u32 = 0x003FFFFF ;
1951
+ const QNAN_MASK : u32 = 0x00400000 ;
1952
+ let nan_masked_fl = f32:: from_bits ( snan) ;
1953
+ let nan_masked = nan_masked_fl. to_bits ( ) ;
1954
+ // Ensure that signaling NaNs don't stay the same
1955
+ assert_ne ! ( nan_masked, snan) ;
1956
+ // Ensure that we have a quiet NaN
1957
+ assert_ne ! ( nan_masked & QNAN_MASK , 0 ) ;
1958
+ assert ! ( nan_masked_fl. is_nan( ) ) ;
1959
+ // Ensure the payload wasn't touched during conversion
1960
+ assert_eq ! ( nan_masked & PAYLOAD_MASK , snan & PAYLOAD_MASK ) ;
1961
+ }
1944
1962
}
0 commit comments