vortex_zigzag/
array.rs

1use vortex_array::stats::{ArrayStats, StatsSetRef};
2use vortex_array::variants::PrimitiveArrayTrait;
3use vortex_array::vtable::VTableRef;
4use vortex_array::{
5    Array, ArrayCanonicalImpl, ArrayImpl, ArrayRef, ArrayStatisticsImpl, ArrayValidityImpl,
6    ArrayVariantsImpl, Canonical, EmptyMetadata, Encoding, ToCanonical, try_from_array_ref,
7};
8use vortex_dtype::{DType, PType};
9use vortex_error::{VortexResult, vortex_bail};
10use vortex_mask::Mask;
11
12use crate::zigzag_decode;
13
14#[derive(Clone, Debug)]
15pub struct ZigZagArray {
16    dtype: DType,
17    encoded: ArrayRef,
18    stats_set: ArrayStats,
19}
20
21try_from_array_ref!(ZigZagArray);
22
23pub struct ZigZagEncoding;
24impl Encoding for ZigZagEncoding {
25    type Array = ZigZagArray;
26    type Metadata = EmptyMetadata;
27}
28
29impl ZigZagArray {
30    pub fn try_new(encoded: ArrayRef) -> VortexResult<Self> {
31        let encoded_dtype = encoded.dtype().clone();
32        if !encoded_dtype.is_unsigned_int() {
33            vortex_bail!(MismatchedTypes: "unsigned int", encoded_dtype);
34        }
35
36        let dtype = DType::from(PType::try_from(&encoded_dtype)?.to_signed())
37            .with_nullability(encoded_dtype.nullability());
38
39        Ok(Self {
40            dtype,
41            encoded,
42            stats_set: Default::default(),
43        })
44    }
45
46    pub fn encoded(&self) -> &ArrayRef {
47        &self.encoded
48    }
49}
50
51impl ArrayImpl for ZigZagArray {
52    type Encoding = ZigZagEncoding;
53
54    fn _len(&self) -> usize {
55        self.encoded.len()
56    }
57
58    fn _dtype(&self) -> &DType {
59        &self.dtype
60    }
61
62    fn _vtable(&self) -> VTableRef {
63        VTableRef::new_ref(&ZigZagEncoding)
64    }
65
66    fn _with_children(&self, children: &[ArrayRef]) -> VortexResult<Self> {
67        let encoded = children[0].clone();
68
69        Self::try_new(encoded)
70    }
71}
72
73impl ArrayCanonicalImpl for ZigZagArray {
74    fn _to_canonical(&self) -> VortexResult<Canonical> {
75        zigzag_decode(self.encoded().to_primitive()?).map(Canonical::Primitive)
76    }
77}
78
79impl ArrayStatisticsImpl for ZigZagArray {
80    fn _stats_ref(&self) -> StatsSetRef<'_> {
81        self.stats_set.to_ref(self)
82    }
83}
84
85impl ArrayValidityImpl for ZigZagArray {
86    fn _is_valid(&self, index: usize) -> VortexResult<bool> {
87        self.encoded.is_valid(index)
88    }
89
90    fn _all_valid(&self) -> VortexResult<bool> {
91        self.encoded.all_valid()
92    }
93
94    fn _all_invalid(&self) -> VortexResult<bool> {
95        self.encoded.all_invalid()
96    }
97
98    fn _validity_mask(&self) -> VortexResult<Mask> {
99        self.encoded.validity_mask()
100    }
101}
102
103impl ArrayVariantsImpl for ZigZagArray {
104    fn _as_primitive_typed(&self) -> Option<&dyn PrimitiveArrayTrait> {
105        Some(self)
106    }
107}
108
109impl PrimitiveArrayTrait for ZigZagArray {}
110
111#[cfg(test)]
112mod test {
113    use vortex_array::IntoArray;
114    use vortex_array::compute::{scalar_at, slice};
115    use vortex_array::vtable::EncodingVTable;
116    use vortex_buffer::buffer;
117    use vortex_scalar::Scalar;
118
119    use super::*;
120
121    #[test]
122    fn test_compute_statistics() {
123        let array = buffer![1i32, -5i32, 2, 3, 4, 5, 6, 7, 8, 9, 10].into_array();
124        let canonical = array.to_canonical().unwrap();
125        let zigzag = ZigZagEncoding.encode(&canonical, None).unwrap().unwrap();
126
127        assert_eq!(
128            zigzag.statistics().compute_max::<i32>(),
129            array.statistics().compute_max::<i32>()
130        );
131        assert_eq!(
132            zigzag.statistics().compute_null_count(),
133            array.statistics().compute_null_count()
134        );
135        assert_eq!(
136            zigzag.statistics().compute_is_constant(),
137            array.statistics().compute_is_constant()
138        );
139
140        let sliced = ZigZagArray::try_from(slice(&zigzag, 0, 2).unwrap()).unwrap();
141        assert_eq!(
142            scalar_at(&sliced, sliced.len() - 1).unwrap(),
143            Scalar::from(-5i32)
144        );
145
146        assert_eq!(
147            sliced.statistics().compute_min::<i32>(),
148            array.statistics().compute_min::<i32>()
149        );
150        assert_eq!(
151            sliced.statistics().compute_null_count(),
152            array.statistics().compute_null_count()
153        );
154        assert_eq!(
155            sliced.statistics().compute_is_constant(),
156            array.statistics().compute_is_constant()
157        );
158    }
159}