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