Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Commit

Permalink
implement any kernel
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchie46 committed Jan 7, 2022
1 parent 299df30 commit 0f324b8
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/compute/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,3 +185,39 @@ pub fn or_scalar(array: &BooleanArray, scalar: &BooleanScalar) -> BooleanArray {
None => BooleanArray::new_null(DataType::Boolean, array.len()),
}
}

/// Check if any of the values in the array is `true`
pub fn any(array: &BooleanArray) -> bool {
if array.is_empty() {
false
} else if array.validity().is_some() {
array.into_iter().any(|v| v == Some(true))
} else {
let vals = array.values();
let (mut bytes, start, mut len) = vals.as_slice();
if start != 0 {
if array.values_iter().take(8 - start).any(|v| v) {
return true;
}
bytes = &bytes[1..];
len -= start;
}
// remaining part of last byte
let remainder = len % 8;
if remainder != 0 {
let last = bytes[bytes.len() - 1];
for i in 0..remainder {
if last & 1 << i != 0 {
return true;
}
}
// exclude last byte
bytes = &bytes[..bytes.len() - 1];
}
// Safety:
// we transmute from integer types and the align_to function deals with correct alignment.
let (head, mid, tail) = unsafe { bytes.align_to::<u64>() };

head.iter().any(|&v| v != 0) || mid.iter().any(|&v| v != 0) || tail.iter().any(|&v| v != 0)
}
}
43 changes: 43 additions & 0 deletions tests/it/compute/boolean.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use arrow2::array::*;
use arrow2::compute::boolean::*;
use arrow2::scalar::BooleanScalar;
use std::iter::FromIterator;

#[test]
fn array_and() {
Expand Down Expand Up @@ -418,3 +419,45 @@ fn array_or_scalar_validity() {
let expected = BooleanArray::from(&[None; 3]);
assert_eq!(real, expected);
}

#[test]
fn test_any() {
let array = BooleanArray::from(&[None, Some(false), Some(true)]);
assert!(any(&array));
let array = BooleanArray::from(&[None, Some(false), Some(false)]);
assert!(!any(&array));

// create some slices and offset to make test more interesting
let mut slices = Vec::with_capacity(8 * 10 + 1);
for offset in 0..8 {
for len in 20..30 {
slices.push((offset, len))
}
}

let all_true = BooleanArray::from_trusted_len_values_iter(std::iter::repeat(true).take(50));
let all_false = BooleanArray::from_trusted_len_values_iter(std::iter::repeat(false).take(50));
let various = BooleanArray::from_iter((0..50).map(|v| Some(v % 2 == 0)));

for (offset, len) in slices {
let arr = all_true.slice(offset, len);
assert!(any(&arr));

let arr = all_false.slice(offset, len);
assert!(!any(&arr));

let arr = various.slice(offset, len);
assert!(any(&arr));
}
let last_value = BooleanArray::from_iter((0..50).map(|v| Some(v == 49)));
assert!(any(&last_value));
// slice of the true value
let arr = last_value.slice(0, 49);
assert!(!any(&arr));

let first_value = BooleanArray::from_iter((0..50).map(|v| Some(v == 0)));
assert!(any(&first_value));
// slice of the true value
let arr = first_value.slice(1, 49);
assert!(!any(&arr));
}

0 comments on commit 0f324b8

Please sign in to comment.