Skip to content

Commit 2ae7fb1

Browse files
committed
Add datums
Signed-off-by: Nicholas Gates <[email protected]>
2 parents 0bf4070 + 84b2f96 commit 2ae7fb1

File tree

38 files changed

+298
-355
lines changed

38 files changed

+298
-355
lines changed

encodings/fastlanes/benches/pipeline_bitpacking_compare_scalar.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use vortex_array::{Array, ArrayRef, IntoArray, ToCanonical};
1313
use vortex_buffer::{BitBuffer, BufferMut};
1414
use vortex_dtype::NativePType;
1515
use vortex_error::VortexResult;
16-
use vortex_expr::{Scope, lit, lt, root};
16+
use vortex_expr::{lit, lt, root};
1717
use vortex_fastlanes::FoRArray;
1818
use vortex_fastlanes::bitpack_compress::bitpack_to_best_bit_width;
1919
use vortex_mask::Mask;
@@ -68,7 +68,7 @@ pub fn eval<T: NativePType + Into<Scalar>>(bencher: Bencher, fraction_kept: f64)
6868
.bench_local_values(|(mask, array)| {
6969
// We run the filter first, then compare.
7070
let array = filter(array.as_ref(), &mask).unwrap();
71-
expr.evaluate(&Scope::new(array)).unwrap().to_canonical()
71+
expr.evaluate(&array).unwrap().to_canonical()
7272
});
7373
}
7474

encodings/sequence/src/compute/min_max.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use vortex_array::compute::{MinMaxKernel, MinMaxKernelAdapter, MinMaxResult};
55
use vortex_array::register_kernel;
6+
use vortex_dtype::Nullability::NonNullable;
67
use vortex_error::VortexResult;
78
use vortex_scalar::Scalar;
89

@@ -19,8 +20,8 @@ impl MinMaxKernel for SequenceVTable {
1920
(last, base)
2021
};
2122
Ok(Some(MinMaxResult {
22-
min: Scalar::new(array.dtype().clone(), min.into()),
23-
max: Scalar::new(array.dtype().clone(), max.into()),
23+
min: Scalar::primitive_value(min, array.ptype(), NonNullable),
24+
max: Scalar::primitive_value(max, array.ptype(), NonNullable),
2425
}))
2526
}
2627
}

fuzz/fuzz_targets/array_ops.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::backtrace::Backtrace;
88

