Skip to content

Commit 74f639c

Browse files
authored
Add dyn_arith_dict feature flag (#2760)
* Add dyn_arith_dict feature flag * Document feature flag
1 parent 5b601b3 commit 74f639c

File tree

4 files changed

+48
-13
lines changed

4 files changed

+48
-13
lines changed

.github/workflows/arrow.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ jobs:
5151
- name: Test
5252
run: |
5353
cargo test -p arrow
54-
- name: Test --features=force_validate,prettyprint,ipc_compression,ffi,dyn_cmp_dict
54+
- name: Test --features=force_validate,prettyprint,ipc_compression,ffi,dyn_cmp_dict,dyn_arith_dict
5555
run: |
56-
cargo test -p arrow --features=force_validate,prettyprint,ipc_compression,ffi,dyn_cmp_dict
56+
cargo test -p arrow --features=force_validate,prettyprint,ipc_compression,ffi,dyn_cmp_dict,dyn_arith_dict
5757
- name: Run examples
5858
run: |
5959
# Test arrow examples
@@ -177,4 +177,4 @@ jobs:
177177
rustup component add clippy
178178
- name: Run clippy
179179
run: |
180-
cargo clippy -p arrow --features=prettyprint,csv,ipc,test_utils,ffi,ipc_compression,dyn_cmp_dict --all-targets -- -D warnings
180+
cargo clippy -p arrow --features=prettyprint,csv,ipc,test_utils,ffi,ipc_compression,dyn_cmp_dict,dyn_arith_dict --all-targets -- -D warnings

arrow/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ ffi = []
9595
# Enable dyn-comparison of dictionary arrays with other arrays
9696
# Note: this does not impact comparison against scalars
9797
dyn_cmp_dict = []
98+
# Enable dyn-arithmetic kernels for dictionary arrays
99+
# Note: this does not impact arithmetic with scalars
100+
dyn_arith_dict = []
98101

99102
[dev-dependencies]
100103
rand = { version = "0.8", default-features = false, features = ["std", "std_rng"] }

arrow/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ The `arrow` crate provides the following features which may be enabled in your `
5454
- `ffi` - bindings for the Arrow C [C Data Interface](https://arrow.apache.org/docs/format/CDataInterface.html)
5555
- `pyarrow` - bindings for pyo3 to call arrow-rs from python
5656
- `dyn_cmp_dict` - enables comparison of dictionary arrays within dyn comparison kernels
57+
- `dyn_arith_dict` - enables arithmetic on dictionary arrays within dyn arithmetic kernels
5758

5859
## Arrow Feature Status
5960

arrow/src/compute/kernels/arithmetic.rs

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,17 @@ use std::ops::{Div, Neg, Rem};
2727
use num::{One, Zero};
2828

2929
use crate::array::*;
30-
use crate::buffer::Buffer;
3130
#[cfg(feature = "simd")]
3231
use crate::buffer::MutableBuffer;
3332
use crate::compute::kernels::arity::unary;
34-
use crate::compute::util::combine_option_bitmap;
3533
use crate::compute::{
3634
binary, binary_opt, try_binary, try_unary, try_unary_dyn, unary_dyn,
3735
};
3836
use crate::datatypes::{
3937
native_op::ArrowNativeTypeOp, ArrowNumericType, DataType, Date32Type, Date64Type,
4038
IntervalDayTimeType, IntervalMonthDayNanoType, IntervalUnit, IntervalYearMonthType,
4139
};
40+
#[cfg(feature = "dyn_arith_dict")]
4241
use crate::datatypes::{
4342
Float32Type, Float64Type, Int16Type, Int32Type, Int64Type, Int8Type, UInt16Type,
4443
UInt32Type, UInt64Type, UInt8Type,
@@ -122,12 +121,13 @@ where
122121
/// This function errors if:
123122
/// * the arrays have different lengths
124123
/// * there is an element where both left and right values are valid and the right value is `0`
124+
#[cfg(feature = "dyn_arith_dict")]
125125
fn math_checked_divide_op_on_iters<T, F>(
126126
left: impl Iterator<Item = Option<T::Native>>,
127127
right: impl Iterator<Item = Option<T::Native>>,
128128
op: F,
129129
len: usize,
130-
null_bit_buffer: Option<Buffer>,
130+
null_bit_buffer: Option<crate::buffer::Buffer>,
131131
) -> Result<PrimitiveArray<T>>
132132
where
133133
T: ArrowNumericType,
@@ -143,15 +143,15 @@ where
143143
}
144144
});
145145
// Safety: Iterator comes from a PrimitiveArray which reports its size correctly
146-
unsafe { Buffer::try_from_trusted_len_iter(values) }
146+
unsafe { crate::buffer::Buffer::try_from_trusted_len_iter(values) }
147147
} else {
148148
// no value is null
149149
let values = left
150150
.map(|l| l.unwrap())
151151
.zip(right.map(|r| r.unwrap()))
152152
.map(|(left, right)| op(left, right));
153153
// Safety: Iterator comes from a PrimitiveArray which reports its size correctly
154-
unsafe { Buffer::try_from_trusted_len_iter(values) }
154+
unsafe { crate::buffer::Buffer::try_from_trusted_len_iter(values) }
155155
}?;
156156

157157
let data = unsafe {
@@ -316,8 +316,10 @@ where
316316
}
317317

318318
// Create the combined `Bitmap`
319-
let null_bit_buffer =
320-
combine_option_bitmap(&[left.data_ref(), right.data_ref()], left.len())?;
319+
let null_bit_buffer = crate::compute::util::combine_option_bitmap(
320+
&[left.data_ref(), right.data_ref()],
321+
left.len(),
322+
)?;
321323

322324
let lanes = T::lanes();
323325
let buffer_size = left.len() * std::mem::size_of::<T::Native>();
@@ -425,6 +427,7 @@ where
425427
}
426428

427429
/// Applies $OP to $LEFT and $RIGHT which are two dictionaries which have (the same) key type $KT
430+
#[cfg(feature = "dyn_arith_dict")]
428431
macro_rules! typed_dict_op {
429432
($LEFT: expr, $RIGHT: expr, $OP: expr, $KT: tt, $MATH_OP: ident) => {{
430433
match ($LEFT.value_type(), $RIGHT.value_type()) {
@@ -476,6 +479,7 @@ macro_rules! typed_dict_op {
476479
}};
477480
}
478481

482+
#[cfg(feature = "dyn_arith_dict")]
479483
macro_rules! typed_dict_math_op {
480484
// Applies `LEFT OP RIGHT` when `LEFT` and `RIGHT` both are `DictionaryArray`
481485
($LEFT: expr, $RIGHT: expr, $OP: expr, $MATH_OP: ident) => {{
@@ -536,8 +540,20 @@ macro_rules! typed_dict_math_op {
536540
}};
537541
}
538542

543+
#[cfg(not(feature = "dyn_arith_dict"))]
544+
macro_rules! typed_dict_math_op {
545+
// Applies `LEFT OP RIGHT` when `LEFT` and `RIGHT` both are `DictionaryArray`
546+
($LEFT: expr, $RIGHT: expr, $OP: expr, $MATH_OP: ident) => {{
547+
Err(ArrowError::CastError(format!(
548+
"Arithmetic on arrays of type {} with array of type {} requires \"dyn_arith_dict\" feature",
549+
$LEFT.data_type(), $RIGHT.data_type()
550+
)))
551+
}};
552+
}
553+
539554
/// Perform given operation on two `DictionaryArray`s.
540555
/// Returns an error if the two arrays have different value type
556+
#[cfg(feature = "dyn_arith_dict")]
541557
fn math_op_dict<K, T, F>(
542558
left: &DictionaryArray<K>,
543559
right: &DictionaryArray<K>,
@@ -593,6 +609,7 @@ where
593609

594610
/// Perform given operation on two `DictionaryArray`s.
595611
/// Returns an error if the two arrays have different value type
612+
#[cfg(feature = "dyn_arith_dict")]
596613
fn math_checked_op_dict<K, T, F>(
597614
left: &DictionaryArray<K>,
598615
right: &DictionaryArray<K>,
@@ -626,6 +643,7 @@ where
626643
/// This function errors if:
627644
/// * the arrays have different lengths
628645
/// * there is an element where both left and right values are valid and the right value is `0`
646+
#[cfg(feature = "dyn_arith_dict")]
629647
fn math_divide_checked_op_dict<K, T, F>(
630648
left: &DictionaryArray<K>,
631649
right: &DictionaryArray<K>,
@@ -645,8 +663,10 @@ where
645663
)));
646664
}
647665

648-
let null_bit_buffer =
649-
combine_option_bitmap(&[left.data_ref(), right.data_ref()], left.len())?;
666+
let null_bit_buffer = crate::compute::util::combine_option_bitmap(
667+
&[left.data_ref(), right.data_ref()],
668+
left.len(),
669+
)?;
650670

651671
// Safety justification: Since the inputs are valid Arrow arrays, all values are
652672
// valid indexes into the dictionary (which is verified during construction)
@@ -1484,7 +1504,7 @@ where
14841504
mod tests {
14851505
use super::*;
14861506
use crate::array::Int32Array;
1487-
use crate::datatypes::Date64Type;
1507+
use crate::datatypes::{Date64Type, Int32Type, Int8Type};
14881508
use chrono::NaiveDate;
14891509

14901510
#[test]
@@ -1605,6 +1625,7 @@ mod tests {
16051625
}
16061626

16071627
#[test]
1628+
#[cfg(feature = "dyn_arith_dict")]
16081629
fn test_primitive_array_add_dyn_dict() {
16091630
let mut builder = PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::new();
16101631
builder.append(5).unwrap();
@@ -1683,6 +1704,7 @@ mod tests {
16831704
}
16841705

16851706
#[test]
1707+
#[cfg(feature = "dyn_arith_dict")]
16861708
fn test_primitive_array_subtract_dyn_dict() {
16871709
let mut builder = PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::new();
16881710
builder.append(15).unwrap();
@@ -1761,6 +1783,7 @@ mod tests {
17611783
}
17621784

17631785
#[test]
1786+
#[cfg(feature = "dyn_arith_dict")]
17641787
fn test_primitive_array_multiply_dyn_dict() {
17651788
let mut builder = PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::new();
17661789
builder.append(5).unwrap();
@@ -1801,6 +1824,7 @@ mod tests {
18011824
}
18021825

18031826
#[test]
1827+
#[cfg(feature = "dyn_arith_dict")]
18041828
fn test_primitive_array_divide_dyn_dict() {
18051829
let mut builder = PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::new();
18061830
builder.append(15).unwrap();
@@ -2322,6 +2346,7 @@ mod tests {
23222346

23232347
#[test]
23242348
#[should_panic(expected = "DivideByZero")]
2349+
#[cfg(feature = "dyn_arith_dict")]
23252350
fn test_int_array_divide_dyn_by_zero_dict() {
23262351
let mut builder =
23272352
PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::with_capacity(1, 1);
@@ -2338,7 +2363,9 @@ mod tests {
23382363

23392364
#[test]
23402365
#[should_panic(expected = "DivideByZero")]
2366+
#[cfg(feature = "dyn_arith_dict")]
23412367
fn test_f32_dict_array_divide_dyn_by_zero() {
2368+
use crate::datatypes::Float32Type;
23422369
let mut builder =
23432370
PrimitiveDictionaryBuilder::<Int8Type, Float32Type>::with_capacity(1, 1);
23442371
builder.append(1.5).unwrap();
@@ -2601,6 +2628,7 @@ mod tests {
26012628
}
26022629

26032630
#[test]
2631+
#[cfg(feature = "dyn_arith_dict")]
26042632
fn test_dictionary_add_dyn_wrapping_overflow() {
26052633
let mut builder =
26062634
PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::with_capacity(2, 2);
@@ -2637,6 +2665,7 @@ mod tests {
26372665
}
26382666

26392667
#[test]
2668+
#[cfg(feature = "dyn_arith_dict")]
26402669
fn test_dictionary_subtract_dyn_wrapping_overflow() {
26412670
let mut builder =
26422671
PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::with_capacity(1, 1);
@@ -2670,6 +2699,7 @@ mod tests {
26702699
}
26712700

26722701
#[test]
2702+
#[cfg(feature = "dyn_arith_dict")]
26732703
fn test_dictionary_mul_dyn_wrapping_overflow() {
26742704
let mut builder =
26752705
PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::with_capacity(1, 1);
@@ -2703,6 +2733,7 @@ mod tests {
27032733
}
27042734

27052735
#[test]
2736+
#[cfg(feature = "dyn_arith_dict")]
27062737
fn test_dictionary_div_dyn_wrapping_overflow() {
27072738
let mut builder =
27082739
PrimitiveDictionaryBuilder::<Int8Type, Int32Type>::with_capacity(1, 1);

0 commit comments

Comments
 (0)