Skip to content

Commit 84e9ae2

Browse files
orlpmbrubeck
authored andcommitted
Optimize signed zero canonicalization
1 parent 1e2dd8b commit 84e9ae2

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

src/lib.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,14 @@ const MAN_MASK: u64 = 0x000fffffffffffffu64;
4242

4343
// canonical raw bit patterns (for hashing)
4444
const CANONICAL_NAN_BITS: u64 = 0x7ff8000000000000u64;
45-
const CANONICAL_ZERO_BITS: u64 = 0x0u64;
45+
46+
#[inline(always)]
47+
fn canonicalize_signed_zero<T: Float>(x: T) -> T {
48+
// -0.0 + 0.0 == +0.0 under IEEE754 roundTiesToEven rounding mode,
49+
// which Rust guarantees. Thus by adding a positive zero we
50+
// canonicalize signed zero without any branches in one instruction.
51+
x + T::zero()
52+
}
4653

4754
/// A wrapper around floats providing implementations of `Eq`, `Ord`, and `Hash`.
4855
///
@@ -174,10 +181,8 @@ impl<T: Float> Hash for OrderedFloat<T> {
174181
fn hash<H: Hasher>(&self, state: &mut H) {
175182
let bits = if self.is_nan() {
176183
CANONICAL_NAN_BITS
177-
} else if self.is_zero() {
178-
CANONICAL_ZERO_BITS
179184
} else {
180-
raw_double_bits(&self.0)
185+
raw_double_bits(&canonicalize_signed_zero(self.0))
181186
};
182187

183188
bits.hash(state)
@@ -1163,12 +1168,7 @@ impl<T: Float> Ord for NotNan<T> {
11631168
impl<T: Float> Hash for NotNan<T> {
11641169
#[inline]
11651170
fn hash<H: Hasher>(&self, state: &mut H) {
1166-
let bits = if self.is_zero() {
1167-
CANONICAL_ZERO_BITS
1168-
} else {
1169-
raw_double_bits(&self.0)
1170-
};
1171-
1171+
let bits = raw_double_bits(&canonicalize_signed_zero(self.0));
11721172
bits.hash(state)
11731173
}
11741174
}

0 commit comments

Comments
 (0)