diff options
Diffstat (limited to 'chilbert/BigBitVec.hpp')
-rw-r--r-- | chilbert/BigBitVec.hpp | 142 |
1 files changed, 53 insertions, 89 deletions
diff --git a/chilbert/BigBitVec.hpp b/chilbert/BigBitVec.hpp index 29d9a5a..7fe260e 100644 --- a/chilbert/BigBitVec.hpp +++ b/chilbert/BigBitVec.hpp @@ -85,7 +85,7 @@ public: explicit CBigBitVec(const size_t bits) : m_pcRacks{make_racks(num_racks(bits))} - , m_iRacks{bits == 0 ? 0 : num_racks(bits)} + , m_size{bits} { } @@ -96,31 +96,38 @@ public: } CBigBitVec(const CBigBitVec& vec) - : m_pcRacks{make_racks(vec.m_iRacks)} - , m_iRacks{vec.m_iRacks} + : m_pcRacks{make_racks(vec.rackCount())} + , m_size{vec.m_size} { if (vec.m_pcRacks) { memcpy( - m_pcRacks.get(), vec.m_pcRacks.get(), sizeof(Rack) * m_iRacks); + m_pcRacks.get(), vec.m_pcRacks.get(), sizeof(Rack) * rackCount()); } } CBigBitVec(CBigBitVec&& vec) = default; /// Return the size in bits - size_t size() const { return m_iRacks * bits_per_rack; } + size_t size() const { return m_size; } /// Set all bits to zero CBigBitVec& reset() { - memset(m_pcRacks.get(), 0, sizeof(Rack) * m_iRacks); + memset(m_pcRacks.get(), 0, sizeof(Rack) * rackCount()); return *this; } /// Set all bits to one CBigBitVec& set() { - memset(m_pcRacks.get(), 0xFF, sizeof(Rack) * m_iRacks); + if (m_size) { + memset(m_pcRacks.get(), 0xFF, sizeof(Rack) * rackCount()); + const auto pad = m_size % bits_per_rack; + if (pad) { + m_pcRacks[rackCount() - 1] |= ~Rack{0} >> pad; + } + } + return *this; } @@ -131,7 +138,7 @@ public: m_pcRacks[m.m_rack] &= (m.m_mask - 1); - for (size_t i = m.m_rack + 1; i < m_iRacks; ++i) { + for (size_t i = m.m_rack + 1; i < rackCount(); ++i) { m_pcRacks[i] = 0; } @@ -151,8 +158,8 @@ public: { assert(size() == vec.size()); - for (size_t ri = 0; ri < m_iRacks; ++ri) { - size_t i = m_iRacks - ri - 1; + for (size_t ri = 0; ri < rackCount(); ++ri) { + size_t i = rackCount() - ri - 1; if (m_pcRacks[i] < vec.m_pcRacks[i]) { return true; } else if (m_pcRacks[i] > vec.m_pcRacks[i]) { @@ -162,20 +169,19 @@ public: return false; } - /// Non-resizing assignment CBigBitVec& operator=(const CBigBitVec& vec) { - if (m_iRacks < vec.m_iRacks) { - m_iRacks = vec.m_iRacks; - m_pcRacks = make_racks(m_iRacks); + if (rackCount() < vec.rackCount()) { + m_pcRacks = make_racks(vec.rackCount()); + m_size = vec.m_size; memcpy( - m_pcRacks.get(), vec.m_pcRacks.get(), sizeof(Rack) * m_iRacks); - } else if (vec.m_iRacks > 0) { - m_iRacks = vec.m_iRacks; + m_pcRacks.get(), vec.m_pcRacks.get(), sizeof(Rack) * rackCount()); + } else if (vec.rackCount() > 0) { + m_size = vec.m_size; memcpy( - m_pcRacks.get(), vec.m_pcRacks.get(), sizeof(Rack) * m_iRacks); + m_pcRacks.get(), vec.m_pcRacks.get(), sizeof(Rack) * rackCount()); } else { - m_iRacks = 0; + m_size = 0; m_pcRacks.reset(); } @@ -239,7 +245,7 @@ public: CBigBitVec& operator&=(const CBigBitVec& vec) { - for (size_t i = 0; i < std::min(m_iRacks, vec.m_iRacks); ++i) { + for (size_t i = 0; i < std::min(rackCount(), vec.rackCount()); ++i) { m_pcRacks[i] &= vec.m_pcRacks[i]; } @@ -256,7 +262,7 @@ public: CBigBitVec& operator|=(const CBigBitVec& vec) { - for (size_t i = 0; i < std::min(m_iRacks, vec.m_iRacks); ++i) { + for (size_t i = 0; i < std::min(rackCount(), vec.rackCount()); ++i) { m_pcRacks[i] |= vec.m_pcRacks[i]; } @@ -273,7 +279,7 @@ public: CBigBitVec& operator^=(const CBigBitVec& vec) { - for (size_t i = 0; i < std::min(m_iRacks, vec.m_iRacks); ++i) { + for (size_t i = 0; i < std::min(rackCount(), vec.rackCount()); ++i) { m_pcRacks[i] ^= vec.m_pcRacks[i]; } @@ -308,7 +314,7 @@ public: if (index.rack > 0) { // Shift entire racks - for (size_t i = m_iRacks - 1; i >= index.rack; --i) { + for (size_t i = rackCount() - 1; i >= index.rack; --i) { m_pcRacks[i] = m_pcRacks[i - index.rack]; } for (size_t i = 0; i < index.rack; ++i) { @@ -320,7 +326,7 @@ public: // Shift bits within racks size_t bi = bits_per_rack - index.bit; size_t i; - for (i = m_iRacks - 1; i >= index.rack + 1; --i) { + for (i = rackCount() - 1; i >= index.rack + 1; --i) { m_pcRacks[i] <<= index.bit; m_pcRacks[i] |= m_pcRacks[i - 1] >> bi; } @@ -351,10 +357,10 @@ public: if (index.rack > 0) { // Shift entire racks size_t i; - for (i = 0; i < m_iRacks - index.rack; ++i) { + for (i = 0; i < rackCount() - index.rack; ++i) { m_pcRacks[i] = m_pcRacks[i + index.rack]; } - for (; i < m_iRacks; ++i) { + for (; i < rackCount(); ++i) { m_pcRacks[i] = 0; } } @@ -363,7 +369,7 @@ public: // Shift bits within racks size_t bi = bits_per_rack - index.bit; size_t i; - for (i = 0; i < m_iRacks - index.rack - 1; ++i) { + for (i = 0; i < rackCount() - index.rack - 1; ++i) { m_pcRacks[i] >>= index.bit; m_pcRacks[i] |= m_pcRacks[i + 1] << bi; } @@ -380,56 +386,42 @@ public: return t; } - /// Right-rotate the least significant `width` bits by `bits` positions - CBigBitVec& rotr(const size_t bits, size_t width) + /// Right-rotate by `bits` positions + CBigBitVec& rotr(const size_t bits) { - // Fill in the width, if necessary. - if (width <= 0) { - width = size(); - } - - // Modulo the number of bits. - assert(bits < width); - if (bits == 0) { + assert(bits <= size()); + if (bits == 0 || bits == size()) { return *this; } - // Ensure we are truncated appropriately. - truncate(width); + truncate(size()); CBigBitVec t1(*this); (*this) >>= bits; - t1 <<= (width - bits); + t1 <<= (size() - bits); (*this) |= t1; - truncate(width); + truncate(size()); return *this; } - /// Left-rotate the least significant `width` bits by `bits` positions - CBigBitVec& rotl(const size_t bits, size_t width) + /// Left-rotate by `bits` positions + CBigBitVec& rotl(const size_t bits) { - // Fill in the width, if necessary. - if (width <= 0) { - width = size(); - } - - // Modulo the number of bits. - assert(bits < width); - if (bits == 0) { + assert(bits <= size()); + if (bits == 0 || bits == size()) { return *this; } - // Ensure we are truncated appropriately. - truncate(width); + truncate(size()); CBigBitVec t1(*this); (*this) <<= bits; - t1 >>= (width - bits); + t1 >>= (size() - bits); (*this) |= t1; - truncate(width); + truncate(size()); return *this; } @@ -437,7 +429,7 @@ public: /// Return true iff all bits are zero bool none() const { - for (size_t i = 0; i < m_iRacks; ++i) { + for (size_t i = 0; i < rackCount(); ++i) { if (m_pcRacks[i]) { return false; } @@ -448,7 +440,7 @@ public: /// Return 1 + the index of the first set bit, or 0 if there are none size_t find_first() const { - for (size_t i = 0; i < m_iRacks; ++i) { + for (size_t i = 0; i < rackCount(); ++i) { const int j = ffs(m_pcRacks[i]); if (j) { return (i * bits_per_rack) + static_cast<size_t>(j); @@ -461,7 +453,7 @@ public: size_t count() const { size_t c = 0; - for (size_t i = 0; i < m_iRacks; ++i) { + for (size_t i = 0; i < rackCount(); ++i) { c += static_cast<size_t>(pop_count(m_pcRacks[i])); } return c; @@ -470,7 +462,7 @@ public: /// Flip all bits (one's complement) CBigBitVec& flip() { - for (size_t i = 0; i < m_iRacks; ++i) { + for (size_t i = 0; i < rackCount(); ++i) { m_pcRacks[i] = ~m_pcRacks[i]; } return *this; @@ -485,7 +477,7 @@ public: const Rack* racks() const { return m_pcRacks.get(); } /// Return the number of racks - size_t rackCount() const { return m_iRacks; } + size_t rackCount() const { return num_racks(m_size); } template <class BitVec> class iterator_base : public Mask @@ -600,36 +592,8 @@ private: return RacksPtr{static_cast<Rack*>(calloc(n, sizeof(Rack)))}; } - // Right rotates entire racks (in place). - void rackRotr(const size_t k) - { - assert(k < m_iRacks); - - if (k == 0) { - return; - } - - size_t c = 0; - for (size_t v = 0; c < m_iRacks; ++v) { - size_t t = v; - size_t tp = v + k; - const Rack tmp = m_pcRacks[v]; - c++; - while (tp != v) { - m_pcRacks[t] = m_pcRacks[tp]; - t = tp; - tp += k; - if (tp >= m_iRacks) { - tp -= m_iRacks; - } - c++; - } - m_pcRacks[t] = tmp; - } - } - RacksPtr m_pcRacks; - size_t m_iRacks; + size_t m_size; }; template <> |