index: add method for checking range on DenseBitSet
This commit is contained in:
parent
a88fc0eaae
commit
a0c19ee577
3 changed files with 46 additions and 4 deletions
|
|
@ -234,6 +234,32 @@ impl<T: Idx> DenseBitSet<T> {
|
|||
self.clear_excess_bits();
|
||||
}
|
||||
|
||||
/// Checks whether any bit in the given range is a 1.
|
||||
#[inline]
|
||||
pub fn contains_any(&self, elems: impl RangeBounds<T>) -> bool {
|
||||
let Some((start, end)) = inclusive_start_end(elems, self.domain_size) else {
|
||||
return false;
|
||||
};
|
||||
let (start_word_index, start_mask) = word_index_and_mask(start);
|
||||
let (end_word_index, end_mask) = word_index_and_mask(end);
|
||||
|
||||
if start_word_index == end_word_index {
|
||||
self.words[start_word_index] & (end_mask | (end_mask - start_mask)) != 0
|
||||
} else {
|
||||
if self.words[start_word_index] & !(start_mask - 1) != 0 {
|
||||
return true;
|
||||
}
|
||||
|
||||
let remaining = start_word_index + 1..end_word_index;
|
||||
if remaining.start <= remaining.end {
|
||||
self.words[remaining].iter().any(|&w| w != 0)
|
||||
|| self.words[end_word_index] & (end_mask | (end_mask - 1)) != 0
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the set has changed.
|
||||
#[inline]
|
||||
pub fn remove(&mut self, elem: T) -> bool {
|
||||
|
|
|
|||
|
|
@ -692,6 +692,25 @@ fn dense_last_set_before() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dense_contains_any() {
|
||||
let mut set: DenseBitSet<usize> = DenseBitSet::new_empty(300);
|
||||
assert!(!set.contains_any(0..300));
|
||||
set.insert_range(10..20);
|
||||
set.insert_range(60..70);
|
||||
set.insert_range(150..=250);
|
||||
|
||||
assert!(set.contains_any(0..30));
|
||||
assert!(set.contains_any(5..100));
|
||||
assert!(set.contains_any(250..255));
|
||||
|
||||
assert!(!set.contains_any(20..59));
|
||||
assert!(!set.contains_any(256..290));
|
||||
|
||||
set.insert(22);
|
||||
assert!(set.contains_any(20..59));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_insert(b: &mut Bencher) {
|
||||
let mut bs = DenseBitSet::new_filled(99999usize);
|
||||
|
|
|
|||
|
|
@ -145,10 +145,7 @@ impl IsolatedAlloc {
|
|||
if pinfo.domain_size() < offset_pinfo + size_pinfo {
|
||||
break;
|
||||
}
|
||||
// FIXME: is there a more efficient way to check whether the entire range is unset
|
||||
// in the bitset?
|
||||
let range_avail = !(offset_pinfo..offset_pinfo + size_pinfo).any(|i| pinfo.contains(i));
|
||||
if range_avail {
|
||||
if !pinfo.contains_any(offset_pinfo..offset_pinfo + size_pinfo) {
|
||||
pinfo.insert_range(offset_pinfo..offset_pinfo + size_pinfo);
|
||||
// SAFETY: We checked the available bytes after `idx` in the call
|
||||
// to `domain_size` above and asserted there are at least `idx +
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue