1use std::{f64, ptr};
5
6use reifydb_value::{reifydb_assertions, value::value_type::ValueType};
7
8use crate::encoded::{row::EncodedRow, shape::RowShape};
9
10impl RowShape {
11 pub fn set_f64(&self, row: &mut EncodedRow, index: usize, value: impl Into<f64>) {
12 let field = &self.fields()[index];
13 reifydb_assertions! {
14 assert!(
15 row.len() >= self.total_static_size(),
16 "row/shape size mismatch: row.len()={} < total_static_size()={}",
17 row.len(),
18 self.total_static_size()
19 );
20 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Float8);
21 }
22 row.set_valid(index, true);
23 unsafe {
24 ptr::write_unaligned(
25 row.make_mut().as_mut_ptr().add(field.offset as usize) as *mut f64,
26 value.into(),
27 )
28 }
29 }
30
31 pub fn get_f64(&self, row: &EncodedRow, index: usize) -> f64 {
32 let field = &self.fields()[index];
33 reifydb_assertions! {
34 assert!(
35 row.len() >= self.total_static_size(),
36 "row/shape size mismatch: row.len()={} < total_static_size()={}",
37 row.len(),
38 self.total_static_size()
39 );
40 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Float8);
41 }
42 unsafe { (row.as_ptr().add(field.offset as usize) as *const f64).read_unaligned() }
43 }
44
45 pub fn try_get_f64(&self, row: &EncodedRow, index: usize) -> Option<f64> {
46 if row.is_defined(index) && self.fields()[index].constraint.get_type() == ValueType::Float8 {
47 Some(self.get_f64(row, index))
48 } else {
49 None
50 }
51 }
52}
53
54#[cfg(test)]
55#[allow(clippy::approx_constant)]
56pub mod tests {
57 use std::f64::consts::{E, PI};
58
59 use reifydb_value::value::value_type::ValueType;
60
61 use crate::encoded::shape::RowShape;
62
63 #[test]
64 fn test_set_get_f64() {
65 let shape = RowShape::testing(&[ValueType::Float8]);
66 let mut row = shape.allocate();
67 shape.set_f64(&mut row, 0, 2.5f64);
68 assert_eq!(shape.get_f64(&row, 0), 2.5f64);
69 }
70
71 #[test]
72 fn test_try_get_f64() {
73 let shape = RowShape::testing(&[ValueType::Float8]);
74 let mut row = shape.allocate();
75
76 assert_eq!(shape.try_get_f64(&row, 0), None);
77
78 shape.set_f64(&mut row, 0, 2.5f64);
79 assert_eq!(shape.try_get_f64(&row, 0), Some(2.5f64));
80 }
81
82 #[test]
83 fn test_special_values() {
84 let shape = RowShape::testing(&[ValueType::Float8]);
85 let mut row = shape.allocate();
86
87 shape.set_f64(&mut row, 0, 0.0f64);
89 assert_eq!(shape.get_f64(&row, 0), 0.0f64);
90
91 let mut row2 = shape.allocate();
93 shape.set_f64(&mut row2, 0, -0.0f64);
94 assert_eq!(shape.get_f64(&row2, 0), -0.0f64);
95
96 let mut row3 = shape.allocate();
98 shape.set_f64(&mut row3, 0, f64::INFINITY);
99 assert_eq!(shape.get_f64(&row3, 0), f64::INFINITY);
100
101 let mut row4 = shape.allocate();
103 shape.set_f64(&mut row4, 0, f64::NEG_INFINITY);
104 assert_eq!(shape.get_f64(&row4, 0), f64::NEG_INFINITY);
105
106 let mut row5 = shape.allocate();
108 shape.set_f64(&mut row5, 0, f64::NAN);
109 assert!(shape.get_f64(&row5, 0).is_nan());
110 }
111
112 #[test]
113 fn test_extreme_values() {
114 let shape = RowShape::testing(&[ValueType::Float8]);
115 let mut row = shape.allocate();
116
117 shape.set_f64(&mut row, 0, f64::MAX);
118 assert_eq!(shape.get_f64(&row, 0), f64::MAX);
119
120 let mut row2 = shape.allocate();
121 shape.set_f64(&mut row2, 0, f64::MIN);
122 assert_eq!(shape.get_f64(&row2, 0), f64::MIN);
123
124 let mut row3 = shape.allocate();
125 shape.set_f64(&mut row3, 0, f64::MIN_POSITIVE);
126 assert_eq!(shape.get_f64(&row3, 0), f64::MIN_POSITIVE);
127 }
128
129 #[test]
130 fn test_high_precision() {
131 let shape = RowShape::testing(&[ValueType::Float8]);
132 let mut row = shape.allocate();
133
134 let pi = PI;
135 shape.set_f64(&mut row, 0, pi);
136 assert_eq!(shape.get_f64(&row, 0), pi);
137
138 let mut row2 = shape.allocate();
139 let e = E;
140 shape.set_f64(&mut row2, 0, e);
141 assert_eq!(shape.get_f64(&row2, 0), e);
142 }
143
144 #[test]
145 fn test_mixed_with_other_types() {
146 let shape = RowShape::testing(&[ValueType::Float8, ValueType::Int8, ValueType::Float8]);
147 let mut row = shape.allocate();
148
149 shape.set_f64(&mut row, 0, 3.14159265359);
150 shape.set_i64(&mut row, 1, 9223372036854775807i64);
151 shape.set_f64(&mut row, 2, -2.718281828459045);
152
153 assert_eq!(shape.get_f64(&row, 0), 3.14159265359);
154 assert_eq!(shape.get_i64(&row, 1), 9223372036854775807);
155 assert_eq!(shape.get_f64(&row, 2), -2.718281828459045);
156 }
157
158 #[test]
159 fn test_undefined_handling() {
160 let shape = RowShape::testing(&[ValueType::Float8, ValueType::Float8]);
161 let mut row = shape.allocate();
162
163 shape.set_f64(&mut row, 0, 2.718281828459045);
164
165 assert_eq!(shape.try_get_f64(&row, 0), Some(2.718281828459045));
166 assert_eq!(shape.try_get_f64(&row, 1), None);
167
168 shape.set_none(&mut row, 0);
169 assert_eq!(shape.try_get_f64(&row, 0), None);
170 }
171
172 #[test]
173 fn test_try_get_f64_wrong_type() {
174 let shape = RowShape::testing(&[ValueType::Boolean]);
175 let mut row = shape.allocate();
176
177 shape.set_bool(&mut row, 0, true);
178
179 assert_eq!(shape.try_get_f64(&row, 0), None);
180 }
181}