reifydb_evaluate/expression/arith/
div.rs1use reifydb_core::value::column::{ColumnWithName, buffer::ColumnBuffer, push::Push};
5use reifydb_value::{
6 error::{BinaryOp, TypeError},
7 fragment::LazyFragment,
8 reifydb_assertions,
9 value::{
10 container::number::NumberContainer,
11 is::IsNumber,
12 number::{promote::Promote, safe::div::SafeDiv},
13 value_type::{ValueType, get::GetType},
14 },
15};
16
17use crate::{
18 Result,
19 expression::{context::EvalContext, option::binary_op_unwrap_option},
20};
21
22pub fn div_columns(
23 ctx: &EvalContext,
24 left: &ColumnWithName,
25 right: &ColumnWithName,
26 fragment: impl LazyFragment + Copy,
27) -> Result<ColumnWithName> {
28 binary_op_unwrap_option(left, right, fragment.fragment(), |left, right| {
29 let target = ValueType::promote(left.get_type(), right.get_type());
30
31 dispatch_arith!(
32 &left.data(), &right.data();
33 fixed: div_numeric, arb: div_numeric_clone (ctx, target, fragment);
34
35 _ => Err(TypeError::BinaryOperatorNotApplicable {
36 operator: BinaryOp::Div,
37 left: left.get_type(),
38 right: right.get_type(),
39 fragment: fragment.fragment(),
40 }.into()),
41 )
42 })
43}
44
45fn div_numeric<L, R>(
46 ctx: &EvalContext,
47 l: &NumberContainer<L>,
48 r: &NumberContainer<R>,
49 target: ValueType,
50 fragment: impl LazyFragment + Copy,
51) -> Result<ColumnWithName>
52where
53 L: GetType + Promote<R> + IsNumber,
54 R: GetType + IsNumber,
55 <L as Promote<R>>::Output: IsNumber,
56 <L as Promote<R>>::Output: SafeDiv,
57 ColumnBuffer: Push<<L as Promote<R>>::Output>,
58{
59 reifydb_assertions! {
60 assert_eq!(l.len(), r.len());
61 }
62
63 let mut data = ColumnBuffer::with_capacity(target, l.len());
64 let l_data = l.data();
65 let r_data = r.data();
66 for i in 0..l.len() {
67 if let Some(value) = ctx.div(&l_data[i], &r_data[i], fragment)? {
68 data.push(value);
69 } else {
70 data.push_none()
71 }
72 }
73 Ok(ColumnWithName {
74 name: fragment.fragment(),
75 data,
76 })
77}
78
79fn div_numeric_clone<L, R>(
80 ctx: &EvalContext,
81 l: &NumberContainer<L>,
82 r: &NumberContainer<R>,
83 target: ValueType,
84 fragment: impl LazyFragment + Copy,
85) -> Result<ColumnWithName>
86where
87 L: Clone + GetType + Promote<R> + IsNumber,
88 R: Clone + GetType + IsNumber,
89 <L as Promote<R>>::Output: IsNumber,
90 <L as Promote<R>>::Output: SafeDiv,
91 ColumnBuffer: Push<<L as Promote<R>>::Output>,
92{
93 reifydb_assertions! {
94 assert_eq!(l.len(), r.len());
95 }
96
97 let mut data = ColumnBuffer::with_capacity(target, l.len());
98 let l_data = l.data();
99 let r_data = r.data();
100 for i in 0..l.len() {
101 let l_clone = l_data[i].clone();
102 let r_clone = r_data[i].clone();
103 if let Some(value) = ctx.div(&l_clone, &r_clone, fragment)? {
104 data.push(value);
105 } else {
106 data.push_none()
107 }
108 }
109 Ok(ColumnWithName {
110 name: fragment.fragment(),
111 data,
112 })
113}