1use crate::{AllOr, Mask};
5
6impl Mask {
7 pub fn intersect_by_rank(&self, mask: &Mask) -> Mask {
29 assert_eq!(self.true_count(), mask.len());
30
31 match (self.indices(), mask.indices()) {
32 (AllOr::All, _) => mask.clone(),
33 (_, AllOr::All) => self.clone(),
34 (AllOr::None, _) => Self::new_false(0),
35 (_, AllOr::None) => Self::new_false(self.len()),
36 (AllOr::Some(self_indices), AllOr::Some(mask_indices)) => {
37 Self::from_indices(
38 self.len(),
39 mask_indices
40 .iter()
41 .map(|idx|
42 unsafe{*self_indices.get_unchecked(*idx)})
46 .collect(),
47 )
48 }
49 }
50 }
51}
52
53#[cfg(test)]
54mod test {
55 use rstest::rstest;
56 use vortex_buffer::BitBuffer;
57
58 use crate::Mask;
59
60 #[test]
61 fn mask_bitand_all_as_bit_and() {
62 let this = Mask::from_buffer(BitBuffer::from_iter(vec![true, true, true, true, true]));
63 let mask = Mask::from_buffer(BitBuffer::from_iter(vec![false, true, false, true, true]));
64 assert_eq!(
65 this.intersect_by_rank(&mask),
66 Mask::from_indices(5, vec![1, 3, 4])
67 );
68 }
69
70 #[test]
71 fn mask_bitand_all_true() {
72 let this = Mask::from_buffer(BitBuffer::from_iter(vec![false, false, true, true, true]));
73 let mask = Mask::from_buffer(BitBuffer::from_iter(vec![true, true, true]));
74 assert_eq!(
75 this.intersect_by_rank(&mask),
76 Mask::from_indices(5, vec![2, 3, 4])
77 );
78 }
79
80 #[test]
81 fn mask_bitand_true() {
82 let this = Mask::from_buffer(BitBuffer::from_iter(vec![true, false, false, true, true]));
83 let mask = Mask::from_buffer(BitBuffer::from_iter(vec![true, false, true]));
84 assert_eq!(
85 this.intersect_by_rank(&mask),
86 Mask::from_indices(5, vec![0, 4])
87 );
88 }
89
90 #[test]
91 fn mask_bitand_false() {
92 let this = Mask::from_buffer(BitBuffer::from_iter(vec![true, false, false, true, true]));
93 let mask = Mask::from_buffer(BitBuffer::from_iter(vec![false, false, false]));
94 assert_eq!(this.intersect_by_rank(&mask), Mask::from_indices(5, vec![]));
95 }
96
97 #[rstest]
98 #[case::all_true_with_all_true(
99 Mask::new_true(5),
100 Mask::new_true(5),
101 vec![0, 1, 2, 3, 4]
102 )]
103 #[case::all_true_with_all_false(
104 Mask::new_true(5),
105 Mask::new_false(5),
106 vec![]
107 )]
108 #[case::all_false_with_any(
109 Mask::new_false(10),
110 Mask::new_true(0),
111 vec![]
112 )]
113 #[case::indices_with_all_true(
114 Mask::from_indices(10, vec![2, 5, 7, 9]),
115 Mask::new_true(4),
116 vec![2, 5, 7, 9]
117 )]
118 #[case::indices_with_all_false(
119 Mask::from_indices(10, vec![2, 5, 7, 9]),
120 Mask::new_false(4),
121 vec![]
122 )]
123 fn test_intersect_by_rank_special_cases(
124 #[case] base_mask: Mask,
125 #[case] rank_mask: Mask,
126 #[case] expected_indices: Vec<usize>,
127 ) {
128 let result = base_mask.intersect_by_rank(&rank_mask);
129
130 match result.indices() {
131 crate::AllOr::All => assert_eq!(expected_indices.len(), result.len()),
132 crate::AllOr::None => assert!(expected_indices.is_empty()),
133 crate::AllOr::Some(indices) => assert_eq!(indices, &expected_indices[..]),
134 }
135 }
136
137 #[test]
138 fn test_intersect_by_rank_example() {
139 let m1 = Mask::from_iter([true, false, false, true, true, true, false, true]);
141 let m2 = Mask::from_iter([false, false, true, false, true]);
142 let result = m1.intersect_by_rank(&m2);
143 let expected = Mask::from_iter([false, false, false, false, true, false, false, true]);
144 assert_eq!(result, expected);
145 }
146
147 #[test]
148 #[should_panic]
149 fn test_intersect_by_rank_wrong_length() {
150 let m1 = Mask::from_indices(10, vec![2, 5, 7]); let m2 = Mask::new_true(5); m1.intersect_by_rank(&m2);
153 }
154
155 #[rstest]
156 #[case::single_element(
157 vec![3],
158 vec![true],
159 vec![3]
160 )]
161 #[case::single_element_masked(
162 vec![3],
163 vec![false],
164 vec![]
165 )]
166 #[case::alternating(
167 vec![0, 2, 4, 6, 8],
168 vec![true, false, true, false, true],
169 vec![0, 4, 8]
170 )]
171 #[case::consecutive(
172 vec![5, 6, 7, 8, 9],
173 vec![false, true, true, true, false],
174 vec![6, 7, 8]
175 )]
176 fn test_intersect_by_rank_patterns(
177 #[case] base_indices: Vec<usize>,
178 #[case] rank_pattern: Vec<bool>,
179 #[case] expected_indices: Vec<usize>,
180 ) {
181 let base = Mask::from_indices(10, base_indices);
182 let rank = Mask::from_iter(rank_pattern);
183 let result = base.intersect_by_rank(&rank);
184
185 match result.indices() {
186 crate::AllOr::Some(indices) => assert_eq!(indices, &expected_indices[..]),
187 crate::AllOr::None => assert!(expected_indices.is_empty()),
188 _ => panic!("Unexpected result"),
189 }
190 }
191}