This is an automated email from the ASF dual-hosted git repository.

jakevin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git


The following commit(s) were added to refs/heads/master by this push:
     new 149a3f8c9f Remove deprecated arithmetic kernels (#4481) (#4594)
149a3f8c9f is described below

commit 149a3f8c9f05a31eef717291cef566ac8baf8c56
Author: Raphael Taylor-Davies <[email protected]>
AuthorDate: Tue Aug 1 09:10:39 2023 +0100

    Remove deprecated arithmetic kernels (#4481) (#4594)
    
    * Remove deprecated arithmetic kernels (#4481)
    
    * Fix tests
    
    * Fix FFI
    
    * Update pyarrow-integration-test
---
 arrow-arith/src/arithmetic.rs                | 3160 +-------------------------
 arrow-arith/src/arity.rs                     |   71 -
 arrow-pyarrow-integration-testing/src/lib.rs |    2 +-
 arrow/src/ffi.rs                             |   11 +-
 arrow/src/lib.rs                             |    2 +-
 5 files changed, 77 insertions(+), 3169 deletions(-)

diff --git a/arrow-arith/src/arithmetic.rs b/arrow-arith/src/arithmetic.rs
index f8c855af01..8635ce0ddd 100644
--- a/arrow-arith/src/arithmetic.rs
+++ b/arrow-arith/src/arithmetic.rs
@@ -31,552 +31,6 @@ use arrow_schema::*;
 use std::cmp::min;
 use std::sync::Arc;
 
-/// Helper function to perform math lambda function on values from two arrays. 
If either
-/// left or right value is null then the output value is also null, so `1 + 
null` is
-/// `null`.
-///
-/// # Errors
-///
-/// This function errors if the arrays have different lengths
-#[deprecated(note = "Use arrow_arith::arity::binary")]
-pub fn math_op<LT, RT, F>(
-    left: &PrimitiveArray<LT>,
-    right: &PrimitiveArray<RT>,
-    op: F,
-) -> Result<PrimitiveArray<LT>, ArrowError>
-where
-    LT: ArrowNumericType,
-    RT: ArrowNumericType,
-    F: Fn(LT::Native, RT::Native) -> LT::Native,
-{
-    binary(left, right, op)
-}
-
-/// Calculates the modulus operation `left % right` on two SIMD inputs.
-/// The lower-most bits of `valid_mask` specify which vector lanes are 
considered as valid.
-///
-/// # Errors
-///
-/// This function returns a [`ArrowError::DivideByZero`] if a valid element in 
`right` is `0`
-#[cfg(feature = "simd")]
-#[inline]
-fn simd_checked_modulus<T: ArrowNumericType>(
-    valid_mask: Option<u64>,
-    left: T::Simd,
-    right: T::Simd,
-) -> Result<T::Simd, ArrowError> {
-    let zero = T::init(T::Native::ZERO);
-    let one = T::init(T::Native::ONE);
-
-    let right_no_invalid_zeros = match valid_mask {
-        Some(mask) => {
-            let simd_mask = T::mask_from_u64(mask);
-            // select `1` for invalid lanes, which will be a no-op during 
division later
-            T::mask_select(simd_mask, right, one)
-        }
-        None => right,
-    };
-
-    let zero_mask = T::eq(right_no_invalid_zeros, zero);
-
-    if T::mask_any(zero_mask) {
-        Err(ArrowError::DivideByZero)
-    } else {
-        Ok(T::bin_op(left, right_no_invalid_zeros, |a, b| a % b))
-    }
-}
-
-/// Calculates the division operation `left / right` on two SIMD inputs.
-/// The lower-most bits of `valid_mask` specify which vector lanes are 
considered as valid.
-///
-/// # Errors
-///
-/// This function returns a [`ArrowError::DivideByZero`] if a valid element in 
`right` is `0`
-#[cfg(feature = "simd")]
-#[inline]
-fn simd_checked_divide<T: ArrowNumericType>(
-    valid_mask: Option<u64>,
-    left: T::Simd,
-    right: T::Simd,
-) -> Result<T::Simd, ArrowError> {
-    let zero = T::init(T::Native::ZERO);
-    let one = T::init(T::Native::ONE);
-
-    let right_no_invalid_zeros = match valid_mask {
-        Some(mask) => {
-            let simd_mask = T::mask_from_u64(mask);
-            // select `1` for invalid lanes, which will be a no-op during 
division later
-            T::mask_select(simd_mask, right, one)
-        }
-        None => right,
-    };
-
-    let zero_mask = T::eq(right_no_invalid_zeros, zero);
-
-    if T::mask_any(zero_mask) {
-        Err(ArrowError::DivideByZero)
-    } else {
-        Ok(T::bin_op(left, right_no_invalid_zeros, |a, b| a / b))
-    }
-}
-
-/// Applies `op` on the remainder elements of two input chunks and writes the 
result into
-/// the remainder elements of `result_chunks`.
-/// The lower-most bits of `valid_mask` specify which elements are considered 
as valid.
-///
-/// # Errors
-///
-/// This function returns a [`ArrowError::DivideByZero`] if a valid element in 
`right` is `0`
-#[cfg(feature = "simd")]
-#[inline]
-fn simd_checked_divide_op_remainder<T, F>(
-    valid_mask: Option<u64>,
-    left_chunks: std::slice::ChunksExact<T::Native>,
-    right_chunks: std::slice::ChunksExact<T::Native>,
-    result_chunks: std::slice::ChunksExactMut<T::Native>,
-    op: F,
-) -> Result<(), ArrowError>
-where
-    T: ArrowNumericType,
-    F: Fn(T::Native, T::Native) -> T::Native,
-{
-    let result_remainder = result_chunks.into_remainder();
-    let left_remainder = left_chunks.remainder();
-    let right_remainder = right_chunks.remainder();
-
-    result_remainder
-        .iter_mut()
-        .zip(left_remainder.iter().zip(right_remainder.iter()))
-        .enumerate()
-        .try_for_each(|(i, (result_scalar, (left_scalar, right_scalar)))| {
-            if valid_mask.map(|mask| mask & (1 << i) != 0).unwrap_or(true) {
-                if right_scalar.is_zero() {
-                    return Err(ArrowError::DivideByZero);
-                }
-                *result_scalar = op(*left_scalar, *right_scalar);
-            } else {
-                *result_scalar = T::default_value();
-            }
-            Ok(())
-        })?;
-
-    Ok(())
-}
-
-/// Creates a new PrimitiveArray by applying `simd_op` to the `left` and 
`right` input array.
-/// If the length of the arrays is not multiple of the number of vector lanes
-/// then the remainder of the array will be calculated using `scalar_op`.
-/// Any operation on a `NULL` value will result in a `NULL` value in the 
output.
-///
-/// # Errors
-///
-/// This function errors if:
-/// * the arrays have different lengths
-/// * there is an element where both left and right values are valid and the 
right value is `0`
-#[cfg(feature = "simd")]
-fn simd_checked_divide_op<T, SI, SC>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-    simd_op: SI,
-    scalar_op: SC,
-) -> Result<PrimitiveArray<T>, ArrowError>
-where
-    T: ArrowNumericType,
-    SI: Fn(Option<u64>, T::Simd, T::Simd) -> Result<T::Simd, ArrowError>,
-    SC: Fn(T::Native, T::Native) -> T::Native,
-{
-    if left.len() != right.len() {
-        return Err(ArrowError::ComputeError(
-            "Cannot perform math operation on arrays of different 
length".to_string(),
-        ));
-    }
-
-    // Create the combined `Bitmap`
-    let nulls = arrow_buffer::NullBuffer::union(left.nulls(), right.nulls());
-
-    let lanes = T::lanes();
-    let buffer_size = left.len() * std::mem::size_of::<T::Native>();
-    let mut result =
-        arrow_buffer::MutableBuffer::new(buffer_size).with_bitset(buffer_size, 
false);
-
-    match &nulls {
-        Some(b) => {
-            let valid_chunks = b.inner().bit_chunks();
-
-            // process data in chunks of 64 elements since we also get 64 bits 
of validity information at a time
-
-            let mut result_chunks = 
result.typed_data_mut().chunks_exact_mut(64);
-            let mut left_chunks = left.values().chunks_exact(64);
-            let mut right_chunks = right.values().chunks_exact(64);
-
-            valid_chunks
-                .iter()
-                .zip((&mut result_chunks).zip((&mut left_chunks).zip(&mut 
right_chunks)))
-                .try_for_each(
-                    |(mut mask, (result_slice, (left_slice, right_slice)))| {
-                        // split chunks further into slices corresponding to 
the vector length
-                        // the compiler is able to unroll this inner loop and 
remove bounds checks
-                        // since the outer chunk size (64) is always a 
multiple of the number of lanes
-                        result_slice
-                            .chunks_exact_mut(lanes)
-                            
.zip(left_slice.chunks_exact(lanes).zip(right_slice.chunks_exact(lanes)))
-                            .try_for_each(|(result_slice, (left_slice, 
right_slice))| -> Result<(), ArrowError> {
-                                let simd_left = T::load(left_slice);
-                                let simd_right = T::load(right_slice);
-
-                                let simd_result = simd_op(Some(mask), 
simd_left, simd_right)?;
-
-                                T::write(simd_result, result_slice);
-
-                                // skip the shift and avoid overflow for u8 
type, which uses 64 lanes.
-                                mask >>= T::lanes() % 64;
-
-                                Ok(())
-                            })
-                    },
-                )?;
-
-            let valid_remainder = valid_chunks.remainder_bits();
-
-            simd_checked_divide_op_remainder::<T, _>(
-                Some(valid_remainder),
-                left_chunks,
-                right_chunks,
-                result_chunks,
-                scalar_op,
-            )?;
-        }
-        None => {
-            let mut result_chunks = 
result.typed_data_mut().chunks_exact_mut(lanes);
-            let mut left_chunks = left.values().chunks_exact(lanes);
-            let mut right_chunks = right.values().chunks_exact(lanes);
-
-            (&mut result_chunks)
-                .zip((&mut left_chunks).zip(&mut right_chunks))
-                .try_for_each(
-                |(result_slice, (left_slice, right_slice))| -> Result<(), 
ArrowError> {
-                    let simd_left = T::load(left_slice);
-                    let simd_right = T::load(right_slice);
-
-                    let simd_result = simd_op(None, simd_left, simd_right)?;
-
-                    T::write(simd_result, result_slice);
-
-                    Ok(())
-                },
-            )?;
-
-            simd_checked_divide_op_remainder::<T, _>(
-                None,
-                left_chunks,
-                right_chunks,
-                result_chunks,
-                scalar_op,
-            )?;
-        }
-    }
-
-    Ok(PrimitiveArray::new(result.into(), nulls))
-}
-
-fn math_safe_divide_op<LT, RT, F>(
-    left: &PrimitiveArray<LT>,
-    right: &PrimitiveArray<RT>,
-    op: F,
-) -> Result<ArrayRef, ArrowError>
-where
-    LT: ArrowNumericType,
-    RT: ArrowNumericType,
-    F: Fn(LT::Native, RT::Native) -> Option<LT::Native>,
-{
-    let array: PrimitiveArray<LT> = binary_opt::<_, _, _, LT>(left, right, 
op)?;
-    Ok(Arc::new(array) as ArrayRef)
-}
-
-/// Perform `left + right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `add_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::add_wrapping")]
-pub fn add<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    binary(left, right, |a, b| a.add_wrapping(b))
-}
-
-/// Perform `left + right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `add` instead.
-#[deprecated(note = "Use arrow_arith::numeric::add")]
-pub fn add_checked<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    try_binary(left, right, |a, b| a.add_checked(b))
-}
-
-/// Perform `left + right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `add_dyn_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::add_wrapping")]
-pub fn add_dyn(left: &dyn Array, right: &dyn Array) -> Result<ArrayRef, 
ArrowError> {
-    crate::numeric::add_wrapping(&left, &right)
-}
-
-/// Perform `left + right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `add_dyn` instead.
-#[deprecated(note = "Use arrow_arith::numeric::add")]
-pub fn add_dyn_checked(
-    left: &dyn Array,
-    right: &dyn Array,
-) -> Result<ArrayRef, ArrowError> {
-    crate::numeric::add(&left, &right)
-}
-
-/// Add every value in an array by a scalar. If any value in the array is null 
then the
-/// result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `add_scalar_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::add_wrapping")]
-pub fn add_scalar<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-    scalar: T::Native,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    Ok(unary(array, |value| value.add_wrapping(scalar)))
-}
-
-/// Add every value in an array by a scalar. If any value in the array is null 
then the
-/// result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `add_scalar` instead.
-#[deprecated(note = "Use arrow_arith::numeric::add")]
-pub fn add_scalar_checked<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-    scalar: T::Native,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    try_unary(array, |value| value.add_checked(scalar))
-}
-
-/// Add every value in an array by a scalar. If any value in the array is null 
then the
-/// result is also null. The given array must be a `PrimitiveArray` of the 
type same as
-/// the scalar, or a `DictionaryArray` of the value type same as the scalar.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `add_scalar_checked_dyn` instead.
-///
-/// This returns an `Err` when the input array is not supported for adding 
operation.
-#[deprecated(note = "Use arrow_arith::numeric::add_wrapping")]
-pub fn add_scalar_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    scalar: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    unary_dyn::<_, T>(array, |value| value.add_wrapping(scalar))
-}
-
-/// Add every value in an array by a scalar. If any value in the array is null 
then the
-/// result is also null. The given array must be a `PrimitiveArray` of the 
type same as
-/// the scalar, or a `DictionaryArray` of the value type same as the scalar.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `add_scalar_dyn` instead.
-///
-/// As this kernel has the branching costs and also prevents LLVM from 
vectorising it correctly,
-/// it is usually much slower than non-checking variant.
-#[deprecated(note = "Use arrow_arith::numeric::add")]
-pub fn add_scalar_checked_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    scalar: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    try_unary_dyn::<_, T>(array, |value| value.add_checked(scalar))
-        .map(|a| Arc::new(a) as ArrayRef)
-}
-
-/// Perform `left - right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `subtract_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::sub_wrapping")]
-pub fn subtract<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    binary(left, right, |a, b| a.sub_wrapping(b))
-}
-
-/// Perform `left - right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `subtract` instead.
-#[deprecated(note = "Use arrow_arith::numeric::sub")]
-pub fn subtract_checked<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    try_binary(left, right, |a, b| a.sub_checked(b))
-}
-
-/// Perform `left - right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `subtract_dyn_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::sub_wrapping")]
-pub fn subtract_dyn(left: &dyn Array, right: &dyn Array) -> Result<ArrayRef, 
ArrowError> {
-    crate::numeric::sub_wrapping(&left, &right)
-}
-
-/// Perform `left - right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `subtract_dyn` instead.
-#[deprecated(note = "Use arrow_arith::numeric::sub")]
-pub fn subtract_dyn_checked(
-    left: &dyn Array,
-    right: &dyn Array,
-) -> Result<ArrayRef, ArrowError> {
-    crate::numeric::sub(&left, &right)
-}
-
-/// Subtract every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `subtract_scalar_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::sub_wrapping")]
-pub fn subtract_scalar<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-    scalar: T::Native,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    Ok(unary(array, |value| value.sub_wrapping(scalar)))
-}
-
-/// Subtract every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `subtract_scalar` instead.
-#[deprecated(note = "Use arrow_arith::numeric::sub")]
-pub fn subtract_scalar_checked<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-    scalar: T::Native,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    try_unary(array, |value| value.sub_checked(scalar))
-}
-
-/// Subtract every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. The given array must be a `PrimitiveArray` of the 
type same as
-/// the scalar, or a `DictionaryArray` of the value type same as the scalar.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `subtract_scalar_checked_dyn` 
instead.
-#[deprecated(note = "Use arrow_arith::numeric::sub_wrapping")]
-pub fn subtract_scalar_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    scalar: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    unary_dyn::<_, T>(array, |value| value.sub_wrapping(scalar))
-}
-
-/// Subtract every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. The given array must be a `PrimitiveArray` of the 
type same as
-/// the scalar, or a `DictionaryArray` of the value type same as the scalar.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `subtract_scalar_dyn` instead.
-#[deprecated(note = "Use arrow_arith::numeric::sub")]
-pub fn subtract_scalar_checked_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    scalar: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    try_unary_dyn::<_, T>(array, |value| value.sub_checked(scalar))
-        .map(|a| Arc::new(a) as ArrayRef)
-}
-
-/// Perform `-` operation on an array. If value is null then the result is 
also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `negate_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::neg_wrapping")]
-pub fn negate<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    Ok(unary(array, |x| x.neg_wrapping()))
-}
-
-/// Perform `-` operation on an array. If value is null then the result is 
also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `negate` instead.
-#[deprecated(note = "Use arrow_arith::numeric::neg")]
-pub fn negate_checked<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    try_unary(array, |value| value.neg_checked())
-}
-
-/// Perform `left * right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `multiply_check` instead.
-#[deprecated(note = "Use arrow_arith::numeric::mul_wrapping")]
-pub fn multiply<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    binary(left, right, |a, b| a.mul_wrapping(b))
-}
-
-/// Perform `left * right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `multiply` instead.
-#[deprecated(note = "Use arrow_arith::numeric::mul")]
-pub fn multiply_checked<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    try_binary(left, right, |a, b| a.mul_checked(b))
-}
-
-/// Perform `left * right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `multiply_dyn_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::mul_wrapping")]
-pub fn multiply_dyn(left: &dyn Array, right: &dyn Array) -> Result<ArrayRef, 
ArrowError> {
-    crate::numeric::mul_wrapping(&left, &right)
-}
-
-/// Perform `left * right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `multiply_dyn` instead.
-#[deprecated(note = "Use arrow_arith::numeric::mul")]
-pub fn multiply_dyn_checked(
-    left: &dyn Array,
-    right: &dyn Array,
-) -> Result<ArrayRef, ArrowError> {
-    crate::numeric::mul(&left, &right)
-}
-
 /// Returns the precision and scale of the result of a multiplication of two 
