Skip to content

Instantly share code, notes, and snippets.

@ofx ofx/bitfield.cpp
Last active Nov 15, 2018

Embed
What would you like to do?
#include <array>
#include <assert.h>
#include <bitset>
#include <iostream>
#include <limits.h>
#include <ostream>
template <size_t N> class bitfield : public std::bitset<N> {
public:
bitfield(std::array<unsigned char, N / CHAR_BIT> bytes)
: std::bitset<N>()
{
for (auto it = bytes.rbegin(); it != bytes.rend(); ++it) {
*this <<= 8;
*this |= *it;
}
}
bitfield(std::bitset<N> bits) : std::bitset<N>(bits) {}
bitfield() : std::bitset<N>() {}
constexpr bitfield<N> rotate_left(const unsigned int n) const {
const int mask = N - 1;
const int c = n & mask;
return (*this << c) | (*this >> ((-c) & mask));
}
constexpr bitfield<N> rotate_right(const unsigned int n) const {
const int mask = N - 1;
const int c = n & mask;
return (*this >> c) | (*this << ((-c) & mask));
}
constexpr bool parity() const { return (this->count() % 2 == 0); }
static constexpr void multiply(const unsigned int n, bool &cf,
bitfield<N> &bitfield) {
if (n > 0) {
cf = bitfield[N - 1];
bitfield <<= 1;
multiply(n - 1, cf, bitfield);
}
}
constexpr bitfield<N> multiply(const unsigned int n, bool &cf) const {
bitfield<N> c = (*this);
multiply(n, cf, c);
return c;
}
static constexpr void divide(const unsigned int n, bool &cf,
bitfield<N> &bitfield) {
if (n > 0) {
cf = bitfield[0];
bitfield >>= 1;
divide(n - 1, cf, bitfield);
}
}
constexpr bitfield<N> divide(const unsigned int n, bool &cf) const {
bitfield<N> c = (*this);
divide(n, cf, c);
return c;
}
static constexpr void signed_divide(const unsigned int n, bool &cf,
bitfield<N> &bitfield) {
if (n > 0) {
const bool s = bitfield[N - 1];
cf = bitfield[0];
bitfield >>= 1;
bitfield[N - 1] = s;
signed_divide(n - 1, cf, bitfield);
}
}
constexpr bitfield<N> signed_divide(const unsigned int n, bool &cf) const {
bitfield<N> c = (*this);
signed_divide(n, cf, c);
return c;
}
template <size_t E>
constexpr bitfield<E> sign_extend() const {
static_assert(
N <= std::size_t(std::numeric_limits<unsigned long long>::digits),
"N is greater than unsigned long long");
const bool s = (*this)[N - 1];
bitfield<E> c(s ? ((1 << N) - 1) << N : 0);
c |= bitfield<E>(this->to_ullong());
return c;
}
template <size_t B>
constexpr bitfield<B> get(unsigned int s = 0) const {
static_assert(
N <= std::size_t(std::numeric_limits<unsigned long long>::digits),
"N is greater than unsigned long long");
bitfield<N> m((1 << B) - 1);
return bitfield<B>(((*this) >> s & m).to_ullong());
}
constexpr void reverse()
{
for (std::size_t i = 0; i < N / 2; ++i) {
bool t = this->test(i);
(*this)[i] = (*this)[N - i - 1];
(*this)[N - i - 1] = t;
}
}
};
int main() {
std::array<unsigned char, 5> bytes = { 0xEA, 0x5B, 0xE0, 0x00, 0xF0 };
bitfield<40> bits(bytes);
std::cout << "Bytes" << std::endl;
for (const auto &byte : bytes)
std::cout << "0x" << std::hex << static_cast<unsigned>(byte) << ", ";
std::cout << std::endl;
std::cout << "Bits" << std::endl;
std::cout << bits << std::endl;
std::cout << "Rotate Left" << std::endl;
std::cout << bits.rotate_left(1) << std::endl;
assert(bits == bits.rotate_left(1).rotate_right(1));
std::cout << "Rotate Right" << std::endl;
std::cout << bits.rotate_right(1) << std::endl;
std::cout << "Parity" << std::endl;
std::cout << bits.parity() << std::endl;
std::cout << "Multiply" << std::endl;
bool cf;
std::cout << bits.multiply(1, cf) << std::endl;
std::cout << "cf: " << cf << std::endl;
std::cout << "Divide" << std::endl;
std::cout << bits.divide(1, cf) << std::endl;
std::cout << "cf: " << cf << std::endl;
std::cout << "Signed divide" << std::endl;
std::cout << bits.signed_divide(1, cf) << std::endl;
std::cout << "cf: " << cf << std::endl;
std::cout << "Sign extend" << std::endl;
std::cout << bits.sign_extend<32>() << std::endl;
std::cout << "Get" << std::endl;
std::cout << bits.get<8>(2) << std::endl;
std::cout << "Reverse" << std::endl;
bitfield<40> r = bits;
r.reverse();
std::cout << r << std::endl;
r.reverse();
assert(r == bits);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.