reifydb_engine/function/math/scalar/
abs.rs1use reifydb_core::value::column::ColumnData;
5
6use crate::function::{ScalarFunction, ScalarFunctionContext};
7
8pub struct Abs;
9
10impl Abs {
11 pub fn new() -> Self {
12 Self {}
13 }
14}
15
16impl ScalarFunction for Abs {
17 fn scalar(&self, ctx: ScalarFunctionContext) -> crate::Result<ColumnData> {
18 let columns = ctx.columns;
19 let row_count = ctx.row_count;
20
21 let column = columns.get(0).unwrap();
22
23 match &column.data() {
24 ColumnData::Int1(container) => {
25 if container.is_fully_defined() {
26 let data: Vec<i8> = container
28 .data()
29 .iter()
30 .take(row_count)
31 .map(|&value| {
32 if value < 0 {
33 value * -1
34 } else {
35 value
36 }
37 })
38 .collect();
39 Ok(ColumnData::int1(data))
40 } else {
41 let mut data = Vec::with_capacity(container.len());
44
45 for i in 0..row_count {
46 if let Some(value) = container.get(i) {
47 data.push(if *value < 0 {
48 *value * -1
49 } else {
50 *value
51 });
52 } else {
53 data.push(0);
56 }
57 }
58
59 Ok(ColumnData::int1_with_bitvec(data, container.bitvec().clone()))
60 }
61 }
62 ColumnData::Int2(container) => {
63 if container.is_fully_defined() {
64 let data: Vec<i16> = container
66 .data()
67 .iter()
68 .take(row_count)
69 .map(|&value| {
70 if value < 0 {
71 value * -1
72 } else {
73 value
74 }
75 })
76 .collect();
77 Ok(ColumnData::int2(data))
78 } else {
79 let mut data = Vec::with_capacity(container.len());
82
83 for i in 0..row_count {
84 if let Some(value) = container.get(i) {
85 data.push(if *value < 0 {
86 *value * -1
87 } else {
88 *value
89 });
90 } else {
91 data.push(0);
94 }
95 }
96
97 Ok(ColumnData::int2_with_bitvec(data, container.bitvec().clone()))
98 }
99 }
100 ColumnData::Int4(container) => {
101 if container.is_fully_defined() {
102 let data: Vec<i32> = container
104 .data()
105 .iter()
106 .take(row_count)
107 .map(|&value| {
108 if value < 0 {
109 value * -1
110 } else {
111 value
112 }
113 })
114 .collect();
115 Ok(ColumnData::int4(data))
116 } else {
117 let mut data = Vec::with_capacity(container.len());
119
120 for i in 0..row_count {
121 if let Some(value) = container.get(i) {
122 data.push(if *value < 0 {
123 *value * -1
124 } else {
125 *value
126 });
127 } else {
128 data.push(0);
130 }
131 }
132
133 Ok(ColumnData::int4_with_bitvec(data, container.bitvec().clone()))
134 }
135 }
136 ColumnData::Float4(container) => {
137 if container.is_fully_defined() {
138 let data: Vec<f32> = container
140 .data()
141 .iter()
142 .take(row_count)
143 .map(|&value| value.abs())
144 .collect();
145 Ok(ColumnData::float4(data))
146 } else {
147 let mut data = Vec::with_capacity(container.len());
149
150 for i in 0..row_count {
151 if let Some(value) = container.get(i) {
152 data.push(value.abs());
153 } else {
154 data.push(0.0);
156 }
157 }
158
159 Ok(ColumnData::float4_with_bitvec(data, container.bitvec().clone()))
160 }
161 }
162 ColumnData::Float8(container) => {
163 if container.is_fully_defined() {
164 let data: Vec<f64> = container
166 .data()
167 .iter()
168 .take(row_count)
169 .map(|&value| value.abs())
170 .collect();
171 Ok(ColumnData::float8(data))
172 } else {
173 let mut data = Vec::with_capacity(container.len());
175
176 for i in 0..row_count {
177 if let Some(value) = container.get(i) {
178 data.push(value.abs());
179 } else {
180 data.push(0.0);
182 }
183 }
184
185 Ok(ColumnData::float8_with_bitvec(data, container.bitvec().clone()))
186 }
187 }
188 _ => unimplemented!(),
189 }
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use reifydb_core::{
196 BitVec,
197 value::column::{Column, Columns},
198 };
199
200 use super::*;
201
202 #[test]
203 fn test_abs_int1_fully_defined() {
204 let function = Abs::new();
205
206 let data = vec![-5i8, 3, -2, 0, 7, -1];
208 let column = Column::int1("test", data.clone());
209
210 let columns = Columns::new(vec![column]);
211 let ctx = ScalarFunctionContext {
212 columns: &columns,
213 row_count: 6,
214 };
215
216 let result = function.scalar(ctx).unwrap();
217
218 if let ColumnData::Int1(container) = result {
220 assert!(container.is_fully_defined());
221 assert_eq!(container.len(), 6);
222
223 let expected = vec![5i8, 3, 2, 0, 7, 1];
225 for (i, &expected_val) in expected.iter().enumerate() {
226 assert_eq!(container.get(i), Some(&expected_val));
227 }
228 } else {
229 panic!("Expected Int1 result");
230 }
231 }
232
233 #[test]
234 fn test_abs_int1_partially_defined() {
235 let function = Abs::new();
236
237 let data = vec![-5i8, 3, -2, 0, 7, -1];
239 let mut bitvec = BitVec::repeat(6, true);
240 bitvec.set(2, false); bitvec.set(4, false); let column = Column::int1_with_bitvec("test", data.clone(), bitvec.clone());
244
245 let columns = Columns::new(vec![column]);
246 let ctx = ScalarFunctionContext {
247 columns: &columns,
248 row_count: 6,
249 };
250
251 let result = function.scalar(ctx).unwrap();
252
253 if let ColumnData::Int1(container) = result {
255 assert!(!container.is_fully_defined());
256 assert_eq!(container.bitvec().count_ones(), 4); assert_eq!(container.get(0), Some(&5));
260 assert_eq!(container.get(1), Some(&3));
261 assert_eq!(container.get(2), None); assert_eq!(container.get(3), Some(&0));
263 assert_eq!(container.get(4), None); assert_eq!(container.get(5), Some(&1));
265 } else {
266 panic!("Expected Int1 result");
267 }
268 }
269
270 #[test]
271 fn test_abs_int2_fully_defined() {
272 let function = Abs::new();
273
274 let data = vec![-500i16, 300, -200, 0, 700, -100];
276 let column = Column::int2("test", data.clone());
277
278 let columns = Columns::new(vec![column]);
279 let ctx = ScalarFunctionContext {
280 columns: &columns,
281 row_count: 6,
282 };
283
284 let result = function.scalar(ctx).unwrap();
285
286 if let ColumnData::Int2(container) = result {
288 assert!(container.is_fully_defined());
289 assert_eq!(container.len(), 6);
290
291 let expected = vec![500i16, 300, 200, 0, 700, 100];
293 for (i, &expected_val) in expected.iter().enumerate() {
294 assert_eq!(container.get(i), Some(&expected_val));
295 }
296 } else {
297 panic!("Expected Int2 result");
298 }
299 }
300}