@@ -33,22 +33,6 @@ pub use num_traits::{Float, Pow};
33
33
#[ cfg( feature = "rand" ) ]
34
34
pub use impl_rand:: { UniformNotNan , UniformOrdered } ;
35
35
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
-
52
36
/// A wrapper around floats providing implementations of `Eq`, `Ord`, and `Hash`.
53
37
///
54
38
/// NaN is sorted as *greater* than all other values and *equal*
@@ -332,18 +316,6 @@ impl<T: FloatCore> PartialEq<T> for OrderedFloat<T> {
332
316
}
333
317
}
334
318
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
-
347
319
impl < T : fmt:: Debug > fmt:: Debug for OrderedFloat < T > {
348
320
#[ inline]
349
321
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -1350,14 +1322,6 @@ impl<T: FloatCore> Ord for NotNan<T> {
1350
1322
}
1351
1323
}
1352
1324
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
-
1361
1325
impl < T : fmt:: Debug > fmt:: Debug for NotNan < T > {
1362
1326
#[ inline]
1363
1327
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
@@ -1790,15 +1754,6 @@ impl From<FloatIsNan> for std::io::Error {
1790
1754
}
1791
1755
}
1792
1756
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
-
1802
1757
impl < T : FloatCore > Zero for NotNan < T > {
1803
1758
#[ inline]
1804
1759
fn zero ( ) -> Self {
@@ -2039,6 +1994,65 @@ impl_float_const!(OrderedFloat, OrderedFloat);
2039
1994
// Float constants are not NaN.
2040
1995
impl_float_const ! ( NotNan , |x| unsafe { NotNan :: new_unchecked( x) } ) ;
2041
1996
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
+
2042
2056
#[ cfg( feature = "serde" ) ]
2043
2057
mod impl_serde {
2044
2058
extern crate serde;
0 commit comments