reifydb_routine/function/math/
floor.rs1use num_traits::ToPrimitive;
5use reifydb_core::value::column::{Column, columns::Columns, data::ColumnData};
6use reifydb_type::value::{
7 container::number::NumberContainer,
8 decimal::Decimal,
9 r#type::{Type, input_types::InputTypes},
10};
11
12use crate::function::{Function, FunctionCapability, FunctionContext, FunctionInfo, error::FunctionError};
13
14pub struct Floor {
15 info: FunctionInfo,
16}
17
18impl Default for Floor {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl Floor {
25 pub fn new() -> Self {
26 Self {
27 info: FunctionInfo::new("math::floor"),
28 }
29 }
30}
31
32impl Function for Floor {
33 fn info(&self) -> &FunctionInfo {
34 &self.info
35 }
36
37 fn capabilities(&self) -> &[FunctionCapability] {
38 &[FunctionCapability::Scalar]
39 }
40
41 fn return_type(&self, input_types: &[Type]) -> Type {
42 input_types.first().cloned().unwrap_or(Type::Float8)
43 }
44
45 fn execute(&self, ctx: &FunctionContext, args: &Columns) -> Result<Columns, FunctionError> {
46 if args.len() != 1 {
47 return Err(FunctionError::ArityMismatch {
48 function: ctx.fragment.clone(),
49 expected: 1,
50 actual: args.len(),
51 });
52 }
53
54 let column = &args[0];
55 let (data, bitvec) = column.data().unwrap_option();
56 let row_count = data.len();
57
58 let result_data = match data {
59 ColumnData::Float4(container) => {
60 let mut data = Vec::with_capacity(row_count);
61 let mut res_bitvec = Vec::with_capacity(row_count);
62 for i in 0..row_count {
63 if let Some(&value) = container.get(i) {
64 data.push(value.floor());
65 res_bitvec.push(true);
66 } else {
67 data.push(0.0);
68 res_bitvec.push(false);
69 }
70 }
71 ColumnData::float4_with_bitvec(data, res_bitvec)
72 }
73 ColumnData::Float8(container) => {
74 let mut data = Vec::with_capacity(row_count);
75 let mut res_bitvec = Vec::with_capacity(row_count);
76 for i in 0..row_count {
77 if let Some(&value) = container.get(i) {
78 data.push(value.floor());
79 res_bitvec.push(true);
80 } else {
81 data.push(0.0);
82 res_bitvec.push(false);
83 }
84 }
85 ColumnData::float8_with_bitvec(data, res_bitvec)
86 }
87 ColumnData::Decimal {
88 container,
89 precision,
90 scale,
91 } => {
92 let mut data = Vec::with_capacity(row_count);
93 for i in 0..row_count {
94 if let Some(value) = container.get(i) {
95 let f = value.0.to_f64().unwrap_or(0.0);
96 data.push(Decimal::from(f.floor()));
97 } else {
98 data.push(Decimal::default());
99 }
100 }
101 ColumnData::Decimal {
102 container: NumberContainer::new(data),
103 precision: *precision,
104 scale: *scale,
105 }
106 }
107 other if other.get_type().is_number() => data.clone(),
108 other => {
109 return Err(FunctionError::InvalidArgumentType {
110 function: ctx.fragment.clone(),
111 argument_index: 0,
112 expected: InputTypes::numeric().expected_at(0).to_vec(),
113 actual: other.get_type(),
114 });
115 }
116 };
117
118 let final_data = if let Some(bv) = bitvec {
119 ColumnData::Option {
120 inner: Box::new(result_data),
121 bitvec: bv.clone(),
122 }
123 } else {
124 result_data
125 };
126
127 Ok(Columns::new(vec![Column::new(ctx.fragment.clone(), final_data)]))
128 }
129}