decimal types,
 /// and the divisor for fixed point multiplication.
 fn get_fixed_point_info(
@@ -740,1861 +194,81 @@ where
     }
 }
 
-/// Multiply every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `multiply_scalar_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::mul_wrapping")]
-pub fn multiply_scalar<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-    scalar: T::Native,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    Ok(unary(array, |value| value.mul_wrapping(scalar)))
-}
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::numeric::mul;
 
-/// Multiply every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `multiply_scalar` instead.
-#[deprecated(note = "Use arrow_arith::numeric::mul")]
-pub fn multiply_scalar_checked<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-    scalar: T::Native,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    try_unary(array, |value| value.mul_checked(scalar))
-}
+    #[test]
+    fn test_decimal_multiply_allow_precision_loss() {
+        // Overflow happening as i128 cannot hold multiplying result.
+        // [123456789]
+        let a = Decimal128Array::from(vec![123456789000000000000000000])
+            .with_precision_and_scale(38, 18)
+            .unwrap();
 
-/// Multiply every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. The given array must be a `PrimitiveArray` of the 
type same as
-/// the scalar, or a `DictionaryArray` of the value type same as the scalar.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `multiply_scalar_checked_dyn` 
instead.
-#[deprecated(note = "Use arrow_arith::numeric::mul_wrapping")]
-pub fn multiply_scalar_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    scalar: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    unary_dyn::<_, T>(array, |value| value.mul_wrapping(scalar))
-}
+        // [10]
+        let b = Decimal128Array::from(vec![10000000000000000000])
+            .with_precision_and_scale(38, 18)
+            .unwrap();
 
-/// Subtract every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. The given array must be a `PrimitiveArray` of the 
type same as
-/// the scalar, or a `DictionaryArray` of the value type same as the scalar.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `multiply_scalar_dyn` instead.
-#[deprecated(note = "Use arrow_arith::numeric::mul")]
-pub fn multiply_scalar_checked_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    scalar: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    try_unary_dyn::<_, T>(array, |value| value.mul_checked(scalar))
-        .map(|a| Arc::new(a) as ArrayRef)
-}
+        let err = mul(&a, &b).unwrap_err();
+        assert!(err.to_string().contains(
+            "Overflow happened on: 123456789000000000000000000 * 
10000000000000000000"
+        ));
 
-/// Perform `left % right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null. If any right hand value is zero then the 
result of this
-/// operation will be `Err(ArrowError::DivideByZero)`.
-#[deprecated(note = "Use arrow_arith::numeric::rem")]
-pub fn modulus<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    #[cfg(feature = "simd")]
-    return simd_checked_divide_op(&left, &right, simd_checked_modulus::<T>, 
|a, b| {
-        a.mod_wrapping(b)
-    });
-    #[cfg(not(feature = "simd"))]
-    return try_binary(left, right, |a, b| {
-        if b.is_zero() {
-            Err(ArrowError::DivideByZero)
-        } else {
-            Ok(a.mod_wrapping(b))
-        }
-    });
-}
+        // Allow precision loss.
+        let result = multiply_fixed_point_checked(&a, &b, 28).unwrap();
+        // [1234567890]
+        let expected =
+            Decimal128Array::from(vec![12345678900000000000000000000000000000])
+                .with_precision_and_scale(38, 28)
+                .unwrap();
 
-/// Perform `left % right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null. If any right hand value is zero then the 
result of this
-/// operation will be `Err(ArrowError::DivideByZero)`.
-#[deprecated(note = "Use arrow_arith::numeric::rem")]
-pub fn modulus_dyn(left: &dyn Array, right: &dyn Array) -> Result<ArrayRef, 
ArrowError> {
-    crate::numeric::rem(&left, &right)
-}
+        assert_eq!(&expected, &result);
+        assert_eq!(
+            result.value_as_string(0),
+            "1234567890.0000000000000000000000000000"
+        );
 
-/// Perform `left / right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null. If any right hand value is zero then the 
result of this
-/// operation will be `Err(ArrowError::DivideByZero)`.
-///
-/// When `simd` feature is not enabled. This detects overflow and returns an 
`Err` for that.
-/// For an non-overflow-checking variant, use `divide` instead.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_checked<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    #[cfg(feature = "simd")]
-    return simd_checked_divide_op(&left, &right, simd_checked_divide::<T>, |a, 
b| {
-        a.div_wrapping(b)
-    });
-    #[cfg(not(feature = "simd"))]
-    return try_binary(left, right, |a, b| a.div_checked(b));
-}
+        // Rounding case
+        // [0.000000000000000001, 123456789.555555555555555555, 
1.555555555555555555]
+        let a = Decimal128Array::from(vec![
+            1,
+            123456789555555555555555555,
+            1555555555555555555,
+        ])
+        .with_precision_and_scale(38, 18)
+        .unwrap();
 
-/// Perform `left / right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// If any right hand value is zero, the operation value will be replaced with 
null in the
-/// result.
-///
-/// Unlike [`divide`] or [`divide_checked`], division by zero will yield a 
null value in the
-/// result instead of returning an `Err`.
-///
-/// For floating point types overflow will saturate at INF or -INF
-/// preserving the expected sign value.
-///
-/// For integer types overflow will wrap around.
-///
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_opt<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    binary_opt(left, right, |a, b| {
-        if b.is_zero() {
-            None
-        } else {
-            Some(a.div_wrapping(b))
-        }
-    })
-}
+        // [1.555555555555555555, 11.222222222222222222, 0.000000000000000001]
+        let b = Decimal128Array::from(vec![1555555555555555555, 
11222222222222222222, 1])
+            .with_precision_and_scale(38, 18)
+            .unwrap();
 
-/// Perform `left / right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null. If any right hand value is zero then the 
result of this
-/// operation will be `Err(ArrowError::DivideByZero)`.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `divide_dyn_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_dyn(left: &dyn Array, right: &dyn Array) -> Result<ArrayRef, 
ArrowError> {
-    fn divide_op<T: ArrowPrimitiveType>(
-        left: &PrimitiveArray<T>,
-        right: &PrimitiveArray<T>,
-    ) -> Result<PrimitiveArray<T>, ArrowError> {
-        try_binary(left, right, |a, b| {
-            if b.is_zero() {
-                Err(ArrowError::DivideByZero)
-            } else {
-                Ok(a.div_wrapping(b))
-            }
-        })
-    }
+        let result = multiply_fixed_point_checked(&a, &b, 28).unwrap();
+        // [
+        //    0.0000000000000000015555555556,
+        //    1385459527.2345679012071330528765432099,
+        //    0.0000000000000000015555555556
+        // ]
+        let expected = Decimal128Array::from(vec![
+            15555555556,
+            13854595272345679012071330528765432099,
+            15555555556,
+        ])
+        .with_precision_and_scale(38, 28)
+        .unwrap();
 
-    downcast_primitive_array!(
-        (left, right) => divide_op(left, right).map(|a| Arc::new(a) as 
ArrayRef),
-        _ => Err(ArrowError::CastError(format!(
-            "Unsupported data type {}, {}",
-            left.data_type(), right.data_type()
-        )))
-    )
-}
+        assert_eq!(&expected, &result);
 
