diff --git a/core/src/execution/datafusion/expressions/avg_decimal.rs b/core/src/execution/datafusion/expressions/avg_decimal.rs index 6fb558109..d99ed041c 100644 --- a/core/src/execution/datafusion/expressions/avg_decimal.rs +++ b/core/src/execution/datafusion/expressions/avg_decimal.rs @@ -34,7 +34,7 @@ use arrow_data::decimal::{ validate_decimal_precision, MAX_DECIMAL_FOR_EACH_PRECISION, MIN_DECIMAL_FOR_EACH_PRECISION, }; -use num::Integer; +use num::{integer::div_ceil, Integer}; use DataType::*; /// AVG aggregate expression @@ -514,7 +514,7 @@ fn avg(sum: i128, count: i128, target_min: i128, target_max: i128, scaler: i128) if let Some(value) = sum.checked_mul(scaler) { // `sum / count` with ROUND_HALF_UP let (div, rem) = value.div_rem(&count); - let half = count.div_ceil(2); + let half = div_ceil(count, 2); let half_neg = half.neg_wrapping(); let new_value = match value >= 0 { true if rem >= half => div.add_wrapping(1), diff --git a/core/src/execution/datafusion/expressions/scalar_funcs.rs b/core/src/execution/datafusion/expressions/scalar_funcs.rs index 78775cd5c..4fca7237b 100644 --- a/core/src/execution/datafusion/expressions/scalar_funcs.rs +++ b/core/src/execution/datafusion/expressions/scalar_funcs.rs @@ -37,7 +37,10 @@ use datafusion_common::{ use datafusion_physical_expr::{ execution_props::ExecutionProps, functions::create_physical_fun, math_expressions, }; -use num::{BigInt, Signed, ToPrimitive}; +use num::{ + integer::{div_ceil, div_floor}, + BigInt, Signed, ToPrimitive, +}; use unicode_segmentation::UnicodeSegmentation; /// Create a physical scalar function. @@ -249,13 +252,13 @@ fn long_to_decimal(v: &Option, precision: u8) -> Option { #[inline] fn decimal_ceil_f(scale: &i8) -> impl Fn(i128) -> i128 { let div = 10_i128.pow_wrapping(*scale as u32); - move |x: i128| x.div_ceil(div) + move |x: i128| div_ceil(x, div) } #[inline] fn decimal_floor_f(scale: &i8) -> impl Fn(i128) -> i128 { let div = 10_i128.pow_wrapping(*scale as u32); - move |x: i128| x.div_floor(div) + move |x: i128| div_floor(x, div) } // Spark uses BigDecimal. See RoundBase implementation in Spark. Instead, we do the same by diff --git a/core/src/execution/datafusion/expressions/utils.rs b/core/src/execution/datafusion/expressions/utils.rs index ec0cf2207..30a469207 100644 --- a/core/src/execution/datafusion/expressions/utils.rs +++ b/core/src/execution/datafusion/expressions/utils.rs @@ -31,6 +31,7 @@ use arrow_schema::DataType; use chrono::{DateTime, Offset, TimeZone}; use datafusion_common::cast::as_generic_string_array; use datafusion_physical_expr::PhysicalExpr; +use num::integer::div_floor; use std::{any::Any, sync::Arc}; /// An utility function from DataFusion. It is not exposed by DataFusion. @@ -198,13 +199,13 @@ pub(crate) fn spark_cast(array: ArrayRef, from_type: &DataType, to_type: &DataTy match (from_type, to_type) { (DataType::Timestamp(_, _), DataType::Int64) => { // See Spark's `Cast` expression - unary_dyn::<_, Int64Type>(&array, |v| v.div_floor(MICROS_PER_SECOND)).unwrap() + unary_dyn::<_, Int64Type>(&array, |v| div_floor(v, MICROS_PER_SECOND)).unwrap() } (DataType::Dictionary(_, value_type), DataType::Int64) if matches!(value_type.as_ref(), &DataType::Timestamp(_, _)) => { // See Spark's `Cast` expression - unary_dyn::<_, Int64Type>(&array, |v| v.div_floor(MICROS_PER_SECOND)).unwrap() + unary_dyn::<_, Int64Type>(&array, |v| div_floor(v, MICROS_PER_SECOND)).unwrap() } (DataType::Timestamp(_, _), DataType::Utf8) => remove_trailing_zeroes(array), (DataType::Dictionary(_, value_type), DataType::Utf8) diff --git a/core/src/lib.rs b/core/src/lib.rs index 2e8513620..f209859a7 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -21,7 +21,6 @@ #![allow(clippy::upper_case_acronyms)] #![allow(clippy::derive_partial_eq_without_eq)] // For prost generated struct #![cfg_attr(feature = "nightly", feature(core_intrinsics))] -#![feature(int_roundings)] #![feature(specialization)] // Branch prediction hint. This is currently only available on nightly.