use std::ops::{BitAnd, BitOr, Not};
use vortex_error::vortex_panic;
use crate::{AllOr, Mask};
impl BitAnd for &Mask {
type Output = Mask;
fn bitand(self, rhs: Self) -> Self::Output {
if self.len() != rhs.len() {
vortex_panic!("Masks must have the same length");
}
match (self.boolean_buffer(), rhs.boolean_buffer()) {
(AllOr::All, _) => rhs.clone(),
(_, AllOr::All) => self.clone(),
(AllOr::None, _) => Mask::new_false(self.len()),
(_, AllOr::None) => Mask::new_false(self.len()),
(AllOr::Some(lhs), AllOr::Some(rhs)) => Mask::from_buffer(lhs & rhs),
}
}
}
impl BitOr for &Mask {
type Output = Mask;
fn bitor(self, rhs: Self) -> Self::Output {
if self.len() != rhs.len() {
vortex_panic!("Masks must have the same length");
}
match (self.boolean_buffer(), rhs.boolean_buffer()) {
(AllOr::All, _) => Mask::new_true(self.len()),
(_, AllOr::All) => Mask::new_true(self.len()),
(AllOr::None, _) => rhs.clone(),
(_, AllOr::None) => self.clone(),
(AllOr::Some(lhs), AllOr::Some(rhs)) => Mask::from_buffer(lhs | rhs),
}
}
}
impl Not for Mask {
type Output = Mask;
fn not(self) -> Self::Output {
!(&self)
}
}
impl Not for &Mask {
type Output = Mask;
fn not(self) -> Self::Output {
match self.boolean_buffer() {
AllOr::All => Mask::new_false(self.len()),
AllOr::None => Mask::new_true(self.len()),
AllOr::Some(buffer) => Mask::from_buffer(!buffer),
}
}
}
#[cfg(test)]
#[allow(clippy::many_single_char_names)]
mod tests {
use arrow_buffer::BooleanBuffer;
use super::*;
#[test]
fn test_bitand_all_combinations() {
let len = 5;
let all_true = Mask::new_true(len);
let result = &all_true & &all_true;
assert!(result.all_true());
assert_eq!(result.true_count(), len);
let all_false = Mask::new_false(len);
let result = &all_true & &all_false;
assert!(result.all_false());
assert_eq!(result.true_count(), 0);
let result = &all_false & &all_true;
assert!(result.all_false());
assert_eq!(result.true_count(), 0);
let result = &all_false & &all_false;
assert!(result.all_false());
assert_eq!(result.true_count(), 0);
}
#[test]
fn test_bitand_with_values() {
let mask1 = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let mask2 = Mask::from_buffer(BooleanBuffer::from_iter([true, true, false, false, true]));
let result = &mask1 & &mask2;
assert_eq!(result.len(), 5);
assert_eq!(result.true_count(), 2);
assert!(result.value(0)); assert!(!result.value(1)); assert!(!result.value(2)); assert!(!result.value(3)); assert!(result.value(4)); }
#[test]
fn test_bitand_all_true_with_values() {
let all_true = Mask::new_true(5);
let values = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let result = &all_true & &values;
assert_eq!(result.true_count(), 3);
assert_eq!(result.len(), 5);
assert!(result.value(0));
assert!(!result.value(1));
assert!(result.value(2));
assert!(!result.value(3));
assert!(result.value(4));
}
#[test]
fn test_bitand_all_false_with_values() {
let all_false = Mask::new_false(5);
let values = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let result = &all_false & &values;
assert!(result.all_false());
assert_eq!(result.true_count(), 0);
}
#[test]
fn test_bitand_values_with_all_true() {
let values = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let all_true = Mask::new_true(5);
let result = &values & &all_true;
assert_eq!(result.true_count(), 3);
assert_eq!(result.len(), 5);
assert!(result.value(0));
assert!(!result.value(1));
assert!(result.value(2));
assert!(!result.value(3));
assert!(result.value(4));
}
#[test]
fn test_bitand_values_with_all_false() {
let values = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let all_false = Mask::new_false(5);
let result = &values & &all_false;
assert!(result.all_false());
assert_eq!(result.true_count(), 0);
}
#[test]
fn test_bitand_empty_masks() {
let empty1 = Mask::new_true(0);
let empty2 = Mask::new_false(0);
let result = &empty1 & &empty2;
assert_eq!(result.len(), 0);
assert!(result.is_empty());
}
#[test]
#[should_panic(expected = "Masks must have the same length")]
fn test_bitand_different_lengths() {
let mask1 = Mask::new_true(5);
let mask2 = Mask::new_true(3);
let _ = &mask1 & &mask2;
}
#[test]
fn test_not_all_true() {
let all_true = Mask::new_true(5);
let result = !all_true;
assert!(result.all_false());
assert_eq!(result.true_count(), 0);
assert_eq!(result.len(), 5);
}
#[test]
fn test_not_all_false() {
let all_false = Mask::new_false(5);
let result = !all_false;
assert!(result.all_true());
assert_eq!(result.true_count(), 5);
assert_eq!(result.len(), 5);
}
#[test]
fn test_not_values() {
let values = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let result = !values;
assert_eq!(result.len(), 5);
assert_eq!(result.true_count(), 2);
assert!(!result.value(0)); assert!(result.value(1)); assert!(!result.value(2)); assert!(result.value(3)); assert!(!result.value(4)); }
#[test]
fn test_not_empty() {
let empty_true = Mask::new_true(0);
let result = !empty_true;
assert_eq!(result.len(), 0);
assert!(result.is_empty());
let empty_false = Mask::new_false(0);
let result = !empty_false;
assert_eq!(result.len(), 0);
assert!(result.is_empty());
}
#[test]
fn test_double_not() {
let original =
Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let double_not = !(!original.clone());
assert_eq!(double_not.true_count(), original.true_count());
for i in 0..5 {
assert_eq!(double_not.value(i), original.value(i));
}
}
#[test]
fn test_demorgan_law() {
let a = Mask::from_buffer(BooleanBuffer::from_iter([true, true, false, false]));
let b = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false]));
let and_result = &a & &b;
let not_and = !and_result;
let not_a = !a;
let not_b = !b;
let or_result = ¬_a | ¬_b;
assert_eq!(not_and.len(), 4);
assert!(!not_and.value(0)); assert!(not_and.value(1)); assert!(not_and.value(2)); assert!(not_and.value(3));
assert_eq!(or_result.len(), 4);
assert_eq!(or_result, not_and)
}
#[test]
fn test_bitand_associativity() {
let a = Mask::from_buffer(BooleanBuffer::from_iter([true, true, false, true]));
let b = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, true]));
let c = Mask::from_buffer(BooleanBuffer::from_iter([false, true, true, true]));
let left_assoc = &(&a & &b) & &c;
let right_assoc = &a & &(&b & &c);
assert_eq!(left_assoc.true_count(), right_assoc.true_count());
for i in 0..4 {
assert_eq!(left_assoc.value(i), right_assoc.value(i));
}
}
#[test]
fn test_bitand_commutativity() {
let a = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false]));
let b = Mask::from_buffer(BooleanBuffer::from_iter([false, true, false, true]));
let a_b = &a & &b;
let b_a = &b & &a;
assert_eq!(a_b.true_count(), b_a.true_count());
for i in 0..4 {
assert_eq!(a_b.value(i), b_a.value(i));
}
}
#[test]
fn test_bitand_identity() {
let mask = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false]));
let all_true = Mask::new_true(4);
let result = &mask & &all_true;
assert_eq!(result.true_count(), mask.true_count());
for i in 0..4 {
assert_eq!(result.value(i), mask.value(i));
}
}
#[test]
fn test_bitand_annihilator() {
let mask = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false]));
let all_false = Mask::new_false(4);
let result = &mask & &all_false;
assert!(result.all_false());
assert_eq!(result.true_count(), 0);
}
#[test]
fn test_bitand_idempotence() {
let mask = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let result = &mask & &mask;
assert_eq!(result.true_count(), mask.true_count());
for i in 0..5 {
assert_eq!(result.value(i), mask.value(i));
}
}
#[test]
fn test_complex_expression() {
let a = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false]));
let b = Mask::from_buffer(BooleanBuffer::from_iter([true, true, false, false]));
let c = Mask::from_buffer(BooleanBuffer::from_iter([false, true, false, true]));
let not_not_a = !(&(!&a));
let not_not_a_or_b = ¬_not_a | &b;
let not_c = !&c;
let result = ¬_not_a_or_b & ¬_c;
assert!(result.value(0)); assert!(!result.value(1)); assert!(result.value(2)); assert!(!result.value(3)); }
#[test]
fn test_bitor() {
let mask1 = Mask::from_buffer(BooleanBuffer::from_iter([true, false, true, false, true]));
let mask2 = Mask::from_buffer(BooleanBuffer::from_iter([true, true, false, false, true]));
let result = &mask1 | &mask2;
assert_eq!(result.len(), 5);
assert_eq!(result.true_count(), 4);
assert!(result.value(0)); assert!(result.value(1)); assert!(result.value(2)); assert!(!result.value(3)); assert!(result.value(4));
let all_true = Mask::new_true(5);
let result = &mask1 | &all_true;
assert!(result.all_true());
let all_false = Mask::new_false(5);
let result = &mask1 | &all_false;
assert_eq!(result.true_count(), mask1.true_count());
}
}