Skip to content

Commit 42335ce

Browse files
shuoli84james7132
andauthored
add grow_and_insert method (#92)
Co-authored-by: James Liu <contact@jamessliu.com>
1 parent 5fc93bf commit 42335ce

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

benches/benches/benches.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ fn insert(c: &mut Criterion) {
9191
});
9292
}
9393

94+
fn grow_and_insert(c: &mut Criterion) {
95+
const N: usize = 1_000_000;
96+
let mut fb = FixedBitSet::with_capacity(N);
97+
98+
c.bench_function("grow_and_insert", |b| {
99+
b.iter(|| {
100+
for i in 0..N {
101+
fb.grow_and_insert(i);
102+
}
103+
})
104+
});
105+
}
106+
94107
fn union_with(c: &mut Criterion) {
95108
const N: usize = 1_000_000;
96109
let mut fb_a = FixedBitSet::with_capacity(N);
@@ -159,5 +172,6 @@ criterion_group!(
159172
symmetric_difference_with,
160173
count_ones,
161174
clear,
175+
grow_and_insert,
162176
);
163177
criterion_main!(benches);

src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,22 @@ impl FixedBitSet {
123123
}
124124
}
125125

126+
/// Grows the internal size of the bitset before inserting a bit
127+
///
128+
/// Unlike `insert`, this cannot panic, but may allocate if the bit is outside of the existing buffer's range.
129+
///
130+
/// This is faster than calling `grow` then `insert` in succession.
131+
#[inline]
132+
pub fn grow_and_insert(&mut self, bits: usize) {
133+
self.grow(bits + 1);
134+
135+
let (blocks, rem) = div_rem(bits);
136+
// SAFETY: The above grow ensures that the block is inside the Vec's allocation.
137+
unsafe {
138+
*self.data.get_unchecked_mut(blocks) |= 1 << rem;
139+
}
140+
}
141+
126142
/// The length of the [`FixedBitSet`] in bits.
127143
///
128144
/// Note: `len` includes both set and unset bits.
@@ -1043,6 +1059,18 @@ mod tests {
10431059
assert!(fb.contains(64));
10441060
}
10451061

1062+
#[test]
1063+
fn grow_and_insert() {
1064+
let mut fb = FixedBitSet::default();
1065+
for i in 0..100 {
1066+
if i % 3 == 0 {
1067+
fb.grow_and_insert(i);
1068+
}
1069+
}
1070+
1071+
assert_eq!(fb.count_ones(..), 34);
1072+
}
1073+
10461074
#[test]
10471075
fn test_toggle() {
10481076
let mut fb = FixedBitSet::with_capacity(16);

0 commit comments

Comments
 (0)