99
use libfuzzer_sys::{Corpus, fuzz_target};
1010
use vortex_array::arrays::ConstantArray;
11-
use vortex_array::compute::{cast, compare, fill_null, filter, min_max, sum, take};
11+
use vortex_array::compute::{cast, compare, fill_null, filter, mask, min_max, sum, take};
1212
use vortex_array::search_sorted::{SearchResult, SearchSorted, SearchSortedSide};
1313
use vortex_array::{Array, ArrayRef, IntoArray};
1414
use vortex_btrblocks::BtrBlocksCompressor;
@@ -99,7 +99,6 @@ fuzz_target!(|fuzz_action: FuzzArrayAction| -> Corpus {
9999
assert_array_eq(&expected.array(), &current_array, i).unwrap();
100100
}
101101
Action::Mask(mask_val) => {
102-
use vortex_array::compute::mask;
103102
current_array = mask(&current_array, &mask_val).vortex_unwrap();
104103
assert_array_eq(&expected.array(), &current_array, i).unwrap();
105104
}

fuzz/fuzz_targets/file_io.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use vortex_array::{Array, Canonical, IntoArray, ToCanonical};
1212
use vortex_buffer::ByteBufferMut;
1313
use vortex_dtype::{DType, StructFields};
1414
use vortex_error::{VortexExpect, VortexUnwrap, vortex_panic};
15-
use vortex_expr::{Scope, lit, root};
15+
use vortex_expr::{lit, root};
1616
use vortex_file::{OpenOptionsSessionExt, WriteOptionsSessionExt, WriteStrategyBuilder};
1717
use vortex_fuzz::{CompressorStrategy, FuzzFileAction, RUNTIME, SESSION};
1818
use vortex_layout::layouts::compact::CompactCompressor;
@@ -36,14 +36,14 @@ fuzz_target!(|fuzz: FuzzFileAction| -> Corpus {
3636
let bool_mask = filter_expr
3737
.clone()
3838
.unwrap_or_else(|| lit(true))
39-
.evaluate(&Scope::new(array_data.clone()))
39+
.evaluate(&array_data)
4040
.vortex_unwrap();
4141
let mask = bool_mask.to_bool().to_mask_fill_null_false();
4242
let filtered = filter(&array_data, &mask).vortex_unwrap();
4343
projection_expr
4444
.clone()
4545
.unwrap_or_else(root)
46-
.evaluate(&Scope::new(filtered))
46+
.evaluate(&filtered)
4747
.vortex_unwrap()
4848
};
4949

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

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
use std::ops::BitAnd;
55

6+
use Nullability::NonNullable;
7+
use vortex_dtype::Nullability;
68
use vortex_error::VortexResult;
79
use vortex_mask::Mask;
810
use vortex_scalar::Scalar;
@@ -30,15 +32,15 @@ impl MinMaxKernel for BoolVTable {
3032
let Some(slice) = true_slices.next() else {
3133
// all false
3234
return Ok(Some(MinMaxResult {
33-
min: Scalar::bool(false, array.dtype().nullability()),
34-
max: Scalar::bool(false, array.dtype().nullability()),
35+
min: Scalar::bool(false, NonNullable),
36+
max: Scalar::bool(false, NonNullable),
3537
}));
3638
};
3739
if slice.0 == 0 && slice.1 == array.len() {
3840
// all true
3941
return Ok(Some(MinMaxResult {
40-
min: Scalar::bool(true, array.dtype().nullability()),
41-
max: Scalar::bool(true, array.dtype().nullability()),
42+
min: Scalar::bool(true, NonNullable),
43+
max: Scalar::bool(true, NonNullable),
4244
}));
4345
};
4446

@@ -53,16 +55,16 @@ impl MinMaxKernel for BoolVTable {
5355
let Some(_) = false_slices.next() else {
5456
// In this case we don't have any false values which means we are all true and null
5557
return Ok(Some(MinMaxResult {
56-
min: Scalar::bool(true, array.dtype().nullability()),
57-
max: Scalar::bool(true, array.dtype().nullability()),
58+
min: Scalar::bool(true, NonNullable),
59+
max: Scalar::bool(true, NonNullable),
5860
}));
5961
};
6062
}
6163
}
6264

6365
Ok(Some(MinMaxResult {
64-
min: Scalar::bool(false, array.dtype().nullability()),
65-
max: Scalar::bool(true, array.dtype().nullability()),
66+
min: Scalar::bool(false, NonNullable),
67+
max: Scalar::bool(true, NonNullable),
6668
}))
6769
}
6870
}
@@ -71,47 +73,47 @@ register_kernel!(MinMaxKernelAdapter(BoolVTable).lift());
7173

