You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by vi...@apache.org on 2022/10/18 21:59:00 UTC
[arrow-rs] branch master updated: Support overflow-checking variant of negate kernel (#2893)
This is an automated email from the ASF dual-hosted git repository.
viirya 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 e118ae2d3 Support overflow-checking variant of negate kernel (#2893)
e118ae2d3 is described below
commit e118ae2d3b3ed9945bd0721a10d001a829d41854
Author: Liang-Chi Hsieh <vi...@gmail.com>
AuthorDate: Tue Oct 18 14:58:55 2022 -0700
Support overflow-checking variant of negate kernel (#2893)
---
arrow/src/compute/kernels/arithmetic.rs | 32 ++++++++++++++++++++++++++++----
arrow/src/datatypes/native.rs | 22 ++++++++++++++++++++++
2 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/arrow/src/compute/kernels/arithmetic.rs b/arrow/src/compute/kernels/arithmetic.rs
index a73ee7eee..e7fcb50cc 100644
--- a/arrow/src/compute/kernels/arithmetic.rs
+++ b/arrow/src/compute/kernels/arithmetic.rs
@@ -22,8 +22,6 @@
//! `RUSTFLAGS="-C target-feature=+avx2"` for example. See the documentation
//! [here](https://doc.rust-lang.org/stable/core/arch/) for more information.
-use std::ops::Neg;
-
use crate::array::*;
#[cfg(feature = "simd")]
use crate::buffer::MutableBuffer;
@@ -1116,12 +1114,27 @@ where
}
/// 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.
pub fn negate<T>(array: &PrimitiveArray<T>) -> Result<PrimitiveArray<T>>
where
T: ArrowNumericType,
- T::Native: Neg<Output = T::Native>,
+ T::Native: ArrowNativeTypeOp,
+{
+ 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.
+pub fn negate_checked<T>(array: &PrimitiveArray<T>) -> Result<PrimitiveArray<T>>
+where
+ T: ArrowNumericType,
+ T::Native: ArrowNativeTypeOp,
{
- Ok(unary(array, |x| -x))
+ try_unary(array, |value| value.neg_checked())
}
/// Raise array with floating point values to the power of a scalar.
@@ -2567,6 +2580,17 @@ mod tests {
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).into_iter().map(Some).collect();
diff --git a/arrow/src/datatypes/native.rs b/arrow/src/datatypes/native.rs
index 444ba39e0..2643025f1 100644
--- a/arrow/src/datatypes/native.rs
+++ b/arrow/src/datatypes/native.rs
@@ -64,6 +64,10 @@ pub trait ArrowNativeTypeOp: ArrowNativeType {
fn mod_wrapping(self, rhs: Self) -> Self;
+ fn neg_checked(self) -> Result<Self>;
+
+ fn neg_wrapping(self) -> Self;
+
fn is_zero(self) -> bool;
fn is_eq(self, rhs: Self) -> bool;
@@ -158,6 +162,16 @@ macro_rules! native_type_op {
self.wrapping_rem(rhs)
}
+ fn neg_checked(self) -> Result<Self> {
+ self.checked_neg().ok_or_else(|| {
+ ArrowError::ComputeError(format!("Overflow happened on: {:?}", self))
+ })
+ }
+
+ fn neg_wrapping(self) -> Self {
+ self.wrapping_neg()
+ }
+
fn is_zero(self) -> bool {
self == 0
}
@@ -253,6 +267,14 @@ macro_rules! native_type_float_op {
self % rhs
}
+ fn neg_checked(self) -> Result<Self> {
+ Ok(-self)
+ }
+
+ fn neg_wrapping(self) -> Self {
+ -self
+ }
+
fn is_zero(self) -> bool {
self == $zero
}