vortex_array/arrays/piecewise_sequence/
vtable.rs1use itertools::Itertools;
5use vortex_error::VortexResult;
6use vortex_error::vortex_bail;
7use vortex_error::vortex_ensure;
8use vortex_error::vortex_err;
9use vortex_error::vortex_panic;
10use vortex_session::VortexSession;
11use vortex_session::registry::CachedId;
12
13use crate::ArrayParts;
14use crate::ArrayRef;
15use crate::ExecutionCtx;
16use crate::ExecutionResult;
17use crate::IntoArray;
18use crate::array::Array;
19use crate::array::ArrayId;
20use crate::array::ArrayView;
21use crate::array::EmptyArrayData;
22use crate::array::OperationsVTable;
23use crate::array::VTable;
24use crate::array::ValidityVTable;
25use crate::array::with_empty_buffers;
26use crate::arrays::PrimitiveArray;
27use crate::arrays::piecewise_sequence::array::PiecewiseSequenceSlots;
28use crate::arrays::piecewise_sequence::check_index_arrays;
29use crate::arrays::piecewise_sequence::execute_index_arrays;
30use crate::arrays::piecewise_sequence::materialize_ranges;
31use crate::arrays::primitive::PrimitiveArrayExt;
32use crate::buffer::BufferHandle;
33use crate::dtype::DType;
34use crate::dtype::PType;
35use crate::dtype::UnsignedPType;
36use crate::match_each_unsigned_integer_ptype;
37use crate::scalar::Scalar;
38use crate::serde::ArrayChildren;
39use crate::validity::Validity;
40
41pub type PiecewiseSequenceArray = Array<PiecewiseSequence>;
43
44#[derive(Clone, Debug)]
45pub struct PiecewiseSequence;
46
47impl VTable for PiecewiseSequence {
48 type TypedArrayData = EmptyArrayData;
49 type OperationsVTable = Self;
50 type ValidityVTable = Self;
51
52 fn id(&self) -> ArrayId {
53 static ID: CachedId = CachedId::new("vortex.piecewise-sequence");
54 *ID
55 }
56
57 fn validate(
58 &self,
59 _data: &Self::TypedArrayData,
60 dtype: &DType,
61 _len: usize,
62 slots: &[Option<ArrayRef>],
63 ) -> VortexResult<()> {
64 vortex_ensure!(
65 dtype == &DType::from(PType::U64),
66 "PiecewiseSequenceArray dtype must be u64, got {dtype}"
67 );
68 vortex_ensure!(
69 slots.len() == PiecewiseSequenceSlots::NAMES.len(),
70 "PiecewiseSequenceArray requires {} slots, got {}",
71 PiecewiseSequenceSlots::NAMES.len(),
72 slots.len()
73 );
74 let starts = slots[PiecewiseSequenceSlots::STARTS]
75 .as_ref()
76 .ok_or_else(|| vortex_err!("PiecewiseSequenceArray starts slot must be present"))?;
77 let lengths = slots[PiecewiseSequenceSlots::LENGTHS]
78 .as_ref()
79 .ok_or_else(|| vortex_err!("PiecewiseSequenceArray lengths slot must be present"))?;
80 let multipliers = slots[PiecewiseSequenceSlots::MULTIPLIERS]
81 .as_ref()
82 .ok_or_else(|| {
83 vortex_err!("PiecewiseSequenceArray multipliers slot must be present")
84 })?;
85 check_index_arrays(starts, lengths, multipliers)
86 }
87
88 fn nbuffers(_array: ArrayView<'_, Self>) -> usize {
89 0
90 }
91
92 fn buffer(_array: ArrayView<'_, Self>, _idx: usize) -> BufferHandle {
93 vortex_panic!("PiecewiseSequenceArray has no buffers")
94 }
95
96 fn buffer_name(_array: ArrayView<'_, Self>, _idx: usize) -> Option<String> {
97 None
98 }
99
100 fn with_buffers(
101 &self,
102 array: ArrayView<'_, Self>,
103 buffers: &[BufferHandle],
104 ) -> VortexResult<ArrayParts<Self>> {
105 with_empty_buffers(self, array, buffers)
106 }
107
108 fn slot_name(_array: ArrayView<'_, Self>, idx: usize) -> String {
109 PiecewiseSequenceSlots::NAMES[idx].to_string()
110 }
111
112 fn serialize(
113 _array: ArrayView<'_, Self>,
114 _session: &VortexSession,
115 ) -> VortexResult<Option<Vec<u8>>> {
116 Ok(None)
117 }
118
119 fn deserialize(
120 &self,
121 _dtype: &DType,
122 _len: usize,
123 _metadata: &[u8],
124 _buffers: &[BufferHandle],
125 _children: &dyn ArrayChildren,
126 _session: &VortexSession,
127 ) -> VortexResult<ArrayParts<Self>> {
128 vortex_bail!("PiecewiseSequenceArray is not serializable")
129 }
130
131 fn execute(array: Array<Self>, ctx: &mut ExecutionCtx) -> VortexResult<ExecutionResult> {
132 let (starts, lengths, multipliers) = execute_index_arrays(array.as_view(), ctx)?;
133
134 let values = match_each_unsigned_integer_ptype!(starts.ptype(), |S| {
135 match_each_unsigned_integer_ptype!(lengths.ptype(), |L| {
136 match_each_unsigned_integer_ptype!(multipliers.ptype(), |M| {
137 materialize_ranges::<S, L, M>(&starts, &lengths, &multipliers, array.len())?
138 })
139 })
140 });
141 Ok(ExecutionResult::done(
142 PrimitiveArray::new(values.freeze(), Validity::NonNullable).into_array(),
143 ))
144 }
145}
146
147impl OperationsVTable<PiecewiseSequence> for PiecewiseSequence {
148 fn scalar_at(
149 array: ArrayView<'_, PiecewiseSequence>,
150 index: usize,
151 ctx: &mut ExecutionCtx,
152 ) -> VortexResult<Scalar> {
153 let (starts, lengths, multipliers) = execute_index_arrays(array, ctx)?;
154
155 let value = match_each_unsigned_integer_ptype!(starts.ptype(), |S| {
156 match_each_unsigned_integer_ptype!(lengths.ptype(), |L| {
157 match_each_unsigned_integer_ptype!(multipliers.ptype(), |M| {
158 scalar_at::<S, L, M>(&starts, &lengths, &multipliers, index)?
159 })
160 })
161 });
162 Ok(value.into())
163 }
164}
165
166impl ValidityVTable<PiecewiseSequence> for PiecewiseSequence {
167 fn validity(_array: ArrayView<'_, PiecewiseSequence>) -> VortexResult<Validity> {
168 Ok(Validity::NonNullable)
169 }
170}
171
172fn scalar_at<S, L, M>(
173 starts: &PrimitiveArray,
174 lengths: &PrimitiveArray,
175 multipliers: &PrimitiveArray,
176 index: usize,
177) -> VortexResult<u64>
178where
179 S: UnsignedPType,
180 L: UnsignedPType,
181 M: UnsignedPType,
182{
183 let mut remaining = index;
184 for ((&start, &length), &multiplier) in starts
185 .as_slice::<S>()
186 .iter()
187 .zip_eq(lengths.as_slice::<L>())
188 .zip_eq(multipliers.as_slice::<M>())
189 {
190 let length: usize = length.as_();
191 if remaining < length {
192 let start: usize = start.as_();
193 let multiplier: usize = multiplier.as_();
194 let offset = remaining
195 .checked_mul(multiplier)
196 .ok_or_else(|| vortex_err!("PiecewiseSequenceArray range overflows usize"))?;
197 let value = start
198 .checked_add(offset)
199 .ok_or_else(|| vortex_err!("PiecewiseSequenceArray range overflows usize"))?;
200 return Ok(value as u64);
201 }
202 remaining -= length;
203 }
204 vortex_bail!("PiecewiseSequenceArray index {index} out of bounds")
205}