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(), b.offset(), b.inner(), a.offset(), a.len());
294        BooleanBuffer::new(buffer, left.offset(), 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_or_nulls() {
399        let a = BooleanArray::from(vec![
400            None,
401            None,
402            None,
403            Some(false),
404            Some(false),
405            Some(false),
406            Some(true),
407            Some(true),
408            Some(true),
409        ]);
410        let b = BooleanArray::from(vec![
411            None,
412            Some(false),
413            Some(true),
414            None,
415            Some(false),
416            Some(true),
417            None,
418            Some(false),
419            Some(true),
420        ]);
421        let c = or(&a, &b).unwrap();
422
423        let expected = BooleanArray::from(vec![
424            None,
425            None,
426            None,
427            None,
428            Some(false),
429            Some(true),
430            None,
431            Some(true),
432            Some(true),
433        ]);
434
435        assert_eq!(c, expected);
436    }
437
438    #[test]
439    fn test_boolean_array_kleene_no_remainder() {
440        let n = 1024;
441        let a = BooleanArray::from(vec![true; n]);
442        let b = BooleanArray::from(vec![None; n]);
443        let result = or_kleene(&a, &b).unwrap();
444
445        assert_eq!(result, a);
446    }
447
448    #[test]
449    fn test_bool_array_and_kleene_nulls() {
450        let a = BooleanArray::from(vec![
451            None,
452            None,
453            None,
454            Some(false),
455            Some(false),
456            Some(false),
457            Some(true),
458            Some(true),
459            Some(true),
460        ]);
461        let b = BooleanArray::from(vec![
462            None,
463            Some(false),
464            Some(true),
465            None,
466            Some(false),
467            Some(true),
468            None,
469            Some(false),
470            Some(true),
471        ]);
472        let c = and_kleene(&a, &b).unwrap();
473
474        let expected = BooleanArray::from(vec![
475            None,
476            Some(false),
477            None,
478            Some(false),
479            Some(false),
480            Some(false),
481            None,
482            Some(false),
483            Some(true),
484        ]);
485
486        assert_eq!(c, expected);
487    }
488
489    #[test]
490    fn test_bool_array_or_kleene_nulls() {
491        let a = BooleanArray::from(vec![
492            None,
493            None,
494            None,
495            Some(false),
496            Some(false),
497            Some(false),
498            Some(true),
499            Some(true),
500            Some(true),
501        ]);
502        let b = BooleanArray::from(vec![
503            None,
504            Some(false),
505            Some(true),
506            None,
507            Some(false),
508            Some(true),
509            None,
510            Some(false),
511            Some(true),
512        ]);
513        let c = or_kleene(&a, &b).unwrap();
514
515        let expected = BooleanArray::from(vec![
516            None,
517            None,
518            Some(true),
519            None,
520            Some(false),
521            Some(true),
522            Some(true),
523            Some(true),
524            Some(true),
525        ]);
526
527        assert_eq!(c, expected);
528    }
529
530    #[test]
531    fn test_bool_array_or_kleene_right_sided_nulls() {
532        let a = BooleanArray::from(vec![false, false, false, true, true, true]);
533
534        // ensure null bitmap of a is absent
535        assert!(a.nulls().is_none());
536
537        let b = BooleanArray::from(vec![
538            Some(true),
539            Some(false),
540            None,
541            Some(true),
542            Some(false),
543            None,
544        ]);
545
546        // ensure null bitmap of b is present
547        assert!(b.nulls().is_some());
548
549        let c = or_kleene(&a, &b).unwrap();
550
551        let expected = BooleanArray::from(vec![
552            Some(true),
553            Some(false),
554            None,
555            Some(true),
556            Some(true),
557            Some(true),
558        ]);
559
560        assert_eq!(c, expected);
561    }
562
563    #[test]
564    fn test_bool_array_or_kleene_left_sided_nulls() {
565        let a = BooleanArray::from(vec![
566            Some(true),
567            Some(false),
568            None,
569            Some(true),
570            Some(false),
571            None,
572        ]);
573
574        // ensure null bitmap of b is absent
575        assert!(a.nulls().is_some());
576
577        let b = BooleanArray::from(vec![false, false, false, true, true, true]);
578
579        // ensure null bitmap of a is present
580        assert!(b.nulls().is_none());
581
582        let c = or_kleene(&a, &b).unwrap();
583
584        let expected = BooleanArray::from(vec![
585            Some(true),
586            Some(false),
587            None,
588            Some(true),
589            Some(true),
590            Some(true),
591        ]);
592
593        assert_eq!(c, expected);
594    }
595
596    #[test]
597    fn test_bool_array_not() {
598        let a = BooleanArray::from(vec![false, true]);
599        let c = not(&a).unwrap();
600
601        let expected = BooleanArray::from(vec![true, false]);
602
603        assert_eq!(c, expected);
604    }
605
606    #[test]
607    fn test_bool_array_not_sliced() {
608        let a = BooleanArray::from(vec![None, Some(true), Some(false), None, Some(true)]);
609        let a = a.slice(1, 4);
610        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
611        let c = not(a).unwrap();
612
613        let expected = BooleanArray::from(vec![Some(false), Some(true), None, Some(false)]);
614
615        assert_eq!(c, expected);
616    }
617
618    #[test]
619    fn test_bool_array_and_nulls() {
620        let a = BooleanArray::from(vec![
621            None,
622            None,
623            None,
624            Some(false),
625            Some(false),
626            Some(false),
627            Some(true),
628            Some(true),
629            Some(true),
630        ]);
631        let b = BooleanArray::from(vec![
632            None,
633            Some(false),
634            Some(true),
635            None,
636            Some(false),
637            Some(true),
638            None,
639            Some(false),
640            Some(true),
641        ]);
642        let c = and(&a, &b).unwrap();
643
644        let expected = BooleanArray::from(vec![
645            None,
646            None,
647            None,
648            None,
649            Some(false),
650            Some(false),
651            None,
652            Some(false),
653            Some(true),
654        ]);
655
656        assert_eq!(c, expected);
657    }
658
659    #[test]
660    fn test_bool_array_and_sliced_same_offset() {
661        let a = BooleanArray::from(vec![
662            false, false, false, false, false, false, false, false, false, false, true, true,
663        ]);
664        let b = BooleanArray::from(vec![
665            false, false, false, false, false, false, false, false, false, true, false, true,
666        ]);
667
668        let a = a.slice(8, 4);
669        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
670        let b = b.slice(8, 4);
671        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
672
673        let c = and(a, b).unwrap();
674
675        let expected = BooleanArray::from(vec![false, false, false, true]);
676
677        assert_eq!(expected, c);
678    }
679
680    #[test]
681    fn test_bool_array_and_sliced_same_offset_mod8() {
682        let a = BooleanArray::from(vec![
683            false, false, true, true, false, false, false, false, false, false, false, false,
684        ]);
685        let b = BooleanArray::from(vec![
686            false, false, false, false, false, false, false, false, false, true, false, true,
687        ]);
688
689        let a = a.slice(0, 4);
690        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
691        let b = b.slice(8, 4);
692        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
693
694        let c = and(a, b).unwrap();
695
696        let expected = BooleanArray::from(vec![false, false, false, true]);
697
698        assert_eq!(expected, c);
699    }
700
701    #[test]
702    fn test_bool_array_and_sliced_offset1() {
703        let a = BooleanArray::from(vec![
704            false, false, false, false, false, false, false, false, false, false, true, true,
705        ]);
706        let b = BooleanArray::from(vec![false, true, false, true]);
707
708        let a = a.slice(8, 4);
709        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
710
711        let c = and(a, &b).unwrap();
712
713        let expected = BooleanArray::from(vec![false, false, false, true]);
714
715        assert_eq!(expected, c);
716    }
717
718    #[test]
719    fn test_bool_array_and_sliced_offset2() {
720        let a = BooleanArray::from(vec![false, false, true, true]);
721        let b = BooleanArray::from(vec![
722            false, false, false, false, false, false, false, false, false, true, false, true,
723        ]);
724
725        let b = b.slice(8, 4);
726        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
727
728        let c = and(&a, b).unwrap();
729
730        let expected = BooleanArray::from(vec![false, false, false, true]);
731
732        assert_eq!(expected, c);
733    }
734
735    #[test]
736    fn test_bool_array_and_nulls_offset() {
737        let a = BooleanArray::from(vec![None, Some(false), Some(true), None, Some(true)]);
738        let a = a.slice(1, 4);
739        let a = a.as_any().downcast_ref::<BooleanArray>().unwrap();
740
741        let b = BooleanArray::from(vec![
742            None,
743            None,
744            Some(true),
745            Some(false),
746            Some(true),
747            Some(true),
748        ]);
749
750        let b = b.slice(2, 4);
751        let b = b.as_any().downcast_ref::<BooleanArray>().unwrap();
752
753        let c = and(a, b).unwrap();
754
755        let expected = BooleanArray::from(vec![Some(false), Some(false), None, Some(true)]);
756
757        assert_eq!(expected, c);
758    }
759
760    #[test]
761    fn test_nonnull_array_is_null() {
762        let a: ArrayRef = Arc::new(Int32Array::from(vec![1, 2, 3, 4]));
763
764        let res = is_null(a.as_ref()).unwrap();
765
766        let expected = BooleanArray::from(vec![false, false, false, false]);
767
768        assert_eq!(expected, res);
769        assert!(res.nulls().is_none());
770    }
771
772    #[test]
773    fn test_nonnull_array_with_offset_is_null() {
774        let a = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1]);
775        let a = a.slice(8, 4);
776
777        let res = is_null(&a).unwrap();
778
779        let expected = BooleanArray::from(vec![false, false, false, false]);
780
781        assert_eq!(expected, res);
782        assert!(res.nulls().is_none());
783    }
784
785    #[test]
786    fn test_nonnull_array_is_not_null() {
787        let a = Int32Array::from(vec![1, 2, 3, 4]);
788
789        let res = is_not_null(&a).unwrap();
790
791        let expected = BooleanArray::from(vec![true, true, true, true]);
792
793        assert_eq!(expected, res);
794        assert!(res.nulls().is_none());
795    }
796
797    #[test]
798    fn test_nonnull_array_with_offset_is_not_null() {
799        let a = Int32Array::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1]);
800        let a = a.slice(8, 4);
801
802        let res = is_not_null(&a).unwrap();
803
804        let expected = BooleanArray::from(vec![true, true, true, true]);
805
806        assert_eq!(expected, res);
807        assert!(res.nulls().is_none());
808    }
809
810    #[test]
811    fn test_nullable_array_is_null() {
812        let a = Int32Array::from(vec![Some(1), None, Some(3), None]);
813
814        let res = is_null(&a).unwrap();
815
816        let expected = BooleanArray::from(vec![false, true, false, true]);
817
818        assert_eq!(expected, res);
819        assert!(res.nulls().is_none());
820    }
821
822    #[test]
823    fn test_nullable_array_with_offset_is_null() {
824        let a = Int32Array::from(vec![
825            None,
826            None,
827            None,
828            None,
829            None,
830            None,
831            None,
832            None,
833            // offset 8, previous None values are skipped by the slice
834            Some(1),
835            None,
836            Some(2),
837            None,
838            Some(3),
839            Some(4),
840            None,
841            None,
842        ]);
843        let a = a.slice(8, 4);
844
845        let res = is_null(&a).unwrap();
846
847        let expected = BooleanArray::from(vec![false, true, false, true]);
848
849        assert_eq!(expected, res);
850        assert!(res.nulls().is_none());
851    }
852
853    #[test]
854    fn test_nullable_array_is_not_null() {
855        let a = Int32Array::from(vec![Some(1), None, Some(3), None]);
856
857        let res = is_not_null(&a).unwrap();
858
859        let expected = BooleanArray::from(vec![true, false, true, false]);
860
861        assert_eq!(expected, res);
862        assert!(res.nulls().is_none());
863    }
864
865    #[test]
866    fn test_nullable_array_with_offset_is_not_null() {
867        let a = Int32Array::from(vec![
868            None,
869            None,
870            None,
871            None,
872            None,
873            None,
874            None,
875            None,
876            // offset 8, previous None values are skipped by the slice
877            Some(1),
878            None,
879            Some(2),
880            None,
881            Some(3),
882            Some(4),
883            None,
884            None,
885        ]);
886        let a = a.slice(8, 4);
887
888        let res = is_not_null(&a).unwrap();
889
890        let expected = BooleanArray::from(vec![true, false, true, false]);
891
892        assert_eq!(expected, res);
893        assert!(res.nulls().is_none());
894    }
895
896    #[test]
897    fn test_null_array_is_null() {
898        let a = NullArray::new(3);
899
900        let res = is_null(&a).unwrap();
901
902        let expected = BooleanArray::from(vec![true, true, true]);
903
904        assert_eq!(expected, res);
905        assert!(res.nulls().is_none());
906    }
907
908    #[test]
909    fn test_null_array_is_not_null() {
910        let a = NullArray::new(3);
911
912        let res = is_not_null(&a).unwrap();
913
914        let expected = BooleanArray::from(vec![false, false, false]);
915
916        assert_eq!(expected, res);
917        assert!(res.nulls().is_none());
918    }
919
920    #[test]
921    fn test_dense_union_is_null() {
922        // union of [{A=1}, {A=}, {B=3.2}, {B=}, {C="a"}, {C=}]
923        let int_array = Int32Array::from(vec![Some(1), None]);
924        let float_array = Float64Array::from(vec![Some(3.2), None]);
925        let str_array = StringArray::from(vec![Some("a"), None]);
926        let type_ids = [0, 0, 1, 1, 2, 2].into_iter().collect::<ScalarBuffer<i8>>();
927        let offsets = [0, 1, 0, 1, 0, 1]
928            .into_iter()
929            .collect::<ScalarBuffer<i32>>();
930
931        let children = vec![
932            Arc::new(int_array) as Arc<dyn Array>,
933            Arc::new(float_array),
934            Arc::new(str_array),
935        ];
936
937        let array = UnionArray::try_new(union_fields(), type_ids, Some(offsets), children).unwrap();
938
939        let result = is_null(&array).unwrap();
940
941        let expected = &BooleanArray::from(vec![false, true, false, true, false, true]);
942        assert_eq!(expected, &result);
943    }
944
945    #[test]
946    fn test_sparse_union_is_null() {
947        // union of [{A=1}, {A=}, {B=3.2}, {B=}, {C="a"}, {C=}]
948        let int_array = Int32Array::from(vec![Some(1), None, None, None, None, None]);
949        let float_array = Float64Array::from(vec![None, None, Some(3.2), None, None, None]);
950        let str_array = StringArray::from(vec![None, None, None, None, Some("a"), None]);
951        let type_ids = [0, 0, 1, 1, 2, 2].into_iter().collect::<ScalarBuffer<i8>>();
952
953        let children = vec![
954            Arc::new(int_array) as Arc<dyn Array>,
955            Arc::new(float_array),
956            Arc::new(str_array),
957        ];
958
959        let array = UnionArray::try_new(union_fields(), type_ids, None, children).unwrap();
960
961        let result = is_null(&array).unwrap();
962
963        let expected = &BooleanArray::from(vec![false, true, false, true, false, true]);
964        assert_eq!(expected, &result);
965    }
966
967    fn union_fields() -> UnionFields {
968        [
969            (0, Arc::new(Field::new("A", DataType::Int32, true))),
970            (1, Arc::new(Field::new("B", DataType::Float64, true))),
971            (2, Arc::new(Field::new("C", DataType::Utf8, true))),
972        ]
973        .into_iter()
974        .collect()
975    }
976}