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, ¬(&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, ¬(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]