tiny_ordered_float/
f64.rs1use core::cmp::Ordering;
2use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
3use core::hash::{Hash, Hasher};
4use core::option::{Option, Option::Some};
5
6pub struct OrderedFloat(pub f64);
7
8const CANONICAL_NAN_BITS: u64 = 0x7ff8000000000000u64;
10
11#[inline(always)]
12fn canonicalize_signed_zero(x: f64) -> f64 {
13 x + 0.0
17}
18
19impl Hash for OrderedFloat {
20 fn hash<H: Hasher>(&self, state: &mut H) {
21 let bits = if self.0.is_nan() {
22 CANONICAL_NAN_BITS
23 } else {
24 canonicalize_signed_zero(self.0).to_bits()
25 };
26
27 bits.hash(state)
28 }
29}
30
31impl Eq for OrderedFloat {}
32
33impl PartialEq for OrderedFloat {
34 #[inline]
35 fn eq(&self, other: &OrderedFloat) -> bool {
36 if self.0.is_nan() {
37 other.0.is_nan()
38 } else {
39 self.0 == other.0
40 }
41 }
42}
43
44impl PartialOrd for OrderedFloat {
45 #[inline]
46 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
47 Some(self.cmp(other))
48 }
49
50 #[inline]
51 fn lt(&self, other: &Self) -> bool {
52 !self.ge(other)
53 }
54
55 #[inline]
56 fn le(&self, other: &Self) -> bool {
57 other.ge(self)
58 }
59
60 #[inline]
61 fn gt(&self, other: &Self) -> bool {
62 !other.ge(self)
63 }
64
65 #[inline]
66 fn ge(&self, other: &Self) -> bool {
67 self.0.is_nan() | (self.0 >= other.0)
73 }
74}
75
76impl Ord for OrderedFloat {
77 #[inline]
78 fn cmp(&self, other: &Self) -> Ordering {
79 #[allow(clippy::comparison_chain)]
80 if self < other {
81 Ordering::Less
82 } else if self > other {
83 Ordering::Greater
84 } else {
85 Ordering::Equal
86 }
87 }
88}