vortex_array/compute/
invert.rs

1use vortex_dtype::DType;
2use vortex_error::{VortexExpect, VortexResult, vortex_bail};
3
4use crate::encoding::Encoding;
5use crate::{Array, ArrayRef, ToCanonical};
6
7pub trait InvertFn<A> {
8    /// Logically invert a boolean array. Converts true -> false, false -> true, null -> null.
9    fn invert(&self, array: A) -> VortexResult<ArrayRef>;
10}
11
12impl<E: Encoding> InvertFn<&dyn Array> for E
13where
14    E: for<'a> InvertFn<&'a E::Array>,
15{
16    fn invert(&self, array: &dyn Array) -> VortexResult<ArrayRef> {
17        let array_ref = array
18            .as_any()
19            .downcast_ref::<E::Array>()
20            .vortex_expect("Failed to downcast array");
21        InvertFn::invert(self, array_ref)
22    }
23}
24
25/// Logically invert a boolean array.
26pub fn invert(array: &dyn Array) -> VortexResult<ArrayRef> {
27    if !matches!(array.dtype(), DType::Bool(..)) {
28        vortex_bail!("Expected boolean array, got {}", array.dtype());
29    }
30
31    if let Some(f) = array.vtable().invert_fn() {
32        let inverted = f.invert(array)?;
33
34        debug_assert_eq!(
35            inverted.len(),
36            array.len(),
37            "Invert length mismatch {}",
38            array.encoding()
39        );
40        debug_assert_eq!(
41            inverted.dtype(),
42            array.dtype(),
43            "Invert dtype mismatch {}",
44            array.encoding()
45        );
46
47        return Ok(inverted);
48    }
49
50    // Otherwise, we canonicalize into a boolean array and invert.
51    log::debug!(
52        "No invert implementation found for encoding {}",
53        array.encoding(),
54    );
55    invert(&array.to_bool()?.into_array())
56}