Skip to content

Commit 1d02918

Browse files
authored
Merge branch 'develop' into ct/begin-vertical-imports-migration
2 parents 317f1e2 + cc195d5 commit 1d02918

File tree

14 files changed

+234
-19
lines changed

14 files changed

+234
-19
lines changed

vortex-compute/src/filter/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ mod slice_mut;
1111
mod vector;
1212

1313
/// Function for filtering based on a selection mask.
14-
pub trait Filter<By: ?Sized> {
14+
pub trait Filter<Selection: ?Sized> {
1515
/// The result type after performing the operation.
1616
type Output;
1717

18-
/// Filters the vector using the provided mask, returning a new value.
18+
/// Filters an object using the provided mask, returning a new value.
1919
///
2020
/// The result value will have length equal to the true count of the provided mask.
2121
///
2222
/// # Panics
2323
///
2424
/// If the length of the mask does not equal the length of the value being filtered.
25-
fn filter(self, selection: &By) -> Self::Output;
25+
fn filter(self, selection: &Selection) -> Self::Output;
2626
}

vortex-compute/src/filter/vector/binaryview.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44
use vortex_buffer::{Buffer, BufferMut};
55
use vortex_mask::{Mask, MaskMut};
6-
use vortex_vector::VectorOps;
76
use vortex_vector::binaryview::{
87
BinaryView, BinaryViewType, BinaryViewVector, BinaryViewVectorMut,
98
};
9+
use vortex_vector::{VectorMutOps, VectorOps};
1010

1111
use crate::filter::Filter;
1212

@@ -42,3 +42,24 @@ where
4242
}
4343
}
4444
}
45+
46+
impl<M, T: BinaryViewType> Filter<M> for BinaryViewVector<T>
47+
where
48+
for<'a> &'a BinaryViewVector<T>: Filter<M, Output = BinaryViewVector<T>>,
49+
for<'a> &'a mut BinaryViewVectorMut<T>: Filter<M, Output = ()>,
50+
{
51+
type Output = Self;
52+
53+
fn filter(self, selection: &M) -> Self {
54+
match self.try_into_mut() {
55+
// If we have exclusive access, we can perform the filter in place.
56+
Ok(mut vector_mut) => {
57+
(&mut vector_mut).filter(selection);
58+
vector_mut.freeze()
59+
}
60+
// Otherwise, allocate a new buffer and fill it in (delegate to the `&BinaryViewVector`
61+
// impl).
62+
Err(vector) => (&vector).filter(selection),
63+
}
64+
}
65+
}

vortex-compute/src/filter/vector/bool.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
use vortex_buffer::{BitBuffer, BitBufferMut};
55
use vortex_mask::{Mask, MaskMut};
6-
use vortex_vector::VectorOps;
76
use vortex_vector::bool::{BoolVector, BoolVectorMut};
7+
use vortex_vector::{VectorMutOps, VectorOps};
88

99
use crate::filter::Filter;
1010

@@ -38,3 +38,23 @@ where
3838
unsafe { self.validity_mut().filter(selection) };
3939
}
4040
}
41+
42+
impl<M> Filter<M> for BoolVector
43+
where
44+
for<'a> &'a BoolVector: Filter<M, Output = BoolVector>,
45+
for<'a> &'a mut BoolVectorMut: Filter<M, Output = ()>,
46+
{
47+
type Output = Self;
48+
49+
fn filter(self, selection: &M) -> Self {
50+
match self.try_into_mut() {
51+
// If we have exclusive access, we can perform the filter in place.
52+
Ok(mut vector_mut) => {
53+
(&mut vector_mut).filter(selection);
54+
vector_mut.freeze()
55+
}
56+
// Otherwise, allocate a new buffer and fill it in (delegate to the `&BoolVector` impl).
57+
Err(vector) => (&vector).filter(selection),
58+
}
59+
}
60+
}

vortex-compute/src/filter/vector/decimal.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use vortex_dtype::i256;
55
use vortex_vector::decimal::{DVector, DVectorMut, DecimalVector, DecimalVectorMut};
6-
use vortex_vector::{match_each_dvector, match_each_dvector_mut};
6+
use vortex_vector::{VectorMutOps, VectorOps, match_each_dvector, match_each_dvector_mut};
77

88
use crate::filter::Filter;
99

