mbutrovich opened a new issue, #11604:
URL: https://github.com/apache/arrow-rs/issues/11604

   ### Describe the bug
   
   Decimal `div` returns quotients past the output's declared precision without 
an error, on both its direct path and the `scaled_div` fallback from #10911. 
The one exception is a negative quotient of exactly the native minimum 
(`i32::MIN`, `i64::MIN`, `i128::MIN`, or `i256::MIN`) on the fallback path. 
`scaled_div` divides magnitudes and negates last, and the minimum's magnitude 
does not fit, so it returns an overflow error.
   
   ### To Reproduce
   
   ```rust
   use arrow_arith::numeric::div;
   use arrow_array::cast::AsArray;
   use arrow_array::types::Decimal32Type;
   use arrow_array::Decimal32Array;
   
   fn dec(v: i32, p: u8, s: i8) -> Decimal32Array {
       Decimal32Array::from(vec![v]).with_precision_and_scale(p, s).unwrap()
   }
   
   fn main() {
       // Decimal32(9, 9) / Decimal32(9, 9) gives Decimal32(9, 9) and scales the
       // dividend by 10^9, which overflows i32, so `div` uses `scaled_div`.
       // The quotient is 2^22 * 10^9 / -(5^9) = -2^31 = i32::MIN
       let r = div(&dec(1 << 22, 9, 9), &dec(-1_953_125, 9, 9));
       println!("{r:?}"); // Err(ArithmeticOverflow("Overflow happened on: 
2147483640 + 8"))
   
       // One less in magnitude is also past precision 9, and is returned
       let r = div(&dec((1 << 22) - 1, 9, 9), &dec(-1_953_125, 9, 9)).unwrap();
       println!("{:?}", r.as_primitive::<Decimal32Type>().values()); // 
[-2147483136]
   
       // The direct path also returns quotients past precision 9
       let r = div(&dec(-214_748, 9, 0), &dec(1, 9, 0)).unwrap();
       println!("{:?}", r.as_primitive::<Decimal32Type>().values()); // 
[-2147480000]
   }
   ```
   
   The same happens for `Decimal128(38, 38)`, where a quotient of `i128::MIN` 
fails with "Overflow happened on: 170141183460469231731687303715884105720 + 8".
   
   ### Expected behavior
   
   Either `[-2147483648]` for the first call, like the other quotients past the 
declared precision, or an error for every quotient past it. As I read the code, 
`div` does neither consistently today.
   
   ### Additional context
   
   The #10911 description states that `T::Native::MIN` is unsupported as an 
operand, because no array with a valid precision holds it. This case has 
operands within precision 9. Only the quotient is the minimum. 
[`scaled_div`](https://github.com/apache/arrow-rs/blob/dd240116c75a15a2a048a041c808d67f3f32a375/arrow-arith/src/numeric.rs#L970-L1011)
 negates the quotient with `neg_checked` after the loop.
   
   #10947 covers casts of values past the declared precision. This is the same 
question for the output of `div`.
   
   Found with property-based tests that build arrays in every physical layout 
the Arrow format allows, on `main` at `72887ed9`. The code is unchanged on 
`main` at `dd240116`.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to