Skip to content

Commit 98a9180

Browse files
committed
Use PiecewiseSequential indices for FSL take
Signed-off-by: Daniel King <dan@spiraldb.com>
1 parent 1748e31 commit 98a9180

9 files changed

Lines changed: 755 additions & 150 deletions

File tree

vortex-array/src/arrays/bool/compute/take.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use itertools::Itertools as _;
55
use num_traits::AsPrimitive;
66
use vortex_buffer::BitBuffer;
7+
use vortex_buffer::BitBufferMut;
78
use vortex_buffer::BitBufferView;
89
use vortex_buffer::get_bit;
910
use vortex_error::VortexResult;
@@ -15,12 +16,17 @@ use crate::array::ArrayView;
1516
use crate::arrays::Bool;
1617
use crate::arrays::BoolArray;
1718
use crate::arrays::ConstantArray;
19+
use crate::arrays::PiecewiseSequential;
1820
use crate::arrays::PrimitiveArray;
1921
use crate::arrays::bool::BoolArrayExt;
2022
use crate::arrays::dict::TakeExecute;
23+
use crate::arrays::piecewise_sequential::execute_index_arrays;
24+
use crate::arrays::piecewise_sequential::index_value_to_usize;
25+
use crate::arrays::piecewise_sequential::validate_index_ranges;
2126
use crate::builtins::ArrayBuiltins;
2227
use crate::executor::ExecutionCtx;
2328
use crate::match_each_integer_ptype;
29+
use crate::match_each_unsigned_integer_ptype;
2430
use crate::scalar::Scalar;
2531