@@ -38,3 +38,24 @@ where
3838
match_each_dvector_mut!(self, |d| { d.filter(selection) });
3939
}
4040
}
41+
42+
impl<M> Filter<M> for DecimalVector
43+
where
44+
for<'a> &'a DecimalVector: Filter<M, Output = DecimalVector>,
45+
for<'a> &'a mut DecimalVectorMut: Filter<M, Output = ()>,
46+
{
47+
type Output = Self;
48+
49+
fn filter(self, selection: &M) -> Self {
50+
match self.try_into_mut() {
51+
// If we have exclusive access, we can perform the filter in place.
52+
Ok(mut vector_mut) => {
53+
(&mut vector_mut).filter(selection);
54+
vector_mut.freeze()
55+
}
56+
// Otherwise, allocate a new buffer and fill it in (delegate to the `&DecimalVector`
57+
// impl).
58+
Err(vector) => (&vector).filter(selection),
59+
}
60+
}
61+
}

vortex-compute/src/filter/vector/dvector.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
use vortex_buffer::{Buffer, BufferMut};
55
use vortex_dtype::NativeDecimalType;
66
use vortex_mask::{Mask, MaskMut};
7-
use vortex_vector::VectorOps;
87
use vortex_vector::decimal::{DVector, DVectorMut};
8+
use vortex_vector::{VectorMutOps, VectorOps};
99

1010
use crate::filter::Filter;
1111

@@ -39,3 +39,23 @@ where
3939
}
4040
}
4141
}
42+
43+
impl<M, D: NativeDecimalType> Filter<M> for DVector<D>
44+
where
45+
for<'a> &'a DVector<D>: Filter<M, Output = DVector<D>>,
46+
for<'a> &'a mut DVectorMut<D>: Filter<M, Output = ()>,
47+
{
48+
type Output = Self;
49+
50+
fn filter(self, selection: &M) -> Self {
51+
match self.try_into_mut() {
52+
// If we have exclusive access, we can perform the filter in place.
53+
Ok(mut vector_mut) => {
54+
(&mut vector_mut).filter(selection);
55+
vector_mut.freeze()
56+
}
57+
// Otherwise, allocate a new buffer and fill it in (delegate to the `&DVector` impl).
58+
Err(vector) => (&vector).filter(selection),
59+
}
60+
}
61+
}

vortex-compute/src/filter/vector/list.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
use std::sync::Arc;
55

66
use vortex_mask::{Mask, MaskMut};
7-
use vortex_vector::VectorOps;
87
use vortex_vector::listview::{ListViewVector, ListViewVectorMut};
98
use vortex_vector::primitive::{PrimitiveVector, PrimitiveVectorMut};
9+
use vortex_vector::{VectorMutOps, VectorOps};
1010

1111
use crate::filter::Filter;
1212

@@ -45,3 +45,24 @@ where
4545
}
4646
}
4747
}
48+
49+
impl<M> Filter<M> for ListViewVector
50+
where
51+
for<'a> &'a ListViewVector: Filter<M, Output = ListViewVector>,
52+
for<'a> &'a mut ListViewVectorMut: Filter<M, Output = ()>,
53+
{
54+
type Output = Self;
55+
56+
fn filter(self, selection: &M) -> Self {
57+
match self.try_into_mut() {
58+
// If we have exclusive access, we can perform the filter in place.
59+
Ok(mut vector_mut) => {
60+
(&mut vector_mut).filter(selection);
61+
vector_mut.freeze()
62+
}
63+
// Otherwise, allocate a new buffer and fill it in (delegate to the `&ListViewVector`
64+
// impl).
65+
Err(vector) => (&vector).filter(selection),
66+
}
67+
}
68+
}

vortex-compute/src/filter/vector/mod.rs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,36 @@
11
// SPDX-License-Identifier: Apache-2.0
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

