decorum/hash.rs
1//! Hashing of IEEE 754 floating-point values.
2//!
3//! This module provides hashing for primitive floating-point values. Given the set of zero
4//! representations $Z$ and set of `NaN` representations $N$, hashing coalesces their
5//! representations such that:
6//!
7//! $$
8//! \begin{aligned}
9//! h(a)=h(b)&\mid a\in{Z},~b\in{Z}\cr\[1em\]
10//! h(a)=h(b)&\mid a\in{N},~b\in{N}
11//! \end{aligned}
12//! $$
13//!
14//! The [`CanonicalHash`] trait agrees with the ordering and equivalence relations of the
15//! [`CanonicalOrd`] and [`CanonicalEq`] traits.
16//!
17//! [`CanonicalEq`]: crate::cmp::CanonicalEq
18//! [`CanonicalOrd`]: crate::cmp::CanonicalOrd
19
20use core::hash::{Hash, Hasher};
21
22use crate::ToCanonical;
23
24pub trait CanonicalHash {
25 fn hash_canonical<H>(&self, state: &mut H)
26 where
27 H: Hasher;
28}
29
30// TODO: This implementation conflicts with implementations over references to a type `T` where
31// `T: CanonicalHash`. However, this is because `rustc` claims that "sealed" traits can be
32// implemented downstream, which isn't true. Write reference implementations when possible
33// (or consider removing this blanket implementation).
34impl<T> CanonicalHash for T
35where
36 T: ToCanonical,
37{
38 fn hash_canonical<H>(&self, state: &mut H)
39 where
40 H: Hasher,
41 {
42 self.to_canonical().hash(state)
43 }
44}
45
46impl<T> CanonicalHash for [T]
47where
48 T: CanonicalHash,
49{
50 fn hash_canonical<H>(&self, state: &mut H)
51 where
52 H: Hasher,
53 {
54 for item in self {
55 item.hash_canonical(state);
56 }
57 }
58}