@@ -33,22 +33,6 @@ pub use num_traits::{Float, Pow};
3333#[ cfg( feature = "rand" ) ]
3434pub use impl_rand:: { UniformNotNan , UniformOrdered } ;
3535
36- // masks for the parts of the IEEE 754 float
37- const SIGN_MASK : u64 = 0x8000000000000000u64 ;
38- const EXP_MASK : u64 = 0x7ff0000000000000u64 ;
39- const MAN_MASK : u64 = 0x000fffffffffffffu64 ;
40-
41- // canonical raw bit patterns (for hashing)
42- const CANONICAL_NAN_BITS : u64 = 0x7ff8000000000000u64 ;
43-
44- #[ inline( always) ]
45- fn canonicalize_signed_zero < T : FloatCore > ( x : T ) -> T {
46- // -0.0 + 0.0 == +0.0 under IEEE754 roundTiesToEven rounding mode,
47- // which Rust guarantees. Thus by adding a positive zero we
48- // canonicalize signed zero without any branches in one instruction.
49- x + T :: zero ( )
50- }
51-
5236/// A wrapper around floats providing implementations of `Eq`, `Ord`, and `Hash`.
5337///
5438/// NaN is sorted as *greater* than all other values and *equal*
@@ -332,18 +316,6 @@ impl<T: FloatCore> PartialEq<T> for OrderedFloat<T> {
332316 }
333317}
334318
335- impl < T : FloatCore > Hash for OrderedFloat < T > {
336- fn hash < H : Hasher > ( & self , state : & mut H ) {
337- let bits = if self . is_nan ( ) {
338- CANONICAL_NAN_BITS
339- } else {
340- raw_double_bits ( & canonicalize_signed_zero ( self . 0 ) )
341- } ;
342-
343- bits. hash ( state)
344- }
345- }
346-
347319impl < T : fmt:: Debug > fmt:: Debug for OrderedFloat < T > {
348320 #[ inline]
349321 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -1350,14 +1322,6 @@ impl<T: FloatCore> Ord for NotNan<T> {
13501322 }
13511323}
13521324
1353- impl < T : FloatCore > Hash for NotNan < T > {
1354- #[ inline]
1355- fn hash < H : Hasher > ( & self , state : & mut H ) {
1356- let bits = raw_double_bits ( & canonicalize_signed_zero ( self . 0 ) ) ;
1357- bits. hash ( state)
1358- }
1359- }
1360-
13611325impl < T : fmt:: Debug > fmt:: Debug for NotNan < T > {
13621326 #[ inline]
13631327 fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -1790,15 +1754,6 @@ impl From<FloatIsNan> for std::io::Error {
17901754 }
17911755}
17921756
1793- #[ inline]
1794- /// Used for hashing. Input must not be zero or NaN.
1795- fn raw_double_bits < F : FloatCore > ( f : & F ) -> u64 {
1796- let ( man, exp, sign) = f. integer_decode ( ) ;
1797- let exp_u64 = exp as u16 as u64 ;
1798- let sign_u64 = ( sign > 0 ) as u64 ;
1799- ( man & MAN_MASK ) | ( ( exp_u64 << 52 ) & EXP_MASK ) | ( ( sign_u64 << 63 ) & SIGN_MASK )
1800- }
1801-
18021757impl < T : FloatCore > Zero for NotNan < T > {
18031758 #[ inline]
18041759 fn zero ( ) -> Self {
@@ -2039,6 +1994,65 @@ impl_float_const!(OrderedFloat, OrderedFloat);
20391994// Float constants are not NaN.
20401995impl_float_const ! ( NotNan , |x| unsafe { NotNan :: new_unchecked( x) } ) ;
20411996
1997+ // canonical raw bit patterns (for hashing)
1998+
1999+ mod hash_internals {
2000+ pub trait SealedTrait : Copy + num_traits:: float:: FloatCore {
2001+ type Bits : core:: hash:: Hash ;
2002+
2003+ const CANONICAL_NAN_BITS : Self :: Bits ;
2004+
2005+ fn canonical_bits ( self ) -> Self :: Bits ;
2006+ }
2007+
2008+ impl SealedTrait for f32 {
2009+ type Bits = u32 ;
2010+
2011+ const CANONICAL_NAN_BITS : u32 = f32:: NAN . to_bits ( ) ;
2012+
2013+ fn canonical_bits ( self ) -> u32 {
2014+ // -0.0 + 0.0 == +0.0 under IEEE754 roundTiesToEven rounding mode,
2015+ // which Rust guarantees. Thus by adding a positive zero we
2016+ // canonicalize signed zero without any branches in one instruction.
2017+ ( self + 0.0 ) . to_bits ( )
2018+ }
2019+ }
2020+
2021+ impl SealedTrait for f64 {
2022+ type Bits = u64 ;
2023+
2024+ const CANONICAL_NAN_BITS : u64 = f64:: NAN . to_bits ( ) ;
2025+
2026+ fn canonical_bits ( self ) -> u64 {
2027+ ( self + 0.0 ) . to_bits ( )
2028+ }
2029+ }
2030+ }
2031+
2032+ /// The built-in floating point types `f32` and `f64`.
2033+ ///
2034+ /// This is a "sealed" trait that cannot be implemented for any other types.
2035+ pub trait PrimitiveFloat : hash_internals:: SealedTrait { }
2036+ impl PrimitiveFloat for f32 { }
2037+ impl PrimitiveFloat for f64 { }
2038+
2039+ impl < T : PrimitiveFloat > Hash for OrderedFloat < T > {
2040+ fn hash < H : Hasher > ( & self , hasher : & mut H ) {
2041+ let bits = if self . 0 . is_nan ( ) {
2042+ T :: CANONICAL_NAN_BITS
2043+ } else {
2044+ self . 0 . canonical_bits ( )
2045+ } ;
2046+ bits. hash ( hasher) ;
2047+ }
2048+ }
2049+
2050+ impl < T : PrimitiveFloat > Hash for NotNan < T > {
2051+ fn hash < H : Hasher > ( & self , hasher : & mut H ) {
2052+ self . 0 . canonical_bits ( ) . hash ( hasher) ;
2053+ }
2054+ }
2055+
20422056#[ cfg( feature = "serde" ) ]
20432057mod impl_serde {
20442058 extern crate serde;
0 commit comments