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