@@ -8,13 +8,24 @@ extern crate unreachable;
88
99use std:: cmp:: Ordering ;
1010use std:: error:: Error ;
11- use std:: ops:: { Add , AddAssign , Deref , DerefMut , Div , DivAssign , Mul , MulAssign , Neg , Rem , RemAssign , Sub , SubAssign } ;
11+ use std:: ops:: { Add , AddAssign , Deref , DerefMut , Div , DivAssign , Mul , MulAssign , Neg , Rem ,
12+ RemAssign , Sub , SubAssign } ;
1213use std:: hash:: { Hash , Hasher } ;
1314use std:: fmt;
1415use std:: io;
16+ use std:: mem;
1517use unreachable:: unreachable;
1618use num_traits:: Float ;
1719
20+ // masks for the parts of the IEEE 754 float
21+ const SIGN_MASK : u64 = 0x8000000000000000u64 ;
22+ const EXP_MASK : u64 = 0x7ff0000000000000u64 ;
23+ const MAN_MASK : u64 = 0x000fffffffffffffu64 ;
24+
25+ // canonical raw bit patterns (for hashing)
26+ const CANONICAL_NAN_BITS : u64 = 0x7ff8000000000000u64 ;
27+ const CANONICAL_ZERO_BITS : u64 = 0x0u64 ;
28+
1829/// A wrapper around Floats providing an implementation of Ord and Hash.
1930///
2031/// NaN is sorted as *greater* than all other values and *equal*
@@ -66,11 +77,7 @@ impl<T: Float + PartialOrd> Ord for OrderedFloat<T> {
6677impl < T : Float + PartialEq > PartialEq for OrderedFloat < T > {
6778 fn eq ( & self , other : & OrderedFloat < T > ) -> bool {
6879 if self . as_ref ( ) . is_nan ( ) {
69- if other. as_ref ( ) . is_nan ( ) {
70- true
71- } else {
72- false
73- }
80+ if other. as_ref ( ) . is_nan ( ) { true } else { false }
7481 } else if other. as_ref ( ) . is_nan ( ) {
7582 false
7683 } else {
@@ -128,7 +135,7 @@ impl<T: Float> DerefMut for OrderedFloat<T> {
128135 }
129136}
130137
131- impl < T : Float + PartialEq > Eq for OrderedFloat < T > { }
138+ impl < T : Float + PartialEq > Eq for OrderedFloat < T > { }
132139
133140/// A wrapper around Floats providing an implementation of Ord and Hash.
134141///
@@ -496,7 +503,7 @@ pub struct FloatIsNaN;
496503
497504impl Error for FloatIsNaN {
498505 fn description ( & self ) -> & str {
499- return "NotNaN constructed with NaN"
506+ return "NotNaN constructed with NaN" ;
500507 }
501508}
502509
@@ -514,14 +521,23 @@ impl Into<io::Error> for FloatIsNaN {
514521
515522#[ inline]
516523fn hash_float < F : Float , H : Hasher > ( f : & F , state : & mut H ) {
524+ raw_double_bits ( f) . hash ( state) ;
525+ }
526+
527+ #[ inline]
528+ fn raw_double_bits < F : Float > ( f : & F ) -> u64 {
529+ if f. is_nan ( ) {
530+ return CANONICAL_NAN_BITS ;
531+ }
532+
517533 let ( man, exp, sign) = f. integer_decode ( ) ;
518534 if man == 0 {
519- // Consolidate the representation of zero, whether signed or not
520- // The IEEE standard considers positive and negative zero to be equal
521- 0
522- } else {
523- ( man ^ ( ( exp as u64 ) << 48 ) ^ sign as u64 )
524- } . hash ( state )
535+ return CANONICAL_ZERO_BITS ;
536+ }
537+
538+ let exp_u64 = unsafe { mem :: transmute :: < i16 , u16 > ( exp ) } as u64 ;
539+ let sign_u64 = if sign > 0 { 1u64 } else { 0u64 } ;
540+ ( man & MAN_MASK ) | ( ( exp_u64 << 52 ) & EXP_MASK ) | ( ( sign_u64 << 63 ) & SIGN_MASK )
525541}
526542
527543#[ cfg( feature = "rustc-serialize" ) ]
@@ -585,7 +601,10 @@ mod impl_serde {
585601
586602 impl < T : Float + Deserialize > Deserialize for NotNaN < T > {
587603 fn deserialize < D : Deserializer > ( d : & mut D ) -> Result < Self , D :: Error > {
588- T :: deserialize ( d) . and_then ( |v| NotNaN :: new ( v) . map_err ( |_| <D :: Error as Error >:: invalid_value ( "value cannot be NaN" ) ) )
604+ T :: deserialize ( d) . and_then ( |v| {
605+ NotNaN :: new ( v)
606+ . map_err ( |_| <D :: Error as Error >:: invalid_value ( "value cannot be NaN" ) )
607+ } )
589608 }
590609 }
591610}
0 commit comments