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();

Reply via email to