@@ -36,7 +36,14 @@ const MAN_MASK: u64 = 0x000fffffffffffffu64;
36
36
37
37
// canonical raw bit patterns (for hashing)
38
38
const CANONICAL_NAN_BITS : u64 = 0x7ff8000000000000u64 ;
39
- const CANONICAL_ZERO_BITS : u64 = 0x0u64 ;
39
+
40
+ #[ inline( always) ]
41
+ fn canonicalize_signed_zero < T : Float > ( x : T ) -> T {
42
+ // -0.0 + 0.0 == +0.0 under IEEE754 roundTiesToEven rounding mode,
43
+ // which Rust guarantees. Thus by adding a positive zero we
44
+ // canonicalize signed zero without any branches in one instruction.
45
+ x + T :: zero ( )
46
+ }
40
47
41
48
/// A wrapper around floats providing implementations of `Eq`, `Ord`, and `Hash`.
42
49
///
@@ -168,10 +175,8 @@ impl<T: Float> Hash for OrderedFloat<T> {
168
175
fn hash < H : Hasher > ( & self , state : & mut H ) {
169
176
let bits = if self . is_nan ( ) {
170
177
CANONICAL_NAN_BITS
171
- } else if self . is_zero ( ) {
172
- CANONICAL_ZERO_BITS
173
178
} else {
174
- raw_double_bits ( & self . 0 )
179
+ raw_double_bits ( & canonicalize_signed_zero ( self . 0 ) )
175
180
} ;
176
181
177
182
bits. hash ( state)
@@ -958,12 +963,7 @@ impl<T: Float> Ord for NotNan<T> {
958
963
impl < T : Float > Hash for NotNan < T > {
959
964
#[ inline]
960
965
fn hash < H : Hasher > ( & self , state : & mut H ) {
961
- let bits = if self . is_zero ( ) {
962
- CANONICAL_ZERO_BITS
963
- } else {
964
- raw_double_bits ( & self . 0 )
965
- } ;
966
-
966
+ let bits = raw_double_bits ( & canonicalize_signed_zero ( self . 0 ) ) ;
967
967
bits. hash ( state)
968
968
}
969
969
}
0 commit comments