Skip to main content

vortex_array/arrays/piecewise_sequence/
vtable.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use 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
41/// A [`PiecewiseSequence`]-encoded Vortex index array.
42pub 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}