1use arrow_array::cast::*;
21use arrow_array::iterator::ArrayIter;
22use arrow_array::*;
23use arrow_buffer::{ArrowNativeType, NullBuffer};
24use arrow_data::bit_iterator::try_for_each_valid_idx;
25use arrow_schema::*;
26use std::borrow::BorrowMut;
27use std::cmp::{self, Ordering};
28use std::ops::{BitAnd, BitOr, BitXor};
29use types::ByteViewType;
30
31trait NumericAccumulator<T: ArrowNativeTypeOp>: Copy + Default {
33 fn accumulate(&mut self, value: T);
35 fn accumulate_nullable(&mut self, value: T, valid: bool);
38 fn merge(&mut self, other: Self);
40 fn finish(&mut self) -> T;
42}
43
44#[inline(always)]
47fn select<T: Copy>(m: bool, a: T, b: T) -> T {
48 if m { a } else { b }
49}
50
51#[derive(Clone, Copy)]
52struct SumAccumulator<T: ArrowNativeTypeOp> {
53 sum: T,
54}
55
56impl<T: ArrowNativeTypeOp> Default for SumAccumulator<T> {
57 fn default() -> Self {
58 Self { sum: T::ZERO }
59 }
60}
61
62impl<T: ArrowNativeTypeOp> NumericAccumulator<T> for SumAccumulator<T> {
63 fn accumulate(&mut self, value: T) {
64 self.sum = self.sum.add_wrapping(value);
65 }
66
67 fn accumulate_nullable(&mut self, value: T, valid: bool) {
68 let sum = self.sum;
69 self.sum = select(valid, sum.add_wrapping(value), sum)
70 }
71
72 fn merge(&mut self, other: Self) {
73 self.sum = self.sum.add_wrapping(other.sum);
74 }
75
76 fn finish(&mut self) -> T {
77 self.sum
78 }
79}
80
81#[derive(Clone, Copy)]
82struct MinAccumulator<T: ArrowNativeTypeOp> {
83 min: T,
84}
85
86impl<T: ArrowNativeTypeOp> Default for MinAccumulator<T> {
87 fn default() -> Self {
88 Self {
89 min: T::MAX_TOTAL_ORDER,
90 }
91 }
92}
93
94impl<T: ArrowNativeTypeOp> NumericAccumulator<T> for MinAccumulator<T> {
95 fn accumulate(&mut self, value: T) {
96 let min = self.min;
97 self.min = select(value.is_lt(min), value, min);
98 }
99
100 fn accumulate_nullable(&mut self, value: T, valid: bool) {
101 let min = self.min;
102 let is_lt = valid & value.is_lt(min);
103 self.min = select(is_lt, value, min);
104 }
105
106 fn merge(&mut self, other: Self) {
107 self.accumulate(other.min)
108 }
109
110 fn finish(&mut self) -> T {
111 self.min
112 }
113}
114
115#[derive(Clone, Copy)]
116struct MaxAccumulator<T: ArrowNativeTypeOp> {
117 max: T,
118}
119
120impl<T: ArrowNativeTypeOp> Default for MaxAccumulator<T> {
121 fn default() -> Self {
122 Self {
123 max: T::MIN_TOTAL_ORDER,
124 }
125 }
126}
127
128impl<T: ArrowNativeTypeOp> NumericAccumulator<T> for MaxAccumulator<T> {
129 fn accumulate(&mut self, value: T) {
130 let max = self.max;
131 self.max = select(value.is_gt(max), value, max);
132 }
133
134 fn accumulate_nullable(&mut self, value: T, valid: bool) {
135 let max = self.max;
136 let is_gt = value.is_gt(max) & valid;
137 self.max = select(is_gt, value, max);
138 }
139
140 fn merge(&mut self, other: Self) {
141 self.accumulate(other.max)
142 }
143
144 fn finish(&mut self) -> T {
145 self.max
146 }
147}
148
149fn reduce_accumulators<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
150 mut acc: [A; LANES],
151) -> A {
152 assert!(LANES > 0 && LANES.is_power_of_two());
153 let mut len = LANES;
154
155 while len >= 2 {
158 let mid = len / 2;
159 let (h, t) = acc[..len].split_at_mut(mid);
160
161 for i in 0..mid {
162 h[i].merge(t[i]);
163 }
164 len /= 2;
165 }
166 acc[0]
167}
168
169#[inline(always)]
170fn aggregate_nonnull_chunk<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
171 acc: &mut [A; LANES],
172 values: &[T; LANES],
173) {
174 for i in 0..LANES {
175 acc[i].accumulate(values[i]);
176 }
177}
178
179#[inline(always)]
180fn aggregate_nullable_chunk<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
181 acc: &mut [A; LANES],
182 values: &[T; LANES],
183 validity: u64,
184) {
185 let mut bit = 1;
186 for i in 0..LANES {
187 acc[i].accumulate_nullable(values[i], (validity & bit) != 0);
188 bit <<= 1;
189 }
190}
191
192fn aggregate_nonnull_simple<T: ArrowNativeTypeOp, A: NumericAccumulator<T>>(values: &[T]) -> T {
193 values
194 .iter()
195 .copied()
196 .fold(A::default(), |mut a, b| {
197 a.accumulate(b);
198 a
199 })
200 .finish()
201}
202
203#[inline(never)]
204fn aggregate_nonnull_lanes<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
205 values: &[T],
206) -> T {
207 let mut acc = [A::default(); LANES];
210 let mut chunks = values.chunks_exact(LANES);
211 chunks.borrow_mut().for_each(|chunk| {
212 aggregate_nonnull_chunk(&mut acc, chunk[..LANES].try_into().unwrap());
213 });
214
215 let remainder = chunks.remainder();
216 for i in 0..remainder.len() {
217 acc[i].accumulate(remainder[i]);
218 }
219
220 reduce_accumulators(acc).finish()
221}
222
223#[inline(never)]
224fn aggregate_nullable_lanes<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
225 values: &[T],
226 validity: &NullBuffer,
227) -> T {
228 assert!(LANES > 0 && 64 % LANES == 0);
229 assert_eq!(values.len(), validity.len());
230
231 let mut acc = [A::default(); LANES];
233 let mut values_chunks = values.chunks_exact(64);
235 let validity_chunks = validity.inner().bit_chunks();
236 let mut validity_chunks_iter = validity_chunks.iter();
237
238 values_chunks.borrow_mut().for_each(|chunk| {
239 let mut validity = unsafe { validity_chunks_iter.next().unwrap_unchecked() };
241 chunk.chunks_exact(LANES).for_each(|chunk| {
243 aggregate_nullable_chunk(&mut acc, chunk[..LANES].try_into().unwrap(), validity);
244 validity >>= LANES;
245 });
246 });
247
248 let remainder = values_chunks.remainder();
249 if !remainder.is_empty() {
250 let mut validity = validity_chunks.remainder_bits();
251
252 let mut remainder_chunks = remainder.chunks_exact(LANES);
253 remainder_chunks.borrow_mut().for_each(|chunk| {
254 aggregate_nullable_chunk(&mut acc, chunk[..LANES].try_into().unwrap(), validity);
255 validity >>= LANES;
256 });
257
258 let remainder = remainder_chunks.remainder();
259 if !remainder.is_empty() {
260 let mut bit = 1;
261 for i in 0..remainder.len() {
262 acc[i].accumulate_nullable(remainder[i], (validity & bit) != 0);
263 bit <<= 1;
264 }
265 }
266 }
267
268 reduce_accumulators(acc).finish()
269}
270
271const PREFERRED_VECTOR_SIZE: usize =
274 if cfg!(all(target_arch = "x86_64", target_feature = "avx512f")) {
275 64
276 } else if cfg!(all(target_arch = "x86_64", target_feature = "avx")) {
277 32
278 } else {
279 16
280 };
281
282const PREFERRED_VECTOR_SIZE_NON_NULL: usize = PREFERRED_VECTOR_SIZE * 2;
284
285fn aggregate<T: ArrowNativeTypeOp, P: ArrowPrimitiveType<Native = T>, A: NumericAccumulator<T>>(
288 array: &PrimitiveArray<P>,
289) -> Option<T> {
290 let null_count = array.null_count();
291 if null_count == array.len() {
292 return None;
293 }
294 let values = array.values().as_ref();
295 match array.nulls() {
296 Some(nulls) if null_count > 0 => {
297 match PREFERRED_VECTOR_SIZE / std::mem::size_of::<T>() {
300 64 => Some(aggregate_nullable_lanes::<T, A, 64>(values, nulls)),
301 32 => Some(aggregate_nullable_lanes::<T, A, 32>(values, nulls)),
302 16 => Some(aggregate_nullable_lanes::<T, A, 16>(values, nulls)),
303 8 => Some(aggregate_nullable_lanes::<T, A, 8>(values, nulls)),
304 4 => Some(aggregate_nullable_lanes::<T, A, 4>(values, nulls)),
305 2 => Some(aggregate_nullable_lanes::<T, A, 2>(values, nulls)),
306 _ => Some(aggregate_nullable_lanes::<T, A, 1>(values, nulls)),
307 }
308 }
309 _ => {
310 let is_float = matches!(
311 array.data_type(),
312 DataType::Float16 | DataType::Float32 | DataType::Float64
313 );
314 if is_float {
315 match PREFERRED_VECTOR_SIZE_NON_NULL / std::mem::size_of::<T>() {
316 64 => Some(aggregate_nonnull_lanes::<T, A, 64>(values)),
317 32 => Some(aggregate_nonnull_lanes::<T, A, 32>(values)),
318 16 => Some(aggregate_nonnull_lanes::<T, A, 16>(values)),
319 8 => Some(aggregate_nonnull_lanes::<T, A, 8>(values)),
320 4 => Some(aggregate_nonnull_lanes::<T, A, 4>(values)),
321 2 => Some(aggregate_nonnull_lanes::<T, A, 2>(values)),
322 _ => Some(aggregate_nonnull_simple::<T, A>(values)),
323 }
324 } else {
325 Some(aggregate_nonnull_simple::<T, A>(values))
328 }
329 }
330 }
331}
332
333pub fn min_boolean(array: &BooleanArray) -> Option<bool> {
343 if array.null_count() == array.len() {
345 return None;
346 }
347
348 match array.nulls() {
350 None => {
351 let bit_chunks = array.values().bit_chunks();
352 if bit_chunks.iter().any(|x| {
353 x != u64::MAX
355 }) {
356 return Some(false);
357 }
358 if bit_chunks.remainder_bits().count_ones() as usize != bit_chunks.remainder_len() {
360 Some(false)
361 } else {
362 Some(true)
363 }
364 }
365 Some(nulls) => {
366 let validity_chunks = nulls.inner().bit_chunks();
367 let value_chunks = array.values().bit_chunks();
368
369 if value_chunks
370 .iter()
371 .zip(validity_chunks.iter())
372 .any(|(value, validity)| {
373 (!value & validity) != 0
376 })
377 {
378 return Some(false);
379 }
380
381 if (!value_chunks.remainder_bits() & validity_chunks.remainder_bits()) != 0 {
383 Some(false)
384 } else {
385 Some(true)
386 }
387 }
388 }
389}
390
391pub fn max_boolean(array: &BooleanArray) -> Option<bool> {
401 if array.null_count() == array.len() {
403 return None;
404 }
405
406 match array.nulls() {
408 None => array
409 .values()
410 .bit_chunks()
411 .iter_padded()
412 .map(|x| x != 0)
414 .find(|b| *b)
415 .or(Some(false)),
416 Some(nulls) => {
417 let validity_chunks = nulls.inner().bit_chunks().iter_padded();
418 let value_chunks = array.values().bit_chunks().iter_padded();
419 value_chunks
420 .zip(validity_chunks)
421 .map(|(value_bits, validity_bits)| (value_bits & validity_bits) != 0)
423 .find(|b| *b)
424 .or(Some(false))
425 }
426 }
427}
428
429fn min_max_helper<T, A: ArrayAccessor<Item = T>, F>(array: A, cmp: F) -> Option<T>
431where
432 F: Fn(&T, &T) -> bool,
433{
434 let null_count = array.null_count();
435 if null_count == array.len() {
436 None
437 } else if null_count == 0 {
438 (0..array.len())
442 .map(|i| unsafe { array.value_unchecked(i) })
443 .reduce(|acc, item| if cmp(&acc, &item) { item } else { acc })
444 } else {
445 let nulls = array.nulls().unwrap();
446 unsafe {
447 let idx = nulls.valid_indices().reduce(|acc_idx, idx| {
448 let acc = array.value_unchecked(acc_idx);
449 let item = array.value_unchecked(idx);
450 if cmp(&acc, &item) { idx } else { acc_idx }
451 });
452 idx.map(|idx| array.value_unchecked(idx))
453 }
454 }
455}
456
457fn min_max_view_helper<T: ByteViewType>(
462 array: &GenericByteViewArray<T>,
463 swap_cond: cmp::Ordering,
464) -> Option<&T::Native> {
465 let null_count = array.null_count();
466 if null_count == array.len() {
467 None
468 } else if null_count == 0 {
469 let target_idx = (0..array.len()).reduce(|acc, item| {
470 let cmp = unsafe { GenericByteViewArray::compare_unchecked(array, item, array, acc) };
472 if cmp == swap_cond { item } else { acc }
473 });
474 unsafe { target_idx.map(|idx| array.value_unchecked(idx)) }
476 } else {
477 let nulls = array.nulls().unwrap();
478
479 let target_idx = nulls.valid_indices().reduce(|acc_idx, idx| {
480 let cmp =
481 unsafe { GenericByteViewArray::compare_unchecked(array, idx, array, acc_idx) };
482 if cmp == swap_cond { idx } else { acc_idx }
483 });
484
485 unsafe { target_idx.map(|idx| array.value_unchecked(idx)) }
487 }
488}
489
490pub fn max_binary<T: OffsetSizeTrait>(array: &GenericBinaryArray<T>) -> Option<&[u8]> {
492 min_max_helper::<&[u8], _, _>(array, |a, b| *a < *b)
493}
494
495pub fn max_binary_view(array: &BinaryViewArray) -> Option<&[u8]> {
497 min_max_view_helper(array, Ordering::Greater)
498}
499
500pub fn max_fixed_size_binary(array: &FixedSizeBinaryArray) -> Option<&[u8]> {
502 min_max_helper::<&[u8], _, _>(array, |a, b| *a < *b)
503}
504
505pub fn min_binary<T: OffsetSizeTrait>(array: &GenericBinaryArray<T>) -> Option<&[u8]> {
507 min_max_helper::<&[u8], _, _>(array, |a, b| *a > *b)
508}
509
510pub fn min_binary_view(array: &BinaryViewArray) -> Option<&[u8]> {
512 min_max_view_helper(array, Ordering::Less)
513}
514
515pub fn min_fixed_size_binary(array: &FixedSizeBinaryArray) -> Option<&[u8]> {
517 min_max_helper::<&[u8], _, _>(array, |a, b| *a > *b)
518}
519
520pub fn max_string<T: OffsetSizeTrait>(array: &GenericStringArray<T>) -> Option<&str> {
522 min_max_helper::<&str, _, _>(array, |a, b| *a < *b)
523}
524
525pub fn max_string_view(array: &StringViewArray) -> Option<&str> {
527 min_max_view_helper(array, Ordering::Greater)
528}
529
530pub fn min_string<T: OffsetSizeTrait>(array: &GenericStringArray<T>) -> Option<&str> {
532 min_max_helper::<&str, _, _>(array, |a, b| *a > *b)
533}
534
535pub fn min_string_view(array: &StringViewArray) -> Option<&str> {
537 min_max_view_helper(array, Ordering::Less)
538}
539
540pub fn sum_array<T, A: ArrayAccessor<Item = T::Native>>(array: A) -> Option<T::Native>
545where
546 T: ArrowNumericType,
547 T::Native: ArrowNativeTypeOp,
548{
549 match array.data_type() {
550 DataType::Dictionary(_, _) => {
551 let null_count = array.null_count();
552
553 if null_count == array.len() {
554 return None;
555 }
556
557 let iter = ArrayIter::new(array);
558 let sum = iter
559 .into_iter()
560 .fold(T::default_value(), |accumulator, value| {
561 if let Some(value) = value {
562 accumulator.add_wrapping(value)
563 } else {
564 accumulator
565 }
566 });
567
568 Some(sum)
569 }
570 DataType::RunEndEncoded(run_ends, _) => match run_ends.data_type() {
571 DataType::Int16 => ree::sum_wrapping::<types::Int16Type, T>(&array),
572 DataType::Int32 => ree::sum_wrapping::<types::Int32Type, T>(&array),
573 DataType::Int64 => ree::sum_wrapping::<types::Int64Type, T>(&array),
574 _ => unreachable!(),
575 },
576 _ => sum::<T>(as_primitive_array(&array)),
577 }
578}
579
580pub fn sum_array_checked<T, A: ArrayAccessor<Item = T::Native>>(
587 array: A,
588) -> Result<Option<T::Native>, ArrowError>
589where
590 T: ArrowNumericType,
591 T::Native: ArrowNativeTypeOp,
592{
593 match array.data_type() {
594 DataType::Dictionary(_, _) => {
595 let null_count = array.null_count();
596
597 if null_count == array.len() {
598 return Ok(None);
599 }
600
601 let iter = ArrayIter::new(array);
602 let sum = iter
603 .into_iter()
604 .try_fold(T::default_value(), |accumulator, value| {
605 if let Some(value) = value {
606 accumulator.add_checked(value)
607 } else {
608 Ok(accumulator)
609 }
610 })?;
611
612 Ok(Some(sum))
613 }
614 DataType::RunEndEncoded(run_ends, _) => match run_ends.data_type() {
615 DataType::Int16 => ree::sum_checked::<types::Int16Type, T>(&array),
616 DataType::Int32 => ree::sum_checked::<types::Int32Type, T>(&array),
617 DataType::Int64 => ree::sum_checked::<types::Int64Type, T>(&array),
618 _ => unreachable!(),
619 },
620 _ => sum_checked::<T>(as_primitive_array(&array)),
621 }
622}
623
624mod ree {
626 use std::convert::Infallible;
627
628 use arrow_array::cast::AsArray;
629 use arrow_array::types::RunEndIndexType;
630 use arrow_array::{Array, ArrowNativeTypeOp, ArrowNumericType, PrimitiveArray, TypedRunArray};
631 use arrow_buffer::ArrowNativeType;
632 use arrow_schema::ArrowError;
633
634 fn downcast<'a, I: RunEndIndexType, V: ArrowNumericType>(
636 array: &'a dyn Array,
637 ) -> Option<TypedRunArray<'a, I, PrimitiveArray<V>>> {
638 let array = array.as_run_opt::<I>()?;
639 array.downcast::<PrimitiveArray<V>>()
641 }
642
643 pub(super) fn sum_wrapping<I: RunEndIndexType, V: ArrowNumericType>(
645 array: &dyn Array,
646 ) -> Option<V::Native> {
647 let ree = downcast::<I, V>(array)?;
648 let Ok(sum) = fold(ree, |acc, val, len| -> Result<V::Native, Infallible> {
649 Ok(acc.add_wrapping(val.mul_wrapping(V::Native::usize_as(len))))
650 });
651 sum
652 }
653
654 pub(super) fn sum_checked<I: RunEndIndexType, V: ArrowNumericType>(
656 array: &dyn Array,
657 ) -> Result<Option<V::Native>, ArrowError> {
658 let Some(ree) = downcast::<I, V>(array) else {
659 return Err(ArrowError::InvalidArgumentError(
660 "Input run array values are not a PrimitiveArray".to_string(),
661 ));
662 };
663 fold(ree, |acc, val, len| -> Result<V::Native, ArrowError> {
664 let Some(len) = V::Native::from_usize(len) else {
665 return Err(ArrowError::ArithmeticOverflow(format!(
666 "Cannot convert a run-end index ({:?}) to the value type ({})",
667 len,
668 std::any::type_name::<V::Native>()
669 )));
670 };
671 acc.add_checked(val.mul_checked(len)?)
672 })
673 }
674
675 fn fold<'a, I: RunEndIndexType, V: ArrowNumericType, F, E>(
677 array: TypedRunArray<'a, I, PrimitiveArray<V>>,
678 mut f: F,
679 ) -> Result<Option<V::Native>, E>
680 where
681 F: FnMut(V::Native, V::Native, usize) -> Result<V::Native, E>,
682 {
683 let run_ends = array.run_ends();
684 let logical_start = run_ends.offset();
685 let logical_end = run_ends.offset() + run_ends.len();
686 let run_ends = run_ends.sliced_values();
687
688 let values_slice = array.run_array().values_slice();
689 let values = values_slice
690 .as_any()
691 .downcast_ref::<PrimitiveArray<V>>()
692 .unwrap();
694
695 let mut prev_end = 0;
696 let mut acc = V::Native::ZERO;
697 let mut has_non_null_value = false;
698
699 for (run_end, value) in run_ends.zip(values) {
700 let current_run_end = run_end.as_usize().clamp(logical_start, logical_end);
701 let run_length = current_run_end - prev_end;
702
703 if let Some(value) = value {
704 has_non_null_value = true;
705 acc = f(acc, value, run_length)?;
706 }
707
708 prev_end = current_run_end;
709 if current_run_end == logical_end {
710 break;
711 }
712 }
713
714 Ok(if has_non_null_value { Some(acc) } else { None })
715 }
716}
717
718pub fn min_array<T, A: ArrayAccessor<Item = T::Native>>(array: A) -> Option<T::Native>
721where
722 T: ArrowNumericType,
723 T::Native: ArrowNativeType,
724{
725 min_max_array_helper::<T, A, _, _>(array, |a, b| a.is_gt(*b), min)
726}
727
728pub fn max_array<T, A: ArrayAccessor<Item = T::Native>>(array: A) -> Option<T::Native>
731where
732 T: ArrowNumericType,
733 T::Native: ArrowNativeTypeOp,
734{
735 min_max_array_helper::<T, A, _, _>(array, |a, b| a.is_lt(*b), max)
736}
737
738fn min_max_array_helper<T, A: ArrayAccessor<Item = T::Native>, F, M>(
739 array: A,
740 cmp: F,
741 m: M,
742) -> Option<T::Native>
743where
744 T: ArrowNumericType,
745 F: Fn(&T::Native, &T::Native) -> bool,
746 M: Fn(&PrimitiveArray<T>) -> Option<T::Native>,
747{
748 match array.data_type() {
749 DataType::Dictionary(_, _) => min_max_helper::<T::Native, _, _>(array, cmp),
750 DataType::RunEndEncoded(run_ends, _) => {
751 let array: &dyn Array = &array;
754 let values = match run_ends.data_type() {
755 DataType::Int16 => array.as_run_opt::<types::Int16Type>()?.values_slice(),
756 DataType::Int32 => array.as_run_opt::<types::Int32Type>()?.values_slice(),
757 DataType::Int64 => array.as_run_opt::<types::Int64Type>()?.values_slice(),
758 _ => return None,
759 };
760 let values = values.as_any().downcast_ref::<PrimitiveArray<T>>()?;
762 m(values)
763 }
764 _ => m(as_primitive_array(&array)),
765 }
766}
767
768macro_rules! bit_operation {
769 ($NAME:ident, $OP:ident, $NATIVE:ident, $DEFAULT:expr, $DOC:expr) => {
770 #[doc = $DOC]
771 pub fn $NAME<T>(array: &PrimitiveArray<T>) -> Option<T::Native>
774 where
775 T: ArrowNumericType,
776 T::Native: $NATIVE<Output = T::Native> + ArrowNativeTypeOp,
777 {
778 let default;
779 if $DEFAULT == -1 {
780 default = T::Native::ONE.neg_wrapping();
781 } else {
782 default = T::default_value();
783 }
784
785 let null_count = array.null_count();
786
787 if null_count == array.len() {
788 return None;
789 }
790
791 let data: &[T::Native] = array.values();
792
793 match array.nulls() {
794 None => {
795 let result = data
796 .iter()
797 .fold(default, |accumulator, value| accumulator.$OP(*value));
798
799 Some(result)
800 }
801 Some(nulls) => {
802 let mut result = default;
803 let data_chunks = data.chunks_exact(64);
804 let remainder = data_chunks.remainder();
805
806 let bit_chunks = nulls.inner().bit_chunks();
807 data_chunks
808 .zip(bit_chunks.iter())
809 .for_each(|(chunk, mask)| {
810 let mut index_mask = 1;
812 chunk.iter().for_each(|value| {
813 if (mask & index_mask) != 0 {
814 result = result.$OP(*value);
815 }
816 index_mask <<= 1;
817 });
818 });
819
820 let remainder_bits = bit_chunks.remainder_bits();
821
822 remainder.iter().enumerate().for_each(|(i, value)| {
823 if remainder_bits & (1 << i) != 0 {
824 result = result.$OP(*value);
825 }
826 });
827
828 Some(result)
829 }
830 }
831 }
832 };
833}
834
835bit_operation!(
836 bit_and,
837 bitand,
838 BitAnd,
839 -1,
840 "Returns the bitwise and of all non-null input values."
841);
842bit_operation!(
843 bit_or,
844 bitor,
845 BitOr,
846 0,
847 "Returns the bitwise or of all non-null input values."
848);
849bit_operation!(
850 bit_xor,
851 bitxor,
852 BitXor,
853 0,
854 "Returns the bitwise xor of all non-null input values."
855);
856
857pub fn bool_and(array: &BooleanArray) -> Option<bool> {
861 min_boolean(array)
862}
863
864pub fn bool_or(array: &BooleanArray) -> Option<bool> {
868 max_boolean(array)
869}
870
871pub fn sum_checked<T>(array: &PrimitiveArray<T>) -> Result<Option<T::Native>, ArrowError>
878where
879 T: ArrowNumericType,
880 T::Native: ArrowNativeTypeOp,
881{
882 let null_count = array.null_count();
883
884 if null_count == array.len() {
885 return Ok(None);
886 }
887
888 let data: &[T::Native] = array.values();
889
890 match array.nulls() {
891 None => {
892 let sum = data
893 .iter()
894 .try_fold(T::default_value(), |accumulator, value| {
895 accumulator.add_checked(*value)
896 })?;
897
898 Ok(Some(sum))
899 }
900 Some(nulls) => {
901 let mut sum = T::default_value();
902
903 try_for_each_valid_idx(
904 nulls.len(),
905 nulls.offset(),
906 nulls.null_count(),
907 Some(nulls.validity()),
908 |idx| {
909 unsafe { sum = sum.add_checked(array.value_unchecked(idx))? };
910 Ok::<_, ArrowError>(())
911 },
912 )?;
913
914 Ok(Some(sum))
915 }
916 }
917}
918
919pub fn sum<T: ArrowNumericType>(array: &PrimitiveArray<T>) -> Option<T::Native>
926where
927 T::Native: ArrowNativeTypeOp,
928{
929 aggregate::<T::Native, T, SumAccumulator<T::Native>>(array)
930}
931
932pub fn min<T: ArrowNumericType>(array: &PrimitiveArray<T>) -> Option<T::Native>
944where
945 T::Native: PartialOrd,
946{
947 aggregate::<T::Native, T, MinAccumulator<T::Native>>(array)
948}
949
950pub fn max<T: ArrowNumericType>(array: &PrimitiveArray<T>) -> Option<T::Native>
962where
963 T::Native: PartialOrd,
964{
965 aggregate::<T::Native, T, MaxAccumulator<T::Native>>(array)
966}
967
968#[cfg(test)]
969mod tests {
970 use super::*;
971 use arrow_array::types::*;
972 use builder::BooleanBuilder;
973 use std::sync::Arc;
974
975 #[test]
976 fn test_primitive_array_sum() {
977 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
978 assert_eq!(15, sum(&a).unwrap());
979 }
980
981 #[test]
982 fn test_primitive_array_float_sum() {
983 let a = Float64Array::from(vec![1.1, 2.2, 3.3, 4.4, 5.5]);
984 assert_eq!(16.5, sum(&a).unwrap());
985 }
986
987 #[test]
988 fn test_primitive_array_sum_with_nulls() {
989 let a = Int32Array::from(vec![None, Some(2), Some(3), None, Some(5)]);
990 assert_eq!(10, sum(&a).unwrap());
991 }
992
993 #[test]
994 fn test_primitive_array_sum_all_nulls() {
995 let a = Int32Array::from(vec![None, None, None]);
996 assert_eq!(None, sum(&a));
997 }
998
999 #[test]
1000 fn test_primitive_array_sum_large_float_64() {
1001 let c = Float64Array::new((1..=100).map(|x| x as f64).collect(), None);
1002 assert_eq!(Some((1..=100).sum::<i64>() as f64), sum(&c));
1003
1004 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
1006 let c = Float64Array::new((1..=100).map(|x| x as f64).collect(), Some(validity));
1007
1008 assert_eq!(
1009 Some((1..=100).filter(|i| i % 3 == 0).sum::<i64>() as f64),
1010 sum(&c)
1011 );
1012 }
1013
1014 #[test]
1015 fn test_primitive_array_sum_large_float_32() {
1016 let c = Float32Array::new((1..=100).map(|x| x as f32).collect(), None);
1017 assert_eq!(Some((1..=100).sum::<i64>() as f32), sum(&c));
1018
1019 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
1021 let c = Float32Array::new((1..=100).map(|x| x as f32).collect(), Some(validity));
1022
1023 assert_eq!(
1024 Some((1..=100).filter(|i| i % 3 == 0).sum::<i64>() as f32),
1025 sum(&c)
1026 );
1027 }
1028
1029 #[test]
1030 fn test_primitive_array_sum_large_64() {
1031 let c = Int64Array::new((1..=100).collect(), None);
1032 assert_eq!(Some((1..=100).sum()), sum(&c));
1033
1034 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
1036 let c = Int64Array::new((1..=100).collect(), Some(validity));
1037
1038 assert_eq!(Some((1..=100).filter(|i| i % 3 == 0).sum()), sum(&c));
1039 }
1040
1041 #[test]
1042 fn test_primitive_array_sum_large_32() {
1043 let c = Int32Array::new((1..=100).collect(), None);
1044 assert_eq!(Some((1..=100).sum()), sum(&c));
1045
1046 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
1048 let c = Int32Array::new((1..=100).collect(), Some(validity));
1049 assert_eq!(Some((1..=100).filter(|i| i % 3 == 0).sum()), sum(&c));
1050 }
1051
1052 #[test]
1053 fn test_primitive_array_sum_large_16() {
1054 let c = Int16Array::new((1..=100).collect(), None);
1055 assert_eq!(Some((1..=100).sum()), sum(&c));
1056
1057 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
1059 let c = Int16Array::new((1..=100).collect(), Some(validity));
1060 assert_eq!(Some((1..=100).filter(|i| i % 3 == 0).sum()), sum(&c));
1061 }
1062
1063 #[test]
1064 fn test_primitive_array_sum_large_8() {
1065 let c = UInt8Array::new((1..=100).collect(), None);
1066 assert_eq!(
1067 Some((1..=100).fold(0_u8, |a, x| a.wrapping_add(x))),
1068 sum(&c)
1069 );
1070
1071 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
1073 let c = UInt8Array::new((1..=100).collect(), Some(validity));
1074 assert_eq!(
1075 Some(
1076 (1..=100)
1077 .filter(|i| i % 3 == 0)
1078 .fold(0_u8, |a, x| a.wrapping_add(x))
1079 ),
1080 sum(&c)
1081 );
1082 }
1083
1084 #[test]
1085 fn test_primitive_array_bit_and() {
1086 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
1087 assert_eq!(0, bit_and(&a).unwrap());
1088 }
1089
1090 #[test]
1091 fn test_primitive_array_bit_and_with_nulls() {
1092 let a = Int32Array::from(vec![None, Some(2), Some(3), None, None]);
1093 assert_eq!(2, bit_and(&a).unwrap());
1094 }
1095
1096 #[test]
1097 fn test_primitive_array_bit_and_all_nulls() {
1098 let a = Int32Array::from(vec![None, None, None]);
1099 assert_eq!(None, bit_and(&a));
1100 }
1101
1102 #[test]
1103 fn test_primitive_array_bit_or() {
1104 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
1105 assert_eq!(7, bit_or(&a).unwrap());
1106 }
1107
1108 #[test]
1109 fn test_primitive_array_bit_or_with_nulls() {
1110 let a = Int32Array::from(vec![None, Some(2), Some(3), None, Some(5)]);
1111 assert_eq!(7, bit_or(&a).unwrap());
1112 }
1113
1114 #[test]
1115 fn test_primitive_array_bit_or_all_nulls() {
1116 let a = Int32Array::from(vec![None, None, None]);
1117 assert_eq!(None, bit_or(&a));
1118 }
1119
1120 #[test]
1121 fn test_primitive_array_bit_xor() {
1122 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
1123 assert_eq!(1, bit_xor(&a).unwrap());
1124 }
1125
1126 #[test]
1127 fn test_primitive_array_bit_xor_with_nulls() {
1128 let a = Int32Array::from(vec![None, Some(2), Some(3), None, Some(5)]);
1129 assert_eq!(4, bit_xor(&a).unwrap());
1130 }
1131
1132 #[test]
1133 fn test_primitive_array_bit_xor_all_nulls() {
1134 let a = Int32Array::from(vec![None, None, None]);
1135 assert_eq!(None, bit_xor(&a));
1136 }
1137
1138 #[test]
1139 fn test_primitive_array_bool_and() {
1140 let a = BooleanArray::from(vec![true, false, true, false, true]);
1141 assert!(!bool_and(&a).unwrap());
1142 }
1143
1144 #[test]
1145 fn test_primitive_array_bool_and_with_nulls() {
1146 let a = BooleanArray::from(vec![None, Some(true), Some(true), None, Some(true)]);
1147 assert!(bool_and(&a).unwrap());
1148 }
1149
1150 #[test]
1151 fn test_primitive_array_bool_and_all_nulls() {
1152 let a = BooleanArray::from(vec![None, None, None]);
1153 assert_eq!(None, bool_and(&a));
1154 }
1155
1156 #[test]
1157 fn test_primitive_array_bool_or() {
1158 let a = BooleanArray::from(vec![true, false, true, false, true]);
1159 assert!(bool_or(&a).unwrap());
1160 }
1161
1162 #[test]
1163 fn test_primitive_array_bool_or_with_nulls() {
1164 let a = BooleanArray::from(vec![None, Some(false), Some(false), None, Some(false)]);
1165 assert!(!bool_or(&a).unwrap());
1166 }
1167
1168 #[test]
1169 fn test_primitive_array_bool_or_all_nulls() {
1170 let a = BooleanArray::from(vec![None, None, None]);
1171 assert_eq!(None, bool_or(&a));
1172 }
1173
1174 #[test]
1175 fn test_primitive_array_min_max() {
1176 let a = Int32Array::from(vec![5, 6, 7, 8, 9]);
1177 assert_eq!(5, min(&a).unwrap());
1178 assert_eq!(9, max(&a).unwrap());
1179 }
1180
1181 #[test]
1182 fn test_primitive_array_min_max_with_nulls() {
1183 let a = Int32Array::from(vec![Some(5), None, None, Some(8), Some(9)]);
1184 assert_eq!(5, min(&a).unwrap());
1185 assert_eq!(9, max(&a).unwrap());
1186 }
1187
1188 #[test]
1189 fn test_primitive_min_max_1() {
1190 let a = Int32Array::from(vec![None, None, Some(5), Some(2)]);
1191 assert_eq!(Some(2), min(&a));
1192 assert_eq!(Some(5), max(&a));
1193 }
1194
1195 #[test]
1196 fn test_primitive_min_max_float_large_nonnull_array() {
1197 let a: Float64Array = (0..256).map(|i| Some((i + 1) as f64)).collect();
1198 assert_eq!(Some(1.0), min(&a));
1200 assert_eq!(Some(256.0), max(&a));
1201
1202 let a: Float64Array = (0..255).map(|i| Some((i + 1) as f64)).collect();
1204 assert_eq!(Some(255.0), max(&a));
1205
1206 let a: Float64Array = (0..257).map(|i| Some((i + 1) as f64)).collect();
1208 assert_eq!(Some(257.0), max(&a));
1209 }
1210
1211 #[test]
1212 fn test_primitive_min_max_float_large_nullable_array() {
1213 let a: Float64Array = (0..256)
1214 .map(|i| {
1215 if (i + 1) % 3 == 0 {
1216 None
1217 } else {
1218 Some((i + 1) as f64)
1219 }
1220 })
1221 .collect();
1222 assert_eq!(Some(1.0), min(&a));
1224 assert_eq!(Some(256.0), max(&a));
1225
1226 let a: Float64Array = (0..256)
1227 .map(|i| {
1228 if i == 0 || i == 255 {
1229 None
1230 } else {
1231 Some((i + 1) as f64)
1232 }
1233 })
1234 .collect();
1235 assert_eq!(Some(2.0), min(&a));
1237 assert_eq!(Some(255.0), max(&a));
1238
1239 let a: Float64Array = (0..256)
1240 .map(|i| if i != 100 { None } else { Some((i) as f64) })
1241 .collect();
1242 assert_eq!(Some(100.0), min(&a));
1244 assert_eq!(Some(100.0), max(&a));
1245
1246 let a: Float64Array = (0..255).map(|i| Some((i + 1) as f64)).collect();
1248 assert_eq!(Some(255.0), max(&a));
1249
1250 let a: Float64Array = (0..257).map(|i| Some((i + 1) as f64)).collect();
1252 assert_eq!(Some(257.0), max(&a));
1253 }
1254
1255 #[test]
1256 fn test_primitive_min_max_float_edge_cases() {
1257 let a: Float64Array = (0..100).map(|_| Some(f64::NEG_INFINITY)).collect();
1258 assert_eq!(Some(f64::NEG_INFINITY), min(&a));
1259 assert_eq!(Some(f64::NEG_INFINITY), max(&a));
1260
1261 let a: Float64Array = (0..100).map(|_| Some(f64::MIN)).collect();
1262 assert_eq!(Some(f64::MIN), min(&a));
1263 assert_eq!(Some(f64::MIN), max(&a));
1264
1265 let a: Float64Array = (0..100).map(|_| Some(f64::MAX)).collect();
1266 assert_eq!(Some(f64::MAX), min(&a));
1267 assert_eq!(Some(f64::MAX), max(&a));
1268
1269 let a: Float64Array = (0..100).map(|_| Some(f64::INFINITY)).collect();
1270 assert_eq!(Some(f64::INFINITY), min(&a));
1271 assert_eq!(Some(f64::INFINITY), max(&a));
1272 }
1273
1274 #[test]
1275 fn test_primitive_min_max_float_all_nans_non_null() {
1276 let a: Float64Array = (0..100).map(|_| Some(f64::NAN)).collect();
1277 assert!(max(&a).unwrap().is_nan());
1278 assert!(min(&a).unwrap().is_nan());
1279 }
1280
1281 #[test]
1282 fn test_primitive_min_max_float_negative_nan() {
1283 let a: Float64Array =
1284 Float64Array::from(vec![f64::NEG_INFINITY, f64::NAN, f64::INFINITY, -f64::NAN]);
1285 let max = max(&a).unwrap();
1286 let min = min(&a).unwrap();
1287 assert!(max.is_nan());
1288 assert!(max.is_sign_positive());
1289
1290 assert!(min.is_nan());
1291 assert!(min.is_sign_negative());
1292 }
1293
1294 #[test]
1295 fn test_primitive_min_max_float_first_nan_nonnull() {
1296 let a: Float64Array = (0..100)
1297 .map(|i| {
1298 if i == 0 {
1299 Some(f64::NAN)
1300 } else {
1301 Some(i as f64)
1302 }
1303 })
1304 .collect();
1305 assert_eq!(Some(1.0), min(&a));
1306 assert!(max(&a).unwrap().is_nan());
1307 }
1308
1309 #[test]
1310 fn test_primitive_min_max_float_last_nan_nonnull() {
1311 let a: Float64Array = (0..100)
1312 .map(|i| {
1313 if i == 99 {
1314 Some(f64::NAN)
1315 } else {
1316 Some((i + 1) as f64)
1317 }
1318 })
1319 .collect();
1320 assert_eq!(Some(1.0), min(&a));
1321 assert!(max(&a).unwrap().is_nan());
1322 }
1323
1324 #[test]
1325 fn test_primitive_min_max_float_first_nan_nullable() {
1326 let a: Float64Array = (0..100)
1327 .map(|i| {
1328 if i == 0 {
1329 Some(f64::NAN)
1330 } else if i % 2 == 0 {
1331 None
1332 } else {
1333 Some(i as f64)
1334 }
1335 })
1336 .collect();
1337 assert_eq!(Some(1.0), min(&a));
1338 assert!(max(&a).unwrap().is_nan());
1339 }
1340
1341 #[test]
1342 fn test_primitive_min_max_float_last_nan_nullable() {
1343 let a: Float64Array = (0..100)
1344 .map(|i| {
1345 if i == 99 {
1346 Some(f64::NAN)
1347 } else if i % 2 == 0 {
1348 None
1349 } else {
1350 Some(i as f64)
1351 }
1352 })
1353 .collect();
1354 assert_eq!(Some(1.0), min(&a));
1355 assert!(max(&a).unwrap().is_nan());
1356 }
1357
1358 #[test]
1359 fn test_primitive_min_max_float_inf_and_nans() {
1360 let a: Float64Array = (0..100)
1361 .map(|i| {
1362 let x = match i % 10 {
1363 0 => f64::NEG_INFINITY,
1364 1 => f64::MIN,
1365 2 => f64::MAX,
1366 4 => f64::INFINITY,
1367 5 => f64::NAN,
1368 _ => i as f64,
1369 };
1370 Some(x)
1371 })
1372 .collect();
1373 assert_eq!(Some(f64::NEG_INFINITY), min(&a));
1374 assert!(max(&a).unwrap().is_nan());
1375 }
1376
1377 fn pad_inputs_and_test_fixed_size_binary(
1378 input: Vec<Option<&[u8]>>,
1379 expected_min: Option<&[u8]>,
1380 expected_max: Option<&[u8]>,
1381 ) {
1382 fn pad_slice(slice: &[u8], len: usize) -> Vec<u8> {
1383 let mut padded = vec![0; len];
1384 padded[..slice.len()].copy_from_slice(slice);
1385 padded
1386 }
1387
1388 let max_len = input
1389 .iter()
1390 .filter_map(|x| x.as_ref().map(|b| b.len()))
1391 .max()
1392 .unwrap_or(0);
1393 let padded_input = input
1394 .iter()
1395 .map(|x| x.as_ref().map(|b| pad_slice(b, max_len)));
1396 let input_arr =
1397 FixedSizeBinaryArray::try_from_sparse_iter_with_size(padded_input, max_len as i32)
1398 .unwrap();
1399 let padded_expected_min = expected_min.map(|b| pad_slice(b, max_len));
1400 let padded_expected_max = expected_max.map(|b| pad_slice(b, max_len));
1401
1402 assert_eq!(
1403 padded_expected_min.as_deref(),
1404 min_fixed_size_binary(&input_arr)
1405 );
1406 assert_eq!(
1407 padded_expected_max.as_deref(),
1408 max_fixed_size_binary(&input_arr)
1409 );
1410 }
1411
1412 macro_rules! test_binary {
1413 ($NAME:ident, $ARRAY:expr, $EXPECTED_MIN:expr, $EXPECTED_MAX: expr) => {
1414 #[test]
1415 fn $NAME() {
1416 let binary = BinaryArray::from($ARRAY);
1417 assert_eq!($EXPECTED_MIN, min_binary(&binary));
1418 assert_eq!($EXPECTED_MAX, max_binary(&binary));
1419
1420 let large_binary = LargeBinaryArray::from($ARRAY);
1421 assert_eq!($EXPECTED_MIN, min_binary(&large_binary));
1422 assert_eq!($EXPECTED_MAX, max_binary(&large_binary));
1423
1424 let binary_view = BinaryViewArray::from($ARRAY);
1425 assert_eq!($EXPECTED_MIN, min_binary_view(&binary_view));
1426 assert_eq!($EXPECTED_MAX, max_binary_view(&binary_view));
1427
1428 pad_inputs_and_test_fixed_size_binary($ARRAY, $EXPECTED_MIN, $EXPECTED_MAX);
1429 }
1430 };
1431 }
1432
1433 test_binary!(
1434 test_binary_min_max_with_nulls,
1435 vec![
1436 Some("b01234567890123".as_bytes()), None,
1438 None,
1439 Some(b"a"),
1440 Some(b"c"),
1441 Some(b"abcdedfg0123456"),
1442 ],
1443 Some("a".as_bytes()),
1444 Some("c".as_bytes())
1445 );
1446
1447 test_binary!(
1448 test_binary_min_max_no_null,
1449 vec![
1450 Some("b".as_bytes()),
1451 Some(b"abcdefghijklmnopqrst"), Some(b"c"),
1453 Some(b"b01234567890123"), ],
1455 Some("abcdefghijklmnopqrst".as_bytes()),
1456 Some("c".as_bytes())
1457 );
1458
1459 test_binary!(test_binary_min_max_all_nulls, vec![None, None], None, None);
1460
1461 test_binary!(
1462 test_binary_min_max_1,
1463 vec![
1464 None,
1465 Some("b01234567890123435".as_bytes()), None,
1467 Some(b"b0123xxxxxxxxxxx"),
1468 Some(b"a")
1469 ],
1470 Some("a".as_bytes()),
1471 Some("b0123xxxxxxxxxxx".as_bytes())
1472 );
1473
1474 macro_rules! test_string {
1475 ($NAME:ident, $ARRAY:expr, $EXPECTED_MIN:expr, $EXPECTED_MAX: expr) => {
1476 #[test]
1477 fn $NAME() {
1478 let string = StringArray::from($ARRAY);
1479 assert_eq!($EXPECTED_MIN, min_string(&string));
1480 assert_eq!($EXPECTED_MAX, max_string(&string));
1481
1482 let large_string = LargeStringArray::from($ARRAY);
1483 assert_eq!($EXPECTED_MIN, min_string(&large_string));
1484 assert_eq!($EXPECTED_MAX, max_string(&large_string));
1485
1486 let string_view = StringViewArray::from($ARRAY);
1487 assert_eq!($EXPECTED_MIN, min_string_view(&string_view));
1488 assert_eq!($EXPECTED_MAX, max_string_view(&string_view));
1489 }
1490 };
1491 }
1492
1493 test_string!(
1494 test_string_min_max_with_nulls,
1495 vec![
1496 Some("b012345678901234"), None,
1498 None,
1499 Some("a"),
1500 Some("c"),
1501 Some("b0123xxxxxxxxxxx")
1502 ],
1503 Some("a"),
1504 Some("c")
1505 );
1506
1507 test_string!(
1508 test_string_min_max_no_null,
1509 vec![
1510 Some("b"),
1511 Some("b012345678901234"), Some("a"),
1513 Some("b012xxxxxxxxxxxx")
1514 ],
1515 Some("a"),
1516 Some("b012xxxxxxxxxxxx")
1517 );
1518
1519 test_string!(
1520 test_string_min_max_all_nulls,
1521 Vec::<Option<&str>>::from_iter([None, None]),
1522 None,
1523 None
1524 );
1525
1526 test_string!(
1527 test_string_min_max_1,
1528 vec![
1529 None,
1530 Some("c12345678901234"), None,
1532 Some("b"),
1533 Some("c1234xxxxxxxxxx")
1534 ],
1535 Some("b"),
1536 Some("c1234xxxxxxxxxx")
1537 );
1538
1539 test_string!(
1540 test_string_min_max_empty,
1541 Vec::<Option<&str>>::new(),
1542 None,
1543 None
1544 );
1545
1546 #[test]
1547 fn test_boolean_min_max_empty() {
1548 let a = BooleanArray::from(vec![] as Vec<Option<bool>>);
1549 assert_eq!(None, min_boolean(&a));
1550 assert_eq!(None, max_boolean(&a));
1551 }
1552
1553 #[test]
1554 fn test_boolean_min_max_all_null() {
1555 let a = BooleanArray::from(vec![None, None]);
1556 assert_eq!(None, min_boolean(&a));
1557 assert_eq!(None, max_boolean(&a));
1558 }
1559
1560 #[test]
1561 fn test_boolean_min_max_no_null() {
1562 let a = BooleanArray::from(vec![Some(true), Some(false), Some(true)]);
1563 assert_eq!(Some(false), min_boolean(&a));
1564 assert_eq!(Some(true), max_boolean(&a));
1565 }
1566
1567 #[test]
1568 fn test_boolean_min_max() {
1569 let a = BooleanArray::from(vec![Some(true), Some(true), None, Some(false), None]);
1570 assert_eq!(Some(false), min_boolean(&a));
1571 assert_eq!(Some(true), max_boolean(&a));
1572
1573 let a = BooleanArray::from(vec![None, Some(true), None, Some(false), None]);
1574 assert_eq!(Some(false), min_boolean(&a));
1575 assert_eq!(Some(true), max_boolean(&a));
1576
1577 let a = BooleanArray::from(vec![Some(false), Some(true), None, Some(false), None]);
1578 assert_eq!(Some(false), min_boolean(&a));
1579 assert_eq!(Some(true), max_boolean(&a));
1580
1581 let a = BooleanArray::from(vec![Some(true), None]);
1582 assert_eq!(Some(true), min_boolean(&a));
1583 assert_eq!(Some(true), max_boolean(&a));
1584
1585 let a = BooleanArray::from(vec![Some(false), None]);
1586 assert_eq!(Some(false), min_boolean(&a));
1587 assert_eq!(Some(false), max_boolean(&a));
1588
1589 let a = BooleanArray::from(vec![Some(true)]);
1590 assert_eq!(Some(true), min_boolean(&a));
1591 assert_eq!(Some(true), max_boolean(&a));
1592
1593 let a = BooleanArray::from(vec![Some(false)]);
1594 assert_eq!(Some(false), min_boolean(&a));
1595 assert_eq!(Some(false), max_boolean(&a));
1596 }
1597
1598 #[test]
1599 fn test_boolean_min_max_smaller() {
1600 let a = BooleanArray::from(vec![Some(false)]);
1601 assert_eq!(Some(false), min_boolean(&a));
1602 assert_eq!(Some(false), max_boolean(&a));
1603
1604 let a = BooleanArray::from(vec![None, Some(false)]);
1605 assert_eq!(Some(false), min_boolean(&a));
1606 assert_eq!(Some(false), max_boolean(&a));
1607
1608 let a = BooleanArray::from(vec![None, Some(true)]);
1609 assert_eq!(Some(true), min_boolean(&a));
1610 assert_eq!(Some(true), max_boolean(&a));
1611
1612 let a = BooleanArray::from(vec![Some(true)]);
1613 assert_eq!(Some(true), min_boolean(&a));
1614 assert_eq!(Some(true), max_boolean(&a));
1615 }
1616
1617 #[test]
1618 fn test_boolean_min_max_64_true_64_false() {
1619 let mut no_nulls = BooleanBuilder::new();
1620 no_nulls.append_slice(&[true; 64]);
1621 no_nulls.append_slice(&[false; 64]);
1622 let no_nulls = no_nulls.finish();
1623
1624 assert_eq!(Some(false), min_boolean(&no_nulls));
1625 assert_eq!(Some(true), max_boolean(&no_nulls));
1626
1627 let mut with_nulls = BooleanBuilder::new();
1628 with_nulls.append_slice(&[true; 31]);
1629 with_nulls.append_null();
1630 with_nulls.append_slice(&[true; 32]);
1631 with_nulls.append_slice(&[false; 1]);
1632 with_nulls.append_nulls(63);
1633 let with_nulls = with_nulls.finish();
1634
1635 assert_eq!(Some(false), min_boolean(&with_nulls));
1636 assert_eq!(Some(true), max_boolean(&with_nulls));
1637 }
1638
1639 #[test]
1640 fn test_boolean_min_max_64_false_64_true() {
1641 let mut no_nulls = BooleanBuilder::new();
1642 no_nulls.append_slice(&[false; 64]);
1643 no_nulls.append_slice(&[true; 64]);
1644 let no_nulls = no_nulls.finish();
1645
1646 assert_eq!(Some(false), min_boolean(&no_nulls));
1647 assert_eq!(Some(true), max_boolean(&no_nulls));
1648
1649 let mut with_nulls = BooleanBuilder::new();
1650 with_nulls.append_slice(&[false; 31]);
1651 with_nulls.append_null();
1652 with_nulls.append_slice(&[false; 32]);
1653 with_nulls.append_slice(&[true; 1]);
1654 with_nulls.append_nulls(63);
1655 let with_nulls = with_nulls.finish();
1656
1657 assert_eq!(Some(false), min_boolean(&with_nulls));
1658 assert_eq!(Some(true), max_boolean(&with_nulls));
1659 }
1660
1661 #[test]
1662 fn test_boolean_min_max_96_true() {
1663 let mut no_nulls = BooleanBuilder::new();
1664 no_nulls.append_slice(&[true; 96]);
1665 let no_nulls = no_nulls.finish();
1666
1667 assert_eq!(Some(true), min_boolean(&no_nulls));
1668 assert_eq!(Some(true), max_boolean(&no_nulls));
1669
1670 let mut with_nulls = BooleanBuilder::new();
1671 with_nulls.append_slice(&[true; 31]);
1672 with_nulls.append_null();
1673 with_nulls.append_slice(&[true; 32]);
1674 with_nulls.append_slice(&[true; 31]);
1675 with_nulls.append_null();
1676 let with_nulls = with_nulls.finish();
1677
1678 assert_eq!(Some(true), min_boolean(&with_nulls));
1679 assert_eq!(Some(true), max_boolean(&with_nulls));
1680 }
1681
1682 #[test]
1683 fn test_boolean_min_max_96_false() {
1684 let mut no_nulls = BooleanBuilder::new();
1685 no_nulls.append_slice(&[false; 96]);
1686 let no_nulls = no_nulls.finish();
1687
1688 assert_eq!(Some(false), min_boolean(&no_nulls));
1689 assert_eq!(Some(false), max_boolean(&no_nulls));
1690
1691 let mut with_nulls = BooleanBuilder::new();
1692 with_nulls.append_slice(&[false; 31]);
1693 with_nulls.append_null();
1694 with_nulls.append_slice(&[false; 32]);
1695 with_nulls.append_slice(&[false; 31]);
1696 with_nulls.append_null();
1697 let with_nulls = with_nulls.finish();
1698
1699 assert_eq!(Some(false), min_boolean(&with_nulls));
1700 assert_eq!(Some(false), max_boolean(&with_nulls));
1701 }
1702
1703 #[test]
1704 fn test_sum_dyn() {
1705 let values = Int8Array::from_iter_values([10_i8, 11, 12, 13, 14, 15, 16, 17]);
1706 let values = Arc::new(values) as ArrayRef;
1707 let keys = Int8Array::from_iter_values([2_i8, 3, 4]);
1708
1709 let dict_array = DictionaryArray::new(keys, values.clone());
1710 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1711 assert_eq!(39, sum_array::<Int8Type, _>(array).unwrap());
1712
1713 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
1714 assert_eq!(15, sum_array::<Int32Type, _>(&a).unwrap());
1715
1716 let keys = Int8Array::from(vec![Some(2_i8), None, Some(4)]);
1717 let dict_array = DictionaryArray::new(keys, values.clone());
1718 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1719 assert_eq!(26, sum_array::<Int8Type, _>(array).unwrap());
1720
1721 let keys = Int8Array::from(vec![None, None, None]);
1722 let dict_array = DictionaryArray::new(keys, values.clone());
1723 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1724 assert!(sum_array::<Int8Type, _>(array).is_none());
1725 }
1726
1727 #[test]
1728 fn test_max_min_dyn() {
1729 let values = Int8Array::from_iter_values([10_i8, 11, 12, 13, 14, 15, 16, 17]);
1730 let keys = Int8Array::from_iter_values([2_i8, 3, 4]);
1731 let values = Arc::new(values) as ArrayRef;
1732
1733 let dict_array = DictionaryArray::new(keys, values.clone());
1734 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1735 assert_eq!(14, max_array::<Int8Type, _>(array).unwrap());
1736
1737 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1738 assert_eq!(12, min_array::<Int8Type, _>(array).unwrap());
1739
1740 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
1741 assert_eq!(5, max_array::<Int32Type, _>(&a).unwrap());
1742 assert_eq!(1, min_array::<Int32Type, _>(&a).unwrap());
1743
1744 let keys = Int8Array::from(vec![Some(2_i8), None, Some(7)]);
1745 let dict_array = DictionaryArray::new(keys, values.clone());
1746 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1747 assert_eq!(17, max_array::<Int8Type, _>(array).unwrap());
1748 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1749 assert_eq!(12, min_array::<Int8Type, _>(array).unwrap());
1750
1751 let keys = Int8Array::from(vec![None, None, None]);
1752 let dict_array = DictionaryArray::new(keys, values.clone());
1753 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1754 assert!(max_array::<Int8Type, _>(array).is_none());
1755 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1756 assert!(min_array::<Int8Type, _>(array).is_none());
1757 }
1758
1759 #[test]
1760 fn test_max_min_dyn_nan() {
1761 let values = Float32Array::from(vec![5.0_f32, 2.0_f32, f32::NAN]);
1762 let keys = Int8Array::from_iter_values([0_i8, 1, 2]);
1763
1764 let dict_array = DictionaryArray::new(keys, Arc::new(values));
1765 let array = dict_array.downcast_dict::<Float32Array>().unwrap();
1766 assert!(max_array::<Float32Type, _>(array).unwrap().is_nan());
1767
1768 let array = dict_array.downcast_dict::<Float32Array>().unwrap();
1769 assert_eq!(2.0_f32, min_array::<Float32Type, _>(array).unwrap());
1770 }
1771
1772 #[test]
1773 fn test_min_max_sliced_primitive() {
1774 let expected = Some(4.0);
1775 let input: Float64Array = vec![None, Some(4.0)].into_iter().collect();
1776 let actual = min(&input);
1777 assert_eq!(actual, expected);
1778 let actual = max(&input);
1779 assert_eq!(actual, expected);
1780
1781 let sliced_input: Float64Array = vec![None, None, None, None, None, Some(4.0)]
1782 .into_iter()
1783 .collect();
1784 let sliced_input = sliced_input.slice(4, 2);
1785
1786 assert_eq!(&sliced_input, &input);
1787
1788 let actual = min(&sliced_input);
1789 assert_eq!(actual, expected);
1790 let actual = max(&sliced_input);
1791 assert_eq!(actual, expected);
1792 }
1793
1794 #[test]
1795 fn test_min_max_sliced_boolean() {
1796 let expected = Some(true);
1797 let input: BooleanArray = vec![None, Some(true)].into_iter().collect();
1798 let actual = min_boolean(&input);
1799 assert_eq!(actual, expected);
1800 let actual = max_boolean(&input);
1801 assert_eq!(actual, expected);
1802
1803 let sliced_input: BooleanArray = vec![None, None, None, None, None, Some(true)]
1804 .into_iter()
1805 .collect();
1806 let sliced_input = sliced_input.slice(4, 2);
1807
1808 assert_eq!(sliced_input, input);
1809
1810 let actual = min_boolean(&sliced_input);
1811 assert_eq!(actual, expected);
1812 let actual = max_boolean(&sliced_input);
1813 assert_eq!(actual, expected);
1814 }
1815
1816 #[test]
1817 fn test_min_max_sliced_string() {
1818 let expected = Some("foo");
1819 let input: StringArray = vec![None, Some("foo")].into_iter().collect();
1820 let actual = min_string(&input);
1821 assert_eq!(actual, expected);
1822 let actual = max_string(&input);
1823 assert_eq!(actual, expected);
1824
1825 let sliced_input: StringArray = vec![None, None, None, None, None, Some("foo")]
1826 .into_iter()
1827 .collect();
1828 let sliced_input = sliced_input.slice(4, 2);
1829
1830 assert_eq!(&sliced_input, &input);
1831
1832 let actual = min_string(&sliced_input);
1833 assert_eq!(actual, expected);
1834 let actual = max_string(&sliced_input);
1835 assert_eq!(actual, expected);
1836 }
1837
1838 #[test]
1839 fn test_min_max_sliced_binary() {
1840 let expected: Option<&[u8]> = Some(&[5]);
1841 let input: BinaryArray = vec![None, Some(&[5])].into_iter().collect();
1842 let actual = min_binary(&input);
1843 assert_eq!(actual, expected);
1844 let actual = max_binary(&input);
1845 assert_eq!(actual, expected);
1846
1847 let sliced_input: BinaryArray = vec![None, None, None, None, None, Some(&[5])]
1848 .into_iter()
1849 .collect();
1850 let sliced_input = sliced_input.slice(4, 2);
1851
1852 assert_eq!(&sliced_input, &input);
1853
1854 let actual = min_binary(&sliced_input);
1855 assert_eq!(actual, expected);
1856 let actual = max_binary(&sliced_input);
1857 assert_eq!(actual, expected);
1858 }
1859
1860 #[test]
1861 fn test_sum_overflow() {
1862 let a = Int32Array::from(vec![i32::MAX, 1]);
1863
1864 assert_eq!(sum(&a).unwrap(), -2147483648);
1865 assert_eq!(sum_array::<Int32Type, _>(&a).unwrap(), -2147483648);
1866 }
1867
1868 #[test]
1869 fn test_sum_checked_overflow() {
1870 let a = Int32Array::from(vec![i32::MAX, 1]);
1871
1872 sum_checked(&a).expect_err("overflow should be detected");
1873 sum_array_checked::<Int32Type, _>(&a).expect_err("overflow should be detected");
1874 }
1875
1876 fn make_run_array<'a, I: RunEndIndexType, V: ArrowNumericType, ItemType>(
1878 values: impl IntoIterator<Item = &'a ItemType>,
1879 ) -> RunArray<I>
1880 where
1881 ItemType: Clone + Into<Option<V::Native>> + 'static,
1882 {
1883 let mut builder = arrow_array::builder::PrimitiveRunBuilder::<I, V>::new();
1884 for v in values.into_iter() {
1885 builder.append_option((*v).clone().into());
1886 }
1887 builder.finish()
1888 }
1889
1890 #[test]
1891 fn test_ree_sum_array_basic() {
1892 let run_array = make_run_array::<Int16Type, Int32Type, _>(&[10, 10, 20, 30, 30, 30]);
1893 let typed_array = run_array.downcast::<Int32Array>().unwrap();
1894
1895 let result = sum_array::<Int32Type, _>(typed_array);
1896 assert_eq!(result, Some(130));
1897
1898 let result = sum_array_checked::<Int32Type, _>(typed_array).unwrap();
1899 assert_eq!(result, Some(130));
1900 }
1901
1902 #[test]
1903 fn test_ree_sum_array_empty() {
1904 let run_array = make_run_array::<Int16Type, Int32Type, i32>(&[]);
1905 let typed_array = run_array.downcast::<Int32Array>().unwrap();
1906
1907 let result = sum_array::<Int32Type, _>(typed_array);
1908 assert_eq!(result, None);
1909
1910 let result = sum_array_checked::<Int32Type, _>(typed_array).unwrap();
1911 assert_eq!(result, None);
1912 }
1913
1914 #[test]
1915 fn test_ree_sum_array_with_nulls() {
1916 let run_array =
1917 make_run_array::<Int16Type, Int32Type, _>(&[Some(10), None, Some(20), None, Some(30)]);
1918 let typed_array = run_array.downcast::<Int32Array>().unwrap();
1919
1920 let result = sum_array::<Int32Type, _>(typed_array);
1921 assert_eq!(result, Some(60));
1922
1923 let result = sum_array_checked::<Int32Type, _>(typed_array).unwrap();
1924 assert_eq!(result, Some(60));
1925 }
1926
1927 #[test]
1928 fn test_ree_sum_array_with_only_nulls() {
1929 let run_array = make_run_array::<Int16Type, Int16Type, _>(&[None, None, None, None, None]);
1930 let typed_array = run_array.downcast::<Int16Array>().unwrap();
1931
1932 let result = sum_array::<Int16Type, _>(typed_array);
1933 assert_eq!(result, None);
1934
1935 let result = sum_array_checked::<Int16Type, _>(typed_array).unwrap();
1936 assert_eq!(result, None);
1937 }
1938
1939 #[test]
1940 fn test_ree_sum_array_overflow() {
1941 let run_array = make_run_array::<Int16Type, Int8Type, _>(&[126, 2]);
1942 let typed_array = run_array.downcast::<Int8Array>().unwrap();
1943
1944 let result = sum_array::<Int8Type, _>(typed_array);
1946 assert_eq!(result, Some(-128));
1947
1948 let result = sum_array_checked::<Int8Type, _>(typed_array);
1949 assert!(result.is_err());
1950 }
1951
1952 #[test]
1953 fn test_ree_sum_array_sliced() {
1954 let run_array = make_run_array::<Int16Type, UInt8Type, _>(&[0, 10, 10, 10, 20, 30, 30, 30]);
1955 let sliced = run_array.slice(2, 5);
1957 let typed_array = sliced.downcast::<UInt8Array>().unwrap();
1958
1959 let result = sum_array::<UInt8Type, _>(typed_array);
1960 assert_eq!(result, Some(100));
1961
1962 let result = sum_array_checked::<UInt8Type, _>(typed_array).unwrap();
1963 assert_eq!(result, Some(100));
1964 }
1965
1966 #[test]
1967 fn test_ree_min_max_array_basic() {
1968 let run_array = make_run_array::<Int16Type, Int32Type, _>(&[30, 30, 10, 20, 20]);
1969 let typed_array = run_array.downcast::<Int32Array>().unwrap();
1970
1971 let result = min_array::<Int32Type, _>(typed_array);
1972 assert_eq!(result, Some(10));
1973
1974 let result = max_array::<Int32Type, _>(typed_array);
1975 assert_eq!(result, Some(30));
1976 }
1977
1978 #[test]
1979 fn test_ree_min_max_array_empty() {
1980 let run_array = make_run_array::<Int16Type, Int32Type, i32>(&[]);
1981 let typed_array = run_array.downcast::<Int32Array>().unwrap();
1982
1983 let result = min_array::<Int32Type, _>(typed_array);
1984 assert_eq!(result, None);
1985
1986 let result = max_array::<Int32Type, _>(typed_array);
1987 assert_eq!(result, None);
1988 }
1989
1990 #[test]
1991 fn test_ree_min_max_array_float() {
1992 let run_array = make_run_array::<Int16Type, Float64Type, _>(&[5.5, 5.5, 2.1, 8.9, 8.9]);
1993 let typed_array = run_array.downcast::<Float64Array>().unwrap();
1994
1995 let result = min_array::<Float64Type, _>(typed_array);
1996 assert_eq!(result, Some(2.1));
1997
1998 let result = max_array::<Float64Type, _>(typed_array);
1999 assert_eq!(result, Some(8.9));
2000 }
2001
2002 #[test]
2003 fn test_ree_min_max_array_with_nulls() {
2004 let run_array = make_run_array::<Int16Type, UInt8Type, _>(&[None, Some(10)]);
2005 let typed_array = run_array.downcast::<UInt8Array>().unwrap();
2006
2007 let result = min_array::<UInt8Type, _>(typed_array);
2008 assert_eq!(result, Some(10));
2009
2010 let result = max_array::<UInt8Type, _>(typed_array);
2011 assert_eq!(result, Some(10));
2012 }
2013
2014 #[test]
2015 fn test_ree_min_max_array_sliced() {
2016 let run_array = make_run_array::<Int16Type, Int32Type, _>(&[0, 30, 30, 10, 20, 20, 100]);
2017 let sliced = run_array.slice(1, 5);
2019 let typed_array = sliced.downcast::<Int32Array>().unwrap();
2020
2021 let result = min_array::<Int32Type, _>(typed_array);
2022 assert_eq!(result, Some(10));
2023
2024 let result = max_array::<Int32Type, _>(typed_array);
2025 assert_eq!(result, Some(30));
2026 }
2027
2028 #[test]
2029 fn test_ree_min_max_array_sliced_mid_run() {
2030 let run_array = make_run_array::<Int16Type, Int32Type, _>(&[0, 0, 30, 10, 20, 100, 100]);
2031 let sliced = run_array.slice(1, 5);
2033 let typed_array = sliced.downcast::<Int32Array>().unwrap();
2034
2035 let result = min_array::<Int32Type, _>(typed_array);
2036 assert_eq!(result, Some(0));
2037
2038 let result = max_array::<Int32Type, _>(typed_array);
2039 assert_eq!(result, Some(100));
2040 }
2041}