vortex_array/arrays/decimal/compute/
min_max.rs1use itertools::Itertools;
2use vortex_dtype::DType;
3use vortex_error::VortexResult;
4use vortex_mask::Mask;
5use vortex_scalar::{
6 DecimalValue, NativeDecimalType, Scalar, ScalarValue, match_each_decimal_value_type,
7};
8
9use crate::arrays::{DecimalArray, DecimalVTable};
10use crate::compute::{MinMaxKernel, MinMaxKernelAdapter, MinMaxResult};
11use crate::register_kernel;
12
13impl MinMaxKernel for DecimalVTable {
14 fn min_max(&self, array: &DecimalArray) -> VortexResult<Option<MinMaxResult>> {
15 match_each_decimal_value_type!(array.values_type(), |T| {
16 compute_min_max_with_validity::<T>(array)
17 })
18 }
19}
20
21register_kernel!(MinMaxKernelAdapter(DecimalVTable).lift());
22
23#[inline]
24fn compute_min_max_with_validity<D>(array: &DecimalArray) -> VortexResult<Option<MinMaxResult>>
25where
26 D: Into<DecimalValue> + NativeDecimalType,
27{
28 Ok(match array.validity_mask()? {
29 Mask::AllTrue(_) => compute_min_max(array.buffer::<D>().iter(), array.dtype()),
30 Mask::AllFalse(_) => None,
31 Mask::Values(v) => compute_min_max(
32 array
33 .buffer::<D>()
34 .iter()
35 .zip(v.boolean_buffer().iter())
36 .filter_map(|(v, m)| m.then_some(v)),
37 array.dtype(),
38 ),
39 })
40}
41
42fn compute_min_max<'a, T>(iter: impl Iterator<Item = &'a T>, dtype: &DType) -> Option<MinMaxResult>
43where
44 T: Into<DecimalValue> + NativeDecimalType + Ord + Copy + 'a,
45{
46 match iter.minmax_by(|a, b| a.cmp(b)) {
47 itertools::MinMaxResult::NoElements => None,
48 itertools::MinMaxResult::OneElement(&x) => {
49 let scalar = Scalar::new(dtype.clone(), ScalarValue::from(x.into()));
50 Some(MinMaxResult {
51 min: scalar.clone(),
52 max: scalar,
53 })
54 }
55 itertools::MinMaxResult::MinMax(&min, &max) => Some(MinMaxResult {
56 min: Scalar::new(dtype.clone(), ScalarValue::from(min.into())),
57 max: Scalar::new(dtype.clone(), ScalarValue::from(max.into())),
58 }),
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use vortex_buffer::buffer;
65 use vortex_dtype::DecimalDType;
66 use vortex_scalar::{DecimalValue, Scalar, ScalarValue};
67
68 use crate::arrays::DecimalArray;
69 use crate::compute::{MinMaxResult, min_max};
70 use crate::validity::Validity;
71
72 #[test]
73 fn min_max_test() {
74 let decimal = DecimalArray::new(
75 buffer![100i32, 2000i32, 200i32],
76 DecimalDType::new(4, 2),
77 Validity::from_iter([true, false, true]),
78 );
79
80 let min_max = min_max(decimal.as_ref()).unwrap();
81
82 let expected = MinMaxResult {
83 min: Scalar::new(
84 decimal.dtype().clone(),
85 ScalarValue::from(DecimalValue::from(100i32)),
86 ),
87 max: Scalar::new(
88 decimal.dtype().clone(),
89 ScalarValue::from(DecimalValue::from(200i32)),
90 ),
91 };
92
93 assert_eq!(Some(expected), min_max)
94 }
95}