1use std::ops::Mul;
5
6use num_traits::One;
7use vortex_array::ArrayRef;
8use vortex_array::execution::{BatchKernel, BatchKernelRef, BindCtx, MaskExecution};
9use vortex_array::vtable::OperatorVTable;
10use vortex_dtype::{NativePType, match_each_native_ptype};
11use vortex_error::{VortexExpect, VortexResult};
12use vortex_mask::AllOr;
13use vortex_vector::primitive::PVectorMut;
14use vortex_vector::{Vector, VectorMutOps};
15
16use crate::{SequenceArray, SequenceVTable};
17
18impl OperatorVTable<SequenceVTable> for SequenceVTable {
19 fn bind(
20 array: &SequenceArray,
21 selection: Option<&ArrayRef>,
22 ctx: &mut dyn BindCtx,
23 ) -> VortexResult<BatchKernelRef> {
24 let selection = ctx.bind_selection(array.len(), selection)?;
25
26 Ok(match_each_native_ptype!(array.ptype(), |T| {
27 if array.multiplier().cast::<T>() == <T as One>::one() {
28 Box::new(SequenceKernel::<T> {
29 base: array.base().cast::<T>(),
30 selection,
31 })
32 } else {
33 Box::new(MultiplierSequenceKernel::<T> {
34 base: array.base().cast::<T>(),
35 multiplier: array.multiplier().cast::<T>(),
36 selection,
37 })
38 }
39 }))
40 }
41}
42
43struct SequenceKernel<T> {
44 base: T,
45 selection: MaskExecution,
46}
47
48impl<T: NativePType> BatchKernel for SequenceKernel<T> {
49 fn execute(self: Box<Self>) -> VortexResult<Vector> {
50 let selection = self.selection.execute()?;
51
52 let elements = match selection.indices() {
53 AllOr::All => PVectorMut::<T>::from_iter((0..selection.len()).map(|i| {
54 let offset = T::from_usize(i).vortex_expect("Overflow converting usize to ptype");
56 self.base + offset
57 })),
58 AllOr::None => PVectorMut::<T>::with_capacity(0),
59 AllOr::Some(indices) => {
60 PVectorMut::<T>::from_iter(indices.iter().map(|i| {
61 let offset =
63 T::from_usize(*i).vortex_expect("Overflow converting usize to ptype");
64 self.base + offset
65 }))
66 }
67 };
68
69 Ok(elements.freeze().into())
70 }
71}
72
73struct MultiplierSequenceKernel<T> {
74 base: T,
75 multiplier: T,
76 selection: MaskExecution,
77}
78
79impl<T: NativePType + Mul> BatchKernel for MultiplierSequenceKernel<T> {
80 fn execute(self: Box<Self>) -> VortexResult<Vector> {
81 let selection = self.selection.execute()?;
82
83 let elements = match selection.indices() {
84 AllOr::All => PVectorMut::<T>::from_iter((0..selection.len()).map(|i| {
85 let offset = T::from_usize(i).vortex_expect("Overflow converting usize to ptype");
87 let scaled = self.multiplier * offset;
88 self.base + scaled
89 })),
90 AllOr::None => PVectorMut::<T>::with_capacity(0),
91 AllOr::Some(indices) => PVectorMut::<T>::from_iter(indices.iter().map(|&i| {
92 let offset = T::from_usize(i).vortex_expect("Overflow converting usize to ptype");
94 let scaled = self.multiplier * offset;
95 self.base + scaled
96 })),
97 };
98
99 Ok(elements.freeze().into())
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use vortex_array::IntoArray;
106 use vortex_buffer::{bitbuffer, buffer};
107 use vortex_dtype::{Nullability, PTypeDowncast};
108 use vortex_vector::VectorOps;
109
110 use crate::SequenceArray;
111
112 #[test]
113 fn test_sequence_operator_unit_multiplier() {
114 let seq = SequenceArray::typed_new(2i32, 1, Nullability::NonNullable, 4)
116 .unwrap()
117 .into_array();
118
119 let result = seq.execute().unwrap().into_primitive().into_i32();
120
121 assert_eq!(
122 result.elements().as_slice(),
123 buffer![2i32, 3, 4, 5].as_slice()
124 );
125 }
126
127 #[test]
128 fn test_sequence_operator_with_multiplier() {
129 let seq = SequenceArray::typed_new(5i64, 3, Nullability::NonNullable, 5)
131 .unwrap()
132 .into_array();
133
134 let result = seq.execute().unwrap().into_primitive().into_i64();
135
136 assert_eq!(
137 result.elements().as_slice(),
138 buffer![5i64, 8, 11, 14, 17].as_slice()
139 );
140 }
141
142 #[test]
143 fn test_sequence_operator_negative_multiplier() {
144 let seq = SequenceArray::typed_new(10i16, -2, Nullability::NonNullable, 4)
146 .unwrap()
147 .into_array();
148
149 let result = seq.execute().unwrap().into_primitive().into_i16();
150
151 assert_eq!(
152 result.elements().as_slice(),
153 buffer![10i16, 8, 6, 4].as_slice()
154 );
155 }
156
157 #[test]
158 fn test_sequence_operator_single_element() {
159 let seq = SequenceArray::typed_new(42i32, 1, Nullability::NonNullable, 1)
161 .unwrap()
162 .into_array();
163
164 let result = seq.execute().unwrap().into_primitive().into_i32();
165
166 assert_eq!(result.elements().as_slice(), buffer![42i32].as_slice());
167 }
168
169 #[test]
170 fn test_sequence_operator_u64() {
171 let seq = SequenceArray::typed_new(100u64, 10, Nullability::NonNullable, 4)
173 .unwrap()
174 .into_array();
175
176 let result = seq.execute().unwrap().into_primitive().into_u64();
177
178 assert_eq!(
179 result.elements().as_slice(),
180 buffer![100u64, 110, 120, 130].as_slice()
181 );
182 }
183
184 #[test]
185 fn test_sequence_operator_with_selection_alternating() {
186 let seq = SequenceArray::typed_new(10i32, 1, Nullability::NonNullable, 5)
188 .unwrap()
189 .into_array();
190
191 let selection = bitbuffer![1 0 1 0 1].into();
192 let result = seq
193 .execute_with_selection(&selection)
194 .unwrap()
195 .into_primitive()
196 .into_i32();
197
198 assert_eq!(
199 result.elements().as_slice(),
200 buffer![10i32, 12, 14].as_slice()
201 );
202 }
203
204 #[test]
205 fn test_sequence_operator_with_selection_beginning() {
206 let seq = SequenceArray::typed_new(5i64, 3, Nullability::NonNullable, 5)
208 .unwrap()
209 .into_array();
210
211 let selection = bitbuffer![1 1 0 0 0].into();
212 let result = seq
213 .execute_with_selection(&selection)
214 .unwrap()
215 .into_primitive()
216 .into_i64();
217
218 assert_eq!(result.elements().as_slice(), buffer![5i64, 8].as_slice());
219 }
220
221 #[test]
222 fn test_sequence_operator_with_selection_end() {
223 let seq = SequenceArray::typed_new(100u64, 10, Nullability::NonNullable, 4)
225 .unwrap()
226 .into_array();
227
228 let selection = bitbuffer![0 0 1 1].into();
229 let result = seq
230 .execute_with_selection(&selection)
231 .unwrap()
232 .into_primitive()
233 .into_u64();
234
235 assert_eq!(
236 result.elements().as_slice(),
237 buffer![120u64, 130].as_slice()
238 );
239 }
240
241 #[test]
242 fn test_sequence_operator_with_selection_none() {
243 let seq = SequenceArray::typed_new(2i32, 1, Nullability::NonNullable, 4)
245 .unwrap()
246 .into_array();
247
248 let selection = bitbuffer![0 0 0 0].into();
249 let result = seq.execute_with_selection(&selection).unwrap();
250 assert!(result.is_empty())
251 }
252
253 #[test]
254 fn test_sequence_operator_with_selection_all() {
255 let seq = SequenceArray::typed_new(10i16, -2, Nullability::NonNullable, 4)
257 .unwrap()
258 .into_array();
259
260 let selection = bitbuffer![1 1 1 1].into();
261 let result = seq
262 .execute_with_selection(&selection)
263 .unwrap()
264 .into_primitive()
265 .into_i16();
266
267 assert_eq!(
268 result.elements().as_slice(),
269 buffer![10i16, 8, 6, 4].as_slice()
270 );
271 }
272
273 #[test]
274 fn test_sequence_operator_with_multiplier_and_selection() {
275 let seq = SequenceArray::typed_new(0i32, 5, Nullability::NonNullable, 6)
277 .unwrap()
278 .into_array();
279
280 let selection = bitbuffer![1 0 0 1 0 1].into();
281 let result = seq
282 .execute_with_selection(&selection)
283 .unwrap()
284 .into_primitive()
285 .into_i32();
286
287 assert_eq!(
288 result.elements().as_slice(),
289 buffer![0i32, 15, 25].as_slice()
290 );
291 }
292}