Skip to content

Commit 614ee88

Browse files
Dandandanalamb
authored andcommitted
Implement boolean equality kernels (#844)
* Implement boolean equality kernels * Respect offset * Simplify
1 parent a721e00 commit 614ee88

2 files changed

Lines changed: 142 additions & 2 deletions

File tree

arrow/src/compute/kernels/boolean.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ where
175175
}
176176

177177
/// Helper function to implement binary kernels
178-
fn binary_boolean_kernel<F>(
178+
pub(crate) fn binary_boolean_kernel<F>(
179179
left: &BooleanArray,
180180
right: &BooleanArray,
181181
op: F,

arrow/src/compute/kernels/comparison.rs

Lines changed: 141 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ use regex::Regex;
2626
use std::collections::HashMap;
2727

2828
use crate::array::*;
29-
use crate::buffer::{Buffer, MutableBuffer};
29+
use crate::buffer::{bitwise_bin_op_helper, buffer_unary_not, Buffer, MutableBuffer};
30+
use crate::compute::binary_boolean_kernel;
3031
use crate::compute::util::combine_option_bitmap;
3132
use crate::datatypes::{ArrowNumericType, DataType};
3233
use crate::error::{ArrowError, Result};
@@ -623,6 +624,84 @@ pub fn eq_utf8_scalar<OffsetSize: StringOffsetSizeTrait>(
623624
compare_op_scalar!(left, right, |a, b| a == b)
624625
}
625626

627+
/// Perform `left == right` operation on [`BooleanArray`]
628+
fn eq_bool(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray> {
629+
binary_boolean_kernel(
630+
left,
631+
right,
632+
|left: &Buffer,
633+
left_offset_in_bits: usize,
634+
right: &Buffer,
635+
right_offset_in_bits: usize,
636+
len_in_bits: usize| {
637+
bitwise_bin_op_helper(
638+
left,
639+
left_offset_in_bits,
640+
right,
641+
right_offset_in_bits,
642+
len_in_bits,
643+
|a, b| !(a ^ b),
644+
)
645+
},
646+
)
647+
}
648+
649+
/// Perform `left != right` operation on [`BooleanArray`]
650+
fn neq_bool(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray> {
651+
binary_boolean_kernel(
652+
left,
653+
right,
654+
|left: &Buffer,
655+
left_offset_in_bits: usize,
656+
right: &Buffer,
657+
right_offset_in_bits: usize,
658+
len_in_bits: usize| {
659+
bitwise_bin_op_helper(
660+
left,
661+
left_offset_in_bits,
662+
right,
663+
right_offset_in_bits,
664+
len_in_bits,
665+
|a, b| (a ^ b),
666+
)
667+
},
668+
)
669+
}
670+
671+
/// Perform `left == right` operation on [`BooleanArray`] and a scalar
672+
fn eq_bool_scalar(left: &BooleanArray, right: bool) -> Result<BooleanArray> {
673+
let len = left.len();
674+
let left_offset = left.offset();
675+
676+
let values = if right {
677+
left.values().bit_slice(left_offset, len)
678+
} else {
679+
buffer_unary_not(left.values(), left.offset(), left.len())
680+
};
681+
682+
let data = unsafe {
683+
ArrayData::new_unchecked(
684+
DataType::Boolean,
685+
len,
686+
None,
687+
left.data_ref()
688+
.null_bitmap()
689+
.as_ref()
690+
.map(|b| b.bits.bit_slice(left_offset, len)),
691+
0,
692+
vec![values],
693+
vec![],
694+
)
695+
};
696+
697+
Ok(BooleanArray::from(data))
698+
}
699+
700+
/// Perform `left != right` operation on [`BooleanArray`] and a scalar
701+
fn neq_bool_scalar(left: &BooleanArray, right: bool) -> Result<BooleanArray> {
702+
eq_bool_scalar(left, !right)
703+
}
704+
626705
/// Perform `left != right` operation on [`StringArray`] / [`LargeStringArray`].
627706
pub fn neq_utf8<OffsetSize: StringOffsetSizeTrait>(
628707
left: &GenericStringArray<OffsetSize>,
@@ -1252,6 +1331,67 @@ mod tests {
12521331
);
12531332
}
12541333

1334+
#[test]
1335+
fn test_boolean_array_eq() {
1336+
let a: BooleanArray =
1337+
vec![Some(true), Some(false), Some(false), Some(true), Some(true), None]
1338+
.into();
1339+
let b: BooleanArray =
1340+
vec![Some(true), Some(true), Some(false), Some(false), None, Some(false)]
1341+
.into();
1342+
1343+
let res: Vec<Option<bool>> = eq_bool(&a, &b).unwrap().iter().collect();
1344+
1345+
assert_eq!(
1346+
res,
1347+
vec![Some(true), Some(false), Some(true), Some(false), None, None]
1348+
)
1349+
}
1350+
1351+
#[test]
1352+
fn test_boolean_array_neq() {
1353+
let a: BooleanArray =
1354+
vec![Some(true), Some(false), Some(false), Some(true), Some(true), None]
1355+
.into();
1356+
let b: BooleanArray =
1357+
vec![Some(true), Some(true), Some(false), Some(false), None, Some(false)]
1358+
.into();
1359+
1360+
let res: Vec<Option<bool>> = neq_bool(&a, &b).unwrap().iter().collect();
1361+
1362+
assert_eq!(
1363+
res,
1364+
vec![Some(false), Some(true), Some(false), Some(true), None, None]
1365+
)
1366+
}
1367+
1368+
#[test]
1369+
fn test_boolean_array_eq_scalar() {
1370+
let a: BooleanArray = vec![Some(true), Some(false), None].into();
1371+
1372+
let res1: Vec<Option<bool>> = eq_bool_scalar(&a, false).unwrap().iter().collect();
1373+
1374+
assert_eq!(res1, vec![Some(false), Some(true), None]);
1375+
1376+
let res2: Vec<Option<bool>> = eq_bool_scalar(&a, true).unwrap().iter().collect();
1377+
1378+
assert_eq!(res2, vec![Some(true), Some(false), None]);
1379+
}
1380+
1381+
#[test]
1382+
fn test_boolean_array_neq_scalar() {
1383+
let a: BooleanArray = vec![Some(true), Some(false), None].into();
1384+
1385+
let res1: Vec<Option<bool>> =
1386+
neq_bool_scalar(&a, false).unwrap().iter().collect();
1387+
1388+
assert_eq!(res1, vec![Some(true), Some(false), None]);
1389+
1390+
let res2: Vec<Option<bool>> = neq_bool_scalar(&a, true).unwrap().iter().collect();
1391+
1392+
assert_eq!(res2, vec![Some(false), Some(true), None]);
1393+
}
1394+
12551395
#[test]
12561396
fn test_primitive_array_lt() {
12571397
cmp_i64!(

0 commit comments

Comments
 (0)