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