Skip to main content

vortex_fastlanes/delta/vtable/
operations.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use vortex_array::ArrayView;
5use vortex_array::ExecutionCtx;
6use vortex_array::IntoArray;
7use vortex_array::arrays::PrimitiveArray;
8use vortex_array::scalar::Scalar;
9use vortex_array::vtable::OperationsVTable;
10use vortex_error::VortexResult;
11
12use super::Delta;
13impl OperationsVTable<Delta> for Delta {
14    fn scalar_at(
15        array: ArrayView<'_, Delta>,
16        index: usize,
17        ctx: &mut ExecutionCtx,
18    ) -> VortexResult<Scalar> {
19        let decompressed = array
20            .array()
21            .slice(index..index + 1)?
22            .execute::<PrimitiveArray>(ctx)?;
23        decompressed.into_array().execute_scalar(0, ctx)
24    }
25}
26
27#[cfg(test)]
28mod tests {
29    use std::sync::LazyLock;
30
31    use rstest::rstest;
32    use vortex_array::IntoArray;
33    use vortex_array::VortexSessionExecute;
34    use vortex_array::array_session;
35    use vortex_array::arrays::PrimitiveArray;
36    use vortex_array::assert_arrays_eq;
37    use vortex_array::compute::conformance::binary_numeric::test_binary_numeric_array;
38    use vortex_array::compute::conformance::consistency::test_array_consistency;
39    use vortex_array::validity::Validity;
40    use vortex_buffer::buffer;
41    use vortex_error::VortexExpect;
42    use vortex_session::VortexSession;
43
44    use crate::Delta;
45    use crate::DeltaArray;
46
47    static SESSION: LazyLock<VortexSession> = LazyLock::new(|| {
48        let session = array_session();
49        crate::initialize(&session);
50        session
51    });
52
53    fn da(array: &PrimitiveArray) -> DeltaArray {
54        Delta::try_from_primitive_array(array, &mut SESSION.create_execution_ctx())
55            .vortex_expect("Delta array construction should succeed")
56    }
57
58    #[test]
59    fn test_slice_non_jagged_array_first_chunk_of_two() {
60        let delta = da(&(0u32..2048).collect());
61
62        let actual = delta.slice(10..250).unwrap();
63        let expected = PrimitiveArray::from_iter(10u32..250).into_array();
64        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
65    }
66
67    #[test]
68    fn test_slice_non_jagged_array_second_chunk_of_two() {
69        let delta = da(&(0u32..2048).collect());
70
71        let actual = delta.slice(1024 + 10..1024 + 250).unwrap();
72        let expected = PrimitiveArray::from_iter((1024 + 10u32)..(1024 + 250)).into_array();
73        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
74    }
75
76    #[test]
77    fn test_slice_non_jagged_array_span_two_chunks_chunk_of_two() {
78        let delta = da(&(0u32..2048).collect());
79
80        let actual = delta.slice(1000..1048).unwrap();
81        let expected = PrimitiveArray::from_iter(1000u32..1048).into_array();
82        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
83    }
84
85    #[test]
86    fn test_slice_non_jagged_array_span_two_chunks_chunk_of_four() {
87        let delta = da(&(0u32..4096).collect());
88
89        let actual = delta.slice(2040..2050).unwrap();
90        let expected = PrimitiveArray::from_iter(2040u32..2050).into_array();
91        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
92    }
93
94    #[test]
95    fn test_slice_non_jagged_array_whole() {
96        let delta = da(&(0u32..4096).collect());
97
98        let actual = delta.slice(0..4096).unwrap();
99        let expected = PrimitiveArray::from_iter(0u32..4096).into_array();
100        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
101    }
102
103    #[test]
104    fn test_slice_non_jagged_array_empty() {
105        let delta = da(&(0u32..4096).collect());
106
107        let actual = delta.slice(0..0).unwrap();
108        let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
109        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
110
111        let actual = delta.slice(4096..4096).unwrap();
112        let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
113        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
114
115        let actual = delta.slice(1024..1024).unwrap();
116        let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
117        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
118    }
119
120    #[test]
121    fn test_slice_jagged_array_second_chunk_of_two() {
122        let delta = da(&(0u32..2000).collect());
123
124        let actual = delta.slice(1024 + 10..1024 + 250).unwrap();
125        let expected = PrimitiveArray::from_iter((1024 + 10u32)..(1024 + 250)).into_array();
126        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
127    }
128
129    #[test]
130    fn test_slice_jagged_array_empty() {
131        let delta = da(&(0u32..4000).collect());
132
133        let actual = delta.slice(0..0).unwrap();
134        let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
135        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
136
137        let actual = delta.slice(4000..4000).unwrap();
138        let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
139        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
140
141        let actual = delta.slice(1024..1024).unwrap();
142        let expected = PrimitiveArray::from_iter(Vec::<u32>::new()).into_array();
143        assert_arrays_eq!(actual, expected, &mut SESSION.create_execution_ctx());
144    }
145
146    #[test]
147    fn test_slice_of_slice_of_non_jagged() {
148        let delta = da(&(0u32..2048).collect());
149
150        let sliced = delta.slice(10..1013).unwrap();
151        let sliced_again = sliced.slice(0..2).unwrap();
152
153        let expected = PrimitiveArray::from_iter(vec![10u32, 11]).into_array();
154        assert_arrays_eq!(sliced_again, expected, &mut SESSION.create_execution_ctx());
155    }
156
157    #[test]
158    fn test_slice_of_slice_of_jagged() {
159        let delta = da(&(0u32..2000).collect());
160
161        let sliced = delta.slice(10..1013).unwrap();
162        let sliced_again = sliced.slice(0..2).unwrap();
163
164        let expected = PrimitiveArray::from_iter(vec![10u32, 11]).into_array();
165        assert_arrays_eq!(sliced_again, expected, &mut SESSION.create_execution_ctx());
166    }
167
168    #[test]
169    fn test_slice_of_slice_second_chunk_of_non_jagged() {
170        let delta = da(&(0u32..2048).collect());
171
172        let sliced = delta.slice(1034..1050).unwrap();
173        let sliced_again = sliced.slice(0..2).unwrap();
174
175        let expected = PrimitiveArray::from_iter(vec![1034u32, 1035]).into_array();
176        assert_arrays_eq!(sliced_again, expected, &mut SESSION.create_execution_ctx());
177    }
178
179    #[test]
180    fn test_slice_of_slice_second_chunk_of_jagged() {
181        let delta = da(&(0u32..2000).collect());
182
183        let sliced = delta.slice(1034..1050).unwrap();
184        let sliced_again = sliced.slice(0..2).unwrap();
185
186        let expected = PrimitiveArray::from_iter(vec![1034u32, 1035]).into_array();
187        assert_arrays_eq!(sliced_again, expected, &mut SESSION.create_execution_ctx());
188    }
189
190    #[test]
191    fn test_slice_of_slice_spanning_two_chunks_of_non_jagged() {
192        let delta = da(&(0u32..2048).collect());
193
194        let sliced = delta.slice(1010..1050).unwrap();
195        let sliced_again = sliced.slice(5..20).unwrap();
196
197        let expected = PrimitiveArray::from_iter(1015u32..1030).into_array();
198        assert_arrays_eq!(sliced_again, expected, &mut SESSION.create_execution_ctx());
199    }
200
201    #[test]
202    fn test_slice_of_slice_spanning_two_chunks_of_jagged() {
203        let delta = da(&(0u32..2000).collect());
204
205        let sliced = delta.slice(1010..1050).unwrap();
206        let sliced_again = sliced.slice(5..20).unwrap();
207
208        let expected = PrimitiveArray::from_iter(1015u32..1030).into_array();
209        assert_arrays_eq!(sliced_again, expected, &mut SESSION.create_execution_ctx());
210    }
211
212    #[test]
213    fn test_scalar_at_non_jagged_array() {
214        let delta = da(&(0u32..2048).collect()).into_array();
215
216        let expected = PrimitiveArray::from_iter(0u32..2048).into_array();
217        assert_arrays_eq!(delta, expected, &mut SESSION.create_execution_ctx());
218    }
219
220    #[test]
221    #[should_panic]
222    fn test_scalar_at_non_jagged_array_oob() {
223        let delta = da(&(0u32..2048).collect()).into_array();
224        delta
225            .execute_scalar(2048, &mut SESSION.create_execution_ctx())
226            .unwrap();
227    }
228    #[test]
229    fn test_scalar_at_jagged_array() {
230        let delta = da(&(0u32..2000).collect()).into_array();
231
232        let expected = PrimitiveArray::from_iter(0u32..2000).into_array();
233        assert_arrays_eq!(delta, expected, &mut SESSION.create_execution_ctx());
234    }
235
236    #[test]
237    #[should_panic]
238    fn test_scalar_at_jagged_array_oob() {
239        let delta = da(&(0u32..2000).collect()).into_array();
240        delta
241            .execute_scalar(2000, &mut SESSION.create_execution_ctx())
242            .unwrap();
243    }
244
245    #[rstest]
246    // Basic delta arrays
247    #[case::delta_u32((0u32..100).collect())]
248    #[case::delta_u64((0..100).map(|i| i as u64 * 10).collect())]
249    // Large arrays (multiple chunks)
250    #[case::delta_large_u32((0u32..2048).collect())]
251    #[case::delta_large_u64((0u64..2048).collect())]
252    // Single element
253    #[case::delta_single(PrimitiveArray::new(buffer![42u32], Validity::NonNullable))]
254    // Signed inputs (added with signed-delta support).
255    #[case::delta_i32_crossing_zero((-100i32..100).collect())]
256    #[case::delta_i64_negative((0i64..100).map(|i| -i * 10).collect())]
257    #[case::delta_large_i32((-1024i32..1024).collect())]
258    #[case::delta_single_negative(PrimitiveArray::new(buffer![-42i32], Validity::NonNullable))]
259    fn test_delta_consistency(#[case] array: PrimitiveArray) {
260        test_array_consistency(
261            &da(&array).into_array(),
262            &mut SESSION.create_execution_ctx(),
263        );
264    }
265
266    #[rstest]
267    #[case::delta_u8_basic(PrimitiveArray::new(buffer![1u8, 1, 1, 1, 1], Validity::NonNullable))]
268    #[case::delta_u16_basic(PrimitiveArray::new(buffer![1u16, 1, 1, 1, 1], Validity::NonNullable))]
269    #[case::delta_u32_basic(PrimitiveArray::new(buffer![1u32, 1, 1, 1, 1], Validity::NonNullable))]
270    #[case::delta_u64_basic(PrimitiveArray::new(buffer![1u64, 1, 1, 1, 1], Validity::NonNullable))]
271    #[case::delta_u32_large(PrimitiveArray::new(buffer![1u32; 100], Validity::NonNullable))]
272    #[case::delta_i8_basic(PrimitiveArray::new(buffer![-1i8, -1, -1, -1, -1], Validity::NonNullable))]
273    #[case::delta_i32_basic(PrimitiveArray::new(buffer![-1i32, -1, -1, -1, -1], Validity::NonNullable))]
274    fn test_delta_binary_numeric(#[case] array: PrimitiveArray) {
275        test_binary_numeric_array(
276            &da(&array).into_array(),
277            &mut SESSION.create_execution_ctx(),
278        );
279    }
280}