vortex_array/arrays/primitive/compute/
between.rs1use arrow_buffer::BooleanBuffer;
2use vortex_dtype::{NativePType, Nullability, match_each_native_ptype};
3use vortex_error::VortexResult;
4
5use crate::arrays::{BoolArray, PrimitiveArray, PrimitiveVTable};
6use crate::compute::{BetweenKernel, BetweenKernelAdapter, BetweenOptions, StrictComparison};
7use crate::vtable::ValidityHelper;
8use crate::{Array, ArrayRef, IntoArray, register_kernel};
9
10impl BetweenKernel for PrimitiveVTable {
11 fn between(
12 &self,
13 arr: &PrimitiveArray,
14 lower: &dyn Array,
15 upper: &dyn Array,
16 options: &BetweenOptions,
17 ) -> VortexResult<Option<ArrayRef>> {
18 let (Some(lower), Some(upper)) = (lower.as_constant(), upper.as_constant()) else {
19 return Ok(None);
20 };
21
22 let nullability =
26 arr.dtype.nullability() | lower.dtype().nullability() | upper.dtype().nullability();
27
28 Ok(Some(match_each_native_ptype!(arr.ptype(), |$P| {
29 between_impl::<$P>(arr, $P::try_from(lower)?, $P::try_from(upper)?, nullability, options)
30 })))
31 }
32}
33
34register_kernel!(BetweenKernelAdapter(PrimitiveVTable).lift());
35
36fn between_impl<T: NativePType + Copy>(
37 arr: &PrimitiveArray,
38 lower: T,
39 upper: T,
40 nullability: Nullability,
41 options: &BetweenOptions,
42) -> ArrayRef {
43 match (options.lower_strict, options.upper_strict) {
44 (StrictComparison::Strict, StrictComparison::Strict) => between_impl_(
46 arr,
47 lower,
48 NativePType::is_lt,
49 upper,
50 NativePType::is_lt,
51 nullability,
52 ),
53 (StrictComparison::Strict, StrictComparison::NonStrict) => between_impl_(
54 arr,
55 lower,
56 NativePType::is_lt,
57 upper,
58 NativePType::is_le,
59 nullability,
60 ),
61 (StrictComparison::NonStrict, StrictComparison::Strict) => between_impl_(
62 arr,
63 lower,
64 NativePType::is_le,
65 upper,
66 NativePType::is_lt,
67 nullability,
68 ),
69 (StrictComparison::NonStrict, StrictComparison::NonStrict) => between_impl_(
70 arr,
71 lower,
72 NativePType::is_le,
73 upper,
74 NativePType::is_le,
75 nullability,
76 ),
77 }
78}
79
80fn between_impl_<T>(
81 arr: &PrimitiveArray,
82 lower: T,
83 lower_fn: impl Fn(T, T) -> bool,
84 upper: T,
85 upper_fn: impl Fn(T, T) -> bool,
86 nullability: Nullability,
87) -> ArrayRef
88where
89 T: NativePType + Copy,
90{
91 let slice = arr.as_slice::<T>();
92 BoolArray::new(
93 BooleanBuffer::collect_bool(slice.len(), |idx| {
94 let i = unsafe { *slice.get_unchecked(idx) };
96 lower_fn(lower, i) & upper_fn(i, upper)
97 }),
98 arr.validity().clone().union_nullability(nullability),
99 )
100 .into_array()
101}