vortex_compute/logical/
not.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! Logical NOT operation.
5
6use std::ops::Not;
7
8use vortex_vector::BoolDatum;
9use vortex_vector::VectorOps;
10use vortex_vector::bool::BoolScalar;
11use vortex_vector::bool::BoolVector;
12use vortex_vector::bool::BoolVectorMut;
13
14use crate::logical::LogicalNot;
15
16impl LogicalNot for &BoolScalar {
17    type Output = BoolScalar;
18
19    fn not(self) -> BoolScalar {
20        BoolScalar::new(self.value().map(|v| !v))
21    }
22}
23
24impl LogicalNot for &BoolVector {
25    type Output = BoolVector;
26
27    fn not(self) -> <Self as LogicalNot>::Output {
28        BoolVector::new(self.bits().not(), self.validity().clone())
29    }
30}
31
32impl LogicalNot for &BoolDatum {
33    type Output = BoolDatum;
34
35    fn not(self) -> BoolDatum {
36        match self {
37            BoolDatum::Scalar(sc) => BoolDatum::Scalar(sc.not()),
38            BoolDatum::Vector(vec) => BoolDatum::Vector(vec.not()),
39        }
40    }
41}
42
43impl LogicalNot for BoolVector {
44    type Output = BoolVector;
45
46    fn not(self) -> <Self as LogicalNot>::Output {
47        // Attempt to re-use the underlying buffer if possible
48        let (bits, validity) = self.into_parts();
49        let bits = match bits.try_into_mut() {
50            Ok(bits) => bits.not().freeze(),
51            Err(bits) => (&bits).not(),
52        };
53        BoolVector::new(bits, validity)
54    }
55}
56
57impl LogicalNot for BoolVectorMut {
58    type Output = BoolVectorMut;
59
60    fn not(self) -> <Self as LogicalNot>::Output {
61        let (bits, validity) = self.into_parts();
62        // SAFETY: we did not change the length of capacity.
63        unsafe { BoolVectorMut::new_unchecked(bits.not(), validity) }
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use vortex_buffer::bitbuffer;
70    use vortex_mask::Mask;
71    use vortex_vector::bool::BoolScalar;
72    use vortex_vector::bool::BoolVector;
73
74    use super::*;
75
76    #[test]
77    fn test_not_basic() {
78        let vec = BoolVector::new(bitbuffer![1 0 1 0], Mask::new_true(4));
79
80        let result = vec.not();
81        assert_eq!(result.bits(), &bitbuffer![0 1 0 1]);
82        assert_eq!(result.validity(), &Mask::new_true(4));
83    }
84
85    #[test]
86    fn test_not_owned() {
87        let vec = BoolVector::new(bitbuffer![1 1], Mask::new_true(2));
88
89        let result = vec.not();
90        assert_eq!(result.bits(), &bitbuffer![0 0]);
91    }
92
93    #[test]
94    fn test_not_scalar() {
95        let sc = BoolScalar::new(Some(true));
96        assert_eq!((&sc).not().value(), Some(false));
97
98        let sc = BoolScalar::new(Some(false));
99        assert_eq!((&sc).not().value(), Some(true));
100
101        let sc = BoolScalar::new(None);
102        assert_eq!((&sc).not().value(), None);
103    }
104
105    #[test]
106    fn test_not_datum_scalar() {
107        let datum = BoolDatum::Scalar(BoolScalar::new(Some(true)));
108        let result = datum.not();
109        let BoolDatum::Scalar(sc) = result else {
110            panic!("Expected Scalar");
111        };
112        assert_eq!(sc.value(), Some(false));
113    }
114
115    #[test]
116    fn test_not_datum_vector() {
117        let datum = BoolDatum::Vector(BoolVector::new(bitbuffer![1 0], Mask::new_true(2)));
118        let result = datum.not();
119        let BoolDatum::Vector(vec) = result else {
120            panic!("Expected Vector");
121        };
122        assert_eq!(vec.bits(), &bitbuffer![0 1]);
123    }
124}