7274
#[cfg(test)]
7375
mod tests {
74-
use vortex_dtype::{DType, Nullability};
76+
use Nullability::NonNullable;
77+
use vortex_dtype::Nullability;
7578
use vortex_scalar::Scalar;
7679

7780
use crate::arrays::BoolArray;
7881
use crate::compute::{MinMaxResult, min_max};
7982

8083
#[test]
8184
fn test_min_max_nulls() {
82-
let dtype = DType::Bool(Nullability::Nullable);
8385
assert_eq!(
8486
min_max(BoolArray::from_iter(vec![Some(true), Some(true), None, None]).as_ref())
8587
.unwrap(),
8688
Some(MinMaxResult {
87-
min: Scalar::new(dtype.clone(), true.into()),
88-
max: Scalar::new(dtype.clone(), true.into()),
89+
min: Scalar::bool(true, NonNullable),
90+
max: Scalar::bool(true, NonNullable),
8991
})
9092
);
9193

9294
assert_eq!(
9395
min_max(BoolArray::from_iter(vec![None, Some(true), Some(true)]).as_ref()).unwrap(),
9496
Some(MinMaxResult {
95-
min: Scalar::new(dtype.clone(), true.into()),
96-
max: Scalar::new(dtype.clone(), true.into()),
97+
min: Scalar::bool(true, NonNullable),
98+
max: Scalar::bool(true, NonNullable),
9799
})
98100
);
99101

100102
assert_eq!(
101103
min_max(BoolArray::from_iter(vec![None, Some(true), Some(true), None]).as_ref())
102104
.unwrap(),
103105
Some(MinMaxResult {
104-
min: Scalar::new(dtype.clone(), true.into()),
105-
max: Scalar::new(dtype.clone(), true.into()),
106+
min: Scalar::bool(true, NonNullable),
107+
max: Scalar::bool(true, NonNullable),
106108
})
107109
);
108110

109111
assert_eq!(
110112
min_max(BoolArray::from_iter(vec![Some(false), Some(false), None, None]).as_ref())
111113
.unwrap(),
112114
Some(MinMaxResult {
113-
min: Scalar::new(dtype.clone(), false.into()),
114-
max: Scalar::new(dtype, false.into()),
115+
min: Scalar::bool(false, NonNullable),
116+
max: Scalar::bool(false, NonNullable),
115117
})
116118
);
117119
}

vortex-array/src/arrays/constant/compute/min_max.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::register_kernel;
1010
impl MinMaxKernel for ConstantVTable {
1111
fn min_max(&self, array: &ConstantArray) -> VortexResult<Option<MinMaxResult>> {
1212
let scalar = array.scalar();
13-
if scalar.is_null() {
13+
if scalar.is_null() || scalar.as_primitive_opt().is_some_and(|p| p.is_nan()) {
1414
return Ok(None);
1515
}
1616
let non_nullable_dtype = scalar.dtype().as_nonnullable();
@@ -22,3 +22,21 @@ impl MinMaxKernel for ConstantVTable {
2222
}
2323

2424
register_kernel!(MinMaxKernelAdapter(ConstantVTable).lift());
25+
26+
#[cfg(test)]
27+
mod test {
28+
use vortex_dtype::Nullability;
29+
use vortex_dtype::half::f16;
30+
use vortex_scalar::Scalar;
31+
32+
use crate::arrays::ConstantArray;
33+
use crate::compute::min_max;
34+
35+
#[test]
36+
fn test_min_max_nan() {
37+
let scalar = Scalar::primitive(f16::NAN, Nullability::NonNullable);
38+
let array = ConstantArray::new(scalar, 2).to_array();
39+
let result = min_max(&array).unwrap();
40+
assert_eq!(result, None);
41+
}
42+
}

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
// SPDX-FileCopyrightText: Copyright the Vortex contributors
33

44
use itertools::Itertools;
5-
use vortex_dtype::{DType, NativeDecimalType, match_each_decimal_value_type};
5+
use vortex_dtype::Nullability::NonNullable;
6+
use vortex_dtype::{DecimalDType, NativeDecimalType, match_each_decimal_value_type};
67
use vortex_error::VortexResult;
78
use vortex_mask::Mask;
8-
use vortex_scalar::{DecimalValue, Scalar, ScalarValue};
9+
use vortex_scalar::{DecimalValue, Scalar};
910

1011
use crate::arrays::{DecimalArray, DecimalVTable};
1112
use crate::compute::{MinMaxKernel, MinMaxKernelAdapter, MinMaxResult};
@@ -27,35 +28,38 @@ where
2728
D: Into<DecimalValue> + NativeDecimalType,
2829
{
2930
Ok(match array.validity_mask() {
30-
Mask::AllTrue(_) => compute_min_max(array.buffer::<D>().iter(), array.dtype()),
31+
Mask::AllTrue(_) => compute_min_max(array.buffer::<D>().iter(), array.decimal_dtype()),
3132
Mask::AllFalse(_) => None,
3233
Mask::Values(v) => compute_min_max(
3334
array
3435
.buffer::<D>()
3536
.iter()
3637
.zip(v.bit_buffer().iter())
3738
.filter_map(|(v, m)| m.then_some(v)),
38-
array.dtype(),
39+
array.decimal_dtype(),
3940
),
4041
})
4142
}
4243

43-
fn compute_min_max<'a, T>(iter: impl Iterator<Item = &'a T>, dtype: &DType) -> Option<MinMaxResult>
44+
fn compute_min_max<'a, T>(
45+
iter: impl Iterator<Item = &'a T>,
46+
decimal_dtype: DecimalDType,
47+
) -> Option<MinMaxResult>
4448
where
4549
T: Into<DecimalValue> + NativeDecimalType + Ord + Copy + 'a,
4650
{
4751
match iter.minmax_by(|a, b| a.cmp(b)) {
4852
itertools::MinMaxResult::NoElements => None,
4953
itertools::MinMaxResult::OneElement(&x) => {
50-
let scalar = Scalar::new(dtype.clone(), ScalarValue::from(x.into()));
54+
let scalar = Scalar::decimal(x.into(), decimal_dtype, NonNullable);
5155
Some(MinMaxResult {
5256
min: scalar.clone(),
5357
max: scalar,
5458
})
5559
}
5660
itertools::MinMaxResult::MinMax(&min, &max) => Some(MinMaxResult {
57-
min: Scalar::new(dtype.clone(), ScalarValue::from(min.into())),
58-
max: Scalar::new(dtype.clone(), ScalarValue::from(max.into())),
61+
min: Scalar::decimal(min.into(), decimal_dtype, NonNullable),
62+
max: Scalar::decimal(max.into(), decimal_dtype, NonNullable),
5963
}),
6064
}
6165
}
@@ -80,13 +84,14 @@ mod tests {
8084

8185
let min_max = min_max(decimal.as_ref()).unwrap();
8286

87+
let non_nullable_dtype = decimal.dtype().as_nonnullable();
8388
let expected = MinMaxResult {
8489
min: Scalar::new(
85-
decimal.dtype().clone(),
90+
non_nullable_dtype.clone(),
8691
ScalarValue::from(DecimalValue::from(100i32)),
8792
),
8893
max: Scalar::new(
89-
decimal.dtype().clone(),
94+
non_nullable_dtype,
9095
ScalarValue::from(DecimalValue::from(200i32)),
9196
),
9297
};

vortex-array/src/arrays/decimal/vtable/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::{EncodingId, EncodingRef, vtable};
88
mod array;
99
mod canonical;
1010
mod operations;
11+
mod operator;
1112
mod serde;
1213
mod validity;
1314
mod visitor;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: Copyright the Vortex contributors
3+
4+
use vortex_compute::filter::Filter;
5+
use vortex_dtype::{PrecisionScale, match_each_decimal_value_type};
6+
use vortex_error::VortexResult;
7+
use vortex_vector::decimal::DVector;
8+
9+
use crate::arrays::{DecimalArray, DecimalVTable, MaskedVTable};
10+
use crate::execution::{BatchKernelRef, BindCtx, kernel};
11+
use crate::vtable::{OperatorVTable, ValidityHelper};
12+
use crate::{ArrayRef, IntoArray};
13+
14+
impl OperatorVTable<DecimalVTable> for DecimalVTable {
15+
fn bind(
16+
array: &DecimalArray,
17+
selection: Option<&ArrayRef>,
18+
ctx: &mut dyn BindCtx,
19+
) -> VortexResult<BatchKernelRef> {
20+
let mask = ctx.bind_selection(array.len(), selection)?;
21+
let validity = ctx.bind_validity(array.validity(), array.len(), selection)?;
22+
23+
match_each_decimal_value_type!(array.values_type(), |D| {
24+
let elements = array.buffer::<D>();
25+
let ps = PrecisionScale::<D>::try_from(&array.decimal_dtype())?;
26+
27+
Ok(kernel(move || {
28+
let mask = mask.execute()?;
29+
let validity = validity.execute()?;
30+
31+
// Note that validity already has the mask applied so we only need to apply it to
32+
// the elements.
33+
let elements = elements.filter(&mask);
34+
35+
Ok(DVector::<D>::try_new(ps, elements, validity)?.into())
36+
}))
37+
})
38+
}
39+
40+
fn reduce_parent(
41+
array: &DecimalArray,
42+
parent: &ArrayRef,
43+
_child_idx: usize,
44+
) -> VortexResult<Option<ArrayRef>> {
45+
// Push-down masking of `validity` from the parent `MaskedArray`.
46+
if let Some(masked) = parent.as_opt::<MaskedVTable>() {
47+
let masked_array = match_each_decimal_value_type!(array.values_type(), |D| {
48+
// SAFETY: Since we are only flipping some bits in the validity, all invariants that
49+
// were upheld are still upheld.
50+
unsafe {
51+
DecimalArray::new_unchecked(
52+
array.buffer::<D>(),
53+
array.decimal_dtype(),
54+
array.validity().clone().and(masked.validity().clone()),
55+
)
56+
}
57+
.into_array()
58+
});
59+
60+
return Ok(Some(masked_array));
61+
}
62+
63+
Ok(None)
64+
}
65+
}

vortex-array/src/arrays/extension/compute/min_max.rs

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

4+
use std::sync::Arc;
5+
6+
use vortex_dtype::Nullability;
47
use vortex_error::VortexResult;
58
use vortex_scalar::Scalar;
69

@@ -10,10 +13,12 @@ use crate::register_kernel;
1013

1114
impl MinMaxKernel for ExtensionVTable {
1215
fn min_max(&self, array: &ExtensionArray) -> VortexResult<Option<MinMaxResult>> {
16+
let non_nullable_ext_dtype =
17+
Arc::new(array.ext_dtype().with_nullability(Nullability::NonNullable));
1318
Ok(
1419
compute::min_max(array.storage())?.map(|MinMaxResult { min, max }| MinMaxResult {
15-
min: Scalar::extension(array.ext_dtype().clone(), min),
16-
max: Scalar::extension(array.ext_dtype().clone(), max),
20+
min: Scalar::extension(non_nullable_ext_dtype.clone(), min),
21+
max: Scalar::extension(non_nullable_ext_dtype, max),
1722
}),
1823
)
1924
}

0 commit comments

Comments
 (0)