1use super::{MaskRunIter, RowSelection, RowSelectionInner, RowSelector};
26use arrow_buffer::{BooleanBuffer, BooleanBufferBuilder, MutableBuffer, bit_util};
27use std::cmp::Ordering;
28use std::iter::Peekable;
29
30pub(super) fn and_then_row_selections(
32 first: &[RowSelector],
33 second: &[RowSelector],
34) -> RowSelection {
35 let mut selectors = vec![];
36 let mut first = first.iter().copied().peekable();
37 let mut second = second.iter().copied().peekable();
38 and_then_iter(&mut selectors, &mut first, &mut second);
39 RowSelection::from_selectors(selectors)
40}
41
42pub(super) fn and_then_selectors_with_mask(
46 first: &[RowSelector],
47 second: &BooleanBuffer,
48) -> RowSelection {
49 let mut selectors = vec![];
50 let mut first = first.iter().copied().peekable();
51 let mut second = MaskRunIter::new(second).peekable();
52 and_then_iter(&mut selectors, &mut first, &mut second);
53 RowSelection::from_selectors(selectors)
54}
55
56fn and_then_iter<I, J>(
57 selectors: &mut Vec<RowSelector>,
58 first: &mut Peekable<I>,
59 second: &mut Peekable<J>,
60) where
61 I: Iterator<Item = RowSelector>,
62 J: Iterator<Item = RowSelector>,
63{
64 let mut to_skip = 0;
65 while let Some(b) = second.peek_mut() {
66 let a = first
67 .peek_mut()
68 .expect("selection exceeds the number of selected rows");
69
70 if b.row_count == 0 {
71 second.next().unwrap();
72 continue;
73 }
74
75 if a.row_count == 0 {
76 first.next().unwrap();
77 continue;
78 }
79
80 if a.skip {
81 to_skip += a.row_count;
83 first.next().unwrap();
84 continue;
85 }
86
87 let skip = b.skip;
88 let to_process = a.row_count.min(b.row_count);
89
90 a.row_count -= to_process;
91 b.row_count -= to_process;
92
93 match skip {
94 true => to_skip += to_process,
95 false => {
96 if to_skip != 0 {
97 selectors.push(RowSelector::skip(to_skip));
98 to_skip = 0;
99 }
100 selectors.push(RowSelector::select(to_process))
101 }
102 }
103 }
104
105 for v in first {
106 if v.row_count != 0 {
107 assert!(
108 v.skip,
109 "selection contains less than the number of selected rows"
110 );
111 to_skip += v.row_count
112 }
113 }
114
115 if to_skip != 0 {
116 selectors.push(RowSelector::skip(to_skip));
117 }
118}
119
120pub(super) fn intersect_row_selections(
127 left: &[RowSelector],
128 right: &[RowSelector],
129) -> RowSelection {
130 let mut l_iter = left.iter().copied().peekable();
131 let mut r_iter = right.iter().copied().peekable();
132
133 let iter = std::iter::from_fn(move || {
134 loop {
135 let l = l_iter.peek_mut();
136 let r = r_iter.peek_mut();
137
138 match (l, r) {
139 (Some(a), _) if a.row_count == 0 => {
140 l_iter.next().unwrap();
141 }
142 (_, Some(b)) if b.row_count == 0 => {
143 r_iter.next().unwrap();
144 }
145 (Some(l), Some(r)) => {
146 return match (l.skip, r.skip) {
147 (false, false) => {
149 if l.row_count < r.row_count {
150 r.row_count -= l.row_count;
151 l_iter.next()
152 } else {
153 l.row_count -= r.row_count;
154 r_iter.next()
155 }
156 }
157 _ => {
159 if l.row_count < r.row_count {
160 let skip = l.row_count;
161 r.row_count -= l.row_count;
162 l_iter.next();
163 Some(RowSelector::skip(skip))
164 } else {
165 let skip = r.row_count;
166 l.row_count -= skip;
167 r_iter.next();
168 Some(RowSelector::skip(skip))
169 }
170 }
171 };
172 }
173 (Some(_), None) => return l_iter.next(),
174 (None, Some(_)) => return r_iter.next(),
175 (None, None) => return None,
176 }
177 }
178 });
179
180 iter.collect()
181}
182
183pub(super) fn union_row_selections(left: &[RowSelector], right: &[RowSelector]) -> RowSelection {
192 let mut l_iter = left.iter().copied().peekable();
193 let mut r_iter = right.iter().copied().peekable();
194
195 let iter = std::iter::from_fn(move || {
196 loop {
197 let l = l_iter.peek_mut();
198 let r = r_iter.peek_mut();
199
200 match (l, r) {
201 (Some(a), _) if a.row_count == 0 => {
202 l_iter.next().unwrap();
203 }
204 (_, Some(b)) if b.row_count == 0 => {
205 r_iter.next().unwrap();
206 }
207 (Some(l), Some(r)) => {
208 return match (l.skip, r.skip) {
209 (true, true) => {
211 if l.row_count < r.row_count {
212 let skip = l.row_count;
213 r.row_count -= l.row_count;
214 l_iter.next();
215 Some(RowSelector::skip(skip))
216 } else {
217 let skip = r.row_count;
218 l.row_count -= skip;
219 r_iter.next();
220 Some(RowSelector::skip(skip))
221 }
222 }
223 (false, true) => {
225 if l.row_count < r.row_count {
226 r.row_count -= l.row_count;
227 l_iter.next()
228 } else {
229 let r_row_count = r.row_count;
230 l.row_count -= r_row_count;
231 r_iter.next();
232 Some(RowSelector::select(r_row_count))
233 }
234 }
235 (true, false) => {
237 if l.row_count < r.row_count {
238 let l_row_count = l.row_count;
239 r.row_count -= l_row_count;
240 l_iter.next();
241 Some(RowSelector::select(l_row_count))
242 } else {
243 l.row_count -= r.row_count;
244 r_iter.next()
245 }
246 }
247 _ => {
249 if l.row_count < r.row_count {
250 r.row_count -= l.row_count;
251 l_iter.next()
252 } else {
253 l.row_count -= r.row_count;
254 r_iter.next()
255 }
256 }
257 };
258 }
259 (Some(_), None) => return l_iter.next(),
260 (None, Some(_)) => return r_iter.next(),
261 (None, None) => return None,
262 }
263 }
264 });
265
266 iter.collect()
267}
268
269pub(super) fn intersect_masks(l: &BooleanBuffer, r: &BooleanBuffer) -> BooleanBuffer {
271 if l.len() == r.len() {
272 return combine_equal_length_masks(l, r, |a, b| a & b);
273 }
274 combine_unequal_length_masks(l, r, |a, b| a & b)
275}
276
277pub(super) fn union_masks(l: &BooleanBuffer, r: &BooleanBuffer) -> BooleanBuffer {
279 if l.len() == r.len() {
280 return combine_equal_length_masks(l, r, |a, b| a | b);
281 }
282 combine_unequal_length_masks(l, r, |a, b| a | b)
283}
284
285fn combine_equal_length_masks<F>(l: &BooleanBuffer, r: &BooleanBuffer, op: F) -> BooleanBuffer
293where
294 F: FnMut(u64, u64) -> u64,
295{
296 BooleanBuffer::from_bitwise_binary_op(
297 l.values(),
298 l.offset(),
299 r.values(),
300 r.offset(),
301 l.len(),
302 op,
303 )
304}
305
306fn combine_unequal_length_masks<F>(l: &BooleanBuffer, r: &BooleanBuffer, op: F) -> BooleanBuffer
320where
321 F: FnMut(u64, u64) -> u64,
322{
323 let (longer, shorter) = if l.len() > r.len() { (l, r) } else { (r, l) };
324
325 let sub_byte_offset = longer.offset() % 8;
326 let start_byte = longer.offset() / 8;
327 let end_byte = bit_util::ceil(longer.offset() + longer.len(), 8);
328 let bytes = &longer.values()[start_byte..end_byte];
329 let mut buffer = MutableBuffer::new(bytes.len());
330 buffer.extend_from_slice(bytes);
331
332 bit_util::apply_bitwise_binary_op(
333 buffer.as_slice_mut(),
334 sub_byte_offset,
335 shorter.values(),
336 shorter.offset(),
337 shorter.len(),
338 op,
339 );
340
341 BooleanBuffer::new(buffer.into(), sub_byte_offset, longer.len())
342}
343
344pub(super) fn and_then_mask(mask: &BooleanBuffer, other: &RowSelection) -> BooleanBuffer {
346 match &other.inner {
347 RowSelectionInner::Mask(other_mask) => and_then_masks(mask, other_mask.mask()),
348 RowSelectionInner::Selectors(selectors) => {
349 and_then_mask_from_selectors(mask, selectors.iter().copied())
350 }
351 }
352}
353
354fn and_then_mask_from_selectors<I>(mask: &BooleanBuffer, other: I) -> BooleanBuffer
355where
356 I: IntoIterator<Item = RowSelector>,
357{
358 let mut builder = BooleanBufferBuilder::new(mask.len());
359 let mut other_iter = other.into_iter();
360 let mut current = other_iter.next();
361 let mut cursor = 0usize;
362
363 for set_idx in mask.set_indices() {
366 if set_idx > cursor {
367 builder.append_n(set_idx - cursor, false);
368 }
369 cursor = set_idx + 1;
370
371 while current.as_ref().is_some_and(|s| s.row_count == 0) {
372 current = other_iter.next();
373 }
374 let selector = current
375 .as_mut()
376 .expect("selection contains less than the number of selected rows");
377 let selected = !selector.skip;
378 selector.row_count -= 1;
379 builder.append(selected);
380 }
381 if cursor < mask.len() {
382 builder.append_n(mask.len() - cursor, false);
383 }
384
385 if current.is_some_and(|s| s.row_count != 0) || other_iter.any(|s| s.row_count != 0) {
386 panic!("selection exceeds the number of selected rows");
387 }
388
389 builder.finish()
390}
391
392fn and_then_masks(mask: &BooleanBuffer, other: &BooleanBuffer) -> BooleanBuffer {
393 let selected_count = mask.count_set_bits();
394 match other.len().cmp(&selected_count) {
395 Ordering::Less => panic!("selection contains less than the number of selected rows"),
396 Ordering::Greater => panic!("selection exceeds the number of selected rows"),
397 Ordering::Equal => {}
398 }
399
400 let other_true_count = other.count_set_bits();
401 if other_true_count == 0 {
402 return BooleanBuffer::new_unset(mask.len());
403 }
404 if other_true_count == selected_count {
405 return mask.clone();
406 }
407
408 let mut builder = BooleanBufferBuilder::new(mask.len());
409 let mut outer_set_indices = mask.set_indices();
410 let mut next_selected_ordinal = 0usize;
411 let mut cursor = 0usize;
412
413 for selected_ordinal in other.set_indices() {
414 let skip = selected_ordinal - next_selected_ordinal;
415 let set_idx = outer_set_indices
416 .nth(skip)
417 .expect("validated other length matches selected row count");
418 if set_idx > cursor {
419 builder.append_n(set_idx - cursor, false);
420 }
421 builder.append(true);
422 cursor = set_idx + 1;
423 next_selected_ordinal = selected_ordinal + 1;
424 }
425
426 if cursor < mask.len() {
427 builder.append_n(mask.len() - cursor, false);
428 }
429
430 builder.finish()
431}
432
433#[cfg(test)]
434mod tests {
435 use super::*;
436 use arrow_array::BooleanArray;
437 use rand::{RngExt, rng};
438
439 #[test]
440 fn test_and() {
441 let mut a = RowSelection::from(vec![
442 RowSelector::skip(12),
443 RowSelector::select(23),
444 RowSelector::skip(3),
445 RowSelector::select(5),
446 ]);
447
448 let b = RowSelection::from(vec![
449 RowSelector::select(5),
450 RowSelector::skip(4),
451 RowSelector::select(15),
452 RowSelector::skip(4),
453 ]);
454
455 let mut expected = RowSelection::from(vec![
456 RowSelector::skip(12),
457 RowSelector::select(5),
458 RowSelector::skip(4),
459 RowSelector::select(14),
460 RowSelector::skip(3),
461 RowSelector::select(1),
462 RowSelector::skip(4),
463 ]);
464
465 assert_eq!(a.and_then(&b), expected);
466
467 a.split_off(7);
468 expected.split_off(7);
469 assert_eq!(a.and_then(&b), expected);
470
471 let a = RowSelection::from(vec![RowSelector::select(5), RowSelector::skip(3)]);
472
473 let b = RowSelection::from(vec![
474 RowSelector::select(2),
475 RowSelector::skip(1),
476 RowSelector::select(1),
477 RowSelector::skip(1),
478 ]);
479
480 assert_eq!(
481 a.and_then(&b).selectors(),
482 vec![
483 RowSelector::select(2),
484 RowSelector::skip(1),
485 RowSelector::select(1),
486 RowSelector::skip(4)
487 ]
488 );
489 }
490
491 #[test]
492 #[should_panic(expected = "selection exceeds the number of selected rows")]
493 fn test_and_longer() {
494 let a = RowSelection::from(vec![
495 RowSelector::select(3),
496 RowSelector::skip(33),
497 RowSelector::select(3),
498 RowSelector::skip(33),
499 ]);
500 let b = RowSelection::from(vec![RowSelector::select(36)]);
501 a.and_then(&b);
502 }
503
504 #[test]
505 #[should_panic(expected = "selection contains less than the number of selected rows")]
506 fn test_and_shorter() {
507 let a = RowSelection::from(vec![
508 RowSelector::select(3),
509 RowSelector::skip(33),
510 RowSelector::select(3),
511 RowSelector::skip(33),
512 ]);
513 let b = RowSelection::from(vec![RowSelector::select(3)]);
514 a.and_then(&b);
515 }
516
517 #[test]
518 fn test_intersect_row_selection_and_combine() {
519 let a = vec![
521 RowSelector::select(5),
522 RowSelector::skip(4),
523 RowSelector::select(1),
524 ];
525 let b = vec![
526 RowSelector::select(8),
527 RowSelector::skip(1),
528 RowSelector::select(1),
529 ];
530
531 let res = intersect_row_selections(&a, &b);
532 assert_eq!(
533 res.selectors(),
534 vec![
535 RowSelector::select(5),
536 RowSelector::skip(4),
537 RowSelector::select(1),
538 ],
539 );
540
541 let a = vec![
543 RowSelector::select(3),
544 RowSelector::skip(33),
545 RowSelector::select(3),
546 RowSelector::skip(33),
547 ];
548 let b = vec![RowSelector::select(36), RowSelector::skip(36)];
549 let res = intersect_row_selections(&a, &b);
550 assert_eq!(
551 res.selectors(),
552 vec![RowSelector::select(3), RowSelector::skip(69)]
553 );
554
555 let a = vec![RowSelector::select(3), RowSelector::skip(7)];
557 let b = vec![
558 RowSelector::select(2),
559 RowSelector::skip(2),
560 RowSelector::select(2),
561 RowSelector::skip(2),
562 RowSelector::select(2),
563 ];
564 let res = intersect_row_selections(&a, &b);
565 assert_eq!(
566 res.selectors(),
567 vec![RowSelector::select(2), RowSelector::skip(8)]
568 );
569
570 let a = vec![RowSelector::select(3), RowSelector::skip(7)];
571 let b = vec![
572 RowSelector::select(2),
573 RowSelector::skip(2),
574 RowSelector::select(2),
575 RowSelector::skip(2),
576 RowSelector::select(2),
577 ];
578 let res = intersect_row_selections(&a, &b);
579 assert_eq!(
580 res.selectors(),
581 vec![RowSelector::select(2), RowSelector::skip(8)]
582 );
583 }
584
585 #[test]
586 fn test_and_fuzz() {
587 let mut rand = rng();
588 for _ in 0..100 {
589 let a_len = rand.random_range(10..100);
590 let a_bools: Vec<_> = (0..a_len).map(|_| rand.random_bool(0.2)).collect();
591 let a = RowSelection::from_filters(&[BooleanArray::from(a_bools.clone())]);
592
593 let b_len: usize = a_bools.iter().map(|x| *x as usize).sum();
594 let b_bools: Vec<_> = (0..b_len).map(|_| rand.random_bool(0.8)).collect();
595 let b = RowSelection::from_filters(&[BooleanArray::from(b_bools.clone())]);
596
597 let mut expected_bools = vec![false; a_len];
598
599 let mut iter_b = b_bools.iter();
600 for (idx, b) in a_bools.iter().enumerate() {
601 if *b && *iter_b.next().unwrap() {
602 expected_bools[idx] = true;
603 }
604 }
605
606 let expected = RowSelection::from_filters(&[BooleanArray::from(expected_bools)]);
607
608 let total_rows: usize = expected.selectors().iter().map(|s| s.row_count).sum();
609 assert_eq!(a_len, total_rows);
610
611 assert_eq!(a.and_then(&b), expected);
612 }
613 }
614
615 #[test]
616 fn test_intersection() {
617 let selection = RowSelection::from(vec![RowSelector::select(1048576)]);
618 let result = selection.intersection(&selection);
619 assert_eq!(result, selection);
620
621 let a = RowSelection::from(vec![
622 RowSelector::skip(10),
623 RowSelector::select(10),
624 RowSelector::skip(10),
625 RowSelector::select(20),
626 ]);
627
628 let b = RowSelection::from(vec![
629 RowSelector::skip(20),
630 RowSelector::select(20),
631 RowSelector::skip(10),
632 ]);
633
634 let result = a.intersection(&b);
635 assert_eq!(
636 result.selectors(),
637 vec![
638 RowSelector::skip(30),
639 RowSelector::select(10),
640 RowSelector::skip(10)
641 ]
642 );
643 }
644
645 #[test]
646 fn test_union() {
647 let selection = RowSelection::from(vec![RowSelector::select(1048576)]);
648 let result = selection.union(&selection);
649 assert_eq!(result, selection);
650
651 let a = RowSelection::from(vec![
653 RowSelector::skip(10),
654 RowSelector::select(10),
655 RowSelector::skip(10),
656 RowSelector::select(20),
657 ]);
658
659 let b = RowSelection::from(vec![
661 RowSelector::skip(20),
662 RowSelector::select(20),
663 RowSelector::skip(10),
664 RowSelector::select(10),
665 RowSelector::skip(10),
666 ]);
667
668 let result = a.union(&b);
669
670 assert_eq!(
672 result.iter().copied().collect::<Vec<_>>(),
673 vec![
674 RowSelector::skip(10),
675 RowSelector::select(50),
676 RowSelector::skip(10),
677 ]
678 );
679 }
680
681 #[test]
682 fn test_mask_and_then_preserves_backing() {
683 let outer_bits = vec![false, true, true, false, true, false, true];
684 let inner_bits = vec![true, false, true, false];
685 let outer_mask = RowSelection::from_boolean_buffer(BooleanBuffer::from(outer_bits.clone()));
686 let inner = RowSelection::from_filters(&[BooleanArray::from(inner_bits.clone())]);
687
688 let result = outer_mask.and_then(&inner);
689 assert!(result.as_mask().is_some());
690
691 let outer_selectors = RowSelection::from_filters(&[BooleanArray::from(outer_bits)]);
692 let expected = outer_selectors.and_then(&inner);
693 assert_eq!(result, expected);
694
695 let result_mask = result.as_mask().unwrap();
696 let actual_bits: Vec<_> = (0..result_mask.len())
697 .map(|i| result_mask.value(i))
698 .collect();
699 assert_eq!(
700 actual_bits,
701 vec![false, true, false, false, true, false, false]
702 );
703 }
704
705 #[test]
706 fn test_mask_and_then_mask_preserves_backing() {
707 let outer_bits = vec![false, true, true, false, true, false, true, true];
708 let inner_bits = vec![false, true, false, true, false];
709 let outer_mask = RowSelection::from_boolean_buffer(BooleanBuffer::from(outer_bits.clone()));
710 let inner_mask = RowSelection::from_boolean_buffer(BooleanBuffer::from(inner_bits));
711
712 let result = outer_mask.and_then(&inner_mask);
713 assert!(result.as_mask().is_some());
714
715 let outer_selectors = RowSelection::from_filters(&[BooleanArray::from(outer_bits)]);
716 let inner_selectors = RowSelection::from_filters(&[BooleanArray::from(vec![
717 false, true, false, true, false,
718 ])]);
719 assert_eq!(result, outer_selectors.and_then(&inner_selectors));
720
721 let result_mask = result.as_mask().unwrap();
722 let actual_bits: Vec<_> = (0..result_mask.len())
723 .map(|i| result_mask.value(i))
724 .collect();
725 assert_eq!(
726 actual_bits,
727 vec![false, false, true, false, false, false, true, false]
728 );
729 }
730
731 #[test]
732 fn test_selector_and_then_mask() {
733 let outer =
734 RowSelection::from_filters(&[BooleanArray::from(vec![false, true, true, false, true])]);
735 let inner = RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![true, false, true]));
736
737 let result = outer.and_then(&inner);
738 assert!(result.as_mask().is_none());
739 assert_eq!(
740 result,
741 RowSelection::from_filters(&[BooleanArray::from(vec![
742 false, true, false, false, true,
743 ])])
744 );
745 }
746
747 #[test]
748 fn test_mask_and_then_none_selected_returns_all_unset() {
749 let outer = RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![
750 false, true, true, false, true,
751 ]));
752 let inner =
753 RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![false, false, false]));
754
755 let result = outer.and_then(&inner);
756 let mask = result.as_mask().unwrap();
757 assert_eq!(mask.len(), 5);
758 assert_eq!(mask.count_set_bits(), 0);
759 }
760
761 #[test]
762 fn test_mask_intersection_uses_bitwise() {
763 let a_bits = vec![true, true, false, true, false, true];
764 let b_bits = vec![true, false, true, true, true, false];
765 let a = RowSelection::from_boolean_buffer(BooleanBuffer::from(a_bits.clone()));
766 let b = RowSelection::from_boolean_buffer(BooleanBuffer::from(b_bits.clone()));
767
768 let r = a.intersection(&b);
769 assert!(r.as_mask().is_some());
770
771 let expected: Vec<bool> = a_bits.iter().zip(&b_bits).map(|(x, y)| *x && *y).collect();
772 let expected_sel = RowSelection::from_filters(&[BooleanArray::from(expected)]);
773 assert_eq!(r, expected_sel);
774 }
775
776 #[test]
777 fn test_mask_union_uses_bitwise() {
778 let a_bits = vec![true, false, false, true, false, false];
779 let b_bits = vec![false, true, false, false, true, false];
780 let a = RowSelection::from_boolean_buffer(BooleanBuffer::from(a_bits.clone()));
781 let b = RowSelection::from_boolean_buffer(BooleanBuffer::from(b_bits.clone()));
782
783 let r = a.union(&b);
784 assert!(r.as_mask().is_some());
785
786 let expected: Vec<bool> = a_bits.iter().zip(&b_bits).map(|(x, y)| *x || *y).collect();
787 let expected_sel = RowSelection::from_filters(&[BooleanArray::from(expected)]);
788 assert_eq!(r, expected_sel);
789 }
790
791 #[test]
792 fn test_mixed_mask_selector_intersection_and_union() {
793 let mask_bits = vec![true, false, true, false, true, false];
794 let selector_bits = vec![false, true, true, false, false, true];
795 let mask = RowSelection::from_boolean_buffer(BooleanBuffer::from(mask_bits.clone()));
796 let selectors = RowSelection::from_filters(&[BooleanArray::from(selector_bits.clone())]);
797
798 let intersection_bits: Vec<_> = mask_bits
799 .iter()
800 .zip(&selector_bits)
801 .map(|(x, y)| *x && *y)
802 .collect();
803 let expected_intersection =
804 RowSelection::from_filters(&[BooleanArray::from(intersection_bits)]);
805 assert_eq!(mask.intersection(&selectors), expected_intersection);
806 assert_eq!(selectors.intersection(&mask), expected_intersection);
807
808 let union_bits: Vec<_> = mask_bits
809 .iter()
810 .zip(&selector_bits)
811 .map(|(x, y)| *x || *y)
812 .collect();
813 let expected_union = RowSelection::from_filters(&[BooleanArray::from(union_bits)]);
814 assert_eq!(mask.union(&selectors), expected_union);
815 assert_eq!(selectors.union(&mask), expected_union);
816 }
817
818 #[test]
819 fn test_mask_intersection_uneven_passes_tail_through() {
820 let a_bits = vec![true, true, true, true, true];
821 let b_bits = vec![true, false, true];
822 let a = RowSelection::from_boolean_buffer(BooleanBuffer::from(a_bits));
823 let b = RowSelection::from_boolean_buffer(BooleanBuffer::from(b_bits));
824
825 let r = a.intersection(&b);
826 let r_mask = r.as_mask().unwrap();
827 assert_eq!(r_mask.len(), 5);
828 let bits: Vec<bool> = (0..5).map(|i| r_mask.value(i)).collect();
829 assert_eq!(bits, vec![true, false, true, true, true]);
830
831 let a = RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![true, false, true]));
833 let b = RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![
834 true, true, true, false, true,
835 ]));
836 let r = a.intersection(&b);
837 let r_mask = r.as_mask().unwrap();
838 assert_eq!(r_mask.len(), 5);
839 let bits: Vec<bool> = (0..5).map(|i| r_mask.value(i)).collect();
840 assert_eq!(bits, vec![true, false, true, false, true]);
841 }
842
843 #[test]
844 fn test_mask_union_uneven_passes_tail_through() {
845 let a_bits = vec![true, false, true];
846 let b_bits = vec![false, true, false, true, false];
847 let a = RowSelection::from_boolean_buffer(BooleanBuffer::from(a_bits));
848 let b = RowSelection::from_boolean_buffer(BooleanBuffer::from(b_bits));
849
850 let r = a.union(&b);
851 let r_mask = r.as_mask().unwrap();
852 assert_eq!(r_mask.len(), 5);
853 let bits: Vec<bool> = (0..5).map(|i| r_mask.value(i)).collect();
854 assert_eq!(bits, vec![true, true, true, true, false]);
855
856 let a = RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![
857 false, true, false, false, true,
858 ]));
859 let b = RowSelection::from_boolean_buffer(BooleanBuffer::from(vec![true, false, false]));
860 let r = a.union(&b);
861 let r_mask = r.as_mask().unwrap();
862 let bits: Vec<bool> = (0..5).map(|i| r_mask.value(i)).collect();
863 assert_eq!(bits, vec![true, true, false, false, true]);
864 }
865
866 fn expected_combined(l: &[bool], r: &[bool], op: fn(bool, bool) -> bool) -> Vec<bool> {
869 let common = l.len().min(r.len());
870 let longer = if l.len() > r.len() { l } else { r };
871 (0..common)
872 .map(|i| op(l[i], r[i]))
873 .chain(longer[common..].iter().copied())
874 .collect()
875 }
876
877 fn assert_mask_eq(actual: &BooleanBuffer, expected: &[bool], context: &str) {
878 assert_eq!(actual.len(), expected.len(), "{context}: length");
879 let actual: Vec<bool> = actual.iter().collect();
880 assert_eq!(actual, expected, "{context}");
881 }
882
883 #[test]
884 fn test_mask_algebra_with_offsets() {
885 let base: Vec<bool> = (0..600).map(|i| i % 7 == 0 || i % 3 == 1).collect();
889 let other: Vec<bool> = (0..600).map(|i| i % 5 == 2 || i % 11 == 4).collect();
890 let base = BooleanBuffer::from(base);
891 let other = BooleanBuffer::from(other);
892
893 for l_offset in [0, 1, 5, 8, 13, 64, 67] {
894 for r_offset in [0, 1, 3, 8, 60, 64, 70] {
895 for (l_len, r_len) in [
896 (0, 9),
897 (9, 0),
898 (1, 200),
899 (200, 1),
900 (63, 130),
901 (321, 65),
902 (0, 0),
903 (1, 1),
904 (63, 63),
905 (64, 64),
906 (200, 200),
907 (321, 321),
908 ] {
909 let l = base.slice(l_offset, l_len);
910 let r = other.slice(r_offset, r_len);
911 let l_bits: Vec<bool> = l.iter().collect();
912 let r_bits: Vec<bool> = r.iter().collect();
913 let context =
914 format!("l_offset={l_offset} r_offset={r_offset} lens=({l_len},{r_len})");
915
916 assert_mask_eq(
917 &intersect_masks(&l, &r),
918 &expected_combined(&l_bits, &r_bits, |a, b| a && b),
919 &format!("intersect {context}"),
920 );
921 assert_mask_eq(
922 &union_masks(&l, &r),
923 &expected_combined(&l_bits, &r_bits, |a, b| a || b),
924 &format!("union {context}"),
925 );
926 }
927 }
928 }
929 }
930
931 #[test]
932 fn test_mask_algebra_does_not_retain_backing_buffer() {
933 let long = BooleanBuffer::from((0..80_000).map(|i| i % 3 == 0).collect::<Vec<bool>>());
938 assert!(long.inner().capacity() >= 10_000);
939
940 for (l, r) in [
941 (long.slice(5, 40), BooleanBuffer::new_unset(0)),
942 (long.slice(5, 40), BooleanBuffer::new_set(7)),
943 (BooleanBuffer::new_set(7), long.slice(5, 40)),
944 ] {
945 for combined in [intersect_masks(&l, &r), union_masks(&l, &r)] {
946 assert!(
947 combined.inner().capacity() < long.inner().capacity(),
948 "result retained the original backing allocation"
949 );
950 }
951 }
952 }
953
954 #[test]
955 fn test_mask_algebra_fuzz() {
956 let mut rng = rng();
957 for _ in 0..200 {
958 let l_offset = rng.random_range(0..70);
959 let r_offset = rng.random_range(0..70);
960 let l_len = rng.random_range(0..300);
961 let r_len = match rng.random_bool(0.25) {
963 true => l_len,
964 false => rng.random_range(0..300),
965 };
966
967 let l_bits: Vec<bool> = (0..l_offset + l_len)
968 .map(|_| rng.random_bool(0.5))
969 .collect();
970 let r_bits: Vec<bool> = (0..r_offset + r_len)
971 .map(|_| rng.random_bool(0.5))
972 .collect();
973 let l = BooleanBuffer::from(l_bits).slice(l_offset, l_len);
974 let r = BooleanBuffer::from(r_bits).slice(r_offset, r_len);
975 let l_bits: Vec<bool> = l.iter().collect();
976 let r_bits: Vec<bool> = r.iter().collect();
977
978 assert_mask_eq(
979 &intersect_masks(&l, &r),
980 &expected_combined(&l_bits, &r_bits, |a, b| a && b),
981 "intersect",
982 );
983 assert_mask_eq(
984 &union_masks(&l, &r),
985 &expected_combined(&l_bits, &r_bits, |a, b| a || b),
986 "union",
987 );
988 }
989 }
990}