1pub const fn f32_total_order_key_from_bits(bits: u32) -> u32 {
9 let mask = if bits >> 31 == 0 {
10 0x8000_0000
11 } else {
12 u32::MAX
13 };
14 bits ^ mask
15}
16
17pub const fn f32_total_order_key(value: f32) -> u32 {
19 f32_total_order_key_from_bits(value.to_bits())
20}
21
22pub const fn f64_total_order_key_from_bits(bits: u64) -> u64 {
28 let mask = if bits >> 63 == 0 {
29 0x8000_0000_0000_0000
30 } else {
31 u64::MAX
32 };
33 bits ^ mask
34}
35
36pub const fn f64_total_order_key(value: f64) -> u64 {
38 f64_total_order_key_from_bits(value.to_bits())
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn fixed_edge_cases_match_standard_total_order() {
47 let f32_values = [
48 f32::from_bits(0xffc0_0002),
49 f32::NEG_INFINITY,
50 -1.0,
51 -0.0,
52 0.0,
53 1.0,
54 f32::INFINITY,
55 f32::from_bits(0x7fc0_0001),
56 f32::from_bits(0x7fc0_0002),
57 ];
58 for &left in &f32_values {
59 for &right in &f32_values {
60 assert_eq!(
61 f32_total_order_key(left).cmp(&f32_total_order_key(right)),
62 left.total_cmp(&right)
63 );
64 }
65 }
66
67 let f64_values = [
68 f64::from_bits(0xfff8_0000_0000_0002),
69 f64::NEG_INFINITY,
70 -1.0,
71 -0.0,
72 0.0,
73 1.0,
74 f64::INFINITY,
75 f64::from_bits(0x7ff8_0000_0000_0001),
76 f64::from_bits(0x7ff8_0000_0000_0002),
77 ];
78 for &left in &f64_values {
79 for &right in &f64_values {
80 assert_eq!(
81 f64_total_order_key(left).cmp(&f64_total_order_key(right)),
82 left.total_cmp(&right)
83 );
84 }
85 }
86 }
87
88 #[test]
89 fn seeded_bit_patterns_match_standard_total_order() {
90 let mut left = 0x243f_6a88_85a3_08d3_u64;
91 let mut right = 0x1319_8a2e_0370_7344_u64;
92 for _ in 0..10_000 {
93 left ^= left << 13;
94 left ^= left >> 7;
95 left ^= left << 17;
96 right = right
97 .wrapping_mul(6_364_136_223_846_793_005)
98 .wrapping_add(1_442_695_040_888_963_407);
99
100 let left_f64 = f64::from_bits(left);
101 let right_f64 = f64::from_bits(right);
102 assert_eq!(
103 f64_total_order_key(left_f64).cmp(&f64_total_order_key(right_f64)),
104 left_f64.total_cmp(&right_f64)
105 );
106
107 let left_f32 = f32::from_bits(left as u32);
108 let right_f32 = f32::from_bits(right as u32);
109 assert_eq!(
110 f32_total_order_key(left_f32).cmp(&f32_total_order_key(right_f32)),
111 left_f32.total_cmp(&right_f32)
112 );
113 }
114 }
115}