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 {
49 a
50 } else {
51 b
52 }
53}
54
55#[derive(Clone, Copy)]
56struct SumAccumulator<T: ArrowNativeTypeOp> {
57 sum: T,
58}
59
60impl<T: ArrowNativeTypeOp> Default for SumAccumulator<T> {
61 fn default() -> Self {
62 Self { sum: T::ZERO }
63 }
64}
65
66impl<T: ArrowNativeTypeOp> NumericAccumulator<T> for SumAccumulator<T> {
67 fn accumulate(&mut self, value: T) {
68 self.sum = self.sum.add_wrapping(value);
69 }
70
71 fn accumulate_nullable(&mut self, value: T, valid: bool) {
72 let sum = self.sum;
73 self.sum = select(valid, sum.add_wrapping(value), sum)
74 }
75
76 fn merge(&mut self, other: Self) {
77 self.sum = self.sum.add_wrapping(other.sum);
78 }
79
80 fn finish(&mut self) -> T {
81 self.sum
82 }
83}
84
85#[derive(Clone, Copy)]
86struct MinAccumulator<T: ArrowNativeTypeOp> {
87 min: T,
88}
89
90impl<T: ArrowNativeTypeOp> Default for MinAccumulator<T> {
91 fn default() -> Self {
92 Self {
93 min: T::MAX_TOTAL_ORDER,
94 }
95 }
96}
97
98impl<T: ArrowNativeTypeOp> NumericAccumulator<T> for MinAccumulator<T> {
99 fn accumulate(&mut self, value: T) {
100 let min = self.min;
101 self.min = select(value.is_lt(min), value, min);
102 }
103
104 fn accumulate_nullable(&mut self, value: T, valid: bool) {
105 let min = self.min;
106 let is_lt = valid & value.is_lt(min);
107 self.min = select(is_lt, value, min);
108 }
109
110 fn merge(&mut self, other: Self) {
111 self.accumulate(other.min)
112 }
113
114 fn finish(&mut self) -> T {
115 self.min
116 }
117}
118
119#[derive(Clone, Copy)]
120struct MaxAccumulator<T: ArrowNativeTypeOp> {
121 max: T,
122}
123
124impl<T: ArrowNativeTypeOp> Default for MaxAccumulator<T> {
125 fn default() -> Self {
126 Self {
127 max: T::MIN_TOTAL_ORDER,
128 }
129 }
130}
131
132impl<T: ArrowNativeTypeOp> NumericAccumulator<T> for MaxAccumulator<T> {
133 fn accumulate(&mut self, value: T) {
134 let max = self.max;
135 self.max = select(value.is_gt(max), value, max);
136 }
137
138 fn accumulate_nullable(&mut self, value: T, valid: bool) {
139 let max = self.max;
140 let is_gt = value.is_gt(max) & valid;
141 self.max = select(is_gt, value, max);
142 }
143
144 fn merge(&mut self, other: Self) {
145 self.accumulate(other.max)
146 }
147
148 fn finish(&mut self) -> T {
149 self.max
150 }
151}
152
153fn reduce_accumulators<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
154 mut acc: [A; LANES],
155) -> A {
156 assert!(LANES > 0 && LANES.is_power_of_two());
157 let mut len = LANES;
158
159 while len >= 2 {
162 let mid = len / 2;
163 let (h, t) = acc[..len].split_at_mut(mid);
164
165 for i in 0..mid {
166 h[i].merge(t[i]);
167 }
168 len /= 2;
169 }
170 acc[0]
171}
172
173#[inline(always)]
174fn aggregate_nonnull_chunk<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
175 acc: &mut [A; LANES],
176 values: &[T; LANES],
177) {
178 for i in 0..LANES {
179 acc[i].accumulate(values[i]);
180 }
181}
182
183#[inline(always)]
184fn aggregate_nullable_chunk<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
185 acc: &mut [A; LANES],
186 values: &[T; LANES],
187 validity: u64,
188) {
189 let mut bit = 1;
190 for i in 0..LANES {
191 acc[i].accumulate_nullable(values[i], (validity & bit) != 0);
192 bit <<= 1;
193 }
194}
195
196fn aggregate_nonnull_simple<T: ArrowNativeTypeOp, A: NumericAccumulator<T>>(values: &[T]) -> T {
197 values
198 .iter()
199 .copied()
200 .fold(A::default(), |mut a, b| {
201 a.accumulate(b);
202 a
203 })
204 .finish()
205}
206
207#[inline(never)]
208fn aggregate_nonnull_lanes<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
209 values: &[T],
210) -> T {
211 let mut acc = [A::default(); LANES];
214 let mut chunks = values.chunks_exact(LANES);
215 chunks.borrow_mut().for_each(|chunk| {
216 aggregate_nonnull_chunk(&mut acc, chunk[..LANES].try_into().unwrap());
217 });
218
219 let remainder = chunks.remainder();
220 for i in 0..remainder.len() {
221 acc[i].accumulate(remainder[i]);
222 }
223
224 reduce_accumulators(acc).finish()
225}
226
227#[inline(never)]
228fn aggregate_nullable_lanes<T: ArrowNativeTypeOp, A: NumericAccumulator<T>, const LANES: usize>(
229 values: &[T],
230 validity: &NullBuffer,
231) -> T {
232 assert!(LANES > 0 && 64 % LANES == 0);
233 assert_eq!(values.len(), validity.len());
234
235 let mut acc = [A::default(); LANES];
237 let mut values_chunks = values.chunks_exact(64);
239 let validity_chunks = validity.inner().bit_chunks();
240 let mut validity_chunks_iter = validity_chunks.iter();
241
242 values_chunks.borrow_mut().for_each(|chunk| {
243 let mut validity = unsafe { validity_chunks_iter.next().unwrap_unchecked() };
245 chunk.chunks_exact(LANES).for_each(|chunk| {
247 aggregate_nullable_chunk(&mut acc, chunk[..LANES].try_into().unwrap(), validity);
248 validity >>= LANES;
249 });
250 });
251
252 let remainder = values_chunks.remainder();
253 if !remainder.is_empty() {
254 let mut validity = validity_chunks.remainder_bits();
255
256 let mut remainder_chunks = remainder.chunks_exact(LANES);
257 remainder_chunks.borrow_mut().for_each(|chunk| {
258 aggregate_nullable_chunk(&mut acc, chunk[..LANES].try_into().unwrap(), validity);
259 validity >>= LANES;
260 });
261
262 let remainder = remainder_chunks.remainder();
263 if !remainder.is_empty() {
264 let mut bit = 1;
265 for i in 0..remainder.len() {
266 acc[i].accumulate_nullable(remainder[i], (validity & bit) != 0);
267 bit <<= 1;
268 }
269 }
270 }
271
272 reduce_accumulators(acc).finish()
273}
274
275const PREFERRED_VECTOR_SIZE: usize =
278 if cfg!(all(target_arch = "x86_64", target_feature = "avx512f")) {
279 64
280 } else if cfg!(all(target_arch = "x86_64", target_feature = "avx")) {
281 32
282 } else {
283 16
284 };
285
286const PREFERRED_VECTOR_SIZE_NON_NULL: usize = PREFERRED_VECTOR_SIZE * 2;
288
289fn aggregate<T: ArrowNativeTypeOp, P: ArrowPrimitiveType<Native = T>, A: NumericAccumulator<T>>(
292 array: &PrimitiveArray<P>,
293) -> Option<T> {
294 let null_count = array.null_count();
295 if null_count == array.len() {
296 return None;
297 }
298 let values = array.values().as_ref();
299 match array.nulls() {
300 Some(nulls) if null_count > 0 => {
301 match PREFERRED_VECTOR_SIZE / std::mem::size_of::<T>() {
304 64 => Some(aggregate_nullable_lanes::<T, A, 64>(values, nulls)),
305 32 => Some(aggregate_nullable_lanes::<T, A, 32>(values, nulls)),
306 16 => Some(aggregate_nullable_lanes::<T, A, 16>(values, nulls)),
307 8 => Some(aggregate_nullable_lanes::<T, A, 8>(values, nulls)),
308 4 => Some(aggregate_nullable_lanes::<T, A, 4>(values, nulls)),
309 2 => Some(aggregate_nullable_lanes::<T, A, 2>(values, nulls)),
310 _ => Some(aggregate_nullable_lanes::<T, A, 1>(values, nulls)),
311 }
312 }
313 _ => {
314 let is_float = matches!(
315 array.data_type(),
316 DataType::Float16 | DataType::Float32 | DataType::Float64
317 );
318 if is_float {
319 match PREFERRED_VECTOR_SIZE_NON_NULL / std::mem::size_of::<T>() {
320 64 => Some(aggregate_nonnull_lanes::<T, A, 64>(values)),
321 32 => Some(aggregate_nonnull_lanes::<T, A, 32>(values)),
322 16 => Some(aggregate_nonnull_lanes::<T, A, 16>(values)),
323 8 => Some(aggregate_nonnull_lanes::<T, A, 8>(values)),
324 4 => Some(aggregate_nonnull_lanes::<T, A, 4>(values)),
325 2 => Some(aggregate_nonnull_lanes::<T, A, 2>(values)),
326 _ => Some(aggregate_nonnull_simple::<T, A>(values)),
327 }
328 } else {
329 Some(aggregate_nonnull_simple::<T, A>(values))
332 }
333 }
334 }
335}
336
337pub fn min_boolean(array: &BooleanArray) -> Option<bool> {
347 if array.null_count() == array.len() {
349 return None;
350 }
351
352 match array.nulls() {
354 None => {
355 let bit_chunks = array.values().bit_chunks();
356 if bit_chunks.iter().any(|x| {
357 x != u64::MAX
359 }) {
360 return Some(false);
361 }
362 if bit_chunks.remainder_bits().count_ones() as usize != bit_chunks.remainder_len() {
364 Some(false)
365 } else {
366 Some(true)
367 }
368 }
369 Some(nulls) => {
370 let validity_chunks = nulls.inner().bit_chunks();
371 let value_chunks = array.values().bit_chunks();
372
373 if value_chunks
374 .iter()
375 .zip(validity_chunks.iter())
376 .any(|(value, validity)| {
377 (!value & validity) != 0
380 })
381 {
382 return Some(false);
383 }
384
385 if (!value_chunks.remainder_bits() & validity_chunks.remainder_bits()) != 0 {
387 Some(false)
388 } else {
389 Some(true)
390 }
391 }
392 }
393}
394
395pub fn max_boolean(array: &BooleanArray) -> Option<bool> {
405 if array.null_count() == array.len() {
407 return None;
408 }
409
410 match array.nulls() {
412 None => array
413 .values()
414 .bit_chunks()
415 .iter_padded()
416 .map(|x| x != 0)
418 .find(|b| *b)
419 .or(Some(false)),
420 Some(nulls) => {
421 let validity_chunks = nulls.inner().bit_chunks().iter_padded();
422 let value_chunks = array.values().bit_chunks().iter_padded();
423 value_chunks
424 .zip(validity_chunks)
425 .map(|(value_bits, validity_bits)| (value_bits & validity_bits) != 0)
427 .find(|b| *b)
428 .or(Some(false))
429 }
430 }
431}
432
433fn min_max_helper<T, A: ArrayAccessor<Item = T>, F>(array: A, cmp: F) -> Option<T>
435where
436 F: Fn(&T, &T) -> bool,
437{
438 let null_count = array.null_count();
439 if null_count == array.len() {
440 None
441 } else if null_count == 0 {
442 (0..array.len())
446 .map(|i| unsafe { array.value_unchecked(i) })
447 .reduce(|acc, item| if cmp(&acc, &item) { item } else { acc })
448 } else {
449 let nulls = array.nulls().unwrap();
450 unsafe {
451 let idx = nulls.valid_indices().reduce(|acc_idx, idx| {
452 let acc = array.value_unchecked(acc_idx);
453 let item = array.value_unchecked(idx);
454 if cmp(&acc, &item) {
455 idx
456 } else {
457 acc_idx
458 }
459 });
460 idx.map(|idx| array.value_unchecked(idx))
461 }
462 }
463}
464
465fn min_max_view_helper<T: ByteViewType>(
470 array: &GenericByteViewArray<T>,
471 swap_cond: cmp::Ordering,
472) -> Option<&T::Native> {
473 let null_count = array.null_count();
474 if null_count == array.len() {
475 None
476 } else if null_count == 0 {
477 let target_idx = (0..array.len()).reduce(|acc, item| {
478 let cmp = unsafe { GenericByteViewArray::compare_unchecked(array, item, array, acc) };
480 if cmp == swap_cond {
481 item
482 } else {
483 acc
484 }
485 });
486 unsafe { target_idx.map(|idx| array.value_unchecked(idx)) }
488 } else {
489 let nulls = array.nulls().unwrap();
490
491 let target_idx = nulls.valid_indices().reduce(|acc_idx, idx| {
492 let cmp =
493 unsafe { GenericByteViewArray::compare_unchecked(array, idx, array, acc_idx) };
494 if cmp == swap_cond {
495 idx
496 } else {
497 acc_idx
498 }
499 });
500
501 unsafe { target_idx.map(|idx| array.value_unchecked(idx)) }
503 }
504}
505
506pub fn max_binary<T: OffsetSizeTrait>(array: &GenericBinaryArray<T>) -> Option<&[u8]> {
508 min_max_helper::<&[u8], _, _>(array, |a, b| *a < *b)
509}
510
511pub fn max_binary_view(array: &BinaryViewArray) -> Option<&[u8]> {
513 min_max_view_helper(array, Ordering::Greater)
514}
515
516pub fn min_binary<T: OffsetSizeTrait>(array: &GenericBinaryArray<T>) -> Option<&[u8]> {
518 min_max_helper::<&[u8], _, _>(array, |a, b| *a > *b)
519}
520
521pub fn min_binary_view(array: &BinaryViewArray) -> Option<&[u8]> {
523 min_max_view_helper(array, Ordering::Less)
524}
525
526pub fn max_string<T: OffsetSizeTrait>(array: &GenericStringArray<T>) -> Option<&str> {
528 min_max_helper::<&str, _, _>(array, |a, b| *a < *b)
529}
530
531pub fn max_string_view(array: &StringViewArray) -> Option<&str> {
533 min_max_view_helper(array, Ordering::Greater)
534}
535
536pub fn min_string<T: OffsetSizeTrait>(array: &GenericStringArray<T>) -> Option<&str> {
538 min_max_helper::<&str, _, _>(array, |a, b| *a > *b)
539}
540
541pub fn min_string_view(array: &StringViewArray) -> Option<&str> {
543 min_max_view_helper(array, Ordering::Less)
544}
545
546pub fn sum_array<T, A: ArrayAccessor<Item = T::Native>>(array: A) -> Option<T::Native>
551where
552 T: ArrowNumericType,
553 T::Native: ArrowNativeTypeOp,
554{
555 match array.data_type() {
556 DataType::Dictionary(_, _) => {
557 let null_count = array.null_count();
558
559 if null_count == array.len() {
560 return None;
561 }
562
563 let iter = ArrayIter::new(array);
564 let sum = iter
565 .into_iter()
566 .fold(T::default_value(), |accumulator, value| {
567 if let Some(value) = value {
568 accumulator.add_wrapping(value)
569 } else {
570 accumulator
571 }
572 });
573
574 Some(sum)
575 }
576 _ => sum::<T>(as_primitive_array(&array)),
577 }
578}
579
580pub fn sum_array_checked<T, A: ArrayAccessor<Item = T::Native>>(
585 array: A,
586) -> Result<Option<T::Native>, ArrowError>
587where
588 T: ArrowNumericType,
589 T::Native: ArrowNativeTypeOp,
590{
591 match array.data_type() {
592 DataType::Dictionary(_, _) => {
593 let null_count = array.null_count();
594
595 if null_count == array.len() {
596 return Ok(None);
597 }
598
599 let iter = ArrayIter::new(array);
600 let sum = iter
601 .into_iter()
602 .try_fold(T::default_value(), |accumulator, value| {
603 if let Some(value) = value {
604 accumulator.add_checked(value)
605 } else {
606 Ok(accumulator)
607 }
608 })?;
609
610 Ok(Some(sum))
611 }
612 _ => sum_checked::<T>(as_primitive_array(&array)),
613 }
614}
615
616pub fn min_array<T, A: ArrayAccessor<Item = T::Native>>(array: A) -> Option<T::Native>
619where
620 T: ArrowNumericType,
621 T::Native: ArrowNativeType,
622{
623 min_max_array_helper::<T, A, _, _>(array, |a, b| a.is_gt(*b), min)
624}
625
626pub fn max_array<T, A: ArrayAccessor<Item = T::Native>>(array: A) -> Option<T::Native>
629where
630 T: ArrowNumericType,
631 T::Native: ArrowNativeTypeOp,
632{
633 min_max_array_helper::<T, A, _, _>(array, |a, b| a.is_lt(*b), max)
634}
635
636fn min_max_array_helper<T, A: ArrayAccessor<Item = T::Native>, F, M>(
637 array: A,
638 cmp: F,
639 m: M,
640) -> Option<T::Native>
641where
642 T: ArrowNumericType,
643 F: Fn(&T::Native, &T::Native) -> bool,
644 M: Fn(&PrimitiveArray<T>) -> Option<T::Native>,
645{
646 match array.data_type() {
647 DataType::Dictionary(_, _) => min_max_helper::<T::Native, _, _>(array, cmp),
648 _ => m(as_primitive_array(&array)),
649 }
650}
651
652macro_rules! bit_operation {
653 ($NAME:ident, $OP:ident, $NATIVE:ident, $DEFAULT:expr, $DOC:expr) => {
654 #[doc = $DOC]
655 pub fn $NAME<T>(array: &PrimitiveArray<T>) -> Option<T::Native>
658 where
659 T: ArrowNumericType,
660 T::Native: $NATIVE<Output = T::Native> + ArrowNativeTypeOp,
661 {
662 let default;
663 if $DEFAULT == -1 {
664 default = T::Native::ONE.neg_wrapping();
665 } else {
666 default = T::default_value();
667 }
668
669 let null_count = array.null_count();
670
671 if null_count == array.len() {
672 return None;
673 }
674
675 let data: &[T::Native] = array.values();
676
677 match array.nulls() {
678 None => {
679 let result = data
680 .iter()
681 .fold(default, |accumulator, value| accumulator.$OP(*value));
682
683 Some(result)
684 }
685 Some(nulls) => {
686 let mut result = default;
687 let data_chunks = data.chunks_exact(64);
688 let remainder = data_chunks.remainder();
689
690 let bit_chunks = nulls.inner().bit_chunks();
691 data_chunks
692 .zip(bit_chunks.iter())
693 .for_each(|(chunk, mask)| {
694 let mut index_mask = 1;
696 chunk.iter().for_each(|value| {
697 if (mask & index_mask) != 0 {
698 result = result.$OP(*value);
699 }
700 index_mask <<= 1;
701 });
702 });
703
704 let remainder_bits = bit_chunks.remainder_bits();
705
706 remainder.iter().enumerate().for_each(|(i, value)| {
707 if remainder_bits & (1 << i) != 0 {
708 result = result.$OP(*value);
709 }
710 });
711
712 Some(result)
713 }
714 }
715 }
716 };
717}
718
719bit_operation!(
720 bit_and,
721 bitand,
722 BitAnd,
723 -1,
724 "Returns the bitwise and of all non-null input values."
725);
726bit_operation!(
727 bit_or,
728 bitor,
729 BitOr,
730 0,
731 "Returns the bitwise or of all non-null input values."
732);
733bit_operation!(
734 bit_xor,
735 bitxor,
736 BitXor,
737 0,
738 "Returns the bitwise xor of all non-null input values."
739);
740
741pub fn bool_and(array: &BooleanArray) -> Option<bool> {
745 min_boolean(array)
746}
747
748pub fn bool_or(array: &BooleanArray) -> Option<bool> {
752 max_boolean(array)
753}
754
755pub fn sum_checked<T>(array: &PrimitiveArray<T>) -> Result<Option<T::Native>, ArrowError>
762where
763 T: ArrowNumericType,
764 T::Native: ArrowNativeTypeOp,
765{
766 let null_count = array.null_count();
767
768 if null_count == array.len() {
769 return Ok(None);
770 }
771
772 let data: &[T::Native] = array.values();
773
774 match array.nulls() {
775 None => {
776 let sum = data
777 .iter()
778 .try_fold(T::default_value(), |accumulator, value| {
779 accumulator.add_checked(*value)
780 })?;
781
782 Ok(Some(sum))
783 }
784 Some(nulls) => {
785 let mut sum = T::default_value();
786
787 try_for_each_valid_idx(
788 nulls.len(),
789 nulls.offset(),
790 nulls.null_count(),
791 Some(nulls.validity()),
792 |idx| {
793 unsafe { sum = sum.add_checked(array.value_unchecked(idx))? };
794 Ok::<_, ArrowError>(())
795 },
796 )?;
797
798 Ok(Some(sum))
799 }
800 }
801}
802
803pub fn sum<T: ArrowNumericType>(array: &PrimitiveArray<T>) -> Option<T::Native>
810where
811 T::Native: ArrowNativeTypeOp,
812{
813 aggregate::<T::Native, T, SumAccumulator<T::Native>>(array)
814}
815
816pub fn min<T: ArrowNumericType>(array: &PrimitiveArray<T>) -> Option<T::Native>
819where
820 T::Native: PartialOrd,
821{
822 aggregate::<T::Native, T, MinAccumulator<T::Native>>(array)
823}
824
825pub fn max<T: ArrowNumericType>(array: &PrimitiveArray<T>) -> Option<T::Native>
828where
829 T::Native: PartialOrd,
830{
831 aggregate::<T::Native, T, MaxAccumulator<T::Native>>(array)
832}
833
834#[cfg(test)]
835mod tests {
836 use super::*;
837 use arrow_array::types::*;
838 use builder::BooleanBuilder;
839 use std::sync::Arc;
840
841 #[test]
842 fn test_primitive_array_sum() {
843 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
844 assert_eq!(15, sum(&a).unwrap());
845 }
846
847 #[test]
848 fn test_primitive_array_float_sum() {
849 let a = Float64Array::from(vec![1.1, 2.2, 3.3, 4.4, 5.5]);
850 assert_eq!(16.5, sum(&a).unwrap());
851 }
852
853 #[test]
854 fn test_primitive_array_sum_with_nulls() {
855 let a = Int32Array::from(vec![None, Some(2), Some(3), None, Some(5)]);
856 assert_eq!(10, sum(&a).unwrap());
857 }
858
859 #[test]
860 fn test_primitive_array_sum_all_nulls() {
861 let a = Int32Array::from(vec![None, None, None]);
862 assert_eq!(None, sum(&a));
863 }
864
865 #[test]
866 fn test_primitive_array_sum_large_float_64() {
867 let c = Float64Array::new((1..=100).map(|x| x as f64).collect(), None);
868 assert_eq!(Some((1..=100).sum::<i64>() as f64), sum(&c));
869
870 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
872 let c = Float64Array::new((1..=100).map(|x| x as f64).collect(), Some(validity));
873
874 assert_eq!(
875 Some((1..=100).filter(|i| i % 3 == 0).sum::<i64>() as f64),
876 sum(&c)
877 );
878 }
879
880 #[test]
881 fn test_primitive_array_sum_large_float_32() {
882 let c = Float32Array::new((1..=100).map(|x| x as f32).collect(), None);
883 assert_eq!(Some((1..=100).sum::<i64>() as f32), sum(&c));
884
885 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
887 let c = Float32Array::new((1..=100).map(|x| x as f32).collect(), Some(validity));
888
889 assert_eq!(
890 Some((1..=100).filter(|i| i % 3 == 0).sum::<i64>() as f32),
891 sum(&c)
892 );
893 }
894
895 #[test]
896 fn test_primitive_array_sum_large_64() {
897 let c = Int64Array::new((1..=100).collect(), None);
898 assert_eq!(Some((1..=100).sum()), sum(&c));
899
900 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
902 let c = Int64Array::new((1..=100).collect(), Some(validity));
903
904 assert_eq!(Some((1..=100).filter(|i| i % 3 == 0).sum()), sum(&c));
905 }
906
907 #[test]
908 fn test_primitive_array_sum_large_32() {
909 let c = Int32Array::new((1..=100).collect(), None);
910 assert_eq!(Some((1..=100).sum()), sum(&c));
911
912 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
914 let c = Int32Array::new((1..=100).collect(), Some(validity));
915 assert_eq!(Some((1..=100).filter(|i| i % 3 == 0).sum()), sum(&c));
916 }
917
918 #[test]
919 fn test_primitive_array_sum_large_16() {
920 let c = Int16Array::new((1..=100).collect(), None);
921 assert_eq!(Some((1..=100).sum()), sum(&c));
922
923 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
925 let c = Int16Array::new((1..=100).collect(), Some(validity));
926 assert_eq!(Some((1..=100).filter(|i| i % 3 == 0).sum()), sum(&c));
927 }
928
929 #[test]
930 fn test_primitive_array_sum_large_8() {
931 let c = UInt8Array::new((1..=100).collect(), None);
932 assert_eq!(
933 Some((1..=100).fold(0_u8, |a, x| a.wrapping_add(x))),
934 sum(&c)
935 );
936
937 let validity = NullBuffer::new((1..=100).map(|x| x % 3 == 0).collect());
939 let c = UInt8Array::new((1..=100).collect(), Some(validity));
940 assert_eq!(
941 Some(
942 (1..=100)
943 .filter(|i| i % 3 == 0)
944 .fold(0_u8, |a, x| a.wrapping_add(x))
945 ),
946 sum(&c)
947 );
948 }
949
950 #[test]
951 fn test_primitive_array_bit_and() {
952 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
953 assert_eq!(0, bit_and(&a).unwrap());
954 }
955
956 #[test]
957 fn test_primitive_array_bit_and_with_nulls() {
958 let a = Int32Array::from(vec![None, Some(2), Some(3), None, None]);
959 assert_eq!(2, bit_and(&a).unwrap());
960 }
961
962 #[test]
963 fn test_primitive_array_bit_and_all_nulls() {
964 let a = Int32Array::from(vec![None, None, None]);
965 assert_eq!(None, bit_and(&a));
966 }
967
968 #[test]
969 fn test_primitive_array_bit_or() {
970 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
971 assert_eq!(7, bit_or(&a).unwrap());
972 }
973
974 #[test]
975 fn test_primitive_array_bit_or_with_nulls() {
976 let a = Int32Array::from(vec![None, Some(2), Some(3), None, Some(5)]);
977 assert_eq!(7, bit_or(&a).unwrap());
978 }
979
980 #[test]
981 fn test_primitive_array_bit_or_all_nulls() {
982 let a = Int32Array::from(vec![None, None, None]);
983 assert_eq!(None, bit_or(&a));
984 }
985
986 #[test]
987 fn test_primitive_array_bit_xor() {
988 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
989 assert_eq!(1, bit_xor(&a).unwrap());
990 }
991
992 #[test]
993 fn test_primitive_array_bit_xor_with_nulls() {
994 let a = Int32Array::from(vec![None, Some(2), Some(3), None, Some(5)]);
995 assert_eq!(4, bit_xor(&a).unwrap());
996 }
997
998 #[test]
999 fn test_primitive_array_bit_xor_all_nulls() {
1000 let a = Int32Array::from(vec![None, None, None]);
1001 assert_eq!(None, bit_xor(&a));
1002 }
1003
1004 #[test]
1005 fn test_primitive_array_bool_and() {
1006 let a = BooleanArray::from(vec![true, false, true, false, true]);
1007 assert!(!bool_and(&a).unwrap());
1008 }
1009
1010 #[test]
1011 fn test_primitive_array_bool_and_with_nulls() {
1012 let a = BooleanArray::from(vec![None, Some(true), Some(true), None, Some(true)]);
1013 assert!(bool_and(&a).unwrap());
1014 }
1015
1016 #[test]
1017 fn test_primitive_array_bool_and_all_nulls() {
1018 let a = BooleanArray::from(vec![None, None, None]);
1019 assert_eq!(None, bool_and(&a));
1020 }
1021
1022 #[test]
1023 fn test_primitive_array_bool_or() {
1024 let a = BooleanArray::from(vec![true, false, true, false, true]);
1025 assert!(bool_or(&a).unwrap());
1026 }
1027
1028 #[test]
1029 fn test_primitive_array_bool_or_with_nulls() {
1030 let a = BooleanArray::from(vec![None, Some(false), Some(false), None, Some(false)]);
1031 assert!(!bool_or(&a).unwrap());
1032 }
1033
1034 #[test]
1035 fn test_primitive_array_bool_or_all_nulls() {
1036 let a = BooleanArray::from(vec![None, None, None]);
1037 assert_eq!(None, bool_or(&a));
1038 }
1039
1040 #[test]
1041 fn test_primitive_array_min_max() {
1042 let a = Int32Array::from(vec![5, 6, 7, 8, 9]);
1043 assert_eq!(5, min(&a).unwrap());
1044 assert_eq!(9, max(&a).unwrap());
1045 }
1046
1047 #[test]
1048 fn test_primitive_array_min_max_with_nulls() {
1049 let a = Int32Array::from(vec![Some(5), None, None, Some(8), Some(9)]);
1050 assert_eq!(5, min(&a).unwrap());
1051 assert_eq!(9, max(&a).unwrap());
1052 }
1053
1054 #[test]
1055 fn test_primitive_min_max_1() {
1056 let a = Int32Array::from(vec![None, None, Some(5), Some(2)]);
1057 assert_eq!(Some(2), min(&a));
1058 assert_eq!(Some(5), max(&a));
1059 }
1060
1061 #[test]
1062 fn test_primitive_min_max_float_large_nonnull_array() {
1063 let a: Float64Array = (0..256).map(|i| Some((i + 1) as f64)).collect();
1064 assert_eq!(Some(1.0), min(&a));
1066 assert_eq!(Some(256.0), max(&a));
1067
1068 let a: Float64Array = (0..255).map(|i| Some((i + 1) as f64)).collect();
1070 assert_eq!(Some(255.0), max(&a));
1071
1072 let a: Float64Array = (0..257).map(|i| Some((i + 1) as f64)).collect();
1074 assert_eq!(Some(257.0), max(&a));
1075 }
1076
1077 #[test]
1078 fn test_primitive_min_max_float_large_nullable_array() {
1079 let a: Float64Array = (0..256)
1080 .map(|i| {
1081 if (i + 1) % 3 == 0 {
1082 None
1083 } else {
1084 Some((i + 1) as f64)
1085 }
1086 })
1087 .collect();
1088 assert_eq!(Some(1.0), min(&a));
1090 assert_eq!(Some(256.0), max(&a));
1091
1092 let a: Float64Array = (0..256)
1093 .map(|i| {
1094 if i == 0 || i == 255 {
1095 None
1096 } else {
1097 Some((i + 1) as f64)
1098 }
1099 })
1100 .collect();
1101 assert_eq!(Some(2.0), min(&a));
1103 assert_eq!(Some(255.0), max(&a));
1104
1105 let a: Float64Array = (0..256)
1106 .map(|i| if i != 100 { None } else { Some((i) as f64) })
1107 .collect();
1108 assert_eq!(Some(100.0), min(&a));
1110 assert_eq!(Some(100.0), max(&a));
1111
1112 let a: Float64Array = (0..255).map(|i| Some((i + 1) as f64)).collect();
1114 assert_eq!(Some(255.0), max(&a));
1115
1116 let a: Float64Array = (0..257).map(|i| Some((i + 1) as f64)).collect();
1118 assert_eq!(Some(257.0), max(&a));
1119 }
1120
1121 #[test]
1122 fn test_primitive_min_max_float_edge_cases() {
1123 let a: Float64Array = (0..100).map(|_| Some(f64::NEG_INFINITY)).collect();
1124 assert_eq!(Some(f64::NEG_INFINITY), min(&a));
1125 assert_eq!(Some(f64::NEG_INFINITY), max(&a));
1126
1127 let a: Float64Array = (0..100).map(|_| Some(f64::MIN)).collect();
1128 assert_eq!(Some(f64::MIN), min(&a));
1129 assert_eq!(Some(f64::MIN), max(&a));
1130
1131 let a: Float64Array = (0..100).map(|_| Some(f64::MAX)).collect();
1132 assert_eq!(Some(f64::MAX), min(&a));
1133 assert_eq!(Some(f64::MAX), max(&a));
1134
1135 let a: Float64Array = (0..100).map(|_| Some(f64::INFINITY)).collect();
1136 assert_eq!(Some(f64::INFINITY), min(&a));
1137 assert_eq!(Some(f64::INFINITY), max(&a));
1138 }
1139
1140 #[test]
1141 fn test_primitive_min_max_float_all_nans_non_null() {
1142 let a: Float64Array = (0..100).map(|_| Some(f64::NAN)).collect();
1143 assert!(max(&a).unwrap().is_nan());
1144 assert!(min(&a).unwrap().is_nan());
1145 }
1146
1147 #[test]
1148 fn test_primitive_min_max_float_negative_nan() {
1149 let a: Float64Array =
1150 Float64Array::from(vec![f64::NEG_INFINITY, f64::NAN, f64::INFINITY, -f64::NAN]);
1151 let max = max(&a).unwrap();
1152 let min = min(&a).unwrap();
1153 assert!(max.is_nan());
1154 assert!(max.is_sign_positive());
1155
1156 assert!(min.is_nan());
1157 assert!(min.is_sign_negative());
1158 }
1159
1160 #[test]
1161 fn test_primitive_min_max_float_first_nan_nonnull() {
1162 let a: Float64Array = (0..100)
1163 .map(|i| {
1164 if i == 0 {
1165 Some(f64::NAN)
1166 } else {
1167 Some(i as f64)
1168 }
1169 })
1170 .collect();
1171 assert_eq!(Some(1.0), min(&a));
1172 assert!(max(&a).unwrap().is_nan());
1173 }
1174
1175 #[test]
1176 fn test_primitive_min_max_float_last_nan_nonnull() {
1177 let a: Float64Array = (0..100)
1178 .map(|i| {
1179 if i == 99 {
1180 Some(f64::NAN)
1181 } else {
1182 Some((i + 1) as f64)
1183 }
1184 })
1185 .collect();
1186 assert_eq!(Some(1.0), min(&a));
1187 assert!(max(&a).unwrap().is_nan());
1188 }
1189
1190 #[test]
1191 fn test_primitive_min_max_float_first_nan_nullable() {
1192 let a: Float64Array = (0..100)
1193 .map(|i| {
1194 if i == 0 {
1195 Some(f64::NAN)
1196 } else if i % 2 == 0 {
1197 None
1198 } else {
1199 Some(i as f64)
1200 }
1201 })
1202 .collect();
1203 assert_eq!(Some(1.0), min(&a));
1204 assert!(max(&a).unwrap().is_nan());
1205 }
1206
1207 #[test]
1208 fn test_primitive_min_max_float_last_nan_nullable() {
1209 let a: Float64Array = (0..100)
1210 .map(|i| {
1211 if i == 99 {
1212 Some(f64::NAN)
1213 } else if i % 2 == 0 {
1214 None
1215 } else {
1216 Some(i as f64)
1217 }
1218 })
1219 .collect();
1220 assert_eq!(Some(1.0), min(&a));
1221 assert!(max(&a).unwrap().is_nan());
1222 }
1223
1224 #[test]
1225 fn test_primitive_min_max_float_inf_and_nans() {
1226 let a: Float64Array = (0..100)
1227 .map(|i| {
1228 let x = match i % 10 {
1229 0 => f64::NEG_INFINITY,
1230 1 => f64::MIN,
1231 2 => f64::MAX,
1232 4 => f64::INFINITY,
1233 5 => f64::NAN,
1234 _ => i as f64,
1235 };
1236 Some(x)
1237 })
1238 .collect();
1239 assert_eq!(Some(f64::NEG_INFINITY), min(&a));
1240 assert!(max(&a).unwrap().is_nan());
1241 }
1242
1243 macro_rules! test_binary {
1244 ($NAME:ident, $ARRAY:expr, $EXPECTED_MIN:expr, $EXPECTED_MAX: expr) => {
1245 #[test]
1246 fn $NAME() {
1247 let binary = BinaryArray::from($ARRAY);
1248 assert_eq!($EXPECTED_MIN, min_binary(&binary));
1249 assert_eq!($EXPECTED_MAX, max_binary(&binary));
1250
1251 let large_binary = LargeBinaryArray::from($ARRAY);
1252 assert_eq!($EXPECTED_MIN, min_binary(&large_binary));
1253 assert_eq!($EXPECTED_MAX, max_binary(&large_binary));
1254
1255 let binary_view = BinaryViewArray::from($ARRAY);
1256 assert_eq!($EXPECTED_MIN, min_binary_view(&binary_view));
1257 assert_eq!($EXPECTED_MAX, max_binary_view(&binary_view));
1258 }
1259 };
1260 }
1261
1262 test_binary!(
1263 test_binary_min_max_with_nulls,
1264 vec![
1265 Some("b01234567890123".as_bytes()), None,
1267 None,
1268 Some(b"a"),
1269 Some(b"c"),
1270 Some(b"abcdedfg0123456"),
1271 ],
1272 Some("a".as_bytes()),
1273 Some("c".as_bytes())
1274 );
1275
1276 test_binary!(
1277 test_binary_min_max_no_null,
1278 vec![
1279 Some("b".as_bytes()),
1280 Some(b"abcdefghijklmnopqrst"), Some(b"c"),
1282 Some(b"b01234567890123"), ],
1284 Some("abcdefghijklmnopqrst".as_bytes()),
1285 Some("c".as_bytes())
1286 );
1287
1288 test_binary!(test_binary_min_max_all_nulls, vec![None, None], None, None);
1289
1290 test_binary!(
1291 test_binary_min_max_1,
1292 vec![
1293 None,
1294 Some("b01234567890123435".as_bytes()), None,
1296 Some(b"b0123xxxxxxxxxxx"),
1297 Some(b"a")
1298 ],
1299 Some("a".as_bytes()),
1300 Some("b0123xxxxxxxxxxx".as_bytes())
1301 );
1302
1303 macro_rules! test_string {
1304 ($NAME:ident, $ARRAY:expr, $EXPECTED_MIN:expr, $EXPECTED_MAX: expr) => {
1305 #[test]
1306 fn $NAME() {
1307 let string = StringArray::from($ARRAY);
1308 assert_eq!($EXPECTED_MIN, min_string(&string));
1309 assert_eq!($EXPECTED_MAX, max_string(&string));
1310
1311 let large_string = LargeStringArray::from($ARRAY);
1312 assert_eq!($EXPECTED_MIN, min_string(&large_string));
1313 assert_eq!($EXPECTED_MAX, max_string(&large_string));
1314
1315 let string_view = StringViewArray::from($ARRAY);
1316 assert_eq!($EXPECTED_MIN, min_string_view(&string_view));
1317 assert_eq!($EXPECTED_MAX, max_string_view(&string_view));
1318 }
1319 };
1320 }
1321
1322 test_string!(
1323 test_string_min_max_with_nulls,
1324 vec![
1325 Some("b012345678901234"), None,
1327 None,
1328 Some("a"),
1329 Some("c"),
1330 Some("b0123xxxxxxxxxxx")
1331 ],
1332 Some("a"),
1333 Some("c")
1334 );
1335
1336 test_string!(
1337 test_string_min_max_no_null,
1338 vec![
1339 Some("b"),
1340 Some("b012345678901234"), Some("a"),
1342 Some("b012xxxxxxxxxxxx")
1343 ],
1344 Some("a"),
1345 Some("b012xxxxxxxxxxxx")
1346 );
1347
1348 test_string!(
1349 test_string_min_max_all_nulls,
1350 Vec::<Option<&str>>::from_iter([None, None]),
1351 None,
1352 None
1353 );
1354
1355 test_string!(
1356 test_string_min_max_1,
1357 vec![
1358 None,
1359 Some("c12345678901234"), None,
1361 Some("b"),
1362 Some("c1234xxxxxxxxxx")
1363 ],
1364 Some("b"),
1365 Some("c1234xxxxxxxxxx")
1366 );
1367
1368 test_string!(
1369 test_string_min_max_empty,
1370 Vec::<Option<&str>>::new(),
1371 None,
1372 None
1373 );
1374
1375 #[test]
1376 fn test_boolean_min_max_empty() {
1377 let a = BooleanArray::from(vec![] as Vec<Option<bool>>);
1378 assert_eq!(None, min_boolean(&a));
1379 assert_eq!(None, max_boolean(&a));
1380 }
1381
1382 #[test]
1383 fn test_boolean_min_max_all_null() {
1384 let a = BooleanArray::from(vec![None, None]);
1385 assert_eq!(None, min_boolean(&a));
1386 assert_eq!(None, max_boolean(&a));
1387 }
1388
1389 #[test]
1390 fn test_boolean_min_max_no_null() {
1391 let a = BooleanArray::from(vec![Some(true), Some(false), Some(true)]);
1392 assert_eq!(Some(false), min_boolean(&a));
1393 assert_eq!(Some(true), max_boolean(&a));
1394 }
1395
1396 #[test]
1397 fn test_boolean_min_max() {
1398 let a = BooleanArray::from(vec![Some(true), Some(true), None, Some(false), None]);
1399 assert_eq!(Some(false), min_boolean(&a));
1400 assert_eq!(Some(true), max_boolean(&a));
1401
1402 let a = BooleanArray::from(vec![None, Some(true), None, Some(false), None]);
1403 assert_eq!(Some(false), min_boolean(&a));
1404 assert_eq!(Some(true), max_boolean(&a));
1405
1406 let a = BooleanArray::from(vec![Some(false), Some(true), None, Some(false), None]);
1407 assert_eq!(Some(false), min_boolean(&a));
1408 assert_eq!(Some(true), max_boolean(&a));
1409
1410 let a = BooleanArray::from(vec![Some(true), None]);
1411 assert_eq!(Some(true), min_boolean(&a));
1412 assert_eq!(Some(true), max_boolean(&a));
1413
1414 let a = BooleanArray::from(vec![Some(false), None]);
1415 assert_eq!(Some(false), min_boolean(&a));
1416 assert_eq!(Some(false), max_boolean(&a));
1417
1418 let a = BooleanArray::from(vec![Some(true)]);
1419 assert_eq!(Some(true), min_boolean(&a));
1420 assert_eq!(Some(true), max_boolean(&a));
1421
1422 let a = BooleanArray::from(vec![Some(false)]);
1423 assert_eq!(Some(false), min_boolean(&a));
1424 assert_eq!(Some(false), max_boolean(&a));
1425 }
1426
1427 #[test]
1428 fn test_boolean_min_max_smaller() {
1429 let a = BooleanArray::from(vec![Some(false)]);
1430 assert_eq!(Some(false), min_boolean(&a));
1431 assert_eq!(Some(false), max_boolean(&a));
1432
1433 let a = BooleanArray::from(vec![None, Some(false)]);
1434 assert_eq!(Some(false), min_boolean(&a));
1435 assert_eq!(Some(false), max_boolean(&a));
1436
1437 let a = BooleanArray::from(vec![None, Some(true)]);
1438 assert_eq!(Some(true), min_boolean(&a));
1439 assert_eq!(Some(true), max_boolean(&a));
1440
1441 let a = BooleanArray::from(vec![Some(true)]);
1442 assert_eq!(Some(true), min_boolean(&a));
1443 assert_eq!(Some(true), max_boolean(&a));
1444 }
1445
1446 #[test]
1447 fn test_boolean_min_max_64_true_64_false() {
1448 let mut no_nulls = BooleanBuilder::new();
1449 no_nulls.append_slice(&[true; 64]);
1450 no_nulls.append_slice(&[false; 64]);
1451 let no_nulls = no_nulls.finish();
1452
1453 assert_eq!(Some(false), min_boolean(&no_nulls));
1454 assert_eq!(Some(true), max_boolean(&no_nulls));
1455
1456 let mut with_nulls = BooleanBuilder::new();
1457 with_nulls.append_slice(&[true; 31]);
1458 with_nulls.append_null();
1459 with_nulls.append_slice(&[true; 32]);
1460 with_nulls.append_slice(&[false; 1]);
1461 with_nulls.append_nulls(63);
1462 let with_nulls = with_nulls.finish();
1463
1464 assert_eq!(Some(false), min_boolean(&with_nulls));
1465 assert_eq!(Some(true), max_boolean(&with_nulls));
1466 }
1467
1468 #[test]
1469 fn test_boolean_min_max_64_false_64_true() {
1470 let mut no_nulls = BooleanBuilder::new();
1471 no_nulls.append_slice(&[false; 64]);
1472 no_nulls.append_slice(&[true; 64]);
1473 let no_nulls = no_nulls.finish();
1474
1475 assert_eq!(Some(false), min_boolean(&no_nulls));
1476 assert_eq!(Some(true), max_boolean(&no_nulls));
1477
1478 let mut with_nulls = BooleanBuilder::new();
1479 with_nulls.append_slice(&[false; 31]);
1480 with_nulls.append_null();
1481 with_nulls.append_slice(&[false; 32]);
1482 with_nulls.append_slice(&[true; 1]);
1483 with_nulls.append_nulls(63);
1484 let with_nulls = with_nulls.finish();
1485
1486 assert_eq!(Some(false), min_boolean(&with_nulls));
1487 assert_eq!(Some(true), max_boolean(&with_nulls));
1488 }
1489
1490 #[test]
1491 fn test_boolean_min_max_96_true() {
1492 let mut no_nulls = BooleanBuilder::new();
1493 no_nulls.append_slice(&[true; 96]);
1494 let no_nulls = no_nulls.finish();
1495
1496 assert_eq!(Some(true), min_boolean(&no_nulls));
1497 assert_eq!(Some(true), max_boolean(&no_nulls));
1498
1499 let mut with_nulls = BooleanBuilder::new();
1500 with_nulls.append_slice(&[true; 31]);
1501 with_nulls.append_null();
1502 with_nulls.append_slice(&[true; 32]);
1503 with_nulls.append_slice(&[true; 31]);
1504 with_nulls.append_null();
1505 let with_nulls = with_nulls.finish();
1506
1507 assert_eq!(Some(true), min_boolean(&with_nulls));
1508 assert_eq!(Some(true), max_boolean(&with_nulls));
1509 }
1510
1511 #[test]
1512 fn test_boolean_min_max_96_false() {
1513 let mut no_nulls = BooleanBuilder::new();
1514 no_nulls.append_slice(&[false; 96]);
1515 let no_nulls = no_nulls.finish();
1516
1517 assert_eq!(Some(false), min_boolean(&no_nulls));
1518 assert_eq!(Some(false), max_boolean(&no_nulls));
1519
1520 let mut with_nulls = BooleanBuilder::new();
1521 with_nulls.append_slice(&[false; 31]);
1522 with_nulls.append_null();
1523 with_nulls.append_slice(&[false; 32]);
1524 with_nulls.append_slice(&[false; 31]);
1525 with_nulls.append_null();
1526 let with_nulls = with_nulls.finish();
1527
1528 assert_eq!(Some(false), min_boolean(&with_nulls));
1529 assert_eq!(Some(false), max_boolean(&with_nulls));
1530 }
1531
1532 #[test]
1533 fn test_sum_dyn() {
1534 let values = Int8Array::from_iter_values([10_i8, 11, 12, 13, 14, 15, 16, 17]);
1535 let values = Arc::new(values) as ArrayRef;
1536 let keys = Int8Array::from_iter_values([2_i8, 3, 4]);
1537
1538 let dict_array = DictionaryArray::new(keys, values.clone());
1539 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1540 assert_eq!(39, sum_array::<Int8Type, _>(array).unwrap());
1541
1542 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
1543 assert_eq!(15, sum_array::<Int32Type, _>(&a).unwrap());
1544
1545 let keys = Int8Array::from(vec![Some(2_i8), None, Some(4)]);
1546 let dict_array = DictionaryArray::new(keys, values.clone());
1547 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1548 assert_eq!(26, sum_array::<Int8Type, _>(array).unwrap());
1549
1550 let keys = Int8Array::from(vec![None, None, None]);
1551 let dict_array = DictionaryArray::new(keys, values.clone());
1552 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1553 assert!(sum_array::<Int8Type, _>(array).is_none());
1554 }
1555
1556 #[test]
1557 fn test_max_min_dyn() {
1558 let values = Int8Array::from_iter_values([10_i8, 11, 12, 13, 14, 15, 16, 17]);
1559 let keys = Int8Array::from_iter_values([2_i8, 3, 4]);
1560 let values = Arc::new(values) as ArrayRef;
1561
1562 let dict_array = DictionaryArray::new(keys, values.clone());
1563 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1564 assert_eq!(14, max_array::<Int8Type, _>(array).unwrap());
1565
1566 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1567 assert_eq!(12, min_array::<Int8Type, _>(array).unwrap());
1568
1569 let a = Int32Array::from(vec![1, 2, 3, 4, 5]);
1570 assert_eq!(5, max_array::<Int32Type, _>(&a).unwrap());
1571 assert_eq!(1, min_array::<Int32Type, _>(&a).unwrap());
1572
1573 let keys = Int8Array::from(vec![Some(2_i8), None, Some(7)]);
1574 let dict_array = DictionaryArray::new(keys, values.clone());
1575 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1576 assert_eq!(17, max_array::<Int8Type, _>(array).unwrap());
1577 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1578 assert_eq!(12, min_array::<Int8Type, _>(array).unwrap());
1579
1580 let keys = Int8Array::from(vec![None, None, None]);
1581 let dict_array = DictionaryArray::new(keys, values.clone());
1582 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1583 assert!(max_array::<Int8Type, _>(array).is_none());
1584 let array = dict_array.downcast_dict::<Int8Array>().unwrap();
1585 assert!(min_array::<Int8Type, _>(array).is_none());
1586 }
1587
1588 #[test]
1589 fn test_max_min_dyn_nan() {
1590 let values = Float32Array::from(vec![5.0_f32, 2.0_f32, f32::NAN]);
1591 let keys = Int8Array::from_iter_values([0_i8, 1, 2]);
1592
1593 let dict_array = DictionaryArray::new(keys, Arc::new(values));
1594 let array = dict_array.downcast_dict::<Float32Array>().unwrap();
1595 assert!(max_array::<Float32Type, _>(array).unwrap().is_nan());
1596
1597 let array = dict_array.downcast_dict::<Float32Array>().unwrap();
1598 assert_eq!(2.0_f32, min_array::<Float32Type, _>(array).unwrap());
1599 }
1600
1601 #[test]
1602 fn test_min_max_sliced_primitive() {
1603 let expected = Some(4.0);
1604 let input: Float64Array = vec![None, Some(4.0)].into_iter().collect();
1605 let actual = min(&input);
1606 assert_eq!(actual, expected);
1607 let actual = max(&input);
1608 assert_eq!(actual, expected);
1609
1610 let sliced_input: Float64Array = vec![None, None, None, None, None, Some(4.0)]
1611 .into_iter()
1612 .collect();
1613 let sliced_input = sliced_input.slice(4, 2);
1614
1615 assert_eq!(&sliced_input, &input);
1616
1617 let actual = min(&sliced_input);
1618 assert_eq!(actual, expected);
1619 let actual = max(&sliced_input);
1620 assert_eq!(actual, expected);
1621 }
1622
1623 #[test]
1624 fn test_min_max_sliced_boolean() {
1625 let expected = Some(true);
1626 let input: BooleanArray = vec![None, Some(true)].into_iter().collect();
1627 let actual = min_boolean(&input);
1628 assert_eq!(actual, expected);
1629 let actual = max_boolean(&input);
1630 assert_eq!(actual, expected);
1631
1632 let sliced_input: BooleanArray = vec![None, None, None, None, None, Some(true)]
1633 .into_iter()
1634 .collect();
1635 let sliced_input = sliced_input.slice(4, 2);
1636
1637 assert_eq!(sliced_input, input);
1638
1639 let actual = min_boolean(&sliced_input);
1640 assert_eq!(actual, expected);
1641 let actual = max_boolean(&sliced_input);
1642 assert_eq!(actual, expected);
1643 }
1644
1645 #[test]
1646 fn test_min_max_sliced_string() {
1647 let expected = Some("foo");
1648 let input: StringArray = vec![None, Some("foo")].into_iter().collect();
1649 let actual = min_string(&input);
1650 assert_eq!(actual, expected);
1651 let actual = max_string(&input);
1652 assert_eq!(actual, expected);
1653
1654 let sliced_input: StringArray = vec![None, None, None, None, None, Some("foo")]
1655 .into_iter()
1656 .collect();
1657 let sliced_input = sliced_input.slice(4, 2);
1658
1659 assert_eq!(&sliced_input, &input);
1660
1661 let actual = min_string(&sliced_input);
1662 assert_eq!(actual, expected);
1663 let actual = max_string(&sliced_input);
1664 assert_eq!(actual, expected);
1665 }
1666
1667 #[test]
1668 fn test_min_max_sliced_binary() {
1669 let expected: Option<&[u8]> = Some(&[5]);
1670 let input: BinaryArray = vec![None, Some(&[5])].into_iter().collect();
1671 let actual = min_binary(&input);
1672 assert_eq!(actual, expected);
1673 let actual = max_binary(&input);
1674 assert_eq!(actual, expected);
1675
1676 let sliced_input: BinaryArray = vec![None, None, None, None, None, Some(&[5])]
1677 .into_iter()
1678 .collect();
1679 let sliced_input = sliced_input.slice(4, 2);
1680
1681 assert_eq!(&sliced_input, &input);
1682
1683 let actual = min_binary(&sliced_input);
1684 assert_eq!(actual, expected);
1685 let actual = max_binary(&sliced_input);
1686 assert_eq!(actual, expected);
1687 }
1688
1689 #[test]
1690 fn test_sum_overflow() {
1691 let a = Int32Array::from(vec![i32::MAX, 1]);
1692
1693 assert_eq!(sum(&a).unwrap(), -2147483648);
1694 assert_eq!(sum_array::<Int32Type, _>(&a).unwrap(), -2147483648);
1695 }
1696
1697 #[test]
1698 fn test_sum_checked_overflow() {
1699 let a = Int32Array::from(vec![i32::MAX, 1]);
1700
1701 sum_checked(&a).expect_err("overflow should be detected");
1702 sum_array_checked::<Int32Type, _>(&a).expect_err("overflow should be detected");
1703 }
1704}