This is an automated email from the ASF dual-hosted git repository.
tustvold pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 3da5e0d010 Avoid overflow of remainder (#7159)
3da5e0d010 is described below
commit 3da5e0d010cb605c2f180c95643fc57dedf4f0fb
Author: Zhen Wang <[email protected]>
AuthorDate: Wed Mar 5 19:12:34 2025 +0800
Avoid overflow of remainder (#7159)
* Support div_wrapping/rem_wrapping for numeric arithmetic kernels
* handle DivideByZero
* add tests for other type
* fix format
* remove div
---
arrow-arith/src/numeric.rs | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/arrow-arith/src/numeric.rs b/arrow-arith/src/numeric.rs
index b6af40f7d7..a2dc391669 100644
--- a/arrow-arith/src/numeric.rs
+++ b/arrow-arith/src/numeric.rs
@@ -70,8 +70,10 @@ pub fn div(lhs: &dyn Datum, rhs: &dyn Datum) ->
Result<ArrayRef, ArrowError> {
/// Perform `lhs % rhs`
///
-/// Overflow or division by zero will result in an error, with exception to
+/// Division by zero will result in an error, with exception to
/// floating point numbers, which instead follow the IEEE 754 rules
+///
+/// `signed_integer::MIN % -1` will not result in an error but return 0
pub fn rem(lhs: &dyn Datum, rhs: &dyn Datum) -> Result<ArrayRef, ArrowError> {
arithmetic_op(Op::Rem, lhs, rhs)
}
@@ -313,7 +315,13 @@ fn integer_op<T: ArrowPrimitiveType>(
Op::MulWrapping => op!(l, l_s, r, r_s, l.mul_wrapping(r)),
Op::Mul => try_op!(l, l_s, r, r_s, l.mul_checked(r)),
Op::Div => try_op!(l, l_s, r, r_s, l.div_checked(r)),
- Op::Rem => try_op!(l, l_s, r, r_s, l.mod_checked(r)),
+ Op::Rem => try_op!(l, l_s, r, r_s, {
+ if r.is_zero() {
+ Err(ArrowError::DivideByZero)
+ } else {
+ Ok(l.mod_wrapping(r))
+ }
+ }),
};
Ok(Arc::new(array))
}
@@ -1042,6 +1050,11 @@ mod tests {
"Arithmetic overflow: Overflow happened on: -32768 / -1"
);
+ let a = Int16Array::from(vec![i16::MIN]);
+ let b = Int16Array::from(vec![-1]);
+ let result = rem(&a, &b).unwrap();
+ assert_eq!(result.as_ref(), &Int16Array::from(vec![0]));
+
let a = Int16Array::from(vec![21]);
let b = Int16Array::from(vec![0]);
let err = div(&a, &b).unwrap_err().to_string();