2632
impl TakeExecute for Bool {
@@ -29,6 +35,10 @@ impl TakeExecute for Bool {
2935
indices: &ArrayRef,
3036
ctx: &mut ExecutionCtx,
3137
) -> VortexResult<Option<ArrayRef>> {
38+
if let Some(piecewise_indices) = indices.as_opt::<PiecewiseSequential>() {
39+
return take_piecewise_sequential(array, piecewise_indices, indices, ctx).map(Some);
40+
}
41+
3242
let indices_nulls_zeroed = match indices.validity()?.execute_mask(indices.len(), ctx)? {
3343
Mask::AllTrue(_) => indices.clone(),
3444
Mask::AllFalse(_) => {
@@ -55,6 +65,27 @@ impl TakeExecute for Bool {
5565
}
5666
}
5767

68+
fn take_piecewise_sequential(
69+
array: ArrayView<'_, Bool>,
70+
indices: ArrayView<'_, PiecewiseSequential>,
71+
indices_ref: &ArrayRef,
72+
ctx: &mut ExecutionCtx,
73+
) -> VortexResult<ArrayRef> {
74+
let (starts, lengths) = execute_index_arrays(indices, ctx)?;
75+
let buffer = match_each_unsigned_integer_ptype!(starts.ptype(), |S| {
76+
match_each_unsigned_integer_ptype!(lengths.ptype(), |L| {
77+
take_piecewise_bits(
78+
&array.to_bit_buffer(),
79+
starts.as_slice::<S>(),
80+
lengths.as_slice::<L>(),
81+
indices_ref.len(),
82+
)?
83+
})
84+
});
85+
86+
Ok(BoolArray::new(buffer, array.validity()?.take(indices_ref)?).into_array())
87+
}
88+
5889
fn take_valid_indices<I: AsPrimitive<usize>>(bools: BitBufferView<'_>, indices: &[I]) -> BitBuffer {
5990
// For boolean arrays that roughly fit into a single page (at least, on Linux), it's worth
6091
// the overhead to convert to a Vec<bool>.
@@ -82,6 +113,28 @@ fn take_bool_impl<I: AsPrimitive<usize>>(bools: BitBufferView<'_>, indices: &[I]
82113
})
83114
}
84115

116+
fn take_piecewise_bits<S, L>(
117+
source: &BitBuffer,
118+
starts: &[S],
119+
lengths: &[L],
120+
output_len: usize,
121+
) -> VortexResult<BitBuffer>
122+
where
123+
S: crate::dtype::UnsignedPType,
124+
L: crate::dtype::UnsignedPType,
125+
{
126+
validate_index_ranges(source.len(), starts, lengths, output_len)?;
127+
128+
let mut values = BitBufferMut::with_capacity(output_len);
129+
for (&start, &length) in starts.iter().zip_eq(lengths) {
130+
let start = index_value_to_usize(start);
131+
let length = index_value_to_usize(length);
132+
values.append_buffer(&source.slice(start..start + length));
133+
}
134+
135+
Ok(values.freeze())
136+
}
137+
85138
#[cfg(test)]
86139
mod test {
87140
use rstest::rstest;

vortex-array/src/arrays/decimal/compute/take.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,39 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
use itertools::Itertools as _;
45
use vortex_buffer::Buffer;
6+
use vortex_buffer::BufferMut;
57
use vortex_error::VortexResult;
68

79
use crate::ArrayRef;
810
use crate::IntoArray;
911
use crate::array::ArrayView;
1012
use crate::arrays::Decimal;
1113
use crate::arrays::DecimalArray;
14+
use crate::arrays::PiecewiseSequential;
1215
use crate::arrays::PrimitiveArray;
1316
use crate::arrays::dict::TakeExecute;
17+
use crate::arrays::piecewise_sequential::execute_index_arrays;
18+
use crate::arrays::piecewise_sequential::index_value_to_usize;
19+
use crate::arrays::piecewise_sequential::validate_index_ranges;
1420
use crate::dtype::IntegerPType;
1521
use crate::dtype::NativeDecimalType;
1622
use crate::executor::ExecutionCtx;
1723
use crate::match_each_decimal_value_type;
1824
use crate::match_each_integer_ptype;
25+
use crate::match_each_unsigned_integer_ptype;
1926

2027
impl TakeExecute for Decimal {
2128
fn take(
2229
array: ArrayView<'_, Decimal>,
2330
indices: &ArrayRef,
2431
ctx: &mut ExecutionCtx,
2532
) -> VortexResult<Option<ArrayRef>> {
33+
if let Some(piecewise_indices) = indices.as_opt::<PiecewiseSequential>() {
34+
return take_piecewise_sequential(array, piecewise_indices, indices, ctx).map(Some);
35+
}
36+
2637
let indices = indices.clone().execute::<PrimitiveArray>(ctx)?;
2738
let validity = array.validity()?.take(&indices.clone().into_array())?;
2839

@@ -42,10 +53,61 @@ impl TakeExecute for Decimal {
4253
}
4354
}
4455

56+
fn take_piecewise_sequential(
57+
array: ArrayView<'_, Decimal>,
58+
indices: ArrayView<'_, PiecewiseSequential>,
59+
indices_ref: &ArrayRef,
60+
ctx: &mut ExecutionCtx,
61+
) -> VortexResult<ArrayRef> {
62+
let (starts, lengths) = execute_index_arrays(indices, ctx)?;
63+
match_each_decimal_value_type!(array.values_type(), |D| {
64+
match_each_unsigned_integer_ptype!(starts.ptype(), |S| {
65+
match_each_unsigned_integer_ptype!(lengths.ptype(), |L| {
66+
let values = take_piecewise_to_buffer::<S, L, D>(
67+
starts.as_slice::<S>(),
68+
lengths.as_slice::<L>(),
69+
array.buffer::<D>().as_slice(),
70+
indices_ref.len(),
71+
)?;
72+
let validity = array.validity()?.take(indices_ref)?;
73+
74+
// SAFETY: contiguous gather preserves the decimal dtype and value representation.
75+
Ok(
76+
unsafe { DecimalArray::new_unchecked(values, array.decimal_dtype(), validity) }
77+
.into_array(),
78+
)
79+
})
80+
})
81+
})
82+
}
83+
4584
fn take_to_buffer<I: IntegerPType, T: NativeDecimalType>(indices: &[I], values: &[T]) -> Buffer<T> {
4685
indices.iter().map(|idx| values[idx.as_()]).collect()
4786
}
4887

88+
fn take_piecewise_to_buffer<S, L, T>(
89+
starts: &[S],
90+
lengths: &[L],
91+
values: &[T],
92+
output_len: usize,
93+
) -> VortexResult<Buffer<T>>
94+
where
95+
S: crate::dtype::UnsignedPType,
96+
L: crate::dtype::UnsignedPType,
97+
T: NativeDecimalType,
98+
{
99+
validate_index_ranges(values.len(), starts, lengths, output_len)?;
100+
101+
let mut result = BufferMut::<T>::with_capacity(output_len);
102+
for (&start, &length) in starts.iter().zip_eq(lengths) {
103+
let start = index_value_to_usize(start);
104+
let length = index_value_to_usize(length);
105+
result.extend_from_slice(&values[start..start + length]);
106+
}
107+
108+
Ok(result.freeze())
109+
}
110+
49111
#[cfg(test)]
50112
mod tests {
51113
use rstest::rstest;

0 commit comments

Comments
 (0)