Skip to main content

arrow_arith/
boolean.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Defines boolean kernels on Arrow `BooleanArray`'s, e.g. `AND`, `OR` and `NOT`.
19//!
20//! These kernels can leverage SIMD if available on your system.  Currently no runtime
21//! detection is provided, you should enable the specific SIMD intrinsics using
22//! `RUSTFLAGS="-C target-feature=+avx2"` for example.  See the documentation
23//! [here](https://doc.rust-lang.org/stable/core/arch/) for more information.
24
25use arrow_array::*;
26use arrow_buffer::buffer::bitwise_quaternary_op_helper;
27use arrow_buffer::{BooleanBuffer, NullBuffer, buffer_bin_and_not};
28use arrow_schema::ArrowError;
29
30/// Logical 'and' boolean values with Kleene logic
31///
32/// # Behavior
33///
34/// This function behaves as follows with nulls:
35///
36/// * `true` and `null` = `null`
37/// * `null` and `true` = `null`
38/// * `false` and `null` = `false`
39/// * `null` and `false` = `false`
40/// * `null` and `null` = `null`
41///
42/// In other words, in this context a null value really means \"unknown\",
43/// and an unknown value 'and' false is always false.
44/// For a different null behavior, see function \"and\".
45///
46/// # Example
47///
48/// ```rust
49/// # use arrow_array::BooleanArray;
50/// # use arrow_arith::boolean::and_kleene;
51/// let a = BooleanArray::from(vec![Some(true), Some(false), None]);
52/// let b = BooleanArray::from(vec![None, None, None]);
53/// let and_ab = and_kleene(&a, &b).unwrap();
54/// assert_eq!(and_ab, BooleanArray::from(vec![None, Some(false), None]));
55/// ```
56///
57/// # Fails
58///
59/// If the operands have different lengths
60pub fn and_kleene(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
61    if left.len() != right.len() {
62        return Err(ArrowError::ComputeError(
63            "Cannot perform bitwise operation on arrays of different length".to_string(),
64        ));
65    }
66
67    let left_values = left.values();
68    let right_values = right.values();
69
70    let buffer = match (left.nulls(), right.nulls()) {
71        (None, None) => None,
72        (Some(left_null_buffer), None) => {
73            // The right side has no null values.
74            // The final null bit is set only if:
75            // 1. left null bit is set, or
76            // 2. right data bit is false (because null AND false = false).
77            Some(BooleanBuffer::from_bitwise_binary_op(
78                left_null_buffer.buffer(),
79                left_null_buffer.offset(),
80                right_values.inner(),
81                right_values.offset(),
82                left.len(),
83                |a, b| a | !b,
84            ))
85        }
86        (None, Some(right_null_buffer)) => {
87            // Same as above
88            Some(BooleanBuffer::from_bitwise_binary_op(
89                right_null_buffer.buffer(),
90                right_null_buffer.offset(),
91                left_values.inner(),
92                left_values.offset(),
93                left.len(),
94                |a, b| a | !b,
95            ))
96        }
97        (Some(left_null_buffer), Some(right_null_buffer)) => {
98            // Follow the same logic above. Both sides have null values.
99            // Assume a is left null bits, b is left data bits, c is right null bits,
100            // d is right data bits.
101            // The final null bits are:
102            // (a | (c & !d)) & (c | (a & !b))
103            let buffer = bitwise_quaternary_op_helper(
104                [
105                    left_null_buffer.buffer(),
106                    left_values.inner(),
107                    right_null_buffer.buffer(),
108                    right_values.inner(),
109                ],
110                [
111                    left_null_buffer.offset(),
112                    left_values.offset(),
113                    right_null_buffer.offset(),
114                    right_values.offset(),
115                ],
116                left.len(),
117                |a, b, c, d| (a | (c & !d)) & (c | (a & !b)),
118            );
119            Some(BooleanBuffer::new(buffer, 0, left.len()))
120        }
121    };
122    let nulls = buffer.map(NullBuffer::new);
123    Ok(BooleanArray::new(left_values & right_values, nulls))
124}
125
126/// Logical 'or' boolean values with Kleene logic
127///
128/// # Behavior
129///
130/// This function behaves as follows with nulls:
131///
132/// * `true` or `null` = `true`
133/// * `null` or `true` = `true`
134/// * `false` or `null` = `null`
135/// * `null` or `false` = `null`
136/// * `null` or `null` = `null`
137///
138/// In other words, in this context a null value really means \"unknown\",
139/// and an unknown value 'or' true is always true.
140/// For a different null behavior, see function \"or\".
141///
142/// # Example
143///
144/// ```rust
145/// # use arrow_array::BooleanArray;
146/// # use arrow_arith::boolean::or_kleene;
147/// let a = BooleanArray::from(vec![Some(true), Some(false), None]);
148/// let b = BooleanArray::from(vec![None, None, None]);
149/// let or_ab = or_kleene(&a, &b).unwrap();
150/// assert_eq!(or_ab, BooleanArray::from(vec![Some(true), None, None]));
151/// ```
152///
153/// # Fails
154///
155/// If the operands have different lengths
156pub fn or_kleene(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
157    if left.len() != right.len() {
158        return Err(ArrowError::ComputeError(
159            "Cannot perform bitwise operation on arrays of different length".to_string(),
160        ));
161    }
162
163    let left_values = left.values();
164    let right_values = right.values();
165
166    let buffer = match (left.nulls(), right.nulls()) {
167        (None, None) => None,
168        (Some(left_nulls), None) => {
169            // The right side has no null values.
170            // The final null bit is set only if:
171            // 1. left null bit is set, or
172            // 2. right data bit is true (because null OR true = true).
173            Some(BooleanBuffer::from_bitwise_binary_op(
174                left_nulls.buffer(),
175                left_nulls.offset(),
176                right_values.inner(),
177                right_values.offset(),
178                left.len(),
179                |a, b| a | b,
180            ))
181        }
182        (None, Some(right_nulls)) => {
183            // Same as above
184            Some(BooleanBuffer::from_bitwise_binary_op(
185                right_nulls.buffer(),
186                right_nulls.offset(),
187                left_values.inner(),
188                left_values.offset(),
189                left.len(),
190                |a, b| a | b,
191            ))
192        }
193        (Some(left_nulls), Some(right_nulls)) => {
194            // Follow the same logic above. Both sides have null values.
195            // Assume a is left null bits, b is left data bits, c is right null bits,
196            // d is right data bits.
197            // The final null bits are:
198            // (a | (c & d)) & (c | (a & b))
199            let buffer = bitwise_quaternary_op_helper(
200                [
201                    left_nulls.buffer(),
202                    left_values.inner(),
203                    right_nulls.buffer(),
204                    right_values.inner(),
205                ],
206                [
207                    left_nulls.offset(),
208                    left_values.offset(),
209                    right_nulls.offset(),
210                    right_values.offset(),
211                ],
212                left.len(),
213                |a, b, c, d| (a | (c & d)) & (c | (a & b)),
214            );
215            Some(BooleanBuffer::new(buffer, 0, left.len()))
216        }
217    };
218
219    let nulls = buffer.map(NullBuffer::new);
220    Ok(BooleanArray::new(left_values | right_values, nulls))
221}
222
223/// Helper function to implement binary kernels
224pub(crate) fn binary_boolean_kernel<F>(
225    left: &BooleanArray,
226    right: &BooleanArray,
227    op: F,
228) -> Result<BooleanArray, ArrowError>
229where
230    F: Fn(&BooleanBuffer, &BooleanBuffer) -> BooleanBuffer,
231{
232    if left.len() != right.len() {
233        return Err(ArrowError::ComputeError(
234            "Cannot perform bitwise operation on arrays of different length".to_string(),
235        ));
236    }
237
238    let nulls = NullBuffer::union(left.nulls(), right.nulls());
239    let values = op(left.values(), right.values());
240    Ok(BooleanArray::new(values, nulls))
241}
242
243/// Performs `AND` operation on two arrays. If either left or right value is null then the
244/// result is also null.
245/// # Error
246/// This function errors when the arrays have different lengths.
247/// # Example
248/// ```rust
249/// # use arrow_array::BooleanArray;
250/// # use arrow_arith::boolean::and;
251/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
252/// let b = BooleanArray::from(vec![Some(true), Some(true), Some(false)]);
253/// let and_ab = and(&a, &b).unwrap();
254/// assert_eq!(and_ab, BooleanArray::from(vec![Some(false), Some(true), None]));
255/// ```
256pub fn and(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
257    binary_boolean_kernel(left, right, |a, b| a & b)
258}
259
260/// Performs `OR` operation on two arrays. If either left or right value is null then the
261/// result is also null.
262/// # Error
263/// This function errors when the arrays have different lengths.
264/// # Example
265/// ```rust
266/// # use arrow_array::BooleanArray;
267/// # use arrow_arith::boolean::or;
268/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
269/// let b = BooleanArray::from(vec![Some(true), Some(true), Some(false)]);
270/// let or_ab = or(&a, &b).unwrap();
271/// assert_eq!(or_ab, BooleanArray::from(vec![Some(true), Some(true), None]));
272/// ```
273pub fn or(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
274    binary_boolean_kernel(left, right, |a, b| a | b)
275}
276
277/// Performs `AND_NOT` operation on two arrays. If either left or right value is null then the
278/// result is also null.
279/// # Error
280/// This function errors when the arrays have different lengths.
281/// # Example
282/// ```rust
283/// # use arrow_array::BooleanArray;
284/// # use arrow_arith::boolean::{and, not, and_not};
285/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
286/// let b = BooleanArray::from(vec![Some(true), Some(true), Some(false)]);
287/// let andn_ab = and_not(&a, &b).unwrap();
288/// assert_eq!(andn_ab, BooleanArray::from(vec![Some(false), Some(false), None]));
289/// // It's equal to and(left, not(right))
290/// assert_eq!(andn_ab, and(&a, &not(&b).unwrap()).unwrap());
291pub fn and_not(left: &BooleanArray, right: &BooleanArray) -> Result<BooleanArray, ArrowError> {
292    binary_boolean_kernel(left, right, |a, b| {
293        let buffer = buffer_bin_and_not(a.inner(), a.offset(), b.inner(), b.offset(), a.len());
294        BooleanBuffer::new(buffer, 0, left.len())
295    })
296}
297
298/// Performs unary `NOT` operation on an arrays. If value is null then the result is also
299/// null.
300/// # Error
301/// This function never errors. It returns an error for consistency.
302/// # Example
303/// ```rust
304/// # use arrow_array::BooleanArray;
305/// # use arrow_arith::boolean::not;
306/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
307/// let not_a = not(&a).unwrap();
308/// assert_eq!(not_a, BooleanArray::from(vec![Some(true), Some(false), None]));
309/// ```
310pub fn not(left: &BooleanArray) -> Result<BooleanArray, ArrowError> {
311    let nulls = left.nulls().cloned();
312    let values = !left.values();
313    Ok(BooleanArray::new(values, nulls))
314}
315
316/// Returns a non-null [BooleanArray] with whether each value of the array is null.
317/// # Error
318/// This function never errors.
319/// # Example
320/// ```rust
321/// # use arrow_array::BooleanArray;
322/// # use arrow_arith::boolean::is_null;
323/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
324/// let a_is_null = is_null(&a).unwrap();
325/// assert_eq!(a_is_null, BooleanArray::from(vec![false, false, true]));
326/// ```
327pub fn is_null(input: &dyn Array) -> Result<BooleanArray, ArrowError> {
328    let values = match input.logical_nulls() {
329        None => BooleanBuffer::new_unset(input.len()),
330        Some(nulls) => !nulls.inner(),
331    };
332
333    Ok(BooleanArray::new(values, None))
334}
335
336/// Returns a non-null [BooleanArray] with whether each value of the array is not null.
337/// # Error
338/// This function never errors.
339/// # Example
340/// ```rust
341/// # use arrow_array::BooleanArray;
342/// # use arrow_arith::boolean::is_not_null;
343/// let a = BooleanArray::from(vec![Some(false), Some(true), None]);
344/// let a_is_not_null = is_not_null(&a).unwrap();
345/// assert_eq!(a_is_not_null, BooleanArray::from(vec![true, true, false]));
346/// ```
347pub fn is_not_null(input: &dyn Array) -> Result<BooleanArray, ArrowError> {
348    let values = match input.logical_nulls() {
349        None => BooleanBuffer::new_set(input.len()),
350        Some(n) => n.inner().clone(),
351    };
352    Ok(BooleanArray::new(values, None))
353}
354
355#[cfg(test)]
356mod tests {
357    use arrow_buffer::ScalarBuffer;
358    use arrow_schema::{DataType, Field, UnionFields};
359
360    use super::*;
361    use std::sync::Arc;
362
363    #[test]
364    fn test_bool_array_and() {
365        let a = BooleanArray::from(vec![false, false, true, true]);
366        let b = BooleanArray::from(vec![false, true, false, true]);
367        let c = and(&a, &b).unwrap();
368
369        let expected = BooleanArray::from(vec![false, false, false, true]);
370
371        assert_eq!(c, expected);
372    }
373
374    #[test]
375    fn test_bool_array_or() {
376        let a = BooleanArray::from(vec![false, false, true, true]);
377        let b = BooleanArray::from(vec![false, true, false, true]);
378        let c = or(&a, &b).unwrap();
379
380        let expected = BooleanArray::from(vec![false, true, true, true]);
381
382        assert_eq!(c, expected);
383    }
384
385    #[test]
386    fn test_bool_array_and_not() {
387        let a = BooleanArray::from(vec![false, false, true, true]);
388        let b = BooleanArray::from(vec![false, true, false, true]);
389        let c = and_not(&a, &b).unwrap();
390
391        let expected = BooleanArray::from(vec![false, false, true, false]);
392
393        assert_eq!(c, expected);
394        assert_eq!(c, and(&a, &not(&b).unwrap()).unwrap());
395    }
396
397    #[test]
398    fn test_bool_array_and_not_sliced() {
399        let a = BooleanArray::from(vec![true, false, true, false, true, false, true]);
400        let b = BooleanArray::from(vec![false, true, false, true, false, true, false]);
401        let a = a.slice(2, 3);
402        let b = b.slice(2, 3);
403        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
404        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
405
406        assert_eq!(and_not(a, b).unwrap(), and(a, &not(b).unwrap()).unwrap());
407    }
408
409    #[test]
410    fn test_bool_array_and_not_sliced_different_offsets() {
411        let a = BooleanArray::from(vec![false, true, true, false, true, false, true]);
412        let b = BooleanArray::from(vec![true, false, false, true, false, true, false]);
413        let a = a.slice(1, 4);
414        let b = b.slice(2, 4);
415        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
416        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
417
418        assert_eq!(and_not(a, b).unwrap(), and(a, &not(b).unwrap()).unwrap());
419    }
420
421    #[test]
422    fn test_bool_array_or_nulls() {
423        let a = BooleanArray::from(vec![
424            None,
425            None,
426            None,
427            Some(false),
428            Some(false),
429            Some(false),
430            Some(true),
431            Some(true),
432            Some(true),
433        ]);
434        let b = BooleanArray::from(vec![
435            None,
436            Some(false),
437            Some(true),
438            None,
439            Some(false),
440            Some(true),
441            None,
442            Some(false),
443            Some(true),
444        ]);
445        let c = or(&a, &b).unwrap();
446
447        let expected = BooleanArray::from(vec![
448            None,
449            None,
450            None,
451            None,
452            Some(false),
453            Some(true),
454            None,
455            Some(true),
456            Some(true),
457        ]);
458
459        assert_eq!(c, expected);
460    }
461
462    #[test]
463    fn test_boolean_array_kleene_no_remainder() {
464        let n = 1024;
465        let a = BooleanArray::from(vec![true; n]);
466        let b = BooleanArray::from(vec![None; n]);
467        let result = or_kleene(&a, &b).unwrap();
468
469        assert_eq!(result, a);
470    }
471
472    #[test]
473    fn test_bool_array_and_kleene_nulls() {
474        let a = BooleanArray::from(vec![
475            None,
476            None,
477            None,
478            Some(false),
479            Some(false),
480            Some(false),
481            Some(true),
482            Some(true),
483            Some(true),
484        ]);
485        let b = BooleanArray::from(vec![
486            None,
487            Some(false),
488            Some(true),
489            None,
490            Some(false),
491            Some(true),
492            None,
493            Some(false),
494            Some(true),
495        ]);
496        let c = and_kleene(&a, &b).unwrap();
497
498        let expected = BooleanArray::from(vec![
499            None,
500            Some(false),
501            None,
502            Some(false),
503            Some(false),
504            Some(false),
505            None,
506            Some(false),
507            Some(true),
508        ]);
509
510        assert_eq!(c, expected);
511    }
512
513    #[test]
514    fn test_bool_array_or_kleene_nulls() {
515        let a = BooleanArray::from(vec![
516            None,
517            None,
518            None,
519            Some(false),
520            Some(false),
521            Some(false),
522            Some(true),
523            Some(true),
524            Some(true),
525        ]);
526        let b = BooleanArray::from(vec![
527            None,
528            Some(false),
529            Some(true),
530            None,
531            Some(false),
532            Some(true),
533            None,
534            Some(false),
535            Some(true),
536        ]);
537        let c = or_kleene(&a, &b).unwrap();
538
539        let expected = BooleanArray::from(vec![
540            None,
541            None,
542            Some(true),
543            None,
544            Some(false),
545            Some(true),
546            Some(true),
547            Some(true),
548            Some(true),
549        ]);
550
551        assert_eq!(c, expected);
552    }
553
554    #[test]
555    fn test_bool_array_or_kleene_right_sided_nulls() {
556        let a = BooleanArray::from(vec![false, false, false, true, true, true]);
557
558        // ensure null bitmap of a is absent
559        assert!(a.nulls().is_none());
560
561        let b = BooleanArray::from(vec![
562            Some(true),
563            Some(false),
564            None,
565            Some(true),
566            Some(false),
567            None,
568        ]);
569
570        // ensure null bitmap of b is present
571        assert!(b.nulls().is_some());
572
573        let c = or_kleene(&a, &b).unwrap();
574
575        let expected = BooleanArray::from(vec![
576            Some(true),
577            Some(false),
578            None,
579            Some(true),
580            Some(true),
581            Some(true),
582        ]);
583
584        assert_eq!(c, expected);
585    }
586
587    #[test]
588    fn test_bool_array_or_kleene_left_sided_nulls() {
589        let a = BooleanArray::from(vec![
590            Some(true),
591            Some(false),
592            None,
593            Some(true),
594            Some(false),
595            None,
596        ]);
597
598        // ensure null bitmap of b is absent
599        assert!(a.nulls().is_some());
600
601        let b = BooleanArray::from(vec![false, false, false, true, true, true]);
602
603        // ensure null bitmap of a is present
604        assert!(b.nulls().is_none());
605
606        let c = or_kleene(&a, &b).unwrap();
607
608        let expected = BooleanArray::from(vec![
609            Some(true),
610            Some(false),
611            None,
612            Some(true),
613            Some(true),
614            Some(true),
615        ]);
616
617        assert_eq!(c, expected);
618    }
619
620    #[test]
621    fn test_bool_array_not() {
622        let a = BooleanArray::from(vec![false, true]);
623        let c = not(&a).unwrap();
624
625        let expected = BooleanArray::from(vec![true, false]);
626
627        assert_eq!(c, expected);
628    }
629
630    #[test]
631    fn test_bool_array_not_sliced() {
632        let a = BooleanArray::from(vec![None, Some(true), Some(false), None, Some(true)]);
633        let a = a.slice(1, 4);
634        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
635        let c = not(a).unwrap();
636
637        let expected = BooleanArray::from(vec![Some(false), Some(true), None, Some(false)]);
638
639        assert_eq!(c, expected);
640    }
641
642    #[test]
643    fn test_bool_array_and_nulls() {
644        let a = BooleanArray::from(vec![
645            None,
646            None,
647            None,
648            Some(false),
649            Some(false),
650            Some(false),
651            Some(true),
652            Some(true),
653            Some(true),
654        ]);
655        let b = BooleanArray::from(vec![
656            None,
657            Some(false),
658            Some(true),
659            None,
660            Some(false),
661            Some(true),
662            None,
663            Some(false),
664            Some(true),
665        ]);
666        let c = and(&a, &b).unwrap();
667
668        let expected = BooleanArray::from(vec![
669            None,
670            None,
671            None,
672            None,
673            Some(false),
674            Some(false),
675            None,
676            Some(false),
677            Some(true),
678        ]);
679
680        assert_eq!(c, expected);
681    }
682
683    #[test]
684    fn test_bool_array_and_sliced_same_offset() {
685        let a = BooleanArray::from(vec![
686            false, false, false, false, false, false, false, false, false, false, true, true,
687        ]);
688        let b = BooleanArray::from(vec![
689            false, false, false, false, false, false, false, false, false, true, false, true,
690        ]);
691
692        let a = a.slice(8, 4);
693        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
694        let b = b.slice(8, 4);
695        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
696
697        let c = and(a, b).unwrap();
698
699        let expected = BooleanArray::from(vec![false, false, false, true]);
700
701        assert_eq!(expected, c);
702    }
703
704    #[test]
705    fn test_bool_array_and_sliced_same_offset_mod8() {
706        let a = BooleanArray::from(vec![
707            false, false, true, true, false, false, false, false, false, false, false, false,
708        ]);
709        let b = BooleanArray::from(vec![
710            false, false, false, false, false, false, false, false, false, true, false, true,
711        ]);
712
713        let a = a.slice(0, 4);
714        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
715        let b = b.slice(8, 4);
716        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
717
718        let c = and(a, b).unwrap();
719
720        let expected = BooleanArray::from(vec![false, false, false, true]);
721
722        assert_eq!(expected, c);
723    }
724
725    #[test]
726    fn test_bool_array_and_sliced_offset1() {
727        let a = BooleanArray::from(vec![
728            false, false, false, false, false, false, false, false, false, false, true, true,
729        ]);
730        let b = BooleanArray::from(vec![false, true, false, true]);
731
732        let a = a.slice(8, 4);
733        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
734
735        let c = and(a, &b).unwrap();
736
737        let expected = BooleanArray::from(vec![false, false, false, true]);
738
739        assert_eq!(expected, c);
740    }
741
742    #[test]
743    fn test_bool_array_and_sliced_offset2() {
744        let a = BooleanArray::from(vec![false, false, true, true]);
745        let b = BooleanArray::from(vec![
746            false, false, false, false, false, false, false, false, false, true, false, true,
747        ]);
748
749        let b = b.slice(8, 4);
750        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
751
752        let c = and(&a, b).unwrap();
753
754        let expected = BooleanArray::from(vec![false, false, false, true]);
755
756        assert_eq!(expected, c);
757    }
758
759    #[test]
760    fn test_bool_array_and_nulls_offset() {
761        let a = BooleanArray::from(vec![None, Some(false), Some(true), None, Some(true)]);
762        let a = a.slice(1, 4);
763        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
764
765        let b = BooleanArray::from(vec![
766            None,
767            None,
768            Some(true),
769            Some(false),
770            Some(true),
771            Some(true),
772        ]);
773
774        let b = b.slice(2, 4);
775        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
776
777        let c = and(a, b).unwrap();
778
779        let expected = BooleanArray::from(vec![Some(false), Some(false), None, Some(true)]);
780
781        assert_eq!(expected, c);
782    }
783
784    #[test]
785    fn test_nonnull_array_is_null() {
786        let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
787
788        let res = is_null(a.as_ref()).unwrap();
789
790        let expected = BooleanArray::from(vec![false, false, false, false]);
791
792        assert_eq!(expected, res);
793        assert!(res.nulls().is_none());
794    }
795
796    #[test]
797    fn test_nonnull_array_with_offset_is_null() {
798        let a = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1]);
799        let a = a.slice(8, 4);
800
801        let res = is_null(&a).unwrap();
802
803        let expected = BooleanArray::from(vec![false, false, false, false]);
804
805        assert_eq!(expected, res);
806        assert!(res.nulls().is_none());
807    }
808
809    #[test]
810    fn test_nonnull_array_is_not_null() {
811        let a = Int32Array::from(vec![1, 2, 3, 4]);
812
813        let res = is_not_null(&a).unwrap();
814
815        let expected = BooleanArray::from(vec![true, true, true, true]);
816
817        assert_eq!(expected, res);
818        assert!(res.nulls().is_none());
819    }
820
821    #[test]
822    fn test_nonnull_array_with_offset_is_not_null() {
823        let a = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1]);
824        let a = a.slice(8, 4);
825
826        let res = is_not_null(&a).unwrap();
827
828        let expected = BooleanArray::from(vec![true, true, true, true]);
829
830        assert_eq!(expected, res);
831        assert!(res.nulls().is_none());
832    }
833
834    #[test]
835    fn test_nullable_array_is_null() {
836        let a = Int32Array::from(vec![Some(1), None, Some(3), None]);
837
838        let res = is_null(&a).unwrap();
839
840        let expected = BooleanArray::from(vec![false, true, false, true]);
841
842        assert_eq!(expected, res);
843        assert!(res.nulls().is_none());
844    }
845
846    #[test]
847    fn test_nullable_array_with_offset_is_null() {
848        let a = Int32Array::from(vec![
849            None,
850            None,
851            None,
852            None,
853            None,
854            None,
855            None,
856            None,
857            // offset 8, previous None values are skipped by the slice
858            Some(1),
859            None,
860            Some(2),
861            None,
862            Some(3),
863            Some(4),
864            None,
865            None,
866        ]);
867        let a = a.slice(8, 4);
868
869        let res = is_null(&a).unwrap();
870
871        let expected = BooleanArray::from(vec![false, true, false, true]);
872
873        assert_eq!(expected, res);
874        assert!(res.nulls().is_none());
875    }
876
877    #[test]
878    fn test_nullable_array_is_not_null() {
879        let a = Int32Array::from(vec![Some(1), None, Some(3), None]);
880
881        let res = is_not_null(&a).unwrap();
882
883        let expected = BooleanArray::from(vec![true, false, true, false]);
884
885        assert_eq!(expected, res);
886        assert!(res.nulls().is_none());
887    }
888
889    #[test]
890    fn test_nullable_array_with_offset_is_not_null() {
891        let a = Int32Array::from(vec![
892            None,
893            None,
894            None,
895            None,
896            None,
897            None,
898            None,
899            None,
900            // offset 8, previous None values are skipped by the slice
901            Some(1),
902            None,
903            Some(2),
904            None,
905            Some(3),
906            Some(4),
907            None,
908            None,
909        ]);
910        let a = a.slice(8, 4);
911
912        let res = is_not_null(&a).unwrap();
913
914        let expected = BooleanArray::from(vec![true, false, true, false]);
915
916        assert_eq!(expected, res);
917        assert!(res.nulls().is_none());
918    }
919
920    #[test]
921    fn test_null_array_is_null() {
922        let a = NullArray::new(3);
923
924        let res = is_null(&a).unwrap();
925
926        let expected = BooleanArray::from(vec![true, true, true]);
927
928        assert_eq!(expected, res);
929        assert!(res.nulls().is_none());
930    }
931
932    #[test]
933    fn test_null_array_is_not_null() {
934        let a = NullArray::new(3);
935
936        let res = is_not_null(&a).unwrap();
937
938        let expected = BooleanArray::from(vec![false, false, false]);
939
940        assert_eq!(expected, res);
941        assert!(res.nulls().is_none());
942    }
943
944    #[test]
945    fn test_dense_union_is_null() {
946        // union of [{A=1}, {A=}, {B=3.2}, {B=}, {C="a"}, {C=}]
947        let int_array = Int32Array::from(vec![Some(1), None]);
948        let float_array = Float64Array::from(vec![Some(3.2), None]);
949        let str_array = StringArray::from(vec![Some("a"), None]);
950        let type_ids = [0, 0, 1, 1, 2, 2].into_iter().collect::<ScalarBuffer<i8>>();
951        let offsets = [0, 1, 0, 1, 0, 1]
952            .into_iter()
953            .collect::<ScalarBuffer<i32>>();
954
955        let children = vec![
956            Arc::new(int_array) as Arc<dyn Array>,
957            Arc::new(float_array),
958            Arc::new(str_array),
959        ];
960
961        let array = UnionArray::try_new(union_fields(), type_ids, Some(offsets), children).unwrap();
962
963        let result = is_null(&array).unwrap();
964
965        let expected = &BooleanArray::from(vec![false, true, false, true, false, true]);
966        assert_eq!(expected, &result);
967    }
968
969    #[test]
970    fn test_sparse_union_is_null() {
971        // union of [{A=1}, {A=}, {B=3.2}, {B=}, {C="a"}, {C=}]
972        let int_array = Int32Array::from(vec![Some(1), None, None, None, None, None]);
973        let float_array = Float64Array::from(vec![None, None, Some(3.2), None, None, None]);
974        let str_array = StringArray::from(vec![None, None, None, None, Some("a"), None]);
975        let type_ids = [0, 0, 1, 1, 2, 2].into_iter().collect::<ScalarBuffer<i8>>();
976
977        let children = vec![
978            Arc::new(int_array) as Arc<dyn Array>,
979            Arc::new(float_array),
980            Arc::new(str_array),
981        ];
982
983        let array = UnionArray::try_new(union_fields(), type_ids, None, children).unwrap();
984
985        let result = is_null(&array).unwrap();
986
987        let expected = &BooleanArray::from(vec![false, true, false, true, false, true]);
988        assert_eq!(expected, &result);
989    }
990
991    fn union_fields() -> UnionFields {
992        [
993            (0, Arc::new(Field::new("A", DataType::Int32, true))),
994            (1, Arc::new(Field::new("B", DataType::Float64, true))),
995            (2, Arc::new(Field::new("C", DataType::Utf8, true))),
996        ]
997        .into_iter()
998        .collect()
999    }
1000}