-/// Perform `left / right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null. If any right hand value is zero then the 
result of this
-/// operation will be `Err(ArrowError::DivideByZero)`.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `divide_dyn` instead.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_dyn_checked(
-    left: &dyn Array,
-    right: &dyn Array,
-) -> Result<ArrayRef, ArrowError> {
-    crate::numeric::div(&left, &right)
-}
-
-/// Perform `left / right` operation on two arrays. If either left or right 
value is null
-/// then the result is also null.
-///
-/// If any right hand value is zero, the operation value will be replaced with 
null in the
-/// result.
-///
-/// Unlike `divide_dyn` or `divide_dyn_checked`, division by zero will get a 
null value instead
-/// returning an `Err`, this also doesn't check overflowing, overflowing will 
just wrap
-/// the result around.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_dyn_opt(
-    left: &dyn Array,
-    right: &dyn Array,
-) -> Result<ArrayRef, ArrowError> {
-    downcast_primitive_array!(
-        (left, right) => {
-            math_safe_divide_op(left, right, |a, b| {
-                if b.is_zero() {
-                    None
-                } else {
-                    Some(a.div_wrapping(b))
-                }
-            })
-        }
-        _ => Err(ArrowError::CastError(format!(
-            "Unsupported data type {}, {}",
-            left.data_type(), right.data_type()
-        )))
-    )
-}
-
-/// Perform `left / right` operation on two arrays without checking for
-/// division by zero or overflow.
-///
-/// For floating point types, overflow and division by zero follows normal 
floating point rules
-///
-/// For integer types overflow will wrap around. Division by zero will 
currently panic, although
-/// this may be subject to change see 
<https://github.com/apache/arrow-rs/issues/2647>
-///
-/// If either left or right value is null then the result is also null.
-///
-/// For an overflow-checking variant, use `divide_checked` instead.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide<T: ArrowNumericType>(
-    left: &PrimitiveArray<T>,
-    right: &PrimitiveArray<T>,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    // TODO: This is incorrect as div_wrapping has side-effects for integer 
types
-    // and so may panic on null values (#2647)
-    binary(left, right, |a, b| a.div_wrapping(b))
-}
-
-/// Modulus every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. If the scalar is zero then the result of this 
operation will be
-/// `Err(ArrowError::DivideByZero)`.
-#[deprecated(note = "Use arrow_arith::numeric::rem")]
-pub fn modulus_scalar<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-    modulo: T::Native,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    if modulo.is_zero() {
-        return Err(ArrowError::DivideByZero);
-    }
-
-    Ok(unary(array, |a| a.mod_wrapping(modulo)))
-}
-
-/// Modulus every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. If the scalar is zero then the result of this 
operation will be
-/// `Err(ArrowError::DivideByZero)`.
-#[deprecated(note = "Use arrow_arith::numeric::rem")]
-pub fn modulus_scalar_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    modulo: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    if modulo.is_zero() {
-        return Err(ArrowError::DivideByZero);
-    }
-    unary_dyn::<_, T>(array, |value| value.mod_wrapping(modulo))
-}
-
-/// Divide every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. If the scalar is zero then the result of this 
operation will be
-/// `Err(ArrowError::DivideByZero)`.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_scalar<T: ArrowNumericType>(
-    array: &PrimitiveArray<T>,
-    divisor: T::Native,
-) -> Result<PrimitiveArray<T>, ArrowError> {
-    if divisor.is_zero() {
-        return Err(ArrowError::DivideByZero);
-    }
-    Ok(unary(array, |a| a.div_wrapping(divisor)))
-}
-
-/// Divide every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. If the scalar is zero then the result of this 
operation will be
-/// `Err(ArrowError::DivideByZero)`. The given array must be a 
`PrimitiveArray` of the type
-/// same as the scalar, or a `DictionaryArray` of the value type same as the 
scalar.
-///
-/// This doesn't detect overflow. Once overflowing, the result will wrap 
around.
-/// For an overflow-checking variant, use `divide_scalar_checked_dyn` instead.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_scalar_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    divisor: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    if divisor.is_zero() {
-        return Err(ArrowError::DivideByZero);
-    }
-    unary_dyn::<_, T>(array, |value| value.div_wrapping(divisor))
-}
-
-/// Divide every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. If the scalar is zero then the result of this 
operation will be
-/// `Err(ArrowError::DivideByZero)`. The given array must be a 
`PrimitiveArray` of the type
-/// same as the scalar, or a `DictionaryArray` of the value type same as the 
scalar.
-///
-/// This detects overflow and returns an `Err` for that. For an 
non-overflow-checking variant,
-/// use `divide_scalar_dyn` instead.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_scalar_checked_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    divisor: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    if divisor.is_zero() {
-        return Err(ArrowError::DivideByZero);
-    }
-
-    try_unary_dyn::<_, T>(array, |value| value.div_checked(divisor))
-        .map(|a| Arc::new(a) as ArrayRef)
-}
-
-/// Divide every value in an array by a scalar. If any value in the array is 
null then the
-/// result is also null. The given array must be a `PrimitiveArray` of the type
-/// same as the scalar, or a `DictionaryArray` of the value type same as the 
scalar.
-///
-/// If any right hand value is zero, the operation value will be replaced with 
null in the
-/// result.
-///
-/// Unlike `divide_scalar_dyn` or `divide_scalar_checked_dyn`, division by 
zero will get a
-/// null value instead returning an `Err`, this also doesn't check 
overflowing, overflowing
-/// will just wrap the result around.
-#[deprecated(note = "Use arrow_arith::numeric::div")]
-pub fn divide_scalar_opt_dyn<T: ArrowNumericType>(
-    array: &dyn Array,
-    divisor: T::Native,
-) -> Result<ArrayRef, ArrowError> {
-    if divisor.is_zero() {
-        match array.data_type() {
-            DataType::Dictionary(_, value_type) => {
-                return Ok(new_null_array(value_type.as_ref(), array.len()))
-            }
-            _ => return Ok(new_null_array(array.data_type(), array.len())),
-        }
-    }
-
-    unary_dyn::<_, T>(array, |value| value.div_wrapping(divisor))
-}
-
-#[cfg(test)]
-#[allow(deprecated)]
-mod tests {
-    use super::*;
-    use arrow_array::builder::{
-        BooleanBufferBuilder, BufferBuilder, PrimitiveDictionaryBuilder,
-    };
-    use arrow_array::cast::AsArray;
-    use arrow_array::temporal_conversions::SECONDS_IN_DAY;
-    use arrow_buffer::buffer::NullBuffer;
-    use arrow_buffer::i256;
-    use arrow_data::ArrayDataBuilder;
-    use chrono::NaiveDate;
-    use half::f16;
-
-    #[test]
-    fn test_primitive_array_add() {
-        let a = Int32Array::from(vec![5, 6, 7, 8, 9]);
-        let b = Int32Array::from(vec![6, 7, 8, 9, 8]);
-        let c = add(&a, &b).unwrap();
-        assert_eq!(11, c.value(0));
-        assert_eq!(13, c.value(1));
-        assert_eq!(15, c.value(2));
-        assert_eq!(17, c.value(3));
-        assert_eq!(17, c.value(4));
-    }
-
-    #[test]
-    fn test_date32_month_add() {
-        let a = Date32Array::from(vec![Date32Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(),
-        )]);
-        let b =
-            
IntervalYearMonthArray::from(vec![IntervalYearMonthType::make_value(1, 2)]);
-        let c = add_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Date32Array>().unwrap();
-        assert_eq!(
-            c.value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2001, 3, 
1).unwrap())
-        );
-
-        let c = add_dyn(&b, &a).unwrap();
-        let c = c.as_any().downcast_ref::<Date32Array>().unwrap();
-        assert_eq!(
-            c.value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2001, 3, 
1).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date32_day_time_add() {
-        let a = Date32Array::from(vec![Date32Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(),
-        )]);
-        let b = 
IntervalDayTimeArray::from(vec![IntervalDayTimeType::make_value(1, 2)]);
-        let c = add_dyn(&a, &b).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date32Type>().value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2000, 1, 
2).unwrap())
-        );
-
-        let c = add_dyn(&b, &a).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date32Type>().value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2000, 1, 
2).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date32_month_day_nano_add() {
-        let a = Date32Array::from(vec![Date32Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(),
-        )]);
-        let b =
-            
IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
-                1, 2, 3,
-            )]);
-        let c = add_dyn(&a, &b).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date32Type>().value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2000, 2, 
3).unwrap())
-        );
-
-        let c = add_dyn(&b, &a).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date32Type>().value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2000, 2, 
3).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date64_month_add() {
-        let a = Date64Array::from(vec![Date64Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(),
-        )]);
-        let b =
-            
IntervalYearMonthArray::from(vec![IntervalYearMonthType::make_value(1, 2)]);
-        let c = add_dyn(&a, &b).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date64Type>().value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2001, 3, 
1).unwrap())
-        );
-
-        let c = add_dyn(&b, &a).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date64Type>().value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2001, 3, 
1).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date64_day_time_add() {
-        let a = Date64Array::from(vec![Date64Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(),
-        )]);
-        let b = 
IntervalDayTimeArray::from(vec![IntervalDayTimeType::make_value(1, 2)]);
-        let c = add_dyn(&a, &b).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date64Type>().value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2000, 1, 
2).unwrap())
-        );
-
-        let c = add_dyn(&b, &a).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date64Type>().value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2000, 1, 
2).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date64_month_day_nano_add() {
-        let a = Date64Array::from(vec![Date64Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2000, 1, 1).unwrap(),
-        )]);
-        let b =
-            
IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
-                1, 2, 3,
-            )]);
-        let c = add_dyn(&a, &b).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date64Type>().value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2000, 2, 
3).unwrap())
-        );
-
-        let c = add_dyn(&b, &a).unwrap();
-        assert_eq!(
-            c.as_primitive::<Date64Type>().value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2000, 2, 
3).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_primitive_array_add_dyn() {
-        let a = Int32Array::from(vec![Some(5), Some(6), Some(7), Some(8), 
Some(9)]);
-        let b = Int32Array::from(vec![Some(6), Some(7), Some(8), None, 
Some(8)]);
-        let c = add_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Int32Array>().unwrap();
-        assert_eq!(11, c.value(0));
-        assert_eq!(13, c.value(1));
-        assert_eq!(15, c.value(2));
-        assert!(c.is_null(3));
-        assert_eq!(17, c.value(4));
-    }
-
-    #[test]
-    fn test_primitive_array_add_scalar_dyn() {
-        let a = Int32Array::from(vec![Some(5), Some(6), Some(7), None, 
Some(9)]);
-        let b = 1_i32;
-        let c = add_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c.as_any().downcast_ref::<Int32Array>().unwrap();
-        assert_eq!(6, c.value(0));
-        assert_eq!(7, c.value(1));
-        assert_eq!(8, c.value(2));
-        assert!(c.is_null(3));
-        assert_eq!(10, c.value(4));
-
-        let mut builder = PrimitiveDictionaryBuilder::<Int8Type, 
Int32Type>::new();
-        builder.append(5).unwrap();
-        builder.append_null();
-        builder.append(7).unwrap();
-        builder.append(8).unwrap();
-        builder.append(9).unwrap();
-        let a = builder.finish();
-        let b = -1_i32;
-
-        let c = add_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c
-            .as_any()
-            .downcast_ref::<DictionaryArray<Int8Type>>()
-            .unwrap();
-        let values = c
-            .values()
-            .as_any()
-            .downcast_ref::<PrimitiveArray<Int32Type>>()
-            .unwrap();
-        assert_eq!(4, values.value(c.key(0).unwrap()));
-        assert!(c.is_null(1));
-        assert_eq!(6, values.value(c.key(2).unwrap()));
-        assert_eq!(7, values.value(c.key(3).unwrap()));
-        assert_eq!(8, values.value(c.key(4).unwrap()));
-    }
-
-    #[test]
-    fn test_primitive_array_subtract_dyn() {
-        let a = Int32Array::from(vec![Some(51), Some(6), Some(15), Some(8), 
Some(9)]);
-        let b = Int32Array::from(vec![Some(6), Some(7), Some(8), None, 
Some(8)]);
-        let c = subtract_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Int32Array>().unwrap();
-        assert_eq!(45, c.value(0));
-        assert_eq!(-1, c.value(1));
-        assert_eq!(7, c.value(2));
-        assert!(c.is_null(3));
-        assert_eq!(1, c.value(4));
-    }
-
-    #[test]
-    fn test_date32_month_subtract() {
-        let a = Date32Array::from(vec![Date32Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2000, 7, 1).unwrap(),
-        )]);
-        let b =
-            
IntervalYearMonthArray::from(vec![IntervalYearMonthType::make_value(6, 3)]);
-        let c = subtract_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Date32Array>().unwrap();
-        assert_eq!(
-            c.value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(1994, 4, 
1).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date32_day_time_subtract() {
-        let a = Date32Array::from(vec![Date32Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2023, 3, 29).unwrap(),
-        )]);
-        let b =
-            IntervalDayTimeArray::from(vec![IntervalDayTimeType::make_value(1, 
86500)]);
-        let c = subtract_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Date32Array>().unwrap();
-        assert_eq!(
-            c.value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2023, 3, 
28).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date32_month_day_nano_subtract() {
-        let a = Date32Array::from(vec![Date32Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2023, 3, 15).unwrap(),
-        )]);
-        let b =
-            
IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
-                1, 2, 0,
-            )]);
-        let c = subtract_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Date32Array>().unwrap();
-        assert_eq!(
-            c.value(0),
-            Date32Type::from_naive_date(NaiveDate::from_ymd_opt(2023, 2, 
13).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date64_month_subtract() {
-        let a = Date64Array::from(vec![Date64Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2000, 7, 1).unwrap(),
-        )]);
-        let b =
-            
IntervalYearMonthArray::from(vec![IntervalYearMonthType::make_value(6, 3)]);
-        let c = subtract_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Date64Array>().unwrap();
-        assert_eq!(
-            c.value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(1994, 4, 
1).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date64_day_time_subtract() {
-        let a = Date64Array::from(vec![Date64Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2023, 3, 29).unwrap(),
-        )]);
-        let b =
-            IntervalDayTimeArray::from(vec![IntervalDayTimeType::make_value(1, 
86500)]);
-        let c = subtract_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Date64Array>().unwrap();
-        assert_eq!(
-            c.value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2023, 3, 
28).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_date64_month_day_nano_subtract() {
-        let a = Date64Array::from(vec![Date64Type::from_naive_date(
-            NaiveDate::from_ymd_opt(2023, 3, 15).unwrap(),
-        )]);
-        let b =
-            
IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNanoType::make_value(
-                1, 2, 0,
-            )]);
-        let c = subtract_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Date64Array>().unwrap();
-        assert_eq!(
-            c.value(0),
-            Date64Type::from_naive_date(NaiveDate::from_ymd_opt(2023, 2, 
13).unwrap())
-        );
-    }
-
-    #[test]
-    fn test_primitive_array_subtract_scalar_dyn() {
-        let a = Int32Array::from(vec![Some(5), Some(6), Some(7), None, 
Some(9)]);
-        let b = 1_i32;
-        let c = subtract_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c.as_any().downcast_ref::<Int32Array>().unwrap();
-        assert_eq!(4, c.value(0));
-        assert_eq!(5, c.value(1));
-        assert_eq!(6, c.value(2));
-        assert!(c.is_null(3));
-        assert_eq!(8, c.value(4));
-
-        let mut builder = PrimitiveDictionaryBuilder::<Int8Type, 
Int32Type>::new();
-        builder.append(5).unwrap();
-        builder.append_null();
-        builder.append(7).unwrap();
-        builder.append(8).unwrap();
-        builder.append(9).unwrap();
-        let a = builder.finish();
-        let b = -1_i32;
-
-        let c = subtract_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c
-            .as_any()
-            .downcast_ref::<DictionaryArray<Int8Type>>()
-            .unwrap();
-        let values = c
-            .values()
-            .as_any()
-            .downcast_ref::<PrimitiveArray<Int32Type>>()
-            .unwrap();
-        assert_eq!(6, values.value(c.key(0).unwrap()));
-        assert!(c.is_null(1));
-        assert_eq!(8, values.value(c.key(2).unwrap()));
-        assert_eq!(9, values.value(c.key(3).unwrap()));
-        assert_eq!(10, values.value(c.key(4).unwrap()));
-    }
-
-    #[test]
-    fn test_primitive_array_multiply_dyn() {
-        let a = Int32Array::from(vec![Some(5), Some(6), Some(7), Some(8), 
Some(9)]);
-        let b = Int32Array::from(vec![Some(6), Some(7), Some(8), None, 
Some(8)]);
-        let c = multiply_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Int32Array>().unwrap();
-        assert_eq!(30, c.value(0));
-        assert_eq!(42, c.value(1));
-        assert_eq!(56, c.value(2));
-        assert!(c.is_null(3));
-        assert_eq!(72, c.value(4));
-    }
-
-    #[test]
-    fn test_primitive_array_divide_dyn() {
-        let a = Int32Array::from(vec![Some(15), Some(6), Some(1), Some(8), 
Some(9)]);
-        let b = Int32Array::from(vec![Some(5), Some(3), Some(1), None, 
Some(3)]);
-        let c = divide_dyn(&a, &b).unwrap();
-        let c = c.as_any().downcast_ref::<Int32Array>().unwrap();
-        assert_eq!(3, c.value(0));
-        assert_eq!(2, c.value(1));
-        assert_eq!(1, c.value(2));
-        assert!(c.is_null(3));
-        assert_eq!(3, c.value(4));
-    }
-
-    #[test]
-    fn test_primitive_array_multiply_scalar_dyn() {
-        let a = Int32Array::from(vec![Some(5), Some(6), Some(7), None, 
Some(9)]);
-        let b = 2_i32;
-        let c = multiply_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c.as_any().downcast_ref::<Int32Array>().unwrap();
-        assert_eq!(10, c.value(0));
-        assert_eq!(12, c.value(1));
-        assert_eq!(14, c.value(2));
-        assert!(c.is_null(3));
-        assert_eq!(18, c.value(4));
-
-        let mut builder = PrimitiveDictionaryBuilder::<Int8Type, 
Int32Type>::new();
-        builder.append(5).unwrap();
-        builder.append_null();
-        builder.append(7).unwrap();
-        builder.append(8).unwrap();
-        builder.append(9).unwrap();
-        let a = builder.finish();
-        let b = -1_i32;
-
-        let c = multiply_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c
-            .as_any()
-            .downcast_ref::<DictionaryArray<Int8Type>>()
-            .unwrap();
-        let values = c
-            .values()
-            .as_any()
-            .downcast_ref::<PrimitiveArray<Int32Type>>()
-            .unwrap();
-        assert_eq!(-5, values.value(c.key(0).unwrap()));
-        assert!(c.is_null(1));
-        assert_eq!(-7, values.value(c.key(2).unwrap()));
-        assert_eq!(-8, values.value(c.key(3).unwrap()));
-        assert_eq!(-9, values.value(c.key(4).unwrap()));
-    }
-
-    #[test]
-    fn test_primitive_array_add_sliced() {
-        let a = Int32Array::from(vec![0, 0, 0, 5, 6, 7, 8, 9, 0]);
-        let b = Int32Array::from(vec![0, 0, 0, 6, 7, 8, 9, 8, 0]);
-        let a = a.slice(3, 5);
-        let b = b.slice(3, 5);
-        let a = a.as_any().downcast_ref::<Int32Array>().unwrap();
-        let b = b.as_any().downcast_ref::<Int32Array>().unwrap();
-
-        assert_eq!(5, a.value(0));
-        assert_eq!(6, b.value(0));
-
-        let c = add(a, b).unwrap();
-        assert_eq!(5, c.len());
-        assert_eq!(11, c.value(0));
-        assert_eq!(13, c.value(1));
-        assert_eq!(15, c.value(2));
-        assert_eq!(17, c.value(3));
-        assert_eq!(17, c.value(4));
-    }
-
-    #[test]
-    fn test_primitive_array_add_mismatched_length() {
-        let a = Int32Array::from(vec![5, 6, 7, 8, 9]);
-        let b = Int32Array::from(vec![6, 7, 8]);
-        let e = add(&a, &b).expect_err("should have failed due to different 
lengths");
-        assert_eq!(
-            "ComputeError(\"Cannot perform binary operation on arrays of 
different length\")",
-            format!("{e:?}")
-        );
-    }
-
-    #[test]
-    fn test_primitive_array_add_scalar() {
-        let a = Int32Array::from(vec![15, 14, 9, 8, 1]);
-        let b = 3;
-        let c = add_scalar(&a, b).unwrap();
-        let expected = Int32Array::from(vec![18, 17, 12, 11, 4]);
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_add_scalar_sliced() {
-        let a = Int32Array::from(vec![Some(15), None, Some(9), Some(8), None]);
-        let a = a.slice(1, 4);
-        let actual = add_scalar(&a, 3).unwrap();
-        let expected = Int32Array::from(vec![None, Some(12), Some(11), None]);
-        assert_eq!(actual, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_subtract() {
-        let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
-        let b = Int32Array::from(vec![5, 4, 3, 2, 1]);
-        let c = subtract(&a, &b).unwrap();
-        assert_eq!(-4, c.value(0));
-        assert_eq!(-2, c.value(1));
-        assert_eq!(0, c.value(2));
-        assert_eq!(2, c.value(3));
-        assert_eq!(4, c.value(4));
-    }
-
-    #[test]
-    fn test_primitive_array_subtract_scalar() {
-        let a = Int32Array::from(vec![15, 14, 9, 8, 1]);
-        let b = 3;
-        let c = subtract_scalar(&a, b).unwrap();
-        let expected = Int32Array::from(vec![12, 11, 6, 5, -2]);
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_subtract_scalar_sliced() {
-        let a = Int32Array::from(vec![Some(15), None, Some(9), Some(8), None]);
-        let a = a.slice(1, 4);
-        let actual = subtract_scalar(&a, 3).unwrap();
-        let expected = Int32Array::from(vec![None, Some(6), Some(5), None]);
-        assert_eq!(actual, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_multiply() {
-        let a = Int32Array::from(vec![5, 6, 7, 8, 9]);
-        let b = Int32Array::from(vec![6, 7, 8, 9, 8]);
-        let c = multiply(&a, &b).unwrap();
-        assert_eq!(30, c.value(0));
-        assert_eq!(42, c.value(1));
-        assert_eq!(56, c.value(2));
-        assert_eq!(72, c.value(3));
-        assert_eq!(72, c.value(4));
-    }
-
-    #[test]
-    fn test_primitive_array_multiply_scalar() {
-        let a = Int32Array::from(vec![15, 14, 9, 8, 1]);
-        let b = 3;
-        let c = multiply_scalar(&a, b).unwrap();
-        let expected = Int32Array::from(vec![45, 42, 27, 24, 3]);
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_multiply_scalar_sliced() {
-        let a = Int32Array::from(vec![Some(15), None, Some(9), Some(8), None]);
-        let a = a.slice(1, 4);
-        let actual = multiply_scalar(&a, 3).unwrap();
-        let expected = Int32Array::from(vec![None, Some(27), Some(24), None]);
-        assert_eq!(actual, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_divide() {
-        let a = Int32Array::from(vec![15, 15, 8, 1, 9]);
-        let b = Int32Array::from(vec![5, 6, 8, 9, 1]);
-        let c = divide(&a, &b).unwrap();
-        assert_eq!(3, c.value(0));
-        assert_eq!(2, c.value(1));
-        assert_eq!(1, c.value(2));
-        assert_eq!(0, c.value(3));
-        assert_eq!(9, c.value(4));
-    }
-
-    #[test]
-    fn test_int_array_modulus() {
-        let a = Int32Array::from(vec![15, 15, 8, 1, 9]);
-        let b = Int32Array::from(vec![5, 6, 8, 9, 1]);
-        let c = modulus(&a, &b).unwrap();
-        assert_eq!(0, c.value(0));
-        assert_eq!(3, c.value(1));
-        assert_eq!(0, c.value(2));
-        assert_eq!(1, c.value(3));
-        assert_eq!(0, c.value(4));
-
-        let c = modulus_dyn(&a, &b).unwrap();
-        let c = c.as_primitive::<Int32Type>();
-        assert_eq!(0, c.value(0));
-        assert_eq!(3, c.value(1));
-        assert_eq!(0, c.value(2));
-        assert_eq!(1, c.value(3));
-        assert_eq!(0, c.value(4));
-    }
-
-    #[test]
-    #[should_panic(
-        expected = "called `Result::unwrap()` on an `Err` value: DivideByZero"
-    )]
-    fn test_int_array_modulus_divide_by_zero() {
-        let a = Int32Array::from(vec![1]);
-        let b = Int32Array::from(vec![0]);
-        modulus(&a, &b).unwrap();
-    }
-
-    #[test]
-    #[should_panic(
-        expected = "called `Result::unwrap()` on an `Err` value: DivideByZero"
-    )]
-    fn test_int_array_modulus_dyn_divide_by_zero() {
-        let a = Int32Array::from(vec![1]);
-        let b = Int32Array::from(vec![0]);
-        modulus_dyn(&a, &b).unwrap();
-    }
-
-    #[test]
-    fn test_int_array_modulus_overflow_wrapping() {
-        let a = Int32Array::from(vec![i32::MIN]);
-        let b = Int32Array::from(vec![-1]);
-        let result = modulus(&a, &b).unwrap();
-        assert_eq!(0, result.value(0))
-    }
-
-    #[test]
-    fn test_primitive_array_divide_scalar() {
-        let a = Int32Array::from(vec![15, 14, 9, 8, 1]);
-        let b = 3;
-        let c = divide_scalar(&a, b).unwrap();
-        let expected = Int32Array::from(vec![5, 4, 3, 2, 0]);
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_divide_scalar_dyn() {
-        let a = Int32Array::from(vec![Some(5), Some(6), Some(7), None, 
Some(9)]);
-        let b = 2_i32;
-        let c = divide_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c.as_any().downcast_ref::<Int32Array>().unwrap();
-        assert_eq!(2, c.value(0));
-        assert_eq!(3, c.value(1));
-        assert_eq!(3, c.value(2));
-        assert!(c.is_null(3));
-        assert_eq!(4, c.value(4));
-
-        let mut builder = PrimitiveDictionaryBuilder::<Int8Type, 
Int32Type>::new();
-        builder.append(5).unwrap();
-        builder.append_null();
-        builder.append(7).unwrap();
-        builder.append(8).unwrap();
-        builder.append(9).unwrap();
-        let a = builder.finish();
-        let b = -2_i32;
-
-        let c = divide_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c
-            .as_any()
-            .downcast_ref::<DictionaryArray<Int8Type>>()
-            .unwrap();
-        let values = c
-            .values()
-            .as_any()
-            .downcast_ref::<PrimitiveArray<Int32Type>>()
-            .unwrap();
-        assert_eq!(-2, values.value(c.key(0).unwrap()));
-        assert!(c.is_null(1));
-        assert_eq!(-3, values.value(c.key(2).unwrap()));
-        assert_eq!(-4, values.value(c.key(3).unwrap()));
-        assert_eq!(-4, values.value(c.key(4).unwrap()));
-
-        let e = divide_scalar_dyn::<Int32Type>(&a, 0_i32)
-            .expect_err("should have failed due to divide by zero");
-        assert_eq!("DivideByZero", format!("{e:?}"));
-    }
-
-    #[test]
-    fn test_primitive_array_divide_scalar_sliced() {
-        let a = Int32Array::from(vec![Some(15), None, Some(9), Some(8), None]);
-        let a = a.slice(1, 4);
-        let actual = divide_scalar(&a, 3).unwrap();
-        let expected = Int32Array::from(vec![None, Some(3), Some(2), None]);
-        assert_eq!(actual, expected);
-    }
-
-    #[test]
-    fn test_int_array_modulus_scalar() {
-        let a = Int32Array::from(vec![15, 14, 9, 8, 1]);
-        let b = 3;
-        let c = modulus_scalar(&a, b).unwrap();
-        let expected = Int32Array::from(vec![0, 2, 0, 2, 1]);
-        assert_eq!(c, expected);
-
-        let c = modulus_scalar_dyn::<Int32Type>(&a, b).unwrap();
-        let c = c.as_primitive::<Int32Type>();
-        let expected = Int32Array::from(vec![0, 2, 0, 2, 1]);
-        assert_eq!(c, &expected);
-    }
-
-    #[test]
-    fn test_int_array_modulus_scalar_sliced() {
-        let a = Int32Array::from(vec![Some(15), None, Some(9), Some(8), None]);
-        let a = a.slice(1, 4);
-        let actual = modulus_scalar(&a, 3).unwrap();
-        let expected = Int32Array::from(vec![None, Some(0), Some(2), None]);
-        assert_eq!(actual, expected);
-
-        let actual = modulus_scalar_dyn::<Int32Type>(&a, 3).unwrap();
-        let actual = actual.as_primitive::<Int32Type>();
-        let expected = Int32Array::from(vec![None, Some(0), Some(2), None]);
-        assert_eq!(actual, &expected);
-    }
-
-    #[test]
-    #[should_panic(
-        expected = "called `Result::unwrap()` on an `Err` value: DivideByZero"
-    )]
-    fn test_int_array_modulus_scalar_divide_by_zero() {
-        let a = Int32Array::from(vec![1]);
-        modulus_scalar(&a, 0).unwrap();
-    }
-
-    #[test]
-    fn test_int_array_modulus_scalar_overflow_wrapping() {
-        let a = Int32Array::from(vec![i32::MIN]);
-        let result = modulus_scalar(&a, -1).unwrap();
-        assert_eq!(0, result.value(0));
-
-        let result = modulus_scalar_dyn::<Int32Type>(&a, -1).unwrap();
-        let result = result.as_primitive::<Int32Type>();
-        assert_eq!(0, result.value(0));
-    }
-
-    #[test]
-    fn test_primitive_array_divide_sliced() {
-        let a = Int32Array::from(vec![0, 0, 0, 15, 15, 8, 1, 9, 0]);
-        let b = Int32Array::from(vec![0, 0, 0, 5, 6, 8, 9, 1, 0]);
-        let a = a.slice(3, 5);
-        let b = b.slice(3, 5);
-        let a = a.as_any().downcast_ref::<Int32Array>().unwrap();
-        let b = b.as_any().downcast_ref::<Int32Array>().unwrap();
-
-        let c = divide(a, b).unwrap();
-        assert_eq!(5, c.len());
-        assert_eq!(3, c.value(0));
-        assert_eq!(2, c.value(1));
-        assert_eq!(1, c.value(2));
-        assert_eq!(0, c.value(3));
-        assert_eq!(9, c.value(4));
-    }
-
-    #[test]
-    fn test_primitive_array_modulus_sliced() {
-        let a = Int32Array::from(vec![0, 0, 0, 15, 15, 8, 1, 9, 0]);
-        let b = Int32Array::from(vec![0, 0, 0, 5, 6, 8, 9, 1, 0]);
-        let a = a.slice(3, 5);
-        let b = b.slice(3, 5);
-        let a = a.as_any().downcast_ref::<Int32Array>().unwrap();
-        let b = b.as_any().downcast_ref::<Int32Array>().unwrap();
-
-        let c = modulus(a, b).unwrap();
-        assert_eq!(5, c.len());
-        assert_eq!(0, c.value(0));
-        assert_eq!(3, c.value(1));
-        assert_eq!(0, c.value(2));
-        assert_eq!(1, c.value(3));
-        assert_eq!(0, c.value(4));
-    }
-
-    #[test]
-    fn test_primitive_array_divide_with_nulls() {
-        let a = Int32Array::from(vec![Some(15), None, Some(8), Some(1), 
Some(9), None]);
-        let b = Int32Array::from(vec![Some(5), Some(6), Some(8), Some(9), 
None, None]);
-        let c = divide_checked(&a, &b).unwrap();
-        assert_eq!(3, c.value(0));
-        assert!(c.is_null(1));
-        assert_eq!(1, c.value(2));
-        assert_eq!(0, c.value(3));
-        assert!(c.is_null(4));
-        assert!(c.is_null(5));
-    }
-
-    #[test]
-    fn test_primitive_array_modulus_with_nulls() {
-        let a = Int32Array::from(vec![Some(15), None, Some(8), Some(1), 
Some(9), None]);
-        let b = Int32Array::from(vec![Some(5), Some(6), Some(8), Some(9), 
None, None]);
-        let c = modulus(&a, &b).unwrap();
-        assert_eq!(0, c.value(0));
-        assert!(c.is_null(1));
-        assert_eq!(0, c.value(2));
-        assert_eq!(1, c.value(3));
-        assert!(c.is_null(4));
-        assert!(c.is_null(5));
-    }
-
-    #[test]
-    fn test_primitive_array_divide_scalar_with_nulls() {
-        let a = Int32Array::from(vec![Some(15), None, Some(8), Some(1), 
Some(9), None]);
-        let b = 3;
-        let c = divide_scalar(&a, b).unwrap();
-        let expected =
-            Int32Array::from(vec![Some(5), None, Some(2), Some(0), Some(3), 
None]);
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_modulus_scalar_with_nulls() {
-        let a = Int32Array::from(vec![Some(15), None, Some(8), Some(1), 
Some(9), None]);
-        let b = 3;
-        let c = modulus_scalar(&a, b).unwrap();
-        let expected =
-            Int32Array::from(vec![Some(0), None, Some(2), Some(1), Some(0), 
None]);
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_primitive_array_divide_with_nulls_sliced() {
-        let a = Int32Array::from(vec![
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            Some(15),
-            None,
-            Some(8),
-            Some(1),
-            Some(9),
-            None,
-            None,
-        ]);
-        let b = Int32Array::from(vec![
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            Some(5),
-            Some(6),
-            Some(8),
-            Some(9),
-            None,
-            None,
-            None,
-        ]);
-
-        let a = a.slice(8, 6);
-        let a = a.as_any().downcast_ref::<Int32Array>().unwrap();
-
-        let b = b.slice(8, 6);
-        let b = b.as_any().downcast_ref::<Int32Array>().unwrap();
-
-        let c = divide_checked(a, b).unwrap();
-        assert_eq!(6, c.len());
-        assert_eq!(3, c.value(0));
-        assert!(c.is_null(1));
-        assert_eq!(1, c.value(2));
-        assert_eq!(0, c.value(3));
-        assert!(c.is_null(4));
-        assert!(c.is_null(5));
-    }
-
-    #[test]
-    fn test_primitive_array_modulus_with_nulls_sliced() {
-        let a = Int32Array::from(vec![
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            Some(15),
-            None,
-            Some(8),
-            Some(1),
-            Some(9),
-            None,
-            None,
-        ]);
-        let b = Int32Array::from(vec![
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            None,
-            Some(5),
-            Some(6),
-            Some(8),
-            Some(9),
-            None,
-            None,
-            None,
-        ]);
-
-        let a = a.slice(8, 6);
-        let a = a.as_any().downcast_ref::<Int32Array>().unwrap();
-
-        let b = b.slice(8, 6);
-        let b = b.as_any().downcast_ref::<Int32Array>().unwrap();
-
-        let c = modulus(a, b).unwrap();
-        assert_eq!(6, c.len());
-        assert_eq!(0, c.value(0));
-        assert!(c.is_null(1));
-        assert_eq!(0, c.value(2));
-        assert_eq!(1, c.value(3));
-        assert!(c.is_null(4));
-        assert!(c.is_null(5));
-    }
-
-    #[test]
-    #[should_panic(expected = "DivideByZero")]
-    fn test_int_array_divide_by_zero_with_checked() {
-        let a = Int32Array::from(vec![15]);
-        let b = Int32Array::from(vec![0]);
-        divide_checked(&a, &b).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "DivideByZero")]
-    fn test_f32_array_divide_by_zero_with_checked() {
-        let a = Float32Array::from(vec![15.0]);
-        let b = Float32Array::from(vec![0.0]);
-        divide_checked(&a, &b).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "attempt to divide by zero")]
-    fn test_int_array_divide_by_zero() {
-        let a = Int32Array::from(vec![15]);
-        let b = Int32Array::from(vec![0]);
-        divide(&a, &b).unwrap();
-    }
-
-    #[test]
-    fn test_f32_array_divide_by_zero() {
-        let a = Float32Array::from(vec![1.5, 0.0, -1.5]);
-        let b = Float32Array::from(vec![0.0, 0.0, 0.0]);
-        let result = divide(&a, &b).unwrap();
-        assert_eq!(result.value(0), f32::INFINITY);
-        assert!(result.value(1).is_nan());
-        assert_eq!(result.value(2), f32::NEG_INFINITY);
-    }
-
-    #[test]
-    #[should_panic(expected = "DivideByZero")]
-    fn test_int_array_divide_dyn_by_zero() {
-        let a = Int32Array::from(vec![15]);
-        let b = Int32Array::from(vec![0]);
-        divide_dyn(&a, &b).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "DivideByZero")]
-    fn test_f32_array_divide_dyn_by_zero() {
-        let a = Float32Array::from(vec![1.5]);
-        let b = Float32Array::from(vec![0.0]);
-        divide_dyn(&a, &b).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "DivideByZero")]
-    fn test_i32_array_modulus_by_zero() {
-        let a = Int32Array::from(vec![15]);
-        let b = Int32Array::from(vec![0]);
-        modulus(&a, &b).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "DivideByZero")]
-    fn test_i32_array_modulus_dyn_by_zero() {
-        let a = Int32Array::from(vec![15]);
-        let b = Int32Array::from(vec![0]);
-        modulus_dyn(&a, &b).unwrap();
-    }
-
-    #[test]
-    #[should_panic(expected = "DivideByZero")]
-    fn test_f32_array_modulus_by_zero() {
-        let a = Float32Array::from(vec![1.5]);
-        let b = Float32Array::from(vec![0.0]);
-        modulus(&a, &b).unwrap();
-    }
-
-    #[test]
-    fn test_f32_array_modulus_dyn_by_zero() {
-        let a = Float32Array::from(vec![1.5]);
-        let b = Float32Array::from(vec![0.0]);
-        let result = modulus_dyn(&a, &b).unwrap();
-        assert!(result.as_primitive::<Float32Type>().value(0).is_nan());
-    }
-
-    #[test]
-    fn test_f64_array_divide() {
-        let a = Float64Array::from(vec![15.0, 15.0, 8.0]);
-        let b = Float64Array::from(vec![5.0, 6.0, 8.0]);
-        let c = divide(&a, &b).unwrap();
-        assert_eq!(3.0, c.value(0));
-        assert_eq!(2.5, c.value(1));
-        assert_eq!(1.0, c.value(2));
-    }
-
-    #[test]
-    fn test_primitive_array_add_with_nulls() {
-        let a = Int32Array::from(vec![Some(5), None, Some(7), None]);
-        let b = Int32Array::from(vec![None, None, Some(6), Some(7)]);
-        let c = add(&a, &b).unwrap();
-        assert!(c.is_null(0));
-        assert!(c.is_null(1));
-        assert!(!c.is_null(2));
-        assert!(c.is_null(3));
-        assert_eq!(13, c.value(2));
-    }
-
-    #[test]
-    fn test_primitive_array_negate() {
-        let a: Int64Array = (0..100).map(Some).collect();
-        let actual = negate(&a).unwrap();
-        let expected: Int64Array = (0..100).map(|i| Some(-i)).collect();
-        assert_eq!(expected, actual);
-    }
-
-    #[test]
-    fn test_primitive_array_negate_checked_overflow() {
-        let a = Int32Array::from(vec![i32::MIN]);
-        let actual = negate(&a).unwrap();
-        let expected = Int32Array::from(vec![i32::MIN]);
-        assert_eq!(expected, actual);
-
-        let err = negate_checked(&a);
-        err.expect_err("negate_checked should detect overflow");
-    }
-
-    #[test]
-    fn test_arithmetic_kernel_should_not_rely_on_padding() {
-        let a: UInt8Array = (0..128_u8).map(Some).collect();
-        let a = a.slice(63, 65);
-        let a = a.as_any().downcast_ref::<UInt8Array>().unwrap();
-
-        let b: UInt8Array = (0..128_u8).map(Some).collect();
-        let b = b.slice(63, 65);
-        let b = b.as_any().downcast_ref::<UInt8Array>().unwrap();
-
-        let actual = add(a, b).unwrap();
-        let actual: Vec<Option<u8>> = actual.iter().collect();
-        let expected: Vec<Option<u8>> =
-            (63..63_u8 + 65_u8).map(|i| Some(i + i)).collect();
-        assert_eq!(expected, actual);
-    }
-
-    #[test]
-    fn test_primitive_add_wrapping_overflow() {
-        let a = Int32Array::from(vec![i32::MAX, i32::MIN]);
-        let b = Int32Array::from(vec![1, 1]);
-
-        let wrapped = add(&a, &b);
-        let expected = Int32Array::from(vec![-2147483648, -2147483647]);
-        assert_eq!(expected, wrapped.unwrap());
-
-        let overflow = add_checked(&a, &b);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_subtract_wrapping_overflow() {
-        let a = Int32Array::from(vec![-2]);
-        let b = Int32Array::from(vec![i32::MAX]);
-
-        let wrapped = subtract(&a, &b);
-        let expected = Int32Array::from(vec![i32::MAX]);
-        assert_eq!(expected, wrapped.unwrap());
-
-        let overflow = subtract_checked(&a, &b);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_mul_wrapping_overflow() {
-        let a = Int32Array::from(vec![10]);
-        let b = Int32Array::from(vec![i32::MAX]);
-
-        let wrapped = multiply(&a, &b);
-        let expected = Int32Array::from(vec![-10]);
-        assert_eq!(expected, wrapped.unwrap());
-
-        let overflow = multiply_checked(&a, &b);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    #[cfg(not(feature = "simd"))]
-    fn test_primitive_div_wrapping_overflow() {
-        let a = Int32Array::from(vec![i32::MIN]);
-        let b = Int32Array::from(vec![-1]);
-
-        let wrapped = divide(&a, &b);
-        let expected = Int32Array::from(vec![-2147483648]);
-        assert_eq!(expected, wrapped.unwrap());
-
-        let overflow = divide_checked(&a, &b);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_add_scalar_wrapping_overflow() {
-        let a = Int32Array::from(vec![i32::MAX, i32::MIN]);
-
-        let wrapped = add_scalar(&a, 1);
-        let expected = Int32Array::from(vec![-2147483648, -2147483647]);
-        assert_eq!(expected, wrapped.unwrap());
-
-        let overflow = add_scalar_checked(&a, 1);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_subtract_scalar_wrapping_overflow() {
-        let a = Int32Array::from(vec![-2]);
-
-        let wrapped = subtract_scalar(&a, i32::MAX);
-        let expected = Int32Array::from(vec![i32::MAX]);
-        assert_eq!(expected, wrapped.unwrap());
-
-        let overflow = subtract_scalar_checked(&a, i32::MAX);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_mul_scalar_wrapping_overflow() {
-        let a = Int32Array::from(vec![10]);
-
-        let wrapped = multiply_scalar(&a, i32::MAX);
-        let expected = Int32Array::from(vec![-10]);
-        assert_eq!(expected, wrapped.unwrap());
-
-        let overflow = multiply_scalar_checked(&a, i32::MAX);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_add_scalar_dyn_wrapping_overflow() {
-        let a = Int32Array::from(vec![i32::MAX, i32::MIN]);
-
-        let wrapped = add_scalar_dyn::<Int32Type>(&a, 1).unwrap();
-        let expected =
-            Arc::new(Int32Array::from(vec![-2147483648, -2147483647])) as 
ArrayRef;
-        assert_eq!(&expected, &wrapped);
-
-        let overflow = add_scalar_checked_dyn::<Int32Type>(&a, 1);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_subtract_scalar_dyn_wrapping_overflow() {
-        let a = Int32Array::from(vec![-2]);
-
-        let wrapped = subtract_scalar_dyn::<Int32Type>(&a, i32::MAX).unwrap();
-        let expected = Arc::new(Int32Array::from(vec![i32::MAX])) as ArrayRef;
-        assert_eq!(&expected, &wrapped);
-
-        let overflow = subtract_scalar_checked_dyn::<Int32Type>(&a, i32::MAX);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_mul_scalar_dyn_wrapping_overflow() {
-        let a = Int32Array::from(vec![10]);
-
-        let wrapped = multiply_scalar_dyn::<Int32Type>(&a, i32::MAX).unwrap();
-        let expected = Arc::new(Int32Array::from(vec![-10])) as ArrayRef;
-        assert_eq!(&expected, &wrapped);
-
-        let overflow = multiply_scalar_checked_dyn::<Int32Type>(&a, i32::MAX);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_div_scalar_dyn_wrapping_overflow() {
-        let a = Int32Array::from(vec![i32::MIN]);
-
-        let wrapped = divide_scalar_dyn::<Int32Type>(&a, -1).unwrap();
-        let expected = Arc::new(Int32Array::from(vec![-2147483648])) as 
ArrayRef;
-        assert_eq!(&expected, &wrapped);
-
-        let overflow = divide_scalar_checked_dyn::<Int32Type>(&a, -1);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_div_opt_overflow_division_by_zero() {
-        let a = Int32Array::from(vec![i32::MIN]);
-        let b = Int32Array::from(vec![-1]);
-
-        let wrapped = divide(&a, &b);
-        let expected = Int32Array::from(vec![-2147483648]);
-        assert_eq!(expected, wrapped.unwrap());
-
-        let overflow = divide_opt(&a, &b);
-        let expected = Int32Array::from(vec![-2147483648]);
-        assert_eq!(expected, overflow.unwrap());
-
-        let b = Int32Array::from(vec![0]);
-        let overflow = divide_opt(&a, &b);
-        let expected = Int32Array::from(vec![None]);
-        assert_eq!(expected, overflow.unwrap());
-    }
-
-    #[test]
-    fn test_primitive_add_dyn_wrapping_overflow() {
-        let a = Int32Array::from(vec![i32::MAX, i32::MIN]);
-        let b = Int32Array::from(vec![1, 1]);
-
-        let wrapped = add_dyn(&a, &b).unwrap();
-        let expected =
-            Arc::new(Int32Array::from(vec![-2147483648, -2147483647])) as 
ArrayRef;
-        assert_eq!(&expected, &wrapped);
-
-        let overflow = add_dyn_checked(&a, &b);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_subtract_dyn_wrapping_overflow() {
-        let a = Int32Array::from(vec![-2]);
-        let b = Int32Array::from(vec![i32::MAX]);
-
-        let wrapped = subtract_dyn(&a, &b).unwrap();
-        let expected = Arc::new(Int32Array::from(vec![i32::MAX])) as ArrayRef;
-        assert_eq!(&expected, &wrapped);
-
-        let overflow = subtract_dyn_checked(&a, &b);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_mul_dyn_wrapping_overflow() {
-        let a = Int32Array::from(vec![10]);
-        let b = Int32Array::from(vec![i32::MAX]);
-
-        let wrapped = multiply_dyn(&a, &b).unwrap();
-        let expected = Arc::new(Int32Array::from(vec![-10])) as ArrayRef;
-        assert_eq!(&expected, &wrapped);
-
-        let overflow = multiply_dyn_checked(&a, &b);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_div_dyn_wrapping_overflow() {
-        let a = Int32Array::from(vec![i32::MIN]);
-        let b = Int32Array::from(vec![-1]);
-
-        let wrapped = divide_dyn(&a, &b).unwrap();
-        let expected = Arc::new(Int32Array::from(vec![-2147483648])) as 
ArrayRef;
-        assert_eq!(&expected, &wrapped);
-
-        let overflow = divide_dyn_checked(&a, &b);
-        overflow.expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_decimal128() {
-        let a = Decimal128Array::from_iter_values([1, 2, 4, 5]);
-        let b = Decimal128Array::from_iter_values([7, -3, 6, 3]);
-        let e = Decimal128Array::from_iter_values([8, -1, 10, 8]);
-        let r = add(&a, &b).unwrap();
-        assert_eq!(e, r);
-
-        let e = Decimal128Array::from_iter_values([-6, 5, -2, 2]);
-        let r = subtract(&a, &b).unwrap();
-        assert_eq!(e, r);
-
-        let e = Decimal128Array::from_iter_values([7, -6, 24, 15]);
-        let r = multiply(&a, &b).unwrap();
-        assert_eq!(e, r);
-
-        let a = Decimal128Array::from_iter_values([23, 56, 32, 55]);
-        let b = Decimal128Array::from_iter_values([1, -2, 4, 5]);
-        let e = Decimal128Array::from_iter_values([23, -28, 8, 11]);
-        let r = divide(&a, &b).unwrap();
-        assert_eq!(e, r);
-    }
-
-    #[test]
-    fn test_decimal256() {
-        let a = Decimal256Array::from_iter_values(
-            [1, 2, 4, 5].into_iter().map(i256::from_i128),
-        );
-        let b = Decimal256Array::from_iter_values(
-            [7, -3, 6, 3].into_iter().map(i256::from_i128),
-        );
-        let e = Decimal256Array::from_iter_values(
-            [8, -1, 10, 8].into_iter().map(i256::from_i128),
-        );
-        let r = add(&a, &b).unwrap();
-        assert_eq!(e, r);
-
-        let e = Decimal256Array::from_iter_values(
-            [-6, 5, -2, 2].into_iter().map(i256::from_i128),
-        );
-        let r = subtract(&a, &b).unwrap();
-        assert_eq!(e, r);
-
-        let e = Decimal256Array::from_iter_values(
-            [7, -6, 24, 15].into_iter().map(i256::from_i128),
-        );
-        let r = multiply(&a, &b).unwrap();
-        assert_eq!(e, r);
-
-        let a = Decimal256Array::from_iter_values(
-            [23, 56, 32, 55].into_iter().map(i256::from_i128),
-        );
-        let b = Decimal256Array::from_iter_values(
-            [1, -2, 4, 5].into_iter().map(i256::from_i128),
-        );
-        let e = Decimal256Array::from_iter_values(
-            [23, -28, 8, 11].into_iter().map(i256::from_i128),
-        );
-        let r = divide(&a, &b).unwrap();
-        assert_eq!(e, r);
-    }
-
-    #[test]
-    fn test_div_scalar_dyn_opt_overflow_division_by_zero() {
-        let a = Int32Array::from(vec![i32::MIN]);
-
-        let division_by_zero = divide_scalar_opt_dyn::<Int32Type>(&a, 0);
-        let expected = Arc::new(Int32Array::from(vec![None])) as ArrayRef;
-        assert_eq!(&expected, &division_by_zero.unwrap());
-
-        let mut builder =
-            PrimitiveDictionaryBuilder::<Int8Type, 
Int32Type>::with_capacity(1, 1);
-        builder.append(i32::MIN).unwrap();
-        let a = builder.finish();
-
-        let division_by_zero = divide_scalar_opt_dyn::<Int32Type>(&a, 0);
-        assert_eq!(&expected, &division_by_zero.unwrap());
-    }
-
-    #[test]
-    fn test_sum_f16() {
-        let a = Float16Array::from_iter_values([
-            f16::from_f32(0.1),
-            f16::from_f32(0.2),
-            f16::from_f32(1.5),
-            f16::from_f32(-0.1),
-        ]);
-        let b = Float16Array::from_iter_values([
-            f16::from_f32(5.1),
-            f16::from_f32(6.2),
-            f16::from_f32(-1.),
-            f16::from_f32(-2.1),
-        ]);
-        let expected = Float16Array::from_iter_values(
-            a.values().iter().zip(b.values()).map(|(a, b)| a + b),
-        );
-
-        let c = add(&a, &b).unwrap();
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_resize_builder() {
-        let mut null_buffer_builder = BooleanBufferBuilder::new(16);
-        null_buffer_builder.append_slice(&[
-            false, false, false, false, false, false, false, false, false, 
false, false,
-            false, false, true, true, true,
-        ]);
-        // `resize` resizes the buffer length to the ceil of byte numbers.
-        // So the underlying buffer is not changed.
-        null_buffer_builder.resize(13);
-        assert_eq!(null_buffer_builder.len(), 13);
-
-        let nulls = null_buffer_builder.finish();
-        assert_eq!(nulls.count_set_bits(), 0);
-        let nulls = NullBuffer::new(nulls);
-        assert_eq!(nulls.null_count(), 13);
-
-        let mut data_buffer_builder = BufferBuilder::<i32>::new(13);
-        data_buffer_builder.append_slice(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
11, 12]);
-        let data_buffer = data_buffer_builder.finish();
-
-        let arg1: Int32Array = ArrayDataBuilder::new(DataType::Int32)
-            .len(13)
-            .nulls(Some(nulls))
-            .buffers(vec![data_buffer])
-            .build()
-            .unwrap()
-            .into();
-
-        assert_eq!(arg1.null_count(), 13);
-
-        let mut data_buffer_builder = BufferBuilder::<i32>::new(13);
-        data_buffer_builder.append_slice(&[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 
11, 12]);
-        let data_buffer = data_buffer_builder.finish();
-
-        let arg2: Int32Array = ArrayDataBuilder::new(DataType::Int32)
-            .len(13)
-            .buffers(vec![data_buffer])
-            .build()
-            .unwrap()
-            .into();
-
-        assert_eq!(arg2.null_count(), 0);
-
-        let result_dyn = add_dyn(&arg1, &arg2).unwrap();
-        let result = result_dyn.as_any().downcast_ref::<Int32Array>().unwrap();
-
-        assert_eq!(result.len(), 13);
-        assert_eq!(result.null_count(), 13);
-    }
-
-    #[test]
-    fn test_primitive_array_add_mut_by_binary_mut() {
-        let a = Int32Array::from(vec![15, 14, 9, 8, 1]);
-        let b = Int32Array::from(vec![Some(1), None, Some(3), None, Some(5)]);
-
-        let c = binary_mut(a, &b, |a, b| a.add_wrapping(b))
-            .unwrap()
-            .unwrap();
-        let expected = Int32Array::from(vec![Some(16), None, Some(12), None, 
Some(6)]);
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_primitive_add_mut_wrapping_overflow_by_try_binary_mut() {
-        let a = Int32Array::from(vec![i32::MAX, i32::MIN]);
-        let b = Int32Array::from(vec![1, 1]);
-
-        let wrapped = binary_mut(a, &b, |a, b| a.add_wrapping(b))
-            .unwrap()
-            .unwrap();
-        let expected = Int32Array::from(vec![-2147483648, -2147483647]);
-        assert_eq!(expected, wrapped);
-
-        let a = Int32Array::from(vec![i32::MAX, i32::MIN]);
-        let b = Int32Array::from(vec![1, 1]);
-        let overflow = try_binary_mut(a, &b, |a, b| a.add_checked(b));
-        let _ = overflow.unwrap().expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_primitive_add_scalar_by_unary_mut() {
-        let a = Int32Array::from(vec![15, 14, 9, 8, 1]);
-        let b = 3;
-        let c = unary_mut(a, |value| value.add_wrapping(b)).unwrap();
-        let expected = Int32Array::from(vec![18, 17, 12, 11, 4]);
-        assert_eq!(c, expected);
-    }
-
-    #[test]
-    fn test_primitive_add_scalar_overflow_by_try_unary_mut() {
-        let a = Int32Array::from(vec![i32::MAX, i32::MIN]);
-
-        let wrapped = unary_mut(a, |value| value.add_wrapping(1)).unwrap();
-        let expected = Int32Array::from(vec![-2147483648, -2147483647]);
-        assert_eq!(expected, wrapped);
-
-        let a = Int32Array::from(vec![i32::MAX, i32::MIN]);
-        let overflow = try_unary_mut(a, |value| value.add_checked(1));
-        let _ = overflow.unwrap().expect_err("overflow should be detected");
-    }
-
-    #[test]
-    fn test_decimal_add_scalar_dyn() {
-        let a = Decimal128Array::from(vec![100, 210, 320])
-            .with_precision_and_scale(38, 2)
-            .unwrap();
-
-        let result = add_scalar_dyn::<Decimal128Type>(&a, 1).unwrap();
-        let result = result
-            .as_primitive::<Decimal128Type>()
-            .clone()
-            .with_precision_and_scale(38, 2)
-            .unwrap();
-        let expected = Decimal128Array::from(vec![101, 211, 321])
-            .with_precision_and_scale(38, 2)
-            .unwrap();
-
-        assert_eq!(&expected, &result);
-    }
-
-    #[test]
-    fn test_decimal_multiply_allow_precision_loss() {
-        // Overflow happening as i128 cannot hold multiplying result.
-        // [123456789]
-        let a = Decimal128Array::from(vec![123456789000000000000000000])
-            .with_precision_and_scale(38, 18)
-            .unwrap();
-
-        // [10]
-        let b = Decimal128Array::from(vec![10000000000000000000])
-            .with_precision_and_scale(38, 18)
-            .unwrap();
-
-        let err = multiply_dyn_checked(&a, &b).unwrap_err();
-        assert!(err.to_string().contains(
-            "Overflow happened on: 123456789000000000000000000 * 
10000000000000000000"
-        ));
-
-        // Allow precision loss.
-        let result = multiply_fixed_point_checked(&a, &b, 28).unwrap();
-        // [1234567890]
-        let expected =
-            Decimal128Array::from(vec![12345678900000000000000000000000000000])
-                .with_precision_and_scale(38, 28)
-                .unwrap();
-
-        assert_eq!(&expected, &result);
-        assert_eq!(
-            result.value_as_string(0),
-            "1234567890.0000000000000000000000000000"
-        );
-
-        // Rounding case
-        // [0.000000000000000001, 123456789.555555555555555555, 
1.555555555555555555]
-        let a = Decimal128Array::from(vec![
-            1,
-            123456789555555555555555555,
-            1555555555555555555,
-        ])
-        .with_precision_and_scale(38, 18)
-        .unwrap();
-
-        // [1.555555555555555555, 11.222222222222222222, 0.000000000000000001]
-        let b = Decimal128Array::from(vec![1555555555555555555, 
11222222222222222222, 1])
-            .with_precision_and_scale(38, 18)
-            .unwrap();
-
-        let result = multiply_fixed_point_checked(&a, &b, 28).unwrap();
-        // [
-        //    0.0000000000000000015555555556,
-        //    1385459527.2345679012071330528765432099,
-        //    0.0000000000000000015555555556
-        // ]
-        let expected = Decimal128Array::from(vec![
-            15555555556,
-            13854595272345679012071330528765432099,
-            15555555556,
-        ])
-        .with_precision_and_scale(38, 28)
-        .unwrap();
-
-        assert_eq!(&expected, &result);
-
-        // Rounded the value "1385459527.234567901207133052876543209876543210".
-        assert_eq!(
-            result.value_as_string(1),
-            "1385459527.2345679012071330528765432099"
-        );
-        assert_eq!(result.value_as_string(0), 
"0.0000000000000000015555555556");
-        assert_eq!(result.value_as_string(2), 
"0.0000000000000000015555555556");
+        // Rounded the value "1385459527.234567901207133052876543209876543210".
+        assert_eq!(
+            result.value_as_string(1),
+            "1385459527.2345679012071330528765432099"
+        );
+        assert_eq!(result.value_as_string(0), 
"0.0000000000000000015555555556");
+        assert_eq!(result.value_as_string(2), 
"0.0000000000000000015555555556");
 
         let a = Decimal128Array::from(vec![1230])
             .with_precision_and_scale(4, 2)
@@ -2609,11 +283,8 @@ mod tests {
         assert_eq!(result.precision(), 9);
         assert_eq!(result.scale(), 4);
 
-        let expected = multiply_checked(&a, &b)
-            .unwrap()
-            .with_precision_and_scale(9, 4)
-            .unwrap();
-        assert_eq!(&expected, &result);
+        let expected = mul(&a, &b).unwrap();
+        assert_eq!(expected.as_ref(), &result);
 
         // Required scale cannot be larger than the product of the input 
scales.
         let result = multiply_fixed_point_checked(&a, &b, 5).unwrap_err();
@@ -2661,12 +332,8 @@ mod tests {
             .unwrap();
 
         // `multiply` overflows on this case.
-        let result = multiply(&a, &b).unwrap();
-        let expected =
-            
Decimal128Array::from(vec![-16672482290199102048610367863168958464])
-                .with_precision_and_scale(38, 10)
-                .unwrap();
-        assert_eq!(&expected, &result);
+        let err = mul(&a, &b).unwrap_err();
+        assert_eq!(err.to_string(), "Compute error: Overflow happened on: 
123456789000000000000000000 * 10000000000000000000");
 
         // Avoid overflow by reducing the scale.
         let result = multiply_fixed_point(&a, &b, 28).unwrap();
@@ -2682,693 +349,4 @@ mod tests {
             "1234567890.0000000000000000000000000000"
         );
     }
-
-    #[test]
-    fn test_timestamp_second_add_interval() {
-        // timestamp second + interval year month
-        let a = TimestampSecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalYearMonthArray::from(vec![
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-        ]);
-
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-
-        let expected = TimestampSecondArray::from(vec![
-            1 + SECONDS_IN_DAY * (365 + 31 + 28),
-            2 + SECONDS_IN_DAY * (365 + 31 + 28),
-            3 + SECONDS_IN_DAY * (365 + 31 + 28),
-            4 + SECONDS_IN_DAY * (365 + 31 + 28),
-            5 + SECONDS_IN_DAY * (365 + 31 + 28),
-        ]);
-        assert_eq!(result, &expected);
-
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-        assert_eq!(result, &expected);
-
-        // timestamp second + interval day time
-        let a = TimestampSecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalDayTimeArray::from(vec![
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-        ]);
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-
-        let expected = TimestampSecondArray::from(vec![
-            1 + SECONDS_IN_DAY,
-            2 + SECONDS_IN_DAY,
-            3 + SECONDS_IN_DAY,
-            4 + SECONDS_IN_DAY,
-            5 + SECONDS_IN_DAY,
-        ]);
-        assert_eq!(&expected, result);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-        assert_eq!(result, &expected);
-
-        // timestamp second + interval month day nanosecond
-        let a = TimestampSecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalMonthDayNanoArray::from(vec![
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-        ]);
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-
-        let expected = TimestampSecondArray::from(vec![
-            1 + SECONDS_IN_DAY,
-            2 + SECONDS_IN_DAY,
-            3 + SECONDS_IN_DAY,
-            4 + SECONDS_IN_DAY,
-            5 + SECONDS_IN_DAY,
-        ]);
-        assert_eq!(&expected, result);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-        assert_eq!(result, &expected);
-    }
-
-    #[test]
-    fn test_timestamp_second_subtract_interval() {
-        // timestamp second + interval year month
-        let a = TimestampSecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalYearMonthArray::from(vec![
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-        ]);
-
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-
-        let expected = TimestampSecondArray::from(vec![
-            1 - SECONDS_IN_DAY * (31 + 30 + 365),
-            2 - SECONDS_IN_DAY * (31 + 30 + 365),
-            3 - SECONDS_IN_DAY * (31 + 30 + 365),
-            4 - SECONDS_IN_DAY * (31 + 30 + 365),
-            5 - SECONDS_IN_DAY * (31 + 30 + 365),
-        ]);
-        assert_eq!(&expected, result);
-
-        // timestamp second + interval day time
-        let a = TimestampSecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalDayTimeArray::from(vec![
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-        ]);
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-
-        let expected = TimestampSecondArray::from(vec![
-            1 - SECONDS_IN_DAY,
-            2 - SECONDS_IN_DAY,
-            3 - SECONDS_IN_DAY,
-            4 - SECONDS_IN_DAY,
-            5 - SECONDS_IN_DAY,
-        ]);
-        assert_eq!(&expected, result);
-
-        // timestamp second + interval month day nanosecond
-        let a = TimestampSecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalMonthDayNanoArray::from(vec![
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-        ]);
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampSecondType>();
-
-        let expected = TimestampSecondArray::from(vec![
-            1 - SECONDS_IN_DAY,
-            2 - SECONDS_IN_DAY,
-            3 - SECONDS_IN_DAY,
-            4 - SECONDS_IN_DAY,
-            5 - SECONDS_IN_DAY,
-        ]);
-        assert_eq!(&expected, result);
-    }
-
-    #[test]
-    fn test_timestamp_millisecond_add_interval() {
-        // timestamp millisecond + interval year month
-        let a = TimestampMillisecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalYearMonthArray::from(vec![
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-        ]);
-
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-
-        let expected = TimestampMillisecondArray::from(vec![
-            1 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000,
-            2 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000,
-            3 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000,
-            4 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000,
-            5 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000,
-        ]);
-        assert_eq!(result, &expected);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-        assert_eq!(result, &expected);
-
-        // timestamp millisecond + interval day time
-        let a = TimestampMillisecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalDayTimeArray::from(vec![
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-        ]);
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-
-        let expected = TimestampMillisecondArray::from(vec![
-            1 + SECONDS_IN_DAY * 1_000,
-            2 + SECONDS_IN_DAY * 1_000,
-            3 + SECONDS_IN_DAY * 1_000,
-            4 + SECONDS_IN_DAY * 1_000,
-            5 + SECONDS_IN_DAY * 1_000,
-        ]);
-        assert_eq!(&expected, result);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-        assert_eq!(result, &expected);
-
-        // timestamp millisecond + interval month day nanosecond
-        let a = TimestampMillisecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalMonthDayNanoArray::from(vec![
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-        ]);
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-
-        let expected = TimestampMillisecondArray::from(vec![
-            1 + SECONDS_IN_DAY * 1_000,
-            2 + SECONDS_IN_DAY * 1_000,
-            3 + SECONDS_IN_DAY * 1_000,
-            4 + SECONDS_IN_DAY * 1_000,
-            5 + SECONDS_IN_DAY * 1_000,
-        ]);
-        assert_eq!(&expected, result);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-        assert_eq!(result, &expected);
-    }
-
-    #[test]
-    fn test_timestamp_millisecond_subtract_interval() {
-        // timestamp millisecond + interval year month
-        let a = TimestampMillisecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalYearMonthArray::from(vec![
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-        ]);
-
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-
-        let expected = TimestampMillisecondArray::from(vec![
-            1 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000,
-            2 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000,
-            3 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000,
-            4 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000,
-            5 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000,
-        ]);
-        assert_eq!(&expected, result);
-
-        // timestamp millisecond + interval day time
-        let a = TimestampMillisecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalDayTimeArray::from(vec![
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-        ]);
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-
-        let expected = TimestampMillisecondArray::from(vec![
-            1 - SECONDS_IN_DAY * 1_000,
-            2 - SECONDS_IN_DAY * 1_000,
-            3 - SECONDS_IN_DAY * 1_000,
-            4 - SECONDS_IN_DAY * 1_000,
-            5 - SECONDS_IN_DAY * 1_000,
-        ]);
-        assert_eq!(&expected, result);
-
-        // timestamp millisecond + interval month day nanosecond
-        let a = TimestampMillisecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalMonthDayNanoArray::from(vec![
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-        ]);
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMillisecondType>();
-
-        let expected = TimestampMillisecondArray::from(vec![
-            1 - SECONDS_IN_DAY * 1_000,
-            2 - SECONDS_IN_DAY * 1_000,
-            3 - SECONDS_IN_DAY * 1_000,
-            4 - SECONDS_IN_DAY * 1_000,
-            5 - SECONDS_IN_DAY * 1_000,
-        ]);
-        assert_eq!(&expected, result);
-    }
-
-    #[test]
-    fn test_timestamp_microsecond_add_interval() {
-        // timestamp microsecond + interval year month
-        let a = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalYearMonthArray::from(vec![
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-        ]);
-
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-
-        let expected = TimestampMicrosecondArray::from(vec![
-            1 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000,
-            2 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000,
-            3 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000,
-            4 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000,
-            5 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000,
-        ]);
-        assert_eq!(result, &expected);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-        assert_eq!(result, &expected);
-
-        // timestamp microsecond + interval day time
-        let a = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalDayTimeArray::from(vec![
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-        ]);
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-
-        let expected = TimestampMicrosecondArray::from(vec![
-            1 + SECONDS_IN_DAY * 1_000_000,
-            2 + SECONDS_IN_DAY * 1_000_000,
-            3 + SECONDS_IN_DAY * 1_000_000,
-            4 + SECONDS_IN_DAY * 1_000_000,
-            5 + SECONDS_IN_DAY * 1_000_000,
-        ]);
-        assert_eq!(&expected, result);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-        assert_eq!(result, &expected);
-
-        // timestamp microsecond + interval month day nanosecond
-        let a = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalMonthDayNanoArray::from(vec![
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-        ]);
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-
-        let expected = TimestampMicrosecondArray::from(vec![
-            1 + SECONDS_IN_DAY * 1_000_000,
-            2 + SECONDS_IN_DAY * 1_000_000,
-            3 + SECONDS_IN_DAY * 1_000_000,
-            4 + SECONDS_IN_DAY * 1_000_000,
-            5 + SECONDS_IN_DAY * 1_000_000,
-        ]);
-        assert_eq!(&expected, result);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-        assert_eq!(result, &expected);
-    }
-
-    #[test]
-    fn test_timestamp_microsecond_subtract_interval() {
-        // timestamp microsecond + interval year month
-        let a = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalYearMonthArray::from(vec![
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-        ]);
-
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-
-        let expected = TimestampMicrosecondArray::from(vec![
-            1 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000,
-            2 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000,
-            3 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000,
-            4 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000,
-            5 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000,
-        ]);
-        assert_eq!(&expected, result);
-
-        // timestamp microsecond + interval day time
-        let a = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalDayTimeArray::from(vec![
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-        ]);
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-
-        let expected = TimestampMicrosecondArray::from(vec![
-            1 - SECONDS_IN_DAY * 1_000_000,
-            2 - SECONDS_IN_DAY * 1_000_000,
-            3 - SECONDS_IN_DAY * 1_000_000,
-            4 - SECONDS_IN_DAY * 1_000_000,
-            5 - SECONDS_IN_DAY * 1_000_000,
-        ]);
-        assert_eq!(&expected, result);
-
-        // timestamp microsecond + interval month day nanosecond
-        let a = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalMonthDayNanoArray::from(vec![
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-        ]);
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampMicrosecondType>();
-
-        let expected = TimestampMicrosecondArray::from(vec![
-            1 - SECONDS_IN_DAY * 1_000_000,
-            2 - SECONDS_IN_DAY * 1_000_000,
-            3 - SECONDS_IN_DAY * 1_000_000,
-            4 - SECONDS_IN_DAY * 1_000_000,
-            5 - SECONDS_IN_DAY * 1_000_000,
-        ]);
-        assert_eq!(&expected, result);
-    }
-
-    #[test]
-    fn test_timestamp_nanosecond_add_interval() {
-        // timestamp nanosecond + interval year month
-        let a = TimestampNanosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalYearMonthArray::from(vec![
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-        ]);
-
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-
-        let expected = TimestampNanosecondArray::from(vec![
-            1 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000_000,
-            2 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000_000,
-            3 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000_000,
-            4 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000_000,
-            5 + SECONDS_IN_DAY * (31 + 28 + 365) * 1_000_000_000,
-        ]);
-        assert_eq!(result, &expected);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-        assert_eq!(result, &expected);
-
-        // timestamp nanosecond + interval day time
-        let a = TimestampNanosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalDayTimeArray::from(vec![
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-        ]);
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-
-        let expected = TimestampNanosecondArray::from(vec![
-            1 + SECONDS_IN_DAY * 1_000_000_000,
-            2 + SECONDS_IN_DAY * 1_000_000_000,
-            3 + SECONDS_IN_DAY * 1_000_000_000,
-            4 + SECONDS_IN_DAY * 1_000_000_000,
-            5 + SECONDS_IN_DAY * 1_000_000_000,
-        ]);
-        assert_eq!(&expected, result);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-        assert_eq!(result, &expected);
-
-        // timestamp nanosecond + interval month day nanosecond
-        let a = TimestampNanosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalMonthDayNanoArray::from(vec![
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-        ]);
-        let result = add_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-
-        let expected = TimestampNanosecondArray::from(vec![
-            1 + SECONDS_IN_DAY * 1_000_000_000,
-            2 + SECONDS_IN_DAY * 1_000_000_000,
-            3 + SECONDS_IN_DAY * 1_000_000_000,
-            4 + SECONDS_IN_DAY * 1_000_000_000,
-            5 + SECONDS_IN_DAY * 1_000_000_000,
-        ]);
-        assert_eq!(&expected, result);
-        let result = add_dyn(&b, &a).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-        assert_eq!(result, &expected);
-    }
-
-    #[test]
-    fn test_timestamp_nanosecond_subtract_interval() {
-        // timestamp nanosecond + interval year month
-        let a = TimestampNanosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalYearMonthArray::from(vec![
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-            Some(IntervalYearMonthType::make_value(1, 2)),
-        ]);
-
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-
-        let expected = TimestampNanosecondArray::from(vec![
-            1 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000_000,
-            2 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000_000,
-            3 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000_000,
-            4 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000_000,
-            5 - SECONDS_IN_DAY * (31 + 30 + 365) * 1_000_000_000,
-        ]);
-        assert_eq!(&expected, result);
-
-        // timestamp nanosecond + interval day time
-        let a = TimestampNanosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalDayTimeArray::from(vec![
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-            Some(IntervalDayTimeType::make_value(1, 0)),
-        ]);
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-
-        let expected = TimestampNanosecondArray::from(vec![
-            1 - SECONDS_IN_DAY * 1_000_000_000,
-            2 - SECONDS_IN_DAY * 1_000_000_000,
-            3 - SECONDS_IN_DAY * 1_000_000_000,
-            4 - SECONDS_IN_DAY * 1_000_000_000,
-            5 - SECONDS_IN_DAY * 1_000_000_000,
-        ]);
-        assert_eq!(&expected, result);
-
-        // timestamp nanosecond + interval month day nanosecond
-        let a = TimestampNanosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let b = IntervalMonthDayNanoArray::from(vec![
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-            Some(IntervalMonthDayNanoType::make_value(0, 1, 0)),
-        ]);
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<TimestampNanosecondType>();
-
-        let expected = TimestampNanosecondArray::from(vec![
-            1 - SECONDS_IN_DAY * 1_000_000_000,
-            2 - SECONDS_IN_DAY * 1_000_000_000,
-            3 - SECONDS_IN_DAY * 1_000_000_000,
-            4 - SECONDS_IN_DAY * 1_000_000_000,
-            5 - SECONDS_IN_DAY * 1_000_000_000,
-        ]);
-        assert_eq!(&expected, result);
-    }
-
-    #[test]
-    fn test_timestamp_second_subtract_timestamp() {
-        let a = TimestampSecondArray::from(vec![0, 2, 4, 6, 8]);
-        let b = TimestampSecondArray::from(vec![1, 2, 3, 4, 5]);
-        let expected = DurationSecondArray::from(vec![-1, 0, 1, 2, 3]);
-
-        // unchecked
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<DurationSecondType>();
-        assert_eq!(&expected, result);
-
-        // checked
-        let result = subtract_dyn_checked(&a, &b).unwrap();
-        let result = result.as_primitive::<DurationSecondType>();
-        assert_eq!(&expected, result);
-    }
-
-    #[test]
-    fn test_timestamp_second_subtract_timestamp_overflow() {
-        let a = TimestampSecondArray::from(vec![
-            <TimestampSecondType as ArrowPrimitiveType>::Native::MAX,
-        ]);
-        let b = TimestampSecondArray::from(vec![
-            <TimestampSecondType as ArrowPrimitiveType>::Native::MIN,
-        ]);
-
-        // checked
-        let result = subtract_dyn_checked(&a, &b);
-        assert!(&result.is_err());
-    }
-
-    #[test]
-    fn test_timestamp_microsecond_subtract_timestamp() {
-        let a = TimestampMicrosecondArray::from(vec![0, 2, 4, 6, 8]);
-        let b = TimestampMicrosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let expected = DurationMicrosecondArray::from(vec![-1, 0, 1, 2, 3]);
-
-        // unchecked
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<DurationMicrosecondType>();
-        assert_eq!(&expected, result);
-
-        // checked
-        let result = subtract_dyn_checked(&a, &b).unwrap();
-        let result = result.as_primitive::<DurationMicrosecondType>();
-        assert_eq!(&expected, result);
-    }
-
-    #[test]
-    fn test_timestamp_microsecond_subtract_timestamp_overflow() {
-        let a = TimestampMicrosecondArray::from(vec![i64::MAX]);
-        let b = TimestampMicrosecondArray::from(vec![i64::MIN]);
-
-        // checked
-        let result = subtract_dyn_checked(&a, &b);
-        assert!(&result.is_err());
-    }
-
-    #[test]
-    fn test_timestamp_millisecond_subtract_timestamp() {
-        let a = TimestampMillisecondArray::from(vec![0, 2, 4, 6, 8]);
-        let b = TimestampMillisecondArray::from(vec![1, 2, 3, 4, 5]);
-        let expected = DurationMillisecondArray::from(vec![-1, 0, 1, 2, 3]);
-
-        // unchecked
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<DurationMillisecondType>();
-        assert_eq!(&expected, result);
-
-        // checked
-        let result = subtract_dyn_checked(&a, &b).unwrap();
-        let result = result.as_primitive::<DurationMillisecondType>();
-        assert_eq!(&expected, result);
-    }
-
-    #[test]
-    fn test_timestamp_millisecond_subtract_timestamp_overflow() {
-        let a = TimestampMillisecondArray::from(vec![i64::MAX]);
-        let b = TimestampMillisecondArray::from(vec![i64::MIN]);
-
-        // checked
-        let result = subtract_dyn_checked(&a, &b);
-        assert!(&result.is_err());
-    }
-
-    #[test]
-    fn test_timestamp_nanosecond_subtract_timestamp() {
-        let a = TimestampNanosecondArray::from(vec![0, 2, 4, 6, 8]);
-        let b = TimestampNanosecondArray::from(vec![1, 2, 3, 4, 5]);
-        let expected = DurationNanosecondArray::from(vec![-1, 0, 1, 2, 3]);
-
-        // unchecked
-        let result = subtract_dyn(&a, &b).unwrap();
-        let result = result.as_primitive::<DurationNanosecondType>();
-        assert_eq!(&expected, result);
-
-        // checked
-        let result = subtract_dyn_checked(&a, &b).unwrap();
-        let result = result.as_primitive::<DurationNanosecondType>();
-        assert_eq!(&expected, result);
-    }
-
-    #[test]
-    fn test_timestamp_nanosecond_subtract_timestamp_overflow() {
-        let a = TimestampNanosecondArray::from(vec![
-            <TimestampNanosecondType as ArrowPrimitiveType>::Native::MAX,
-        ]);
-        let b = TimestampNanosecondArray::from(vec![
-            <TimestampNanosecondType as ArrowPrimitiveType>::Native::MIN,
-        ]);
-
-        // checked
-        let result = subtract_dyn_checked(&a, &b);
-        assert!(&result.is_err());
-    }
 }
diff --git a/arrow-arith/src/arity.rs b/arrow-arith/src/arity.rs
index ce766aff66..2dac33a4f2 100644
--- a/arrow-arith/src/arity.rs
+++ b/arrow-arith/src/arity.rs
@@ -18,7 +18,6 @@
 //! Defines kernels suitable to perform operations to primitive arrays.
 
 use arrow_array::builder::BufferBuilder;
-use arrow_array::iterator::ArrayIter;
 use arrow_array::types::ArrowDictionaryKeyType;
 use arrow_array::*;
 use arrow_buffer::buffer::NullBuffer;
@@ -425,76 +424,6 @@ where
     Ok(Ok(builder.finish()))
 }
 
-#[inline(never)]
-fn try_binary_opt_no_nulls<A: ArrayAccessor, B: ArrayAccessor, F, O>(
-    len: usize,
-    a: A,
-    b: B,
-    op: F,
-) -> Result<PrimitiveArray<O>, ArrowError>
-where
-    O: ArrowPrimitiveType,
-    F: Fn(A::Item, B::Item) -> Option<O::Native>,
-{
-    let mut buffer = Vec::with_capacity(10);
-    for idx in 0..len {
-        unsafe {
-            buffer.push(op(a.value_unchecked(idx), b.value_unchecked(idx)));
-        };
-    }
-    Ok(buffer.iter().collect())
-}
-
-/// Applies the provided binary operation across `a` and `b`, collecting the 
optional results
-/// into a [`PrimitiveArray`]. If any index is null in either `a` or `b`, the 
corresponding
-/// index in the result will also be null. The binary operation could return 
`None` which
-/// results in a new null in the collected [`PrimitiveArray`].
-///
-/// The function is only evaluated for non-null indices
-///
-/// # Error
-///
-/// This function gives error if the arrays have different lengths
-pub(crate) fn binary_opt<A: ArrayAccessor + Array, B: ArrayAccessor + Array, 
F, O>(
-    a: A,
-    b: B,
-    op: F,
-) -> Result<PrimitiveArray<O>, ArrowError>
-where
-    O: ArrowPrimitiveType,
-    F: Fn(A::Item, B::Item) -> Option<O::Native>,
-{
-    if a.len() != b.len() {
-        return Err(ArrowError::ComputeError(
-            "Cannot perform binary operation on arrays of different 
length".to_string(),
-        ));
-    }
-
-    if a.is_empty() {
-        return Ok(PrimitiveArray::from(ArrayData::new_empty(&O::DATA_TYPE)));
-    }
-
-    if a.null_count() == 0 && b.null_count() == 0 {
-        return try_binary_opt_no_nulls(a.len(), a, b, op);
-    }
-
-    let iter_a = ArrayIter::new(a);
-    let iter_b = ArrayIter::new(b);
-
-    let values = iter_a
-        .into_iter()
-        .zip(iter_b.into_iter())
-        .map(|(item_a, item_b)| {
-            if let (Some(a), Some(b)) = (item_a, item_b) {
-                op(a, b)
-            } else {
-                None
-            }
-        });
-
-    Ok(values.collect())
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/arrow-pyarrow-integration-testing/src/lib.rs 
b/arrow-pyarrow-integration-testing/src/lib.rs
index 730409b377..89395bd2ed 100644
--- a/arrow-pyarrow-integration-testing/src/lib.rs
+++ b/arrow-pyarrow-integration-testing/src/lib.rs
@@ -49,7 +49,7 @@ fn double(array: &PyAny, py: Python) -> PyResult<PyObject> {
         .ok_or_else(|| ArrowError::ParseError("Expects an int64".to_string()))
         .map_err(to_py_err)?;
 
-    let array = kernels::arithmetic::add(array, array).map_err(to_py_err)?;
+    let array = kernels::numeric::add(array, array).map_err(to_py_err)?;
 
     // export
     array.to_data().to_pyarrow(py)
diff --git a/arrow/src/ffi.rs b/arrow/src/ffi.rs
index a392d1deec..7fbbaa7a39 100644
--- a/arrow/src/ffi.rs
+++ b/arrow/src/ffi.rs
@@ -31,10 +31,11 @@
 //! # use std::sync::Arc;
 //! # use arrow::array::{Int32Array, Array, ArrayData, make_array};
 //! # use arrow::error::Result;
-//! # use arrow::compute::kernels::arithmetic;
+//! # use arrow_arith::numeric::add;
 //! # use arrow::ffi::{to_ffi, from_ffi};
 //! # fn main() -> Result<()> {
 //! // create an array natively
+//!
 //! let array = Int32Array::from(vec![Some(1), None, Some(3)]);
 //! let data = array.into_data();
 //!
@@ -46,10 +47,10 @@
 //! let array = Int32Array::from(data);
 //!
 //! // perform some operation
-//! let array = arithmetic::add(&array, &array)?;
+//! let array = add(&array, &array)?;
 //!
 //! // verify
-//! assert_eq!(array, Int32Array::from(vec![Some(2), None, Some(6)]));
+//! assert_eq!(array.as_ref(), &Int32Array::from(vec![Some(2), None, 
Some(6)]));
 //! #
 //! # Ok(())
 //! # }
@@ -948,10 +949,10 @@ mod tests {
 
         // perform some operation
         let array = array.as_any().downcast_ref::<Int32Array>().unwrap();
-        let array = kernels::arithmetic::add(array, array).unwrap();
+        let array = kernels::numeric::add(array, array).unwrap();
 
         // verify
-        assert_eq!(array, Int32Array::from(vec![2, 4, 6]));
+        assert_eq!(array.as_ref(), &Int32Array::from(vec![2, 4, 6]));
         Ok(())
     }
 
diff --git a/arrow/src/lib.rs b/arrow/src/lib.rs
index 96cc98177a..e347f99ee4 100644
--- a/arrow/src/lib.rs
+++ b/arrow/src/lib.rs
@@ -184,7 +184,7 @@
 //!
 //! This module also implements many common vertical operations:
 //!
-//! * All mathematical binary operators, such as 
[`subtract`](compute::kernels::arithmetic::subtract)
+//! * All mathematical binary operators, such as 
[`sub`](compute::kernels::numeric::sub)
 //! * All boolean binary operators such as 
[`equality`](compute::kernels::comparison::eq)
 //! * [`cast`](compute::kernels::cast::cast)
 //! * [`filter`](compute::kernels::filter::filter)

Reply via email to