4+
//! Filter implementations for vector types.
5+
//!
6+
//! This module provides [`Filter`] trait implementations for all vector types with three distinct
7+
//! patterns optimized for different ownership scenarios:
8+
//!
9+
//! ### 1. Reference Implementation (`&Vector`)
10+
//!
11+
//! Filters by allocating new memory and copying selected elements. Returns a new owned vector.
12+
//! This is the base implementation that all other patterns can fall back to.
13+
//!
14+
//! ### 2. Mutable Reference Implementation (`&mut VectorMut`)
15+
//!
16+
//! Filters in-place when exclusive mutable access is available, avoiding allocation. Returns `()`
17+
//! as the vector is modified directly. This is the most efficient when you already have a mutable
18+
//! vector (it is only less efficient if the vector is very small and the output vector is already
19+
//! in the L1 cache).
20+
//!
21+
//! ### 3. Owned Implementation (`Vector`)
22+
//!
23+
//! Uses [`VectorOps::try_into_mut`] to check for exclusive ownership. If successful, performs
24+
//! in-place filtering via the mutable implementation and calls [`VectorMutOps::freeze`] to convert
25+
//! back. Otherwise, delegates to the reference implementation and makes an allocation.
26+
//!
27+
//! ## Breaking Recursive Trait Bounds
28+
//!
29+
//! To allow all vector types to implement filter generically over a "mask" type `M`, we must break
30+
//! the recursive trait bounds (e.g. from [`StructVector`] requiring `Vector: Filter<M>` for its
31+
//! fields) by manually implementing [`Filter`] for [`Vector`] and [`VectorMut`] for each concrete
32+
//! mask type in this file.
33+
434
use vortex_buffer::BitView;
535
use vortex_mask::Mask;
636
use vortex_vector::{Vector, VectorMut, match_each_vector, match_each_vector_mut};
@@ -18,9 +48,8 @@ mod primitive;
1848
mod pvector;
1949
mod struct_;
2050

21-
// To allow all vector types to implement filter generically over `M`, we must break the recursive
22-
// trait bounds (e.g. from StructVector requiring Vector: Filter<M> for its fields) by manually
23-
// implementing Filter for Vector and VectorMut for each concrete mask type here.
51+
// We manually implement Filter for Vector and VectorMut for each concrete mask type here to break
52+
// the recursive trait bounds.
2453

2554
impl Filter<Mask> for &Vector {
2655
type Output = Vector;

vortex-compute/src/filter/vector/null.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,22 @@ impl<const NB: usize> Filter<BitView<'_, NB>> for &mut NullVectorMut {
3939
}
4040
}
4141

42+
impl Filter<Mask> for NullVector {
43+
type Output = Self;
44+
45+
fn filter(self, selection: &Mask) -> Self {
46+
(&self).filter(selection)
47+
}
48+
}
49+
50+
impl<const NB: usize> Filter<BitView<'_, NB>> for NullVector {
51+
type Output = Self;
52+
53+
fn filter(self, selection: &BitView<'_, NB>) -> Self {
54+
(&self).filter(selection)
55+
}
56+
}
57+
4258
#[cfg(test)]
4359
mod tests {
4460
use vortex_mask::Mask;

vortex-compute/src/filter/vector/primitive.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use vortex_dtype::half::f16;
55
use vortex_vector::primitive::{PVector, PVectorMut, PrimitiveVector, PrimitiveVectorMut};
6-
use vortex_vector::{match_each_pvector, match_each_pvector_mut};
6+
use vortex_vector::{VectorMutOps, VectorOps, match_each_pvector, match_each_pvector_mut};
77

88
use crate::filter::Filter;
99

@@ -48,3 +48,24 @@ where
4848
match_each_pvector_mut!(self, |v| { v.filter(selection) })
4949
}
5050
}
51+
52+
impl<M> Filter<M> for PrimitiveVector
53+
where
54+
for<'a> &'a PrimitiveVector: Filter<M, Output = PrimitiveVector>,
55+
for<'a> &'a mut PrimitiveVectorMut: Filter<M, Output = ()>,
56+
{
57+
type Output = Self;
58+
59+
fn filter(self, selection: &M) -> Self {
60+
match self.try_into_mut() {
61+
// If we have exclusive access, we can perform the filter in place.
62+
Ok(mut vector_mut) => {
63+
(&mut vector_mut).filter(selection);
64+
vector_mut.freeze()
65+
}
66+
// Otherwise, allocate a new buffer and fill it in (delegate to the `&PrimitiveVector`
67+
// impl).
68+
Err(vector) => (&vector).filter(selection),
69+
}
70+
}
71+
}

vortex-compute/src/filter/vector/pvector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ where
5151
type Output = Self;
5252

5353
fn filter(self, selection_mask: &M) -> Self {
54-
// If we have exclusive access, we can perform the filter in place.
5554
match self.try_into_mut() {
55+
// If we have exclusive access, we can perform the filter in place.
5656
Ok(mut vector_mut) => {
5757
(&mut vector_mut).filter(selection_mask);
5858
vector_mut.freeze()

0 commit comments

Comments
 (0)