Skip to content

Commit

Permalink
Merge pull request #84 from contain-rs/get-unchecked
Browse files Browse the repository at this point in the history
Implement unsafe `get_unchecked`
  • Loading branch information
pczarn authored May 31, 2024
2 parents 5a84760 + 9d0466c commit 56ab55d
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
55 changes: 55 additions & 0 deletions benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// except according to those terms.

#![feature(test)]
#![feature(hint_assert_unchecked)]

extern crate bit_vec;
extern crate rand;
Expand Down Expand Up @@ -76,6 +77,60 @@ fn bench_bit_set_small(b: &mut Bencher) {
});
}

#[bench]
fn bench_bit_get_checked_small(b: &mut Bencher) {
let mut r = small_rng();
let size = 200;
let mut bit_vec = BitVec::from_elem(size, false);
for _ in 0..20 {
bit_vec.set((r.next_u32() as usize) % size, true);
}
let bit_vec = black_box(bit_vec);
b.iter(|| {
for _ in 0..100 {
black_box(bit_vec.get((r.next_u32() as usize) % size));
}
});
}

#[bench]
fn bench_bit_get_unchecked_small(b: &mut Bencher) {
let mut r = small_rng();
let size = 200;
let mut bit_vec = BitVec::from_elem(size, false);
for _ in 0..20 {
bit_vec.set((r.next_u32() as usize) % size, true);
}
let bit_vec = black_box(bit_vec);
b.iter(|| {
for _ in 0..100 {
unsafe {
black_box(bit_vec.get_unchecked((r.next_u32() as usize) % size));
}
}
});
}

#[bench]
fn bench_bit_get_unchecked_small_assume(b: &mut Bencher) {
let mut r = small_rng();
let size = 200;
let mut bit_vec = BitVec::from_elem(size, false);
for _ in 0..20 {
bit_vec.set((r.next_u32() as usize) % size, true);
}
let bit_vec = black_box(bit_vec);
b.iter(|| {
for _ in 0..100 {
unsafe {
let idx = (r.next_u32() as usize) % size;
::std::hint::assert_unchecked(!(idx >= bit_vec.len()));
black_box(bit_vec.get(idx));
}
}
});
}

#[bench]
fn bench_bit_vec_big_or(b: &mut Bencher) {
let mut b1 = BitVec::from_elem(BENCH_BITS, false);
Expand Down
29 changes: 29 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,35 @@ impl<B: BitBlock> BitVec<B> {
.map(|&block| (block & (B::one() << b)) != B::zero())
}

/// Retrieves the value at index `i`, without doing bounds checking.
///
/// For a safe alternative, see `get`.
///
/// # Safety
///
/// Calling this method with an out-of-bounds index is undefined behavior
/// even if the resulting reference is not used.
///
/// # Examples
///
/// ```
/// use bit_vec::BitVec;
///
/// let bv = BitVec::from_bytes(&[0b01100000]);
/// unsafe {
/// assert_eq!(bv.get_unchecked(0), false);
/// assert_eq!(bv.get_unchecked(1), true);
/// }
/// ```
#[inline]
pub unsafe fn get_unchecked(&self, i: usize) -> bool {
self.ensure_invariant();
let w = i / B::bits();
let b = i % B::bits();
let block = *self.storage.get_unchecked(w);
block & (B::one() << b) != B::zero()
}

/// Sets the value of a bit at an index `i`.
///
/// # Panics
Expand Down

0 comments on commit 56ab55d

Please sign in to comment.