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

   ### Describe the bug
   
   `arrow_arith::boolean::and_not` produces incorrect values when called on
   sliced `BooleanArray`s.
   
   The API documentation states that `and_not(left, right)` is equivalent to
   `and(left, not(right))`. This holds for arrays with an offset of zero, but 
not
   for sliced arrays with a non-zero bitmap offset.
   
   ### To Reproduce
   
   Reproduced on `main`. version  59.2.0
   
   ```rust
   use arrow_array::{Array, BooleanArray};
   use arrow_arith::boolean::{and, and_not, not};
   
   fn values(array: &BooleanArray) -> Vec<Option<bool>> {
       array.iter().collect()
   }
   
   fn main() {
       let full_left =
           BooleanArray::from(vec![true, false, true, false, true, false, 
true]);
       let full_right =
           BooleanArray::from(vec![false, true, false, true, false, true, 
false]);
   
       // The documented equivalence holds for offset-zero arrays.
       assert_eq!(
           and_not(&full_left, &full_right).unwrap(),
           and(&full_left, &not(&full_right).unwrap()).unwrap(),
       );
   
       let left_slice = full_left.slice(2, 3);
       let right_slice = full_right.slice(2, 3);
       let left = left_slice
           .as_any()
           .downcast_ref::<BooleanArray>()
           .unwrap();
       let right = right_slice
           .as_any()
           .downcast_ref::<BooleanArray>()
           .unwrap();
   
       let actual = and_not(left, right).unwrap();
       let expected = and(left, &not(right).unwrap()).unwrap();
   
       println!("actual:   {:?}", values(&actual));
       println!("expected: {:?}", values(&expected));
   
       assert_eq!(actual, expected);
   }
   
   Output:
   
   actual:   [Some(true), Some(false), Some(false)]
   expected: [Some(true), Some(false), Some(true)]
   
   thread 'main' panicked: assertion `left == right` failed
   
   ### Expected behavior
   
   For both sliced and unsliced arrays:
   
   and_not(left, right) == and(left, not(right))
   
   For the reproduction above, and_not should return:
   [Some(true), Some(false), Some(true)]
   
   ### Additional context
   
   The issue appears to be in arrow-arith/src/boolean.rs:
   
   let buffer = buffer_bin_and_not(
       a.inner(),
       b.offset(),
       b.inner(),
       a.offset(),
       a.len(),
   );
   BooleanBuffer::new(buffer, left.offset(), left.len())
   
   buffer_bin_and_not accepts arguments in the order
   (left, left_offset, right, right_offset, len), but the offsets are passed in
   reverse order.
   Additionally, buffer_bin_and_not normalizes a non-zero-offset result to an
   offset-zero Buffer. Wrapping that result in BooleanBuffer::new with
   left.offset() applies the original slice offset a second time.
   A potential fix is to pass a.offset() and b.offset() in the corresponding
   positions and construct the result with offset 0. A regression test should
   cover sliced arrays, including inputs with different slice offsets.
   ```


-- 
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