Skip to content

Commit 06884ae

Browse files
committed
Optimize signed zero canonicalization
1 parent deff8d0 commit 06884ae

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

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

4653
/// A wrapper around floats providing implementations of `Eq`, `Ord`, and `Hash`.
4754
///
@@ -173,10 +180,8 @@ impl<T: FloatCore> Hash for OrderedFloat<T> {
173180
fn hash<H: Hasher>(&self, state: &mut H) {
174181
let bits = if self.is_nan() {
175182
CANONICAL_NAN_BITS
176-
} else if self.is_zero() {
177-
CANONICAL_ZERO_BITS
178183
} else {
179-
raw_double_bits(&self.0)
184+
raw_double_bits(&canonicalize_signed_zero(self.0))
180185
};
181186

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

0 commit comments

Comments
 (0)