@@ -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