Skip to main content

reifydb_engine/expression/arith/
div.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use 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(crate) 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}