Skip to content

Commit 8f4d6db

Browse files
authored
feat: print diagnostic for function implementations (#1103)
This can be further simplified with use of proc macros
1 parent ed138f8 commit 8f4d6db

File tree

6 files changed

+277
-4
lines changed

6 files changed

+277
-4
lines changed

Cargo.lock

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

IMPLS.md

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
| Encoding | cast | fill_forward | filter | scalar_at | subtract_scalar | search_sorted | slice | take | and | or |
2+
| :------------------: | :--: | :----------: | :----: | :-------: | :-------------: | :-----------: | :---: | :--: | :-: | :-: |
3+
| vortex.alp | 𐄂 | 𐄂 ||| 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
4+
| vortex.alprd | 𐄂 | 𐄂 ||| 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
5+
| fastlanes.bitpacked | 𐄂 | 𐄂 | 𐄂 || 𐄂 |||| 𐄂 | 𐄂 |
6+
| vortex.bool | 𐄂 || 𐄂 || 𐄂 | 𐄂 |||||
7+
| vortex.bytebool | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
8+
| vortex.chunked || 𐄂 |||| 𐄂 ||| 𐄂 | 𐄂 |
9+
| vortex.constant | 𐄂 | 𐄂 ||| 𐄂 ||||||
10+
| vortex.datetimeparts | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
11+
| fastlanes.delta | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 || 𐄂 | 𐄂 | 𐄂 |
12+
| vortex.dict | 𐄂 | 𐄂 ||| 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
13+
| vortex.fsst | 𐄂 | 𐄂 ||| 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
14+
| fastlanes.for | 𐄂 | 𐄂 ||| 𐄂 |||| 𐄂 | 𐄂 |
15+
| vortex.null | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
16+
| vortex.primitive ||| 𐄂 |||||| 𐄂 | 𐄂 |
17+
| vortex.roaring_bool | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 || 𐄂 | 𐄂 | 𐄂 |
18+
| vortex.roaring_int | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 || 𐄂 | 𐄂 | 𐄂 |
19+
| vortex.runend | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
20+
| vortex.runendbool | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
21+
| vortex.sparse | 𐄂 | 𐄂 ||| 𐄂 |||| 𐄂 | 𐄂 |
22+
| vortex.struct | 𐄂 | 𐄂 ||| 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
23+
| vortex.varbin | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 ||| 𐄂 | 𐄂 |
24+
| vortex.varbinview | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 || 𐄂 | 𐄂 | 𐄂 |
25+
| vortex.zigzag | 𐄂 | 𐄂 | 𐄂 || 𐄂 | 𐄂 || 𐄂 | 𐄂 | 𐄂 |

bench-vortex/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ vortex-array = { workspace = true }
5959
vortex-buffer = { workspace = true }
6060
vortex-bytebool = { workspace = true }
6161
vortex-datafusion = { workspace = true }
62+
vortex-datetime-dtype = { workspace = true }
6263
vortex-datetime-parts = { workspace = true }
6364
vortex-dict = { workspace = true }
6465
vortex-dtype = { workspace = true }
@@ -69,6 +70,7 @@ vortex-roaring = { workspace = true }
6970
vortex-runend = { workspace = true }
7071
vortex-runend-bool = { workspace = true }
7172
vortex-sampling-compressor = { workspace = true }
73+
vortex-scalar = { workspace = true }
7274
vortex-serde = { workspace = true, features = [
7375
"futures",
7476
"monoio",
+244
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
#![feature(float_next_up_down)]
2+
3+
use std::process::ExitCode;
4+
5+
use prettytable::{Cell, Row, Table};
6+
use vortex::array::builder::VarBinBuilder;
7+
use vortex::array::{
8+
BoolArray, ChunkedArray, ConstantArray, NullArray, PrimitiveArray, SparseArray, StructArray,
9+
VarBinViewArray,
10+
};
11+
use vortex::compute::Operator;
12+
use vortex::validity::Validity;
13+
use vortex::{Array, IntoArray};
14+
use vortex_alp::{ALPArray, Exponents, RDEncoder};
15+
use vortex_bytebool::ByteBoolArray;
16+
use vortex_datetime_dtype::{TemporalMetadata, TimeUnit, TIME_ID};
17+
use vortex_datetime_parts::DateTimePartsArray;
18+
use vortex_dict::DictArray;
19+
use vortex_dtype::{DType, ExtDType, Nullability, PType};
20+
use vortex_fastlanes::{BitPackedArray, DeltaArray, FoRArray};
21+
use vortex_fsst::{fsst_compress, fsst_train_compressor};
22+
use vortex_roaring::{Bitmap, RoaringBoolArray, RoaringIntArray};
23+
use vortex_runend::RunEndArray;
24+
use vortex_runend_bool::RunEndBoolArray;
25+
use vortex_scalar::ScalarValue;
26+
use vortex_zigzag::ZigZagArray;
27+
28+
const OPERATORS: [Operator; 6] = [
29+
Operator::Lte,
30+
Operator::Lt,
31+
Operator::Gt,
32+
Operator::Gte,
33+
Operator::Eq,
34+
Operator::NotEq,
35+
];
36+
37+
fn fsst_array() -> Array {
38+
let input_array = varbin_array();
39+
let compressor = fsst_train_compressor(&input_array).unwrap();
40+
41+
fsst_compress(&input_array, &compressor)
42+
.unwrap()
43+
.into_array()
44+
}
45+
46+
fn varbin_array() -> Array {
47+
let mut input_array = VarBinBuilder::<i32>::with_capacity(3);
48+
input_array.push_value(b"The Greeks never said that the limit could not he overstepped");
49+
input_array.push_value(
50+
b"They said it existed and that whoever dared to exceed it was mercilessly struck down",
51+
);
52+
input_array.push_value(b"Nothing in present history can contradict them");
53+
input_array
54+
.finish(DType::Utf8(Nullability::NonNullable))
55+
.into_array()
56+
}
57+
58+
fn varbinview_array() -> Array {
59+
VarBinViewArray::from_iter_str(vec![
60+
"The Greeks never said that the limit could not he overstepped",
61+
"They said it existed and that whoever dared to exceed it was mercilessly struck down",
62+
"Nothing in present history can contradict them",
63+
])
64+
.into_array()
65+
}
66+
67+
fn enc_impls() -> Vec<Array> {
68+
vec![
69+
ALPArray::try_new(
70+
PrimitiveArray::from(vec![1]).into_array(),
71+
Exponents { e: 1, f: 1 },
72+
None,
73+
)
74+
.unwrap()
75+
.into_array(),
76+
RDEncoder::new(&[1.123_848_f32.powi(-2)])
77+
.encode(&PrimitiveArray::from(vec![0.1f64.next_up()]))
78+
.into_array(),
79+
BitPackedArray::encode(&PrimitiveArray::from(vec![100u32]).into_array(), 8)
80+
.unwrap()
81+
.into_array(),
82+
BoolArray::from(vec![false]).into_array(),
83+
ByteBoolArray::from(vec![false]).into_array(),
84+
ChunkedArray::try_new(
85+
vec![
86+
BoolArray::from(vec![false]).into_array(),
87+
BoolArray::from(vec![true]).into_array(),
88+
],
89+
DType::Bool(Nullability::NonNullable),
90+
)
91+
.unwrap()
92+
.into_array(),
93+
ConstantArray::new(10, 1).into_array(),
94+
DateTimePartsArray::try_new(
95+
DType::Extension(
96+
ExtDType::new(
97+
TIME_ID.clone(),
98+
Some(TemporalMetadata::Time(TimeUnit::S).into()),
99+
),
100+
Nullability::NonNullable,
101+
),
102+
PrimitiveArray::from(vec![1]).into_array(),
103+
PrimitiveArray::from(vec![0]).into_array(),
104+
PrimitiveArray::from(vec![0]).into_array(),
105+
)
106+
.unwrap()
107+
.into_array(),
108+
DeltaArray::try_from_primitive_array(&PrimitiveArray::from(vec![0u32, 1]))
109+
.unwrap()
110+
.into_array(),
111+
DictArray::try_new(
112+
PrimitiveArray::from(vec![0u32, 1, 0]).into_array(),
113+
PrimitiveArray::from(vec![1, 2]).into_array(),
114+
)
115+
.unwrap()
116+
.into_array(),
117+
fsst_array(),
118+
FoRArray::try_new(
119+
PrimitiveArray::from(vec![0u32, 1, 2]).into_array(),
120+
10.into(),
121+
5,
122+
)
123+
.unwrap()
124+
.into_array(),
125+
NullArray::new(10).into_array(),
126+
PrimitiveArray::from(vec![0, 1]).into_array(),
127+
RoaringBoolArray::try_new(Bitmap::from([0u32, 10, 20]), 30)
128+
.unwrap()
129+
.into_array(),
130+
RoaringIntArray::try_new(Bitmap::from([5u32, 6, 8]), PType::U32)
131+
.unwrap()
132+
.into_array(),
133+
RunEndArray::try_new(
134+
PrimitiveArray::from(vec![5u32, 8]).into_array(),
135+
PrimitiveArray::from(vec![0, 1]).into_array(),
136+
Validity::NonNullable,
137+
)
138+
.unwrap()
139+
.into_array(),
140+
RunEndBoolArray::try_new(
141+
PrimitiveArray::from(vec![5u32, 8]).into_array(),
142+
true,
143+
Validity::NonNullable,
144+
)
145+
.unwrap()
146+
.into_array(),
147+
SparseArray::try_new(
148+
PrimitiveArray::from(vec![5u64, 8]).into_array(),
149+
PrimitiveArray::from_vec(vec![3u32, 6], Validity::AllValid).into_array(),
150+
10,
151+
ScalarValue::Null,
152+
)
153+
.unwrap()
154+
.into_array(),
155+
StructArray::try_new(
156+
["a".into(), "b".into()].into(),
157+
vec![
158+
PrimitiveArray::from(vec![0, 1, 2]).into_array(),
159+
PrimitiveArray::from(vec![0.1f64, 1.1f64, 2.1f64]).into_array(),
160+
],
161+
3,
162+
Validity::NonNullable,
163+
)
164+
.unwrap()
165+
.into_array(),
166+
varbin_array(),
167+
varbinview_array(),
168+
ZigZagArray::encode(&PrimitiveArray::from(vec![-1, 1, -9, 9]).into_array()).unwrap(),
169+
]
170+
}
171+
172+
fn bool_to_cell(val: bool) -> Cell {
173+
let style = if val { "bcFdBG" } else { "bcBr" };
174+
Cell::new(if val { "✓" } else { "𐄂" }).style_spec(style)
175+
}
176+
177+
fn compute_funcs(encodings: &[Array]) {
178+
let mut table = Table::new();
179+
table.add_row(Row::new(
180+
vec![
181+
"Encoding",
182+
"cast",
183+
"fill_forward",
184+
"filter",
185+
"scalar_at",
186+
"subtract_scalar",
187+
"search_sorted",
188+
"slice",
189+
"take",
190+
"and",
191+
"or",
192+
]
193+
.into_iter()
194+
.map(Cell::new)
195+
.collect(),
196+
));
197+
for arr in encodings {
198+
let mut impls = vec![Cell::new(arr.encoding().id().as_ref())];
199+
impls.push(bool_to_cell(arr.with_dyn(|a| a.cast().is_some())));
200+
impls.push(bool_to_cell(arr.with_dyn(|a| a.fill_forward().is_some())));
201+
impls.push(bool_to_cell(arr.with_dyn(|a| a.filter().is_some())));
202+
impls.push(bool_to_cell(arr.with_dyn(|a| a.scalar_at().is_some())));
203+
impls.push(bool_to_cell(
204+
arr.with_dyn(|a| a.subtract_scalar().is_some()),
205+
));
206+
impls.push(bool_to_cell(arr.with_dyn(|a| a.search_sorted().is_some())));
207+
impls.push(bool_to_cell(arr.with_dyn(|a| a.slice().is_some())));
208+
impls.push(bool_to_cell(arr.with_dyn(|a| a.take().is_some())));
209+
impls.push(bool_to_cell(arr.with_dyn(|a| a.and().is_some())));
210+
impls.push(bool_to_cell(arr.with_dyn(|a| a.or().is_some())));
211+
table.add_row(Row::new(impls));
212+
}
213+
table.printstd();
214+
}
215+
216+
fn compare_funcs(encodings: &[Array]) {
217+
for arr in encodings {
218+
println!("\nArray {} compare functions", arr.encoding().id().as_ref());
219+
let mut table = Table::new();
220+
table.add_row(Row::new(
221+
[Cell::new("Encoding")]
222+
.into_iter()
223+
.chain(OPERATORS.iter().map(|a| Cell::new(a.to_string().as_ref())))
224+
.collect(),
225+
));
226+
for arr2 in encodings {
227+
let mut impls = vec![Cell::new(arr2.encoding().id().as_ref())];
228+
for op in OPERATORS {
229+
impls.push(bool_to_cell(
230+
arr.with_dyn(|a1| a1.compare(arr2, op).is_some()),
231+
));
232+
}
233+
table.add_row(Row::new(impls));
234+
}
235+
table.printstd();
236+
}
237+
}
238+
239+
fn main() -> ExitCode {
240+
let arrays = enc_impls();
241+
compute_funcs(&arrays);
242+
compare_funcs(&arrays);
243+
ExitCode::SUCCESS
244+
}

encodings/alp/src/alp/compute.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,11 @@ impl MaybeCompareFn for ALPArray {
109109
match pvalue {
110110
Some(PValue::F32(f)) => Some(alp_scalar_compare(self, f, operator)),
111111
Some(PValue::F64(f)) => Some(alp_scalar_compare(self, f, operator)),
112-
None => Some(Ok(BoolArray::from_vec(
112+
Some(_) | None => Some(Ok(BoolArray::from_vec(
113113
vec![false; self.len()],
114114
Validity::AllValid,
115115
)
116116
.into_array())),
117-
_ => unreachable!(),
118117
}
119118
} else {
120119
None

vortex-array/src/array/primitive/compute/compare.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use arrow_buffer::bit_util::ceil;
22
use arrow_buffer::{BooleanBuffer, MutableBuffer};
33
use vortex_dtype::{match_each_native_ptype, NativePType};
4-
use vortex_error::{VortexExpect, VortexResult};
4+
use vortex_error::{vortex_err, VortexExpect, VortexResult};
55
use vortex_scalar::PrimitiveScalar;
66

77
use crate::array::primitive::PrimitiveArray;
@@ -45,7 +45,8 @@ fn primitive_const_compare(
4545
.vortex_expect("Expected a primitive scalar");
4646

4747
let buffer = match_each_native_ptype!(this.ptype(), |$T| {
48-
let typed_value = primitive_scalar.typed_value::<$T>().unwrap();
48+
let typed_value = primitive_scalar.typed_value::<$T>()
49+
.ok_or_else(|| vortex_err!("Type mismatch between array and constant"))?;
4950
primitive_value_compare::<$T>(this, typed_value, operator)
5051
});
5152

0 commit comments

Comments
 (0)