https://github.com/magnetrwn/runtime-bitset-cpp
Very compact header-only C++ bitset library for creating bitsets at runtime.
https://github.com/magnetrwn/runtime-bitset-cpp
bitset data-structures header-only runtime
Last synced: about 1 year ago
JSON representation
Very compact header-only C++ bitset library for creating bitsets at runtime.
- Host: GitHub
- URL: https://github.com/magnetrwn/runtime-bitset-cpp
- Owner: magnetrwn
- License: mit
- Created: 2023-08-30T12:56:30.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2023-08-31T20:35:55.000Z (over 2 years ago)
- Last Synced: 2025-01-10T09:11:09.227Z (about 1 year ago)
- Topics: bitset, data-structures, header-only, runtime
- Language: C++
- Homepage:
- Size: 29.3 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Runtime Bitset CPP
**This is a very compact header-only library for creating bitsets like `std::bitset` at runtime.**
```cpp
#include "rbitset.hpp"
using RB::RuntimeBitset;
// Simple syntax...
RuntimeBitset<> p(20);
// ...templated for selectable underlying types...
RuntimeBitset q(20);
// ...with overloaded constructors...
RuntimeBitset<> r;
r = RuntimeBitset<>(20);
// ...and fill on creation...
RuntimeBitset<> s(20, true); // All true!
// ...as well as move and copy assignments.
r = s; // Copy!
s = std::move(p); // Move!
```
# Installation
To use the library, you can:
```sh
cd lib
git clone https://github.com/magnetrwn/runtime-bitset-cpp
```
and include the library from its location, usually from inside `lib/` in your project root.
The library contains just two classes:
+ `RuntimeBitset` → Main wrapper for bitsets
+ `BitReference` → Friend class, returned by accessing a bit in the bitset
# Operations
When working with a RuntimeBitset, index accessing has a bit of a quirk:
```cpp
#include "rbitset.hpp"
using RB::RuntimeBitset;
bool demonstratingBitsets() {
RuntimeBitset<> bs(20);
bs[0] = true;
// Calls operator[] on RuntimeBitset instance, which returns BitReference.
// BitReference operator= is then called to set the value.
auto firstIndexRef = bs[0];
// This might be confused as getting the bool rvalue, but
// it's actually returning a BitReference to the requested bit!
return (bool) bs[0] == (bool) firstIndexRef;
// To actually get the rvalue, casting to bool through BitReference's
// operator bool() is required.
}
```
BitReference is able to act on a single bit by using a bit mask stored in the instance, together with a block index to locate the block where the bit is located.
# Includes
Here are the includes used by the library:
+ `` → Used for `memset()` and `memcpy()`. You can change the precompiler define `RUNTIME_BITSET_USE_CSTRING_` to false if necessary, which will adjust the code to `for` loop alternatives.
+ `` → Used only for standard C types, specifically `size_t`.
# Speed
`benchmark.cpp` basically has simple benchmarks to test speed against other possible implementations of data structures using bitsets and arrays, and more. Cache linearity is a relevant factor here, so the benchmark tries to be a little randomic as well.
**Note:** keep in mind using a one-dimensional data structure with index offsetting is not being benchmarked here, but quite likely to improve speed and memory footprint.
Here is a sample run from running `benchmark.cpp`:
```
Running 4 rounds with 1000 rows and 1000 cols.
Round: Done
------------------------------------------------------------------
RuntimeBitset<>(cols)[rows] | 326710 us | Baseline
std::array, rows> | 300917 us | -7.9%
std::deque> | 538531 us | +64.8%
std::array, rows> | 229400 us | -29.8%
bool[rows][cols] | 220894 us | -32.4%
------------------------------------------------------------------
```
Of course time results on different machines will change, but there is consistency between results from runs, and similarities on performance deltas between implementations.
# Examples
This is a simple way to implement a memory efficient grid (although I guess it can be improved even more by making it all fit in a single big bitset and then offset indexes?):
```cpp
#include
#include
#include
#include "rbitset.hpp"
using RB::RuntimeBitset;
std::unique_ptr[]> bitsetGridGen(const size_t rows, const size_t cols) {
auto grid = std::make_unique[]>(rows);
for (size_t i = 0; i < rows; i++) {
grid[i] = RuntimeBitset<>(cols, false);
}
return grid;
}
int main() {
const size_t rows = 8, cols = 30;
auto grid = bitsetGridGen(rows, cols);
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
grid[i][j] = (i%2 == j%2);
printf("%hhx ", (bool) grid[i][j]);
}
printf("\n");
}
return 0;
}
```
When run:
```
$ ./example
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
```
# Contributing and License
All code is under MIT, enjoy. Feel free to help, report issues, fork or send PRs if you want!
**Note:** I created this because I needed a runtime bitset with a simple implementation, and reasonably small memory footprint, for my other project at `magnetrwn/margolus-cpp`, but it's still inefficient in access time versus compile-time `std::bitset`. It's also missing some relevant features like counting and bitwise operations for now.