turbonss/cxxmph/mph_bits.h

82 lines
2.2 KiB
C
Raw Normal View History

#ifndef __CXXMPH_MPH_BITS_H__
#define __CXXMPH_MPH_BITS_H__
#include <stdint.h> // for uint32_t and friends
#include <array>
2012-03-14 21:43:38 +02:00
#include <cassert>
#include <climits>
2012-03-14 23:26:26 +02:00
#include <cmath>
2012-03-14 21:43:38 +02:00
#include <cstdio>
#include <cstring>
#include <limits>
#include <vector>
#include <utility>
namespace cxxmph {
2012-03-14 21:43:38 +02:00
class dynamic_2bitset {
public:
dynamic_2bitset() : size_(0), fill_(false) {}
2012-03-14 23:26:26 +02:00
dynamic_2bitset(uint32_t size, bool fill = false)
: size_(size), fill_(fill), data_(ceil(size / 4.0), ones()*fill) {
2012-03-14 21:43:38 +02:00
}
const uint8_t operator[](uint32_t i) const { return get(i); }
const uint8_t get(uint32_t i) const {
assert(i < size());
assert((i >> 2) < data_.size());
2012-03-14 21:43:38 +02:00
return (data_[(i >> 2)] >> (((i & 3) << 1)) & 3);
}
uint8_t set(uint32_t i, uint8_t v) {
assert((i >> 2) < data_.size());
2012-03-14 23:26:26 +02:00
data_[(i >> 2)] |= ones() ^ dynamic_2bitset::vmask[i & 3];
2012-03-14 21:43:38 +02:00
data_[(i >> 2)] &= ((v << ((i & 3) << 1)) | dynamic_2bitset::vmask[i & 3]);
2012-03-14 23:26:26 +02:00
assert(v <= 3);
2012-03-14 21:43:38 +02:00
assert(get(i) == v);
}
void resize(uint32_t size) {
size_ = size;
2012-03-14 23:26:26 +02:00
data_.resize(size >> 2, fill_*ones());
2012-03-14 21:43:38 +02:00
}
2012-03-14 23:26:26 +02:00
void swap(dynamic_2bitset& other) {
std::swap(other.size_, size_);
std::swap(other.fill_, fill_);
other.data_.swap(data_);
2012-03-14 23:26:26 +02:00
}
void clear() { data_.clear(); size_ = 0; }
2012-03-14 23:26:26 +02:00
uint32_t size() const { return size_; }
2012-03-14 21:43:38 +02:00
static const uint8_t vmask[];
const std::vector<uint8_t>& data() const { return data_; }
2012-03-19 08:18:57 +02:00
private:
2012-03-14 21:43:38 +02:00
uint32_t size_;
2012-03-14 23:26:26 +02:00
bool fill_;
std::vector<uint8_t> data_;
const uint8_t ones() { return std::numeric_limits<uint8_t>::max(); }
2012-03-14 21:43:38 +02:00
};
static uint32_t nextpoweroftwo(uint32_t k) {
if (k == 0) return 1;
k--;
for (int i=1; i<sizeof(uint32_t)*CHAR_BIT; i<<=1) k = k | k >> i;
return k+1;
}
// Interesting bit tricks that might end up here:
// http://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
// Fast a % (k*2^t)
// http://www.azillionmonkeys.com/qed/adiv.html
2012-03-20 03:48:11 +02:00
// rank and select:
// http://vigna.dsi.unimi.it/ftp/papers/Broadword.pdf
2012-03-22 01:19:16 +02:00
struct Ranktable { static uint8_t get(uint8_t); };
static uint8_t rank64(uint64_t bits) {
auto bytes = reinterpret_cast<const uint8_t*>(&bits);
return Ranktable::get(bytes[0]) + Ranktable::get(bytes[1]) +
Ranktable::get(bytes[2]) + Ranktable::get(bytes[3]);
};
} // namespace cxxmph
#endif