Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Commit

Permalink
Added and_scalar and or_scalar for boolean kleene. (#723)
Browse files Browse the repository at this point in the history
  • Loading branch information
silathdiir committed Jan 2, 2022
1 parent b617331 commit ef7937d
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 3 deletions.
72 changes: 69 additions & 3 deletions src/compute/boolean_kleene.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
//! Boolean operators of [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics).
use crate::datatypes::DataType;
use crate::error::{ArrowError, Result};
use crate::scalar::BooleanScalar;
use crate::{
array::BooleanArray,
bitmap::{quaternary, ternary},
bitmap::{binary, quaternary, ternary, unary, Bitmap, MutableBitmap},
};

/// Logical 'or' with [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics)
/// Logical 'or' operation on two arrays with [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics)
/// # Errors
/// This function errors if the operands have different lengths.
/// # Example
Expand Down Expand Up @@ -96,7 +97,7 @@ pub fn or(lhs: &BooleanArray, rhs: &BooleanArray) -> Result<BooleanArray> {
))
}

/// Logical 'and' with [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics)
/// Logical 'and' operation on two arrays with [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics)
/// # Errors
/// This function errors if the operands have different lengths.
/// # Example
Expand Down Expand Up @@ -184,3 +185,68 @@ pub fn and(lhs: &BooleanArray, rhs: &BooleanArray) -> Result<BooleanArray> {
validity,
))
}

/// Logical 'or' operation on an array and a scalar value with [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics)
/// # Example
///
/// ```rust
/// use arrow2::array::BooleanArray;
/// use arrow2::scalar::BooleanScalar;
/// use arrow2::compute::boolean_kleene::or_scalar;
/// # fn main() {
/// let array = BooleanArray::from(&[Some(true), Some(false), None]);
/// let scalar = BooleanScalar::new(Some(false));
/// let result = or_scalar(&array, &scalar);
/// assert_eq!(result, BooleanArray::from(&[Some(true), Some(false), None]));
/// # }
/// ```
pub fn or_scalar(array: &BooleanArray, scalar: &BooleanScalar) -> BooleanArray {
match scalar.value() {
Some(true) => {
let mut values = MutableBitmap::new();
values.extend_constant(array.len(), true);
BooleanArray::from_data(DataType::Boolean, values.into(), None)
}
Some(false) => array.clone(),
None => {
let values = array.values();
let validity = match array.validity() {
Some(validity) => binary(values, validity, |value, validity| validity & value),
None => unary(values, |value| value),
};
BooleanArray::from_data(DataType::Boolean, values.clone(), Some(validity))
}
}
}

/// Logical 'and' operation on an array and a scalar value with [Kleene logic](https://en.wikipedia.org/wiki/Three-valued_logic#Kleene_and_Priest_logics)
/// # Example
///
/// ```rust
/// use arrow2::array::BooleanArray;
/// use arrow2::scalar::BooleanScalar;
/// use arrow2::compute::boolean_kleene::and_scalar;
/// # fn main() {
/// let array = BooleanArray::from(&[Some(true), Some(false), None]);
/// let scalar = BooleanScalar::new(None);
/// let result = and_scalar(&array, &scalar);
/// assert_eq!(result, BooleanArray::from(&[None, Some(false), None]));
/// # }
/// ```
pub fn and_scalar(array: &BooleanArray, scalar: &BooleanScalar) -> BooleanArray {
match scalar.value() {
Some(true) => array.clone(),
Some(false) => {
let values = Bitmap::new_zeroed(array.len());
BooleanArray::from_data(DataType::Boolean, values, None)
}
None => {
let values = array.values();
let validity = match array.validity() {
Some(validity) => binary(values, validity, |value, validity| validity & !value),
None => unary(values, |value| !value),
};
BooleanArray::from_data(DataType::Boolean, array.values().clone(), Some(validity))
}
}
}
85 changes: 85 additions & 0 deletions tests/it/compute/boolean_kleene.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use arrow2::array::BooleanArray;
use arrow2::compute::boolean_kleene::*;
use arrow2::scalar::BooleanScalar;

#[test]
fn and_generic() {
Expand Down Expand Up @@ -129,3 +130,87 @@ fn or_left_nulls() {

assert_eq!(c, expected);
}

#[test]
fn array_and_true() {
let array = BooleanArray::from(&[Some(true), Some(false), None, Some(true), Some(false), None]);

let scalar = BooleanScalar::new(Some(true));
let result = and_scalar(&array, &scalar);

// Should be same as argument array if scalar is true.
assert_eq!(result, array);
}

#[test]
fn array_and_false() {
let array = BooleanArray::from(&[Some(true), Some(false), None, Some(true), Some(false), None]);

let scalar = BooleanScalar::new(Some(false));
let result = and_scalar(&array, &scalar);

let expected = BooleanArray::from(&[
Some(false),
Some(false),
Some(false),
Some(false),
Some(false),
Some(false),
]);

assert_eq!(result, expected);
}

#[test]
fn array_and_none() {
let array = BooleanArray::from(&[Some(true), Some(false), None, Some(true), Some(false), None]);

let scalar = BooleanScalar::new(None);
let result = and_scalar(&array, &scalar);

let expected = BooleanArray::from(&[None, Some(false), None, None, Some(false), None]);

assert_eq!(result, expected);
}

#[test]
fn array_or_true() {
let array = BooleanArray::from(&[Some(true), Some(false), None, Some(true), Some(false), None]);

let scalar = BooleanScalar::new(Some(true));
let result = or_scalar(&array, &scalar);

let expected = BooleanArray::from(&[
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
Some(true),
]);

assert_eq!(result, expected);
}

#[test]
fn array_or_false() {
let array = BooleanArray::from(&[Some(true), Some(false), None, Some(true), Some(false), None]);

let scalar = BooleanScalar::new(Some(false));
let result = or_scalar(&array, &scalar);

// Should be same as argument array if scalar is false.
assert_eq!(result, array);
}

#[test]
fn array_or_none() {
let array = BooleanArray::from(&[Some(true), Some(false), None, Some(true), Some(false), None]);

let scalar = BooleanScalar::new(None);
let result = or_scalar(&array, &scalar);

let expected = BooleanArray::from(&[Some(true), None, None, Some(true), None, None]);

assert_eq!(result, expected);
}

0 comments on commit ef7937d

Please sign in to comment.