vortex_mask/
eq.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use crate::Mask;
5
6impl PartialEq for Mask {
7    #[inline]
8    fn eq(&self, other: &Self) -> bool {
9        if self.len() != other.len() {
10            return false;
11        }
12        if self.true_count() != other.true_count() {
13            return false;
14        }
15
16        // TODO(ngates): we could compare by indices if density is low enough
17        self.bit_buffer() == other.bit_buffer()
18    }
19}
20
21impl Eq for Mask {}
22
23#[cfg(test)]
24mod test {
25    use vortex_buffer::BitBuffer;
26
27    use crate::Mask;
28
29    #[test]
30    fn filter_mask_eq() {
31        assert_eq!(Mask::new_true(5), Mask::from_buffer(BitBuffer::new_set(5)));
32        assert_eq!(
33            Mask::new_false(5),
34            Mask::from_buffer(BitBuffer::new_unset(5))
35        );
36        assert_eq!(
37            Mask::from_indices(5, vec![0, 2, 3]),
38            Mask::from_slices(5, vec![(0, 1), (2, 4)])
39        );
40        assert_eq!(
41            Mask::from_indices(5, vec![0, 2, 3]),
42            Mask::from_buffer(BitBuffer::from_iter([true, false, true, true, false]))
43        );
44    }
45
46    #[test]
47    fn test_mask_eq_different_lengths() {
48        let mask1 = Mask::new_true(5);
49        let mask2 = Mask::new_true(3);
50        assert_ne!(mask1, mask2);
51    }
52
53    #[test]
54    fn test_mask_eq_different_true_counts() {
55        let mask1 = Mask::from_buffer(BitBuffer::from_iter([true, true, false]));
56        let mask2 = Mask::from_buffer(BitBuffer::from_iter([true, false, false]));
57        assert_ne!(mask1, mask2);
58    }
59
60    #[test]
61    fn test_mask_eq_same_count_different_positions() {
62        let mask1 = Mask::from_buffer(BitBuffer::from_iter([true, false, false]));
63        let mask2 = Mask::from_buffer(BitBuffer::from_iter([false, true, false]));
64        assert_ne!(mask1, mask2);
65    }
66
67    #[test]
68    fn test_mask_eq_all_variants() {
69        // Test AllTrue == AllTrue
70        let all_true1 = Mask::new_true(5);
71        let all_true2 = Mask::new_true(5);
72        assert_eq!(all_true1, all_true2);
73
74        // Test AllFalse == AllFalse
75        let all_false1 = Mask::new_false(5);
76        let all_false2 = Mask::new_false(5);
77        assert_eq!(all_false1, all_false2);
78
79        // Test AllTrue != AllFalse
80        assert_ne!(all_true1, all_false1);
81
82        // Test Values == Values
83        let values1 = Mask::from_buffer(BitBuffer::from_iter([true, false, true]));
84        let values2 = Mask::from_buffer(BitBuffer::from_iter([true, false, true]));
85        assert_eq!(values1, values2);
86
87        // Test AllTrue != Values (even if all values are true)
88        let all_true_values = Mask::from_buffer(BitBuffer::new_set(5));
89        assert_eq!(all_true1, all_true_values); // They should be equal
90
91        // Test AllFalse != Values (even if all values are false)
92        let all_false_values = Mask::from_buffer(BitBuffer::new_unset(5));
93        assert_eq!(all_false1, all_false_values); // They should be equal
94    }
95
96    #[test]
97    fn test_mask_eq_reflexive() {
98        // Test that a mask equals itself
99        let mask = Mask::from_buffer(BitBuffer::from_iter([true, false, true, false, true]));
100        assert_eq!(mask, mask);
101    }
102
103    #[test]
104    fn test_mask_eq_symmetric() {
105        // Test that if a == b then b == a
106        let mask1 = Mask::from_indices(5, vec![0, 2, 4]);
107        let mask2 = Mask::from_slices(5, vec![(0, 1), (2, 3), (4, 5)]);
108        assert_eq!(mask1, mask2);
109        assert_eq!(mask2, mask1);
110    }
111
112    #[test]
113    fn test_mask_eq_transitive() {
114        // Test that if a == b and b == c then a == c
115        let mask1 = Mask::from_indices(5, vec![1, 3]);
116        let mask2 = Mask::from_slices(5, vec![(1, 2), (3, 4)]);
117        let mask3 = Mask::from_buffer(BitBuffer::from_iter([false, true, false, true, false]));
118
119        assert_eq!(mask1, mask2);
120        assert_eq!(mask2, mask3);
121        assert_eq!(mask1, mask3);
122    }
123
124    #[test]
125    fn test_mask_eq_empty() {
126        // All empty masks become AllFalse regardless of input type
127        let empty1 = Mask::new_true(0);
128        let empty2 = Mask::new_false(0);
129        let empty3 = Mask::from_buffer(BitBuffer::new_set(0));
130        let empty4 = Mask::from_buffer(BitBuffer::new_unset(0));
131
132        // All should be AllFalse(0) when created from buffer
133        assert!(matches!(empty3, Mask::AllFalse(0)));
134        assert!(matches!(empty4, Mask::AllFalse(0)));
135
136        // new_true(0) is AllTrue(0), new_false(0) is AllFalse(0)
137        assert!(matches!(empty1, Mask::AllTrue(0)));
138        assert!(matches!(empty2, Mask::AllFalse(0)));
139    }
140
141    #[test]
142    fn test_mask_eq_different_representations() {
143        // Test that masks with the same logical values but different internal representations are equal
144        let indices = vec![0, 1, 2, 5, 6, 9];
145        let slices = vec![(0, 3), (5, 7), (9, 10)];
146        let buffer = BitBuffer::from_iter([
147            true, true, true, false, false, true, true, false, false, true,
148        ]);
149
150        let mask1 = Mask::from_indices(10, indices);
151        let mask2 = Mask::from_slices(10, slices);
152        let mask3 = Mask::from_buffer(buffer);
153
154        assert_eq!(mask1, mask2);
155        assert_eq!(mask2, mask3);
156        assert_eq!(mask1, mask3);
157    }
158}