vortex_array/arrays/patched/vtable/
operations.rs1use vortex_error::VortexResult;
5
6use crate::ExecutionCtx;
7use crate::array::ArrayView;
8use crate::array::OperationsVTable;
9use crate::arrays::PrimitiveArray;
10use crate::arrays::patched::Patched;
11use crate::arrays::patched::PatchedArrayExt;
12use crate::arrays::patched::PatchedArraySlotsExt;
13use crate::optimizer::ArrayOptimizer;
14use crate::scalar::Scalar;
15
16impl OperationsVTable<Patched> for Patched {
17 type ProbeState = ();
18
19 fn scalar_at(
20 array: ArrayView<'_, Patched>,
21 index: usize,
22 ctx: &mut ExecutionCtx,
23 ) -> VortexResult<Scalar> {
24 let chunk = (index + array.offset()) / 1024;
25
26 #[expect(
27 clippy::cast_possible_truncation,
28 reason = "N % 1024 always fits in u16"
29 )]
30 let chunk_index = ((index + array.offset()) % 1024) as u16;
31
32 let lane = (index + array.offset()) % array.n_lanes();
33
34 let range = array.lane_range(chunk, lane, ctx)?;
35
36 let patch_indices = array
39 .patch_indices()
40 .slice(range.clone())?
41 .optimize()?
42 .execute::<PrimitiveArray>(ctx)?;
43
44 for (&patch_index, idx) in std::iter::zip(patch_indices.as_slice::<u16>(), range) {
47 if patch_index == chunk_index {
48 return array
49 .patch_values()
50 .execute_scalar(idx, ctx)?
51 .cast(array.dtype());
52 }
53 }
54
55 array.inner().execute_scalar(index, ctx)
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use vortex_buffer::buffer;
63 use vortex_session::VortexSession;
64
65 use crate::IntoArray;
66 use crate::VortexSessionExecute;
67 use crate::array_session;
68 use crate::arrays::Patched;
69 use crate::dtype::Nullability;
70 use crate::optimizer::ArrayOptimizer;
71 use crate::patches::Patches;
72 use crate::scalar::Scalar;
73
74 #[test]
75 fn test_simple() {
76 let mut ctx = array_session().create_execution_ctx();
77 let values = buffer![0u16; 1024].into_array();
78 let patches = Patches::new(
79 1024,
80 0,
81 buffer![1u32, 2, 3].into_array(),
82 buffer![1u16; 3].into_array(),
83 None,
84 &mut ctx,
85 )
86 .unwrap();
87
88 let session = VortexSession::empty();
89 let mut ctx = session.create_execution_ctx();
90
91 let array = Patched::from_array_and_patches(values, &patches, &mut ctx)
92 .unwrap()
93 .into_array();
94
95 assert_eq!(
96 array
97 .execute_scalar(0, &mut array_session().create_execution_ctx())
98 .unwrap(),
99 Scalar::primitive(0u16, Nullability::NonNullable)
100 );
101 assert_eq!(
102 array
103 .execute_scalar(1, &mut array_session().create_execution_ctx())
104 .unwrap(),
105 Scalar::primitive(1u16, Nullability::NonNullable)
106 );
107 assert_eq!(
108 array
109 .execute_scalar(2, &mut array_session().create_execution_ctx())
110 .unwrap(),
111 Scalar::primitive(1u16, Nullability::NonNullable)
112 );
113 assert_eq!(
114 array
115 .execute_scalar(3, &mut array_session().create_execution_ctx())
116 .unwrap(),
117 Scalar::primitive(1u16, Nullability::NonNullable)
118 );
119 }
120
121 #[test]
122 fn test_multi_chunk() {
123 let mut ctx = array_session().create_execution_ctx();
124 let values = buffer![0u16; 4096].into_array();
125 let patches = Patches::new(
126 4096,
127 0,
128 buffer![1u32, 2, 3].into_array(),
129 buffer![1u16; 3].into_array(),
130 None,
131 &mut ctx,
132 )
133 .unwrap();
134
135 let session = VortexSession::empty();
136 let mut ctx = session.create_execution_ctx();
137
138 let array = Patched::from_array_and_patches(values, &patches, &mut ctx)
139 .unwrap()
140 .into_array();
141
142 for index in 0..array.len() {
143 let value = array
144 .execute_scalar(index, &mut array_session().create_execution_ctx())
145 .unwrap();
146
147 if [1, 2, 3].contains(&index) {
148 assert_eq!(value, 1u16.into());
149 } else {
150 assert_eq!(value, 0u16.into());
151 }
152 }
153 }
154
155 #[test]
156 fn test_multi_chunk_sliced() {
157 let mut ctx = array_session().create_execution_ctx();
158 let values = buffer![0u16; 4096].into_array();
159 let patches = Patches::new(
160 4096,
161 0,
162 buffer![1u32, 2, 3].into_array(),
163 buffer![1u16; 3].into_array(),
164 None,
165 &mut ctx,
166 )
167 .unwrap();
168
169 let session = VortexSession::empty();
170 let mut ctx = session.create_execution_ctx();
171
172 let array = Patched::from_array_and_patches(values, &patches, &mut ctx)
173 .unwrap()
174 .into_array()
175 .slice(3..4096)
176 .unwrap()
177 .optimize()
178 .unwrap();
179
180 assert!(array.is::<Patched>());
181
182 assert_eq!(
183 array
184 .execute_scalar(0, &mut array_session().create_execution_ctx())
185 .unwrap(),
186 1u16.into()
187 );
188 for index in 1..array.len() {
189 assert_eq!(
190 array
191 .execute_scalar(index, &mut array_session().create_execution_ctx())
192 .unwrap(),
193 0u16.into()
194 );
195 }
196 }
197}