Skip to content

Commit 06a0a2d

Browse files
committed
Add bitand_many, union_many, and relevant tests.
1 parent b36beac commit 06a0a2d

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

arrow-buffer/src/buffer/boolean.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,20 @@ impl BooleanBuffer {
625625
pub fn set_slices(&self) -> BitSliceIterator<'_> {
626626
BitSliceIterator::new(self.values(), self.bit_offset, self.bit_len)
627627
}
628+
629+
/// Bitwise AND of multiple [`BooleanBuffer`]s
630+
///
631+
/// # Panics
632+
///
633+
/// Panics if `buffers` is empty, or if the buffers have different lengths
634+
pub fn bitand_many(buffers: &[&BooleanBuffer]) -> BooleanBuffer {
635+
assert!(!buffers.is_empty(), "requires at least one buffer");
636+
let mut result = buffers[0].clone();
637+
for buf in &buffers[1..] {
638+
result &= *buf;
639+
}
640+
result
641+
}
628642
}
629643

630644
impl Not for &BooleanBuffer {
@@ -1245,4 +1259,29 @@ mod tests {
12451259
let buffer = BooleanBuffer::new_unset(100);
12461260
assert_eq!(buffer.clone().find_nth_set_bit_position(0, 1), 100);
12471261
}
1262+
1263+
#[test]
1264+
fn test_bitand_many_single() {
1265+
let a = BooleanBuffer::from(&[true, false, true, true] as &[bool]);
1266+
let result = BooleanBuffer::bitand_many(&[&a]);
1267+
assert_eq!(result, a);
1268+
}
1269+
1270+
#[test]
1271+
fn test_bitand_many_two() {
1272+
let a = BooleanBuffer::from(&[true, false, true, true] as &[bool]);
1273+
let b = BooleanBuffer::from(&[true, true, false, true] as &[bool]);
1274+
let result = BooleanBuffer::bitand_many(&[&a, &b]);
1275+
assert_eq!(result, &a & &b);
1276+
}
1277+
1278+
#[test]
1279+
fn test_bitand_many_three() {
1280+
let a = BooleanBuffer::from(&[true, false, true, true] as &[bool]);
1281+
let b = BooleanBuffer::from(&[true, true, false, true] as &[bool]);
1282+
let c = BooleanBuffer::from(&[false, true, true, true] as &[bool]);
1283+
let result = BooleanBuffer::bitand_many(&[&a, &b, &c]);
1284+
let expected = BooleanBuffer::from(&[false, false, false, true] as &[bool]);
1285+
assert_eq!(result, expected);
1286+
}
12481287
}

arrow-buffer/src/buffer/null.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,21 @@ impl NullBuffer {
8484
}
8585
}
8686

87+
/// Computes the union of the nulls in multiple optional [`NullBuffer`]s
88+
///
89+
/// See [`union`](Self::union)
90+
pub fn union_many(nulls: &[Option<&NullBuffer>]) -> Option<NullBuffer> {
91+
// Unwrap to BooleanBuffer because BitAndAssign is not implemented for NullBuffer
92+
let buffers: Vec<&BooleanBuffer> = nulls
93+
.iter()
94+
.filter_map(|nb| nb.map(NullBuffer::inner))
95+
.collect();
96+
if buffers.is_empty() {
97+
return None;
98+
}
99+
Some(Self::new(BooleanBuffer::bitand_many(&buffers)))
100+
}
101+
87102
/// Returns true if all nulls in `other` also exist in self
88103
pub fn contains(&self, other: &NullBuffer) -> bool {
89104
if other.null_count == 0 {
@@ -336,4 +351,51 @@ mod tests {
336351
let result = NullBuffer::from_unsliced_buffer(buf, 0);
337352
assert!(result.is_none());
338353
}
354+
355+
#[test]
356+
fn test_union_many_all_none() {
357+
let result = NullBuffer::union_many(&[None, None, None]);
358+
assert!(result.is_none());
359+
}
360+
361+
#[test]
362+
fn test_union_many_single_some() {
363+
let a = NullBuffer::from(&[true, false, true, true]);
364+
let result = NullBuffer::union_many(&[Some(&a)]);
365+
assert_eq!(result, Some(a));
366+
}
367+
368+
#[test]
369+
fn test_union_many_two_inputs() {
370+
let a = NullBuffer::from(&[true, false, true, true]);
371+
let b = NullBuffer::from(&[true, true, false, true]);
372+
let result = NullBuffer::union_many(&[Some(&a), Some(&b)]);
373+
let expected = NullBuffer::union(Some(&a), Some(&b));
374+
assert_eq!(result, expected);
375+
}
376+
377+
#[test]
378+
fn test_union_many_three_inputs() {
379+
let a = NullBuffer::from(&[true, false, true, true]);
380+
let b = NullBuffer::from(&[true, true, false, true]);
381+
let c = NullBuffer::from(&[false, true, true, true]);
382+
let result = NullBuffer::union_many(&[Some(&a), Some(&b), Some(&c)]);
383+
let expected = NullBuffer::from(&[false, false, false, true]);
384+
assert_eq!(result, Some(expected));
385+
}
386+
387+
#[test]
388+
fn test_union_many_mixed_none() {
389+
let a = NullBuffer::from(&[true, false, true, true]);
390+
let b = NullBuffer::from(&[false, true, true, true]);
391+
let result = NullBuffer::union_many(&[Some(&a), None, Some(&b)]);
392+
let expected = NullBuffer::union(Some(&a), Some(&b));
393+
assert_eq!(result, expected);
394+
}
395+
396+
#[test]
397+
fn test_union_many_empty_slice() {
398+
let result = NullBuffer::union_many(&[]);
399+
assert!(result.is_none());
400+
}
339401
}

0 commit comments

Comments
 (0)