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

Commit

Permalink
use cached null counts
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchie46 committed Jan 8, 2022
1 parent 0f324b8 commit 8fdbbf4
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 59 deletions.
34 changes: 10 additions & 24 deletions src/compute/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,30 +194,16 @@ pub fn any(array: &BooleanArray) -> bool {
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>() };
vals.null_count() != 0
}
}

head.iter().any(|&v| v != 0) || mid.iter().any(|&v| v != 0) || tail.iter().any(|&v| v != 0)
/// Check if all of the values in the array are `true`
pub fn all(array: &BooleanArray) -> bool {
if array.is_empty() || array.null_count() > 0 {
false
} else {
let vals = array.values();
vals.null_count() == 0
}
}
50 changes: 15 additions & 35 deletions tests/it/compute/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,43 +421,23 @@ fn array_or_scalar_validity() {
}

#[test]
fn test_any() {
fn test_any_all() {
let array = BooleanArray::from(&[None, Some(false), Some(true)]);
assert!(any(&array));
assert!(!all(&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));
assert!(!all(&array));
let array = BooleanArray::from(&[None, Some(true), Some(true)]);
assert!(!all(&array));
assert!(any(&array));
let array = BooleanArray::from_iter(std::iter::repeat(false).take(10).map(Some));
assert!(!any(&array));
assert!(!all(&array));
let array = BooleanArray::from_iter(std::iter::repeat(true).take(10).map(Some));
assert!(all(&array));
assert!(any(&array));
let array = BooleanArray::from_iter([true, false, true, true].map(Some));
assert!(!all(&array));
assert!(any(&array));
}

0 comments on commit 8fdbbf4

Please sign in to comment.