vortex_array/arrays/patched/vtable/
slice.rs1use std::ops::Range;
5
6use vortex_error::VortexResult;
7
8use crate::ArrayRef;
9use crate::IntoArray;
10use crate::array::ArrayView;
11use crate::arrays::Patched;
12use crate::arrays::patched::PatchedArrayExt;
13use crate::arrays::patched::PatchedArraySlotsExt;
14use crate::arrays::patched::PatchedSlots;
15use crate::arrays::slice::SliceReduce;
16
17impl SliceReduce for Patched {
18 fn slice(array: ArrayView<'_, Self>, range: Range<usize>) -> VortexResult<Option<ArrayRef>> {
19 let new_offset = (range.start + array.offset()) % 1024;
22 let chunk_start = (range.start + array.offset()) / 1024;
23 let chunk_stop = (range.end + array.offset()).div_ceil(1024);
24 let sliced_lane_offsets = array
25 .lane_offsets()
26 .slice((chunk_start * array.n_lanes())..(chunk_stop * array.n_lanes()) + 1)?;
27
28 let inner = array.inner().slice(range.start..range.end)?;
32 let len = inner.len();
33
34 let slots = PatchedSlots {
35 inner,
36 lane_offsets: sliced_lane_offsets,
37 patch_indices: array.patch_indices().clone(),
38 patch_values: array.patch_values().clone(),
39 }
40 .into_slots();
41
42 Ok(Some(
43 unsafe {
44 Patched::new_unchecked(
45 array.dtype().clone(),
46 len,
47 slots,
48 array.n_lanes(),
49 new_offset,
50 )
51 }
52 .into_array(),
53 ))
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use std::ops::Range;
60
61 use rstest::rstest;
62 use vortex_buffer::Buffer;
63 use vortex_buffer::BufferMut;
64 use vortex_buffer::buffer;
65 use vortex_error::VortexResult;
66
67 use crate::Canonical;
68 use crate::IntoArray;
69 use crate::VortexSessionExecute;
70 use crate::array_session;
71 use crate::arrays::Patched;
72 use crate::arrays::PrimitiveArray;
73 use crate::assert_arrays_eq;
74 use crate::dtype::NativePType;
75 use crate::patches::Patches;
76
77 #[test]
78 fn test_reduce() -> VortexResult<()> {
79 let mut ctx = array_session().create_execution_ctx();
80 let values = buffer![0u16; 512].into_array();
81 let patch_indices = buffer![1u32, 8, 30].into_array();
82 let patch_values = buffer![u16::MAX; 3].into_array();
83 let patches = Patches::new(512, 0, patch_indices, patch_values, None, &mut ctx)?;
84
85 let mut ctx = array_session().create_execution_ctx();
86
87 let patched_array = Patched::from_array_and_patches(values, &patches, &mut ctx)?;
88
89 let sliced = patched_array.into_array().slice(1..10)?;
90
91 insta::assert_snapshot!(
92 sliced.display_tree_encodings_only(),
93 @r#"
94 root: vortex.patched(u16, len=9)
95 inner: vortex.primitive(u16, len=9)
96 lane_offsets: vortex.primitive(u32, len=33)
97 patch_indices: vortex.primitive(u16, len=3)
98 patch_values: vortex.primitive(u16, len=3)
99 "#);
100
101 let executed = sliced.execute::<Canonical>(&mut ctx)?.into_primitive();
102
103 assert_eq!(
104 &[u16::MAX, 0, 0, 0, 0, 0, 0, u16::MAX, 0],
105 executed.as_slice::<u16>()
106 );
107
108 Ok(())
109 }
110
111 #[rstest]
112 #[case::trivial(buffer![1u64; 2], buffer![1u32], buffer![u64::MAX], 1..2)]
113 #[case::one_chunk(buffer![0u64; 1024], buffer![1u32, 8, 30], buffer![u64::MAX; 3], 1..10)]
114 #[case::multichunk(buffer![1u64; 10_000], buffer![0u32, 1, 2, 3, 4, 16, 17, 18, 19, 1024, 2048, 2049], buffer![u64::MAX; 12], 1024..5000)]
115 fn test_cases<T: NativePType>(
116 #[case] inner: Buffer<T>,
117 #[case] patch_indices: Buffer<u32>,
118 #[case] patch_values: Buffer<T>,
119 #[case] range: Range<usize>,
120 ) {
121 let mut expected = inner.to_vec();
122 for (&index, &value) in patch_indices.iter().zip(patch_values.iter()) {
123 expected[index as usize] = value;
124 }
125 let expected = PrimitiveArray::from_iter(expected[range.clone()].iter().copied());
126
127 let patches = Patches::new(
129 inner.len(),
130 0,
131 patch_indices.into_array(),
132 patch_values.into_array(),
133 None,
134 &mut array_session().create_execution_ctx(),
135 )
136 .unwrap();
137
138 let mut ctx = array_session().create_execution_ctx();
139
140 let patched_array = Patched::from_array_and_patches(inner.into_array(), &patches, &mut ctx)
141 .unwrap()
142 .into_array();
143
144 let slice_first = patched_array.slice(range).unwrap();
145
146 assert_arrays_eq!(slice_first, &expected, &mut ctx);
147 }
148
149 #[test]
150 fn test_stacked_slices() {
151 let mut ctx = array_session().create_execution_ctx();
152 let values = PrimitiveArray::from_iter(0u64..10_000).into_array();
153
154 let patched_indices = buffer![1u32, 2, 1024, 2048, 3072, 3088].into_array();
155 let patched_values = buffer![0u64, 1, 2, 3, 4, 5].into_array();
156
157 let patches =
158 Patches::new(10_000, 0, patched_indices, patched_values, None, &mut ctx).unwrap();
159
160 let patched_array = Patched::from_array_and_patches(values, &patches, &mut ctx)
161 .unwrap()
162 .into_array();
163
164 let sliced = patched_array
165 .slice(1024..5000)
166 .unwrap()
167 .slice(1..2065)
168 .unwrap();
169
170 let mut expected = BufferMut::from_iter(1025u64..=3088);
171 expected[1023] = 3;
172 expected[2047] = 4;
173 expected[2063] = 5;
174
175 let expected = expected.into_array();
176
177 assert_arrays_eq!(sliced, expected, &mut ctx);
178 }
179}