@@ -1276,14 +1276,17 @@ impl f32 {
12761276 /// ```
12771277 #[ unstable( feature = "float_bits_conv" , reason = "recently added" , issue = "40470" ) ]
12781278 #[ 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 ;
12861288 }
1289+ unsafe { :: mem:: transmute ( v) }
12871290 }
12881291}
12891292
@@ -1941,4 +1944,19 @@ mod tests {
19411944 assert_approx_eq ! ( f32 :: from_bits( 0x44a72000 ) , 1337.0 ) ;
19421945 assert_approx_eq ! ( f32 :: from_bits( 0xc1640000 ) , -14.25 ) ;
19431946 }
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+ }
19441962}
0 commit comments