Skip to content

Commit 9f61d67

Browse files
committed
readd bitm to apply changes
1 parent 0ef6bbe commit 9f61d67

File tree

10 files changed

+2706
-0
lines changed

10 files changed

+2706
-0
lines changed

bitm/Cargo.toml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
[package]
2+
name = "bitm"
3+
version = "0.4.3"
4+
edition = "2021"
5+
authors = ["Piotr Beling <[email protected]>"]
6+
license = "MIT OR Apache-2.0"
7+
description = "The library for bit and bitmap (bit vector) manipulation."
8+
documentation = "https://docs.rs/bitm"
9+
repository = "https://github.com/beling/bsuccinct-rs"
10+
readme = "README.md"
11+
include = [ "**/*.rs", "Cargo.toml", "README.md" ]
12+
categories = [ "algorithms", "data-structures", "science", "encoding" ]
13+
keywords = [ "bit", "bitmap", "rank", "bitvector", "bitset" ]
14+
15+
[dependencies]
16+
dyn_size_of = { version=">=0.4.3", path="../dyn_size_of" }
17+
aligned-vec = { version="0.6", optional=true } # for construcing cache-aligment bit vectors, which usually speeds up rank and select
18+
19+
[dev-dependencies]
20+
criterion = "0.5"
21+
iai-callgrind = "0.10"
22+
23+
[features]
24+
aligned-vec = ["dep:aligned-vec", "dyn_size_of/aligned-vec"]
25+
26+
27+
[[bench]]
28+
name = "bitvec"
29+
harness = false
30+
31+
[[bench]]
32+
name = "rank_select"
33+
harness = false
34+
35+
[[bench]]
36+
name = "bitvec-iai"
37+
harness = false
38+
39+
#[profile.bench]
40+
#debug = true

