reifydb_value/value/
ordered_f32.rs1use std::{
5 cmp::Ordering,
6 fmt,
7 fmt::{Display, Formatter},
8 hash::{Hash, Hasher},
9 ops::Deref,
10};
11
12use serde::{Deserialize, Deserializer, Serialize, Serializer, de, de::Visitor};
13
14use crate::{
15 error::{Error, TypeError},
16 util::float_format::format_f32,
17};
18
19#[repr(transparent)]
20#[derive(Debug, Copy, Clone, Default)]
21pub struct OrderedF32(f32);
22
23impl Serialize for OrderedF32 {
24 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
25 where
26 S: Serializer,
27 {
28 serializer.serialize_f32(self.0)
29 }
30}
31
32impl<'de> Deserialize<'de> for OrderedF32 {
33 fn deserialize<D>(deserializer: D) -> Result<OrderedF32, D::Error>
34 where
35 D: Deserializer<'de>,
36 {
37 struct F32Visitor;
38
39 impl Visitor<'_> for F32Visitor {
40 type Value = OrderedF32;
41
42 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
43 formatter.write_str("a 32-bit floating point number")
44 }
45
46 fn visit_f32<E>(self, value: f32) -> Result<Self::Value, E> {
47 Ok(OrderedF32(value))
48 }
49
50 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
51 where
52 E: de::Error,
53 {
54 Ok(OrderedF32(value as f32))
55 }
56 }
57
58 deserializer.deserialize_f32(F32Visitor)
59 }
60}
61
62impl OrderedF32 {
63 pub fn value(&self) -> f32 {
64 self.0
65 }
66
67 pub fn zero() -> OrderedF32 {
68 OrderedF32(0.0f32)
69 }
70}
71
72impl Deref for OrderedF32 {
73 type Target = f32;
74
75 fn deref(&self) -> &Self::Target {
76 &self.0
77 }
78}
79
80impl Display for OrderedF32 {
81 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
82 f.write_str(&format_f32(self.0))
83 }
84}
85
86impl PartialEq for OrderedF32 {
87 fn eq(&self, other: &Self) -> bool {
88 self.0.to_bits() == other.0.to_bits()
89 }
90}
91
92impl Eq for OrderedF32 {}
93
94impl PartialOrd for OrderedF32 {
95 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
96 Some(self.cmp(other))
97 }
98}
99
100impl Ord for OrderedF32 {
101 fn cmp(&self, other: &Self) -> Ordering {
102 let l = float_to_ordered_u32(self.0);
103 let r = float_to_ordered_u32(other.0);
104 l.cmp(&r)
105 }
106}
107
108#[inline]
109fn float_to_ordered_u32(f: f32) -> u32 {
110 let bits = f.to_bits();
111 if bits & 0x80000000 == 0 {
112 bits ^ 0x80000000
113 } else {
114 !bits
115 }
116}
117
118impl Hash for OrderedF32 {
119 fn hash<H: Hasher>(&self, state: &mut H) {
120 self.0.to_bits().hash(state);
121 }
122}
123
124impl From<OrderedF32> for f32 {
125 fn from(v: OrderedF32) -> Self {
126 v.0
127 }
128}
129
130impl TryFrom<f32> for OrderedF32 {
131 type Error = Error;
132
133 fn try_from(f: f32) -> Result<Self, Self::Error> {
134 let normalized = if f == 0.0 {
135 0.0
136 } else {
137 f
138 };
139 if f.is_nan() {
140 Err(TypeError::NanNotAllowed.into())
141 } else {
142 Ok(OrderedF32(normalized))
143 }
144 }
145}
146
147#[cfg(test)]
148pub mod tests {
149 use std::{collections::HashSet, convert::TryFrom};
150
151 use super::*;
152
153 #[test]
154 fn test_sorting() {
155 let mut values = vec![
156 OrderedF32::try_from(10.0).unwrap(),
157 OrderedF32::try_from(2.0).unwrap(),
158 OrderedF32::try_from(5.0).unwrap(),
159 ];
160 values.sort();
161 let sorted: Vec<f32> = values.into_iter().map(|v| v.0).collect();
162 assert_eq!(sorted, vec![2.0, 5.0, 10.0]);
163 }
164
165 #[test]
166 fn test_hash_eq() {
167 let a = OrderedF32::try_from(1.0).unwrap();
168 let b = OrderedF32::try_from(1.0).unwrap();
169
170 let mut set = HashSet::new();
171 set.insert(a);
172 assert!(set.contains(&b));
173 }
174
175 #[test]
176 fn test_normalizes_zero() {
177 let pos_zero = OrderedF32::try_from(0.0).unwrap();
178 let neg_zero = OrderedF32::try_from(-0.0).unwrap();
179
180 assert_eq!(pos_zero, neg_zero);
181
182 let mut set = HashSet::new();
183 set.insert(pos_zero);
184 assert!(set.contains(&neg_zero));
185 }
186
187 #[test]
188 fn test_nan_fails() {
189 assert!(OrderedF32::try_from(f32::NAN).is_err());
190 }
191
192 #[test]
193 fn test_negative_less_than_positive() {
194 let neg = OrderedF32::try_from(-1.5).unwrap();
195 let pos = OrderedF32::try_from(1.5).unwrap();
196 assert!(neg < pos);
197 }
198
199 #[test]
200 fn test_negative_less_than_zero() {
201 let neg = OrderedF32::try_from(-0.0001).unwrap();
202 let zero = OrderedF32::try_from(0.0).unwrap();
203 assert!(neg < zero);
204 }
205
206 #[test]
207 fn test_sorting_with_negatives() {
208 let mut values = vec![
209 OrderedF32::try_from(3.14).unwrap(),
210 OrderedF32::try_from(-1.5).unwrap(),
211 OrderedF32::try_from(0.0).unwrap(),
212 OrderedF32::try_from(99999.0).unwrap(),
213 OrderedF32::try_from(-100.0).unwrap(),
214 ];
215 values.sort();
216 let sorted: Vec<f32> = values.into_iter().map(|v| v.0).collect();
217 assert_eq!(sorted, vec![-100.0, -1.5, 0.0, 3.14, 99999.0]);
218 }
219}