vortex_array/arrays/chunked/compute/
is_constant.rs1use vortex_error::VortexExpect;
5use vortex_error::VortexResult;
6
7use crate::Array;
8use crate::arrays::ChunkedArray;
9use crate::arrays::ChunkedVTable;
10use crate::compute::IsConstantKernel;
11use crate::compute::IsConstantKernelAdapter;
12use crate::compute::IsConstantOpts;
13use crate::compute::is_constant_opts;
14use crate::register_kernel;
15
16impl IsConstantKernel for ChunkedVTable {
17 fn is_constant(
18 &self,
19 array: &ChunkedArray,
20 opts: &IsConstantOpts,
21 ) -> VortexResult<Option<bool>> {
22 let mut chunks = array.non_empty_chunks();
23
24 let first_chunk = chunks
25 .next()
26 .vortex_expect("Must have at least one non-empty chunk");
27
28 match is_constant_opts(first_chunk, opts)? {
29 None => return Ok(None),
31 Some(false) => return Ok(Some(false)),
32 Some(true) => {}
33 }
34
35 let first_value = first_chunk.scalar_at(0).into_nullable();
36
37 for chunk in chunks {
38 match is_constant_opts(chunk, opts)? {
39 None => return Ok(None),
41 Some(false) => return Ok(Some(false)),
42 Some(true) => {}
43 }
44
45 if first_value != chunk.scalar_at(0).into_nullable() {
46 return Ok(Some(false));
47 }
48 }
49
50 Ok(Some(true))
51 }
52}
53
54register_kernel!(IsConstantKernelAdapter(ChunkedVTable).lift());
55
56#[cfg(test)]
57mod tests {
58 use vortex_buffer::Buffer;
59 use vortex_buffer::buffer;
60 use vortex_dtype::DType;
61 use vortex_dtype::Nullability;
62 use vortex_dtype::PType;
63
64 use crate::Array;
65 use crate::IntoArray;
66 use crate::arrays::ChunkedArray;
67
68 #[test]
69 fn empty_chunk_is_constant() {
70 let chunked = ChunkedArray::try_new(
71 vec![
72 Buffer::<u8>::empty().into_array(),
73 Buffer::<u8>::empty().into_array(),
74 buffer![255u8, 255].into_array(),
75 Buffer::<u8>::empty().into_array(),
76 buffer![255u8, 255].into_array(),
77 ],
78 DType::Primitive(PType::U8, Nullability::NonNullable),
79 )
80 .unwrap()
81 .into_array();
82
83 assert!(chunked.statistics().compute_is_constant().unwrap());
84 }
85}