mod checked;
mod decimal;
mod primitive;
#[cfg(test)]
mod tests;
use decimal::execute_numeric_decimal;
use decimal::result_decimal_dtype;
pub(crate) use decimal::result_decimal_dtype as numeric_op_result_decimal_dtype;
pub(crate) use primitive::PrimitiveOperand;
use primitive::execute_numeric_primitive;
use vortex_error::VortexResult;
use vortex_error::vortex_ensure;
use crate::ArrayRef;
use crate::Canonical;
use crate::ExecutionCtx;
use crate::IntoArray;
use crate::dtype::DType;
use crate::scalar::NumericOperator;
pub(crate) fn execute_numeric(
lhs: &ArrayRef,
rhs: &ArrayRef,
op: NumericOperator,
ctx: &mut ExecutionCtx,
) -> VortexResult<ArrayRef> {
vortex_ensure!(
lhs.dtype().eq_ignore_nullability(rhs.dtype()),
"numeric operator requires matching types, got {} and {}",
lhs.dtype(),
rhs.dtype()
);
let dtype = lhs.dtype();
vortex_ensure!(
matches!(dtype, DType::Primitive(..) | DType::Decimal(..)),
"numeric operator is not supported for dtype {}",
dtype
);
vortex_ensure!(
lhs.len() == rhs.len(),
"numeric operator requires equal lengths, got {} and {}",
lhs.len(),
rhs.len()
);
if lhs.is_empty() {
return build_empty_result(lhs, rhs, op);
}
match dtype {
DType::Primitive(..) => execute_numeric_primitive(lhs, rhs, op, ctx),
DType::Decimal(..) => execute_numeric_decimal(lhs, rhs, op, ctx),
_ => unreachable!("dtype is either Primitive or Decimal"),
}
}
fn build_empty_result(
lhs: &ArrayRef,
rhs: &ArrayRef,
op: NumericOperator,
) -> VortexResult<ArrayRef> {
let nullability = lhs.dtype().nullability() | rhs.dtype().nullability();
let result_dtype = match lhs.dtype() {
DType::Primitive(..) => lhs.dtype().with_nullability(nullability),
DType::Decimal(decimal_dtype, _) => {
DType::Decimal(result_decimal_dtype(*decimal_dtype, op)?, nullability)
}
_ => unreachable!("dtype is either Primitive or Decimal"),
};
Ok(Canonical::empty(&result_dtype).into_array())
}