You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by vi...@apache.org on 2022/09/06 16:07:04 UTC
[arrow-rs] branch master updated: Change macro to generic helper function (#2658)
This is an automated email from the ASF dual-hosted git repository.
viirya pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/master by this push:
new 463240adc Change macro to generic helper function (#2658)
463240adc is described below
commit 463240adc92197c3f2260007cc6e5e574cbd1942
Author: Liang-Chi Hsieh <vi...@gmail.com>
AuthorDate: Tue Sep 6 09:06:58 2022 -0700
Change macro to generic helper function (#2658)
---
arrow/src/compute/kernels/aggregate.rs | 123 ++++++++++-----------------------
1 file changed, 35 insertions(+), 88 deletions(-)
diff --git a/arrow/src/compute/kernels/aggregate.rs b/arrow/src/compute/kernels/aggregate.rs
index d7726fbf9..c2e3e8cc2 100644
--- a/arrow/src/compute/kernels/aggregate.rs
+++ b/arrow/src/compute/kernels/aggregate.rs
@@ -41,7 +41,7 @@ where
T: ArrowNumericType,
T::Native: ArrowNativeType,
{
- min_max_helper(array, |a, b| (is_nan(*a) & !is_nan(*b)) || a > b)
+ min_max_helper::<T::Native, _, _>(array, |a, b| (is_nan(*a) & !is_nan(*b)) || a > b)
}
/// Returns the maximum value in the array, according to the natural order.
@@ -52,44 +52,7 @@ where
T: ArrowNumericType,
T::Native: ArrowNativeType,
{
- min_max_helper(array, |a, b| (!is_nan(*a) & is_nan(*b)) || a < b)
-}
-
-/// Helper function to perform min/max lambda function on values from a numeric array.
-#[multiversion]
-#[clone(target = "x86_64+avx")]
-fn min_max_helper<T, F>(array: &PrimitiveArray<T>, cmp: F) -> Option<T::Native>
-where
- T: ArrowNumericType,
- F: Fn(&T::Native, &T::Native) -> bool,
-{
- let null_count = array.null_count();
-
- // Includes case array.len() == 0
- if null_count == array.len() {
- return None;
- }
-
- let data = array.data();
- let m = array.values();
- let mut n;
-
- if null_count == 0 {
- // optimized path for arrays without null values
- n = m[1..]
- .iter()
- .fold(m[0], |max, item| if cmp(&max, item) { *item } else { max });
- } else {
- n = T::default_value();
- let mut has_value = false;
- for (i, item) in m.iter().enumerate() {
- if data.is_valid(i) && (!has_value || cmp(&n, item)) {
- has_value = true;
- n = *item
- }
- }
- }
- Some(n)
+ min_max_helper::<T::Native, _, _>(array, |a, b| (!is_nan(*a) & is_nan(*b)) || a < b)
}
/// Returns the minimum value in the boolean array.
@@ -142,46 +105,48 @@ pub fn max_boolean(array: &BooleanArray) -> Option<bool> {
.or(Some(false))
}
-/// Helper to compute min/max of [`GenericStringArray`] and [`GenericBinaryArray`]
-macro_rules! min_max_binary_string {
- ($array: expr, $cmp: expr) => {{
- let null_count = $array.null_count();
- if null_count == $array.len() {
- None
- } else if null_count == 0 {
- // JUSTIFICATION
- // Benefit: ~8% speedup
- // Soundness: `i` is always within the array bounds
- (0..$array.len())
- .map(|i| unsafe { $array.value_unchecked(i) })
- .reduce(|acc, item| if $cmp(acc, item) { item } else { acc })
- } else {
- $array
- .iter()
- .flatten()
- .reduce(|acc, item| if $cmp(acc, item) { item } else { acc })
- }
- }};
+/// Helper to compute min/max of [`ArrayAccessor`].
+#[multiversion]
+#[clone(target = "x86_64+avx")]
+fn min_max_helper<T, A: ArrayAccessor<Item = T>, F>(array: A, cmp: F) -> Option<T>
+where
+ F: Fn(&T, &T) -> bool,
+{
+ let null_count = array.null_count();
+ if null_count == array.len() {
+ None
+ } else if null_count == 0 {
+ // JUSTIFICATION
+ // Benefit: ~8% speedup
+ // Soundness: `i` is always within the array bounds
+ (0..array.len())
+ .map(|i| unsafe { array.value_unchecked(i) })
+ .reduce(|acc, item| if cmp(&acc, &item) { item } else { acc })
+ } else {
+ let iter = ArrayIter::new(array);
+ iter.flatten()
+ .reduce(|acc, item| if cmp(&acc, &item) { item } else { acc })
+ }
}
/// Returns the maximum value in the binary array, according to the natural order.
pub fn max_binary<T: OffsetSizeTrait>(array: &GenericBinaryArray<T>) -> Option<&[u8]> {
- min_max_binary_string!(array, |a, b| a < b)
+ min_max_helper::<&[u8], _, _>(array, |a, b| *a < *b)
}
/// Returns the minimum value in the binary array, according to the natural order.
pub fn min_binary<T: OffsetSizeTrait>(array: &GenericBinaryArray<T>) -> Option<&[u8]> {
- min_max_binary_string!(array, |a, b| a > b)
+ min_max_helper::<&[u8], _, _>(array, |a, b| *a > *b)
}
/// Returns the maximum value in the string array, according to the natural order.
pub fn max_string<T: OffsetSizeTrait>(array: &GenericStringArray<T>) -> Option<&str> {
- min_max_binary_string!(array, |a, b| a < b)
+ min_max_helper::<&str, _, _>(array, |a, b| *a < *b)
}
/// Returns the minimum value in the string array, according to the natural order.
pub fn min_string<T: OffsetSizeTrait>(array: &GenericStringArray<T>) -> Option<&str> {
- min_max_binary_string!(array, |a, b| a > b)
+ min_max_helper::<&str, _, _>(array, |a, b| *a > *b)
}
/// Returns the sum of values in the array.
@@ -215,7 +180,8 @@ where
}
}
-/// Returns the min of values in the array.
+/// Returns the min of values in the array of `ArrowNumericType` type, or dictionary
+/// array with value of `ArrowNumericType` type.
pub fn min_array<T, A: ArrayAccessor<Item = T::Native>>(array: A) -> Option<T::Native>
where
T: ArrowNumericType,
@@ -223,12 +189,13 @@ where
{
min_max_array_helper::<T, A, _, _>(
array,
- |a, b| (!is_nan(*a) & is_nan(*b)) || a < b,
+ |a, b| (is_nan(*a) & !is_nan(*b)) || a > b,
min,
)
}
-/// Returns the max of values in the array.
+/// Returns the max of values in the array of `ArrowNumericType` type, or dictionary
+/// array with value of `ArrowNumericType` type.
pub fn max_array<T, A: ArrayAccessor<Item = T::Native>>(array: A) -> Option<T::Native>
where
T: ArrowNumericType,
@@ -236,7 +203,7 @@ where
{
min_max_array_helper::<T, A, _, _>(
array,
- |a, b| (is_nan(*a) & !is_nan(*b)) || a > b,
+ |a, b| (!is_nan(*a) & is_nan(*b)) || a < b,
max,
)
}
@@ -252,27 +219,7 @@ where
M: Fn(&PrimitiveArray<T>) -> Option<T::Native>,
{
match array.data_type() {
- DataType::Dictionary(_, _) => {
- let null_count = array.null_count();
-
- if null_count == array.len() {
- return None;
- }
-
- let mut has_value = false;
- let mut n = T::default_value();
- let iter = ArrayIter::new(array);
- iter.into_iter().for_each(|value| {
- if let Some(value) = value {
- if !has_value || cmp(&value, &n) {
- has_value = true;
- n = value;
- }
- }
- });
-
- Some(n)
- }
+ DataType::Dictionary(_, _) => min_max_helper::<T::Native, _, _>(array, cmp),
_ => m(as_primitive_array(&array)),
}
}