@@ -32,7 +32,7 @@ use crate::buffer::Buffer;
32
32
use crate :: buffer:: MutableBuffer ;
33
33
use crate :: compute:: kernels:: arity:: unary;
34
34
use crate :: compute:: util:: combine_option_bitmap;
35
- use crate :: compute:: { binary, try_binary, try_unary, unary_dyn} ;
35
+ use crate :: compute:: { binary, binary_opt , try_binary, try_unary, unary_dyn} ;
36
36
use crate :: datatypes:: {
37
37
native_op:: ArrowNativeTypeOp , ArrowNumericType , DataType , Date32Type , Date64Type ,
38
38
IntervalDayTimeType , IntervalMonthDayNanoType , IntervalUnit , IntervalYearMonthType ,
@@ -711,7 +711,7 @@ where
711
711
}
712
712
713
713
/// Perform `left + right` operation on two arrays. If either left or right value is null
714
- /// then the result is also null. Once
714
+ /// then the result is also null.
715
715
///
716
716
/// This detects overflow and returns an `Err` for that. For an non-overflow-checking variant,
717
717
/// use `add` instead.
@@ -1118,6 +1118,32 @@ where
1118
1118
return math_checked_divide_op ( left, right, |a, b| a. div_checked ( b) ) ;
1119
1119
}
1120
1120
1121
+ /// Perform `left / right` operation on two arrays. If either left or right value is null
1122
+ /// then the result is also null.
1123
+ ///
1124
+ /// If any right hand value is zero, the operation value will be replaced with null in the
1125
+ /// result.
1126
+ ///
1127
+ /// Unlike `divide` or `divide_checked`, division by zero will get a null value instead
1128
+ /// returning an `Err`, this also doesn't check overflowing, overflowing will just wrap
1129
+ /// the result around.
1130
+ pub fn divide_opt < T > (
1131
+ left : & PrimitiveArray < T > ,
1132
+ right : & PrimitiveArray < T > ,
1133
+ ) -> Result < PrimitiveArray < T > >
1134
+ where
1135
+ T : ArrowNumericType ,
1136
+ T :: Native : ArrowNativeTypeOp + Zero + One ,
1137
+ {
1138
+ Ok ( binary_opt ( left, right, |a, b| {
1139
+ if b. is_zero ( ) {
1140
+ None
1141
+ } else {
1142
+ Some ( a. div_wrapping ( b) )
1143
+ }
1144
+ } ) )
1145
+ }
1146
+
1121
1147
/// Perform `left / right` operation on two arrays. If either left or right value is null
1122
1148
/// then the result is also null. If any right hand value is zero then the result of this
1123
1149
/// operation will be `Err(ArrowError::DivideByZero)`.
@@ -1152,7 +1178,7 @@ pub fn divide<T>(
1152
1178
right : & PrimitiveArray < T > ,
1153
1179
) -> Result < PrimitiveArray < T > >
1154
1180
where
1155
- T : datatypes :: ArrowNumericType ,
1181
+ T : ArrowNumericType ,
1156
1182
T :: Native : ArrowNativeTypeOp ,
1157
1183
{
1158
1184
math_op ( left, right, |a, b| a. div_wrapping ( b) )
@@ -2195,4 +2221,23 @@ mod tests {
2195
2221
let overflow = multiply_scalar_checked ( & a, i32:: MAX ) ;
2196
2222
overflow. expect_err ( "overflow should be detected" ) ;
2197
2223
}
2224
+
2225
+ #[ test]
2226
+ fn test_primitive_div_opt_overflow_division_by_zero ( ) {
2227
+ let a = Int32Array :: from ( vec ! [ i32 :: MIN ] ) ;
2228
+ let b = Int32Array :: from ( vec ! [ -1 ] ) ;
2229
+
2230
+ let wrapped = divide ( & a, & b) ;
2231
+ let expected = Int32Array :: from ( vec ! [ -2147483648 ] ) ;
2232
+ assert_eq ! ( expected, wrapped. unwrap( ) ) ;
2233
+
2234
+ let overflow = divide_opt ( & a, & b) ;
2235
+ let expected = Int32Array :: from ( vec ! [ -2147483648 ] ) ;
2236
+ assert_eq ! ( expected, overflow. unwrap( ) ) ;
2237
+
2238
+ let b = Int32Array :: from ( vec ! [ 0 ] ) ;
2239
+ let overflow = divide_opt ( & a, & b) ;
2240
+ let expected = Int32Array :: from ( vec ! [ None ] ) ;
2241
+ assert_eq ! ( expected, overflow. unwrap( ) ) ;
2242
+ }
2198
2243
}
0 commit comments