Skip to content

Commit 2753a02

Browse files
orlpmbrubeck
authored andcommitted
Optimize signed zero canonicalization
1 parent ec00343 commit 2753a02

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
@@ -36,7 +36,14 @@ const MAN_MASK: u64 = 0x000fffffffffffffu64;
3636

3737
// canonical raw bit patterns (for hashing)
3838
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+
}
4047

4148
/// A wrapper around floats providing implementations of `Eq`, `Ord`, and `Hash`.
4249
///
@@ -168,10 +175,8 @@ impl<T: Float> Hash for OrderedFloat<T> {
168175
fn hash<H: Hasher>(&self, state: &mut H) {
169176
let bits = if self.is_nan() {
170177
CANONICAL_NAN_BITS
171-
} else if self.is_zero() {
172-
CANONICAL_ZERO_BITS
173178
} else {
174-
raw_double_bits(&self.0)
179+
raw_double_bits(&canonicalize_signed_zero(self.0))
175180
};
176181

177182
bits.hash(state)
@@ -958,12 +963,7 @@ impl<T: Float> Ord for NotNan<T> {
958963
impl<T: Float> Hash for NotNan<T> {
959964
#[inline]
960965
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));
967967
bits.hash(state)
968968
}
969969
}

0 commit comments

Comments
 (0)