Skip to content

Commit 3be9edb

Browse files
authored
Implement VarBinView take using ScalarBuffer selection (#1344)
1 parent 1867f98 commit 3be9edb

File tree

1 file changed

+57
-16
lines changed

1 file changed

+57
-16
lines changed

vortex-array/src/array/varbinview/compute.rs

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,25 @@ use std::sync::Arc;
33
use arrow_array::cast::AsArray;
44
use arrow_array::types::ByteViewType;
55
use arrow_array::{Datum, GenericByteViewArray};
6+
use arrow_buffer::ScalarBuffer;
67
use arrow_ord::cmp;
78
use arrow_schema::DataType;
9+
use itertools::Itertools;
10+
use num_traits::AsPrimitive;
811
use vortex_buffer::Buffer;
12+
use vortex_dtype::{match_each_integer_ptype, PType};
913
use vortex_error::{vortex_bail, VortexResult, VortexUnwrap};
1014
use vortex_scalar::Scalar;
1115

1216
use crate::array::varbin::varbin_scalar;
1317
use crate::array::varbinview::{VarBinViewArray, VIEW_SIZE_BYTES};
14-
use crate::array::{varbinview_as_arrow, ConstantArray};
18+
use crate::array::{ConstantArray, PrimitiveArray};
1519
use crate::arrow::FromArrowArray;
1620
use crate::compute::unary::ScalarAtFn;
1721
use crate::compute::{slice, ArrayCompute, MaybeCompareFn, Operator, SliceFn, TakeFn, TakeOptions};
18-
use crate::{ArrayDType, ArrayData, IntoArrayData, IntoCanonical};
22+
use crate::validity::Validity;
23+
use crate::variants::PrimitiveArrayTrait;
24+
use crate::{ArrayDType, ArrayData, IntoArrayData, IntoArrayVariant, IntoCanonical};
1925

2026
impl ArrayCompute for VarBinViewArray {
2127
fn compare(&self, other: &ArrayData, operator: Operator) -> Option<VortexResult<ArrayData>> {
@@ -67,23 +73,58 @@ impl SliceFn for VarBinViewArray {
6773
/// Take involves creating a new array that references the old array, just with the given set of views.
6874
impl TakeFn for VarBinViewArray {
6975
fn take(&self, indices: &ArrayData, options: TakeOptions) -> VortexResult<ArrayData> {
70-
let array_ref = varbinview_as_arrow(self);
71-
let indices_arrow = indices.clone().into_canonical()?.into_arrow()?;
72-
73-
let take_arrow = arrow_select::take::take(
74-
&array_ref,
75-
&indices_arrow,
76-
Some(arrow_select::take::TakeOptions {
77-
check_bounds: !options.skip_bounds_check,
78-
}),
79-
)?;
80-
Ok(ArrayData::from_arrow(
81-
take_arrow,
82-
self.dtype().is_nullable(),
83-
))
76+
// Compute the new validity
77+
let validity = self.validity().take(indices, options)?;
78+
79+
// Convert our views array into an Arrow u128 ScalarBuffer (16 bytes per view)
80+
let views_buffer =
81+
ScalarBuffer::<u128>::from(self.views().into_primitive()?.into_buffer().into_arrow());
82+
83+
let indices = indices.clone().into_primitive()?;
84+
85+
let views_buffer = match_each_integer_ptype!(indices.ptype(), |$I| {
86+
if options.skip_bounds_check {
87+
take_views_unchecked(views_buffer, indices.maybe_null_slice::<$I>())
88+
} else {
89+
take_views(views_buffer, indices.maybe_null_slice::<$I>())
90+
}
91+
});
92+
93+
// Cast views back to u8
94+
let views_array = PrimitiveArray::new(
95+
views_buffer.into_inner().into(),
96+
PType::U8,
97+
Validity::NonNullable,
98+
);
99+
100+
Ok(Self::try_new(
101+
views_array.into_array(),
102+
self.buffers().collect_vec(),
103+
self.dtype().clone(),
104+
validity,
105+
)?
106+
.into_array())
84107
}
85108
}
86109

110+
fn take_views<I: AsPrimitive<usize>>(
111+
views: ScalarBuffer<u128>,
112+
indices: &[I],
113+
) -> ScalarBuffer<u128> {
114+
ScalarBuffer::<u128>::from_iter(indices.iter().map(|i| views[i.as_()]))
115+
}
116+
117+
fn take_views_unchecked<I: AsPrimitive<usize>>(
118+
views: ScalarBuffer<u128>,
119+
indices: &[I],
120+
) -> ScalarBuffer<u128> {
121+
ScalarBuffer::<u128>::from_iter(
122+
indices
123+
.iter()
124+
.map(|i| unsafe { *views.get_unchecked(i.as_()) }),
125+
)
126+
}
127+
87128
impl MaybeCompareFn for VarBinViewArray {
88129
fn maybe_compare(
89130
&self,

0 commit comments

Comments
 (0)