From 759e1fbcdbd746309cbe489c2c768e5714fb945a Mon Sep 17 00:00:00 2001 From: shuo Date: Thu, 16 Feb 2023 12:30:13 +0800 Subject: [PATCH 1/2] add grow_and_insert method --- benches/benches/benches.rs | 14 ++++++++++++++ src/lib.rs | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/benches/benches/benches.rs b/benches/benches/benches.rs index b8c4ba6..3165707 100644 --- a/benches/benches/benches.rs +++ b/benches/benches/benches.rs @@ -91,6 +91,19 @@ fn insert(c: &mut Criterion) { }); } +fn grow_and_insert(c: &mut Criterion) { + const N: usize = 1_000_000; + let mut fb = FixedBitSet::with_capacity(N); + + c.bench_function("grow_and_insert", |b| { + b.iter(|| { + for i in 0..N { + fb.grow_and_insert(i); + } + }) + }); +} + fn union_with(c: &mut Criterion) { const N: usize = 1_000_000; let mut fb_a = FixedBitSet::with_capacity(N); @@ -159,5 +172,6 @@ criterion_group!( symmetric_difference_with, count_ones, clear, + grow_and_insert, ); criterion_main!(benches); diff --git a/src/lib.rs b/src/lib.rs index 23fea19..93b9424 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,6 +123,18 @@ impl FixedBitSet { } } + /// First grow to bits just like `grow`, then enable the bit + #[inline] + pub fn grow_and_insert(&mut self, bits: usize) { + self.grow(bits + 1); + + let (blocks, rem) = div_rem(bits); + // SAFETY: The above grow ensures that the block is inside the Vec's allocation. + unsafe { + *self.data.get_unchecked_mut(blocks) |= 1 << rem; + } + } + /// The length of the [`FixedBitSet`] in bits. /// /// Note: `len` includes both set and unset bits. @@ -1043,6 +1055,18 @@ mod tests { assert!(fb.contains(64)); } + #[test] + fn grow_and_insert() { + let mut fb = FixedBitSet::default(); + for i in 0..100 { + if i % 3 == 0 { + fb.grow_and_insert(i); + } + } + + assert_eq!(fb.count_ones(..), 34); + } + #[test] fn test_toggle() { let mut fb = FixedBitSet::with_capacity(16); From 16fcb19f3fb6c7b136afce646f079081534d6810 Mon Sep 17 00:00:00 2001 From: James Liu Date: Thu, 16 Feb 2023 12:11:31 -0800 Subject: [PATCH 2/2] Update doc comment in grow_and_insert --- src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 93b9424..b34e11d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -123,7 +123,11 @@ impl FixedBitSet { } } - /// First grow to bits just like `grow`, then enable the bit + /// Grows the internal size of the bitset before inserting a bit + /// + /// Unlike `insert`, this cannot panic, but may allocate if the bit is outside of the existing buffer's range. + /// + /// This is faster than calling `grow` then `insert` in succession. #[inline] pub fn grow_and_insert(&mut self, bits: usize) { self.grow(bits + 1);