vortex_array/arrays/bool/compute/
is_constant.rs

1use vortex_error::VortexResult;
2
3use crate::arrays::{BoolArray, BoolVTable};
4use crate::compute::{IsConstantKernel, IsConstantKernelAdapter, IsConstantOpts};
5use crate::register_kernel;
6
7impl IsConstantKernel for BoolVTable {
8    fn is_constant(&self, array: &BoolArray, opts: &IsConstantOpts) -> VortexResult<Option<bool>> {
9        // If the array is small, then it is a constant time operation.
10        if opts.is_negligible_cost() && array.len() > 64 {
11            return Ok(None);
12        }
13
14        let buffer = array.boolean_buffer();
15
16        // Safety:
17        // We must have at least one value at this point
18        let first_value = unsafe { buffer.value_unchecked(0) };
19        let value_block = if first_value { u64::MAX } else { 0_u64 };
20
21        let bit_chunks = buffer.bit_chunks();
22        let packed = bit_chunks.iter().all(|chunk| chunk == value_block);
23        let reminder = bit_chunks.remainder_bits().count_ones() as usize
24            == bit_chunks.remainder_len() * (first_value as usize);
25
26        // We iterate on blocks of u64
27        Ok(Some(packed & reminder))
28    }
29}
30
31register_kernel!(IsConstantKernelAdapter(BoolVTable).lift());
32
33#[cfg(test)]
34mod tests {
35    use rstest::rstest;
36
37    use super::*;
38
39    #[rstest]
40    #[case(vec![true], true)]
41    #[case(vec![false; 65], true)]
42    #[case({
43        let mut v = vec![true; 64];
44        v.push(false);
45        v
46    }, false)]
47    fn test_is_constant(#[case] input: Vec<bool>, #[case] expected: bool) {
48        let array = BoolArray::from_iter(input);
49        assert_eq!(array.is_constant(), expected);
50    }
51}