bitm/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
`bitm` is the Rust library by Piotr Beling for bit and bitmap (bit vector) manipulation.
2+
3+
# Example
4+
5+
```rust
6+
use bitm::{BitAccess, BitVec, Rank, ArrayWithRank101111};
7+
8+
let mut b = Box::<[u64]>::with_zeroed_bits(2048); // b can store 2048 bits
9+
assert_eq!(b.get_bit(100), false); // b is zeroed so bit at index 100 is not set
10+
b.set_bit(100); // set the bit
11+
assert_eq!(b.get_bit(100), true); // now it is set
12+
assert_eq!(b.get_bits(99, 5), 0b00010); // 5 bits, beginning from index 99, should be 00010
13+
14+
let (r, ones) = ArrayWithRank101111::build(b);
15+
assert_eq!(ones, 1); // one bit is set in b
16+
assert_eq!(r.rank(100), 0); // no ones in the first 100 bits of b
17+
assert_eq!(r.rank(101), 1); // 1 one in the first 101 bits of b
18+
assert_eq!(r.rank(999), 1); // 1 one in the first 999 bits of b
19+
```
20+
21+
# Benchmarks
22+
The performance of some of the structures included in `bitm` can be tested with the [cseq_benchmark](https://crates.io/crates/cseq_benchmark) crate. Its documentation contains benchmark results.
23+

bitm/benches/bitvec-iai.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use iai_callgrind::{black_box, main, library_benchmark_group, library_benchmark};
2+
use bitm::BitAccess;
3+
4+
#[library_benchmark]
5+
#[bench::short(&[0x6A_21_55_79_10_90_32_F3; 2], 10, 30)]
6+
#[bench::long(&[0x6A_21_55_79_10_90_32_F3; 2], 10, 60)]
7+
fn get_bits(tab: &[u64], index: usize, v_size: u8) -> u64 {
8+
black_box(tab.get_bits(index, v_size))
9+
}
10+
11+
#[library_benchmark]
12+
#[bench::short(&[0x6A_21_55_79_10_90_32_F3; 2], 10, 30)]
13+
#[bench::long(&[0x6A_21_55_79_10_90_32_F3; 2], 10, 60)]
14+
fn get_bits_unchecked(tab: &[u64], index: usize, v_size: u8) -> u64 {
15+
black_box(unsafe{tab.get_bits_unchecked(index, v_size)})
16+
}
17+
18+
#[library_benchmark]
19+
#[bench::short(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, 0xaa_aa_aa, 30)]
20+
#[bench::long(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, 0xaa_aa_aa_aa_aa_aa, 60)]
21+
fn set_bits(tab: &mut [u64], index: usize, v: u64, v_size: u8) {
22+
tab.set_bits(index, v, v_size)
23+
}
24+
25+
#[library_benchmark]
26+
#[bench::short(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, 0xaa_aa_aa, 30)]
27+
#[bench::long(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, 0xaa_aa_aa_aa_aa_aa, 60)]
28+
fn set_bits_unchecked(tab: &mut [u64], index: usize, v: u64, v_size: u8) {
29+
unsafe { tab.set_bits_unchecked(index, v, v_size) }
30+
}
31+
32+
#[library_benchmark]
33+
#[bench::zero(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, false)]
34+
#[bench::one(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, true)]
35+
fn set_bit_to(tab: &mut [u64], index: usize, value: bool) {
36+
tab.set_bit_to(index, value)
37+
}
38+
39+
#[library_benchmark]
40+
#[bench::zero(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, false)]
41+
#[bench::one(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, true)]
42+
fn set_bit_to_unchecked(tab: &mut [u64], index: usize, value: bool) {
43+
unsafe{tab.set_bit_to_unchecked(index, value)}
44+
}
45+
46+
#[library_benchmark]
47+
#[bench::short(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, 30)]
48+
#[bench::long(&mut [0x6A_21_55_79_10_90_32_F3; 2], 10, 60)]
49+
fn conditionally_change_bits(tab: &mut [u64], index: usize, v_size: u8) -> u64 {
50+
black_box(tab.conditionally_change_bits(|v| (v>2).then(|| v-1), index, v_size))
51+
}
52+
53+
library_benchmark_group!(
54+
name = bitvec;
55+
benchmarks =
56+
get_bits, get_bits_unchecked,
57+
set_bits, set_bits_unchecked,
58+
set_bit_to, set_bit_to_unchecked,
59+
conditionally_change_bits
60+
);
61+
62+
main!(library_benchmark_groups = bitvec);

bitm/benches/bitvec.rs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Criterion, BenchmarkId};
2+
use bitm::BitAccess;
3+
4+
pub fn get_bits(c: &mut Criterion) {
5+
let v = [0x6A_21_55_79_10_90_32_F3; 4];
6+
7+
c.bench_function("get_bit (checked)", |b| b.iter(|| v.get_bit(black_box(30))));
8+
c.bench_function("get_bit (unchecked)", |b| b.iter(|| unsafe{v.get_bit_unchecked(black_box(30))}));
9+
10+
let mut group = c.benchmark_group("get_bits (checked)");
11+
for size in [20, 40, 60].iter() {
12+
//group.throughput(Throughput::Bytes(*size as u64));
13+
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
14+
b.iter(|| v.get_bits(black_box(30), size))
15+
});
16+
}
17+
group.finish();
18+
19+
let mut group = c.benchmark_group("get_bits_unchecked");
20+
for size in [20, 40, 60].iter() {
21+
//group.throughput(Throughput::Bytes(*size as u64));
22+
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
23+
b.iter(|| unsafe{ v.get_bits_unchecked(black_box(30), size) })
24+
});
25+
}
26+
group.finish();
27+
}
28+
29+
pub fn set_bits(c: &mut Criterion) {
30+
let mut v = [0x6A_21_55_79_10_90_32_F3; 4];
31+
32+
c.bench_function("set_bit (checked)", |b| b.iter(|| v.set_bit(black_box(30))));
33+
c.bench_function("set_bit (unchecked)", |b| b.iter(|| unsafe{v.set_bit_unchecked(black_box(30))}));
34+
35+
let mut group = c.benchmark_group("set_bit_to (checked)");
36+
for value in [false, true] {
37+
group.bench_with_input(BenchmarkId::from_parameter(value), &value, |b, value| {
38+
b.iter(|| v.set_bit_to(black_box(30), black_box(*value)))
39+
});
40+
}
41+
group.finish();
42+
43+
let mut group = c.benchmark_group("set_bit_to (unchecked)");
44+
for value in [false, true] {
45+
group.bench_with_input(BenchmarkId::from_parameter(value), &value, |b, value| {
46+
b.iter(|| unsafe{v.set_bit_to_unchecked(black_box(30), black_box(*value))})
47+
});
48+
}
49+
group.finish();
50+
51+
c.bench_function("set_bit_to (checked)", |b| b.iter(|| v.set_bit_to(black_box(30), true)));
52+
c.bench_function("set_bit_to (unchecked)", |b| b.iter(|| unsafe{v.set_bit_unchecked(black_box(30))}));
53+
54+
let mut group = c.benchmark_group("set_bits (checked)");
55+
for size in [20, 40, 60].iter() {
56+
//group.throughput(Throughput::Bytes(*size as u64));
57+
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
58+
b.iter(|| v.set_bits(black_box(30), black_box(0), size))
59+
});
60+
}
61+
group.finish();
62+
63+
let mut group = c.benchmark_group("set_bits_unchecked");
64+
for size in [20, 40, 60].iter() {
65+
//group.throughput(Throughput::Bytes(*size as u64));
66+
group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| {
67+
b.iter(|| unsafe{v.set_bits_unchecked(black_box(30), black_box(0), size)})
68+
});
69+
}
70+
group.finish();
71+
}
72+
73+
criterion_group!(bit_vector, get_bits, set_bits);
74+
criterion_main!(bit_vector);

bitm/benches/rank_select.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
2+
use bitm::{RankSelect101111, Rank};
3+
4+
pub fn rank(c: &mut Criterion) {
5+
let bitmap = vec![0x6A_21_55_79_10_90_32_F3; 16].into_boxed_slice();
6+
let r: RankSelect101111 = bitmap.into();
7+
8+
c.bench_function("rank (checked)", |b| b.iter(|| r.rank(black_box(18*7))));
9+
c.bench_function("try_rank", |b| b.iter(|| r.try_rank(black_box(18*7))));
10+
c.bench_function("rank_unchecked", |b| b.iter(|| unsafe{r.rank_unchecked(black_box(18*7))}));
11+
}
12+
13+
criterion_group!(rank_select, rank);
14+
criterion_main!(rank_select);

0 commit comments

Comments
 (0)