vortex_array/arrays/chunked/compute/
min_max.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_error::VortexResult;
5use vortex_error::vortex_err;
6use vortex_scalar::Scalar;
7
8use crate::arrays::ChunkedArray;
9use crate::arrays::ChunkedVTable;
10use crate::compute::MinMaxKernel;
11use crate::compute::MinMaxKernelAdapter;
12use crate::compute::MinMaxResult;
13use crate::compute::min_max;
14use crate::partial_ord::partial_max;
15use crate::partial_ord::partial_min;
16use crate::register_kernel;
17
18impl MinMaxKernel for ChunkedVTable {
19    fn min_max(&self, array: &ChunkedArray) -> VortexResult<Option<MinMaxResult>> {
20        let mut min_max_all_null = true;
21        let res = array
22            .array_iterator()
23            .map(|chunk| {
24                let chunk = chunk?;
25                if let Some(min_max) = min_max(&chunk)? {
26                    min_max_all_null = false;
27                    Ok((Some(min_max.min), Some(min_max.max)))
28                } else {
29                    Ok((None, None))
30                }
31            })
32            .collect::<VortexResult<Vec<_>>>()?;
33
34        // There are no chunks that have min/max stats, so return early
35        if min_max_all_null {
36            return Ok(None);
37        }
38
39        let (min_values, max_values): (Vec<Option<Scalar>>, Vec<Option<Scalar>>) =
40            res.into_iter().unzip();
41
42        Ok(Some(MinMaxResult {
43            min: min_values
44                .into_iter()
45                .flatten()
46                // This is None iff all the values `None` (refuted above) or partial_min returns None
47                .fold(None, |acc, x| {
48                    if let Some(acc) = acc {
49                        partial_min(x, acc)
50                    } else {
51                        Some(x)
52                    }
53                })
54                .ok_or_else(|| {
55                    vortex_err!("Incomparable scalars (from partial_min), this is likely a bug",)
56                })?,
57            max: max_values
58                .into_iter()
59                .flatten()
60                .fold(None, |acc, x| {
61                    if let Some(acc) = acc {
62                        partial_max(x, acc)
63                    } else {
64                        Some(x)
65                    }
66                })
67                .ok_or_else(|| vortex_err!("Incomparable scalars, this is likely a bug"))?,
68        }))
69    }
70}
71
72register_kernel!(MinMaxKernelAdapter(ChunkedVTable).lift());