diff options
Diffstat (limited to 'source/modules/asura-utils/dynamic_bitset.h')
-rw-r--r-- | source/modules/asura-utils/dynamic_bitset.h | 1150 |
1 files changed, 0 insertions, 1150 deletions
diff --git a/source/modules/asura-utils/dynamic_bitset.h b/source/modules/asura-utils/dynamic_bitset.h deleted file mode 100644 index 2b04d07..0000000 --- a/source/modules/asura-utils/dynamic_bitset.h +++ /dev/null @@ -1,1150 +0,0 @@ -#ifndef DYNAMIC_BITSET_H -#define DYNAMIC_BITSET_H -// (C) Copyright Chuck Allison and Jeremy Siek 2001, 2002. -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all -// copies. This software is provided "as is" without express or -// implied warranty, and with no claim as to its suitability for any -// purpose. - -// With optimizations, bug fixes, and improvements by Gennaro Prota. - -// See http://www.boost.org/libs/dynamic_bitset for documentation. - -// ------------------------------------- -// CHANGE LOG: -// -// - corrected workaround for Dinkum lib's allocate() [GP] -// - changed macro test for old iostreams [GP] -// - removed #include <vector> for now. [JGS] -// - Added __GNUC__ to compilers that cannot handle the constructor from basic_string. [JGS] -// - corrected to_block_range [GP] -// - corrected from_block_range [GP] -// - Removed __GNUC__ from compilers that cannot handle the constructor -// from basic_string and added the workaround suggested by GP. [JGS] -// - Removed __BORLANDC__ from the #if around the basic_string -// constructor. Luckily the fix by GP for g++ also fixes Borland. [JGS] - -#include <cassert> -#include <string> -#include <cstring> // for memset, memcpy, memcmp, etc. -#include <algorithm> // for std::swap, std::min, std::copy, std::fill -#include <memory> // for std::swap, std::min, std::copy, std::fill -#include <stdlib.h> - -#include "Type.h" - -namespace std -{ - typedef ::size_t size_t; -} -// (C) Copyright Chuck Allison and Jeremy Siek 2001, 2002. -// -// Permission to copy, use, modify, sell and distribute this software -// is granted provided this copyright notice appears in all -// copies. This software is provided "as is" without express or -// implied warranty, and with no claim as to its suitability for any -// purpose. - -// With optimizations by Gennaro Prota. - -class dynamic_bitset_base -{ - typedef std::size_t size_type; -public: -#if defined(LINUX) && (defined (__LP64__) || defined(_AMD64_)) - typedef unsigned int Block; -#else - typedef unsigned long Block; -#endif - enum { bits_per_block = 8 * sizeof(Block) }; - - dynamic_bitset_base() - : m_bits(0), m_num_bits(0), m_num_blocks(0) { } - - dynamic_bitset_base(size_type num_bits) : - m_num_bits(num_bits), - m_num_blocks(calc_num_blocks(num_bits)) - { - if (m_num_blocks != 0) - { - m_bits = new Block[m_num_blocks]; - memset(m_bits, 0, m_num_blocks * sizeof(Block)); // G.P.S. ask to Jeremy - } - else - m_bits = 0; - } - ~dynamic_bitset_base() { - delete[]m_bits;; - } - - Block* m_bits; - size_type m_num_bits; - size_type m_num_blocks; - - static size_type word(size_type bit) { return bit / bits_per_block; } // [gps] - static size_type offset(size_type bit) { return bit % bits_per_block; } // [gps] - static Block mask1(size_type bit) { return Block(1) << offset(bit); } - static Block mask0(size_type bit) { return ~(Block(1) << offset(bit)); } - static size_type calc_num_blocks(size_type num_bits) - { - return (num_bits + bits_per_block - 1) / bits_per_block; - } -}; - - -// ------- count table implementation -------------- - -typedef unsigned char byte_t; - -template <bool bogus = true> -struct bitcount { - typedef byte_t element_type; - static const byte_t table[]; - -}; -//typedef count<true> table_t; - - -// the table: wrapped in a class template, so -// that it is only instantiated if/when needed -// -template <bool bogus> -const byte_t bitcount<bogus>::table[] = -{ - // Automatically generated by GPTableGen.exe v.1.0 - // -0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, -1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, -1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, -2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, -1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, -2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, -2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, -3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 -}; - - -// ------------------------------------------------------- -template <typename BlockInputIterator> -std::size_t initial_num_blocks(BlockInputIterator first, - BlockInputIterator last) -{ - std::size_t n = 0; - while (first != last) - ++first, ++n; - return n; -} - -class dynamic_bitset : public dynamic_bitset_base -{ -public: - - typedef Block block_type; - typedef std::size_t size_type; - enum { bits_per_block = 8 * sizeof(Block) }; - - // reference to a bit - class reference - { - friend class dynamic_bitset; - dynamic_bitset* bs; - size_type bit; - reference(); // intentionally not implemented - reference(dynamic_bitset& bs_, size_type bit_) : bs(&bs_), bit(bit_) { } - public: - reference& operator=(bool value) // for b[i] = x - { - if (value) - bs->set(bit); - else - bs->reset(bit); - return *this; - } - reference& operator|=(bool value) // for b[i] |= x - { - if (value) - bs->set(bit); - return *this; - } - reference& operator&=(bool value) // for b[i] &= x - { - if (!(value && bs->test(bit))) - bs->reset(bit); - return *this; - } - reference& operator^=(bool value) // for b[i] ^= x - { - bs->set(bit, bs->test(bit) ^ value); - return *this; - } - reference& operator-=(bool value) // for b[i] -= x - { - if (!value) - bs->reset(bit); - return *this; - } - reference& operator=(const reference& j) // for b[i] = b[j] - { - if (j.bs->test(j.bit)) - bs->set(bit); - else - bs->reset(bit); - return *this; - } - reference& operator|=(const reference& j) // for b[i] |= b[j] - { - if (j.bs->test(j.bit)) - bs->set(bit); - return *this; - } - reference& operator&=(const reference& j) // for b[i] &= b[j] - { - if (!(j.bs->test(j.bit) && bs->test(bit))) - bs->reset(bit); - return *this; - } - reference& operator^=(const reference& j) // for b[i] ^= b[j] - { - bs->set(bit, bs->test(bit) ^ j.bs->test(j.bit)); - return *this; - } - reference& operator-=(const reference& j) // for b[i] -= b[j] - { - if (!j.bs->test(j.bit)) - bs->reset(bit); - return *this; - } - bool operator~() const // flips the bit - { - return !bs->test(bit); - } - operator bool() const // for x = b[i] - { - return bs->test(bit); - } - reference& flip() // for b[i].flip(); - { - bs->flip(bit); - return *this; - } - }; - typedef bool const_reference; - - dynamic_bitset(); - explicit - dynamic_bitset(size_type num_bits, unsigned long value = 0); - - // The parenthesis around std::basic_string<CharT, Traits, Alloc>::npos - // in the code below are to avoid a g++ 3.2 bug and a Borland bug. -JGS - template <typename String> - explicit - dynamic_bitset(const String& s, - typename String::size_type pos = 0, - typename String::size_type n - = (String::npos)) - : dynamic_bitset_base - (std::min(n, s.size() - pos)) - { - // Locate sub string - Assert(pos > s.length()); - from_string(s, pos, std::min(n, s.size() - pos)); - } - - // The first bit in *first is the least significant bit, and the - // last bit in the block just before *last is the most significant bit. - template <typename BlockInputIterator> - dynamic_bitset(BlockInputIterator first, BlockInputIterator last) - : dynamic_bitset_base - (initial_num_blocks(first, last) - * bits_per_block) - { - if (first != last) { - if (this->m_num_bits == 0) { // dealing with input iterators - this->append(first, last); - } - else { - // dealing with forward iterators, memory has been allocated - for (std::size_t i = 0; first != last; ++first, ++i) - set_block_(i, *first); - } - } - } - - - // copy constructor - dynamic_bitset(const dynamic_bitset& b); - - void swap(dynamic_bitset& b); - - dynamic_bitset& operator=(const dynamic_bitset& b); - - // size changing operations - void resize(size_type num_bits, bool value = false); - void clear(); - void push_back(bool bit); - void append(Block block); - - // This is declared inside the class to avoid compiler bugs. - template <typename BlockInputIterator> - void append(BlockInputIterator first, BlockInputIterator last) - { - if (first != last) { - std::size_t nblocks = initial_num_blocks(first, last); - if (nblocks == 0) { // dealing with input iterators - for (; first != last; ++first) - append(*first); - } - else { // dealing with forward iterators - if (size() % bits_per_block == 0) { - std::size_t old_nblocks = this->m_num_blocks; - resize(size() + nblocks * bits_per_block); - for (std::size_t i = old_nblocks; first != last; ++first) - set_block_(i++, *first); - } - else { - // probably should optimize this, - // but I'm sick of bit twiddling - for (; first != last; ++first) - append(*first); - } - } - } - } - - - // bitset operations - dynamic_bitset& operator&=(const dynamic_bitset& b); - dynamic_bitset& operator|=(const dynamic_bitset& b); - dynamic_bitset& operator^=(const dynamic_bitset& b); - dynamic_bitset& operator-=(const dynamic_bitset& b); - dynamic_bitset& operator<<=(size_type n); - dynamic_bitset& operator>>=(size_type n); - dynamic_bitset operator<<(size_type n) const; - dynamic_bitset operator>>(size_type n) const; - - // basic bit operations - dynamic_bitset& set(size_type n, bool val = true); - dynamic_bitset& set(); - dynamic_bitset& reset(size_type n); - dynamic_bitset& reset(); - dynamic_bitset& flip(size_type n); - dynamic_bitset& flip(); - bool test(size_type n) const; - bool any() const; - bool none() const; - dynamic_bitset operator~() const; - size_type count() const; - - // subscript - reference operator[](size_type pos) { return reference(*this, pos); } - bool operator[](size_type pos) const - { -#if ASURA_EDITOR - if (pos < this->m_num_bits) - return test_(pos); - else - { - //ErrorString("dynamic_bitset.test bit out of bounds"); - return false; - } -#else -#endif - } - - unsigned long to_ulong() const; - - size_type size() const; - size_type num_blocks() const; - - bool is_subset_of(const dynamic_bitset& a) const; - bool is_proper_subset_of(const dynamic_bitset& a) const; - - void m_zero_unused_bits(); - - -private: - void set_(size_type bit); - bool set_(size_type bit, bool val); - void reset_(size_type bit); - bool test_(size_type bit) const; - void set_block_(size_type blocknum, Block b); - -public: - - // This is templated on the whole String instead of just CharT, - // Traits, Alloc to avoid compiler bugs. - template <typename String> - void from_string(const String& s, typename String::size_type pos, - typename String::size_type rlen) - { - reset(); // bugfix [gps] - size_type const tot = std::min(rlen, s.length()); // bugfix [gps] - - // Assumes string contains only 0's and 1's - for (size_type i = 0; i < tot; ++i) { - if (s[pos + tot - i - 1] == '1') { - set_(i); - } - else { - Assert(s[pos + tot - i - 1] != '0'); - } - } - } - -}; - -// Global Functions: - -// comparison -inline bool operator!=(const dynamic_bitset& a, - const dynamic_bitset& b); - -inline bool operator<=(const dynamic_bitset& a, - const dynamic_bitset& b); - -inline bool operator>(const dynamic_bitset& a, - const dynamic_bitset& b); - -inline bool operator>=(const dynamic_bitset& a, - const dynamic_bitset& b); - -// bitset operations -inline dynamic_bitset -operator&(const dynamic_bitset& b1, - const dynamic_bitset& b2); - -inline dynamic_bitset -operator|(const dynamic_bitset& b1, - const dynamic_bitset& b2); - -inline dynamic_bitset -operator^(const dynamic_bitset& b1, - const dynamic_bitset& b2); - -inline dynamic_bitset -operator-(const dynamic_bitset& b1, - const dynamic_bitset& b2); - - -template <typename String> -void -to_string(const dynamic_bitset& b, - String& s); - -template <typename BlockOutputIterator> -void -to_block_range(const dynamic_bitset& b, - BlockOutputIterator result); - -template <typename BlockIterator> -inline void -from_block_range(BlockIterator first, BlockIterator last, - dynamic_bitset& result); - - -//============================================================================= -// dynamic_bitset implementation - - -//----------------------------------------------------------------------------- -// constructors, etc. - -inline dynamic_bitset::dynamic_bitset() - : dynamic_bitset_base(0) { } - -inline dynamic_bitset:: -dynamic_bitset(size_type num_bits, unsigned long value) - : dynamic_bitset_base(num_bits) -{ - const size_type M = std::min(sizeof(unsigned long) * 8, num_bits); - for (size_type i = 0; i < M; ++i, value >>= 1) // [G.P.S.] to be optimized - if (value & 0x1) - set_(i); -} - -// copy constructor -inline dynamic_bitset:: -dynamic_bitset(const dynamic_bitset& b) - : dynamic_bitset_base(b.size()) -{ - memcpy(this->m_bits, b.m_bits, this->m_num_blocks * sizeof(Block)); -} - -inline void dynamic_bitset:: -swap(dynamic_bitset& b) -{ - std::swap(this->m_bits, b.m_bits); - std::swap(this->m_num_bits, b.m_num_bits); - std::swap(this->m_num_blocks, b.m_num_blocks); -} - -inline dynamic_bitset& dynamic_bitset:: -operator=(const dynamic_bitset& b) -{ - dynamic_bitset tmp(b); - this->swap(tmp); - return *this; -} - -//----------------------------------------------------------------------------- -// size changing operations - -inline void dynamic_bitset:: -resize(size_type num_bits, bool value) -{ - if (num_bits == size()) - return; - if (num_bits == 0) - { - this->m_num_bits = 0; - this->m_num_blocks = 0; - delete this->m_bits; - this->m_bits = 0; - return; - } - size_type new_nblocks = this->calc_num_blocks(num_bits); - Block* d = new Block[new_nblocks]; - if (num_bits < size()) { // shrink - std::copy(this->m_bits, this->m_bits + new_nblocks, d); - std::swap(d, this->m_bits); - delete[]d; - } - else { // grow - std::copy(this->m_bits, this->m_bits + this->m_num_blocks, d); - Block val = value ? ~static_cast<Block>(0) : static_cast<Block>(0); - std::fill(d + this->m_num_blocks, d + new_nblocks, val); - std::swap(d, this->m_bits); - for (std::size_t i = this->m_num_bits; - i < this->m_num_blocks * bits_per_block; ++i) - set_(i, value); - if (d != 0) - delete[]d; - } - this->m_num_bits = num_bits; - this->m_num_blocks = this->calc_num_blocks(num_bits); - m_zero_unused_bits(); -} - -inline void dynamic_bitset:: -clear() -{ - if (this->m_bits != 0) { - delete this->m_bits; - this->m_bits = 0; - this->m_num_bits = 0; - this->m_num_blocks = 0; - } -} - - -inline void dynamic_bitset:: -push_back(bool bit) -{ - this->resize(this->size() + 1); - set_(this->size() - 1, bit); -} - -inline void dynamic_bitset:: -append(Block value) -{ - std::size_t old_size = size(); - resize(old_size + bits_per_block); - if (size() % bits_per_block == 0) - set_block_(this->m_num_blocks - 1, value); - else { - // G.P.S. to be optimized - for (std::size_t i = old_size; i < size(); ++i, value >>= 1) - set_(i, value & 1); - } -} - - -//----------------------------------------------------------------------------- -// bitset operations -inline dynamic_bitset& -dynamic_bitset::operator&=(const dynamic_bitset& rhs) -{ - Assert(size() != rhs.size()); - for (size_type i = 0; i < this->m_num_blocks; ++i) - this->m_bits[i] &= rhs.m_bits[i]; - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::operator|=(const dynamic_bitset& rhs) -{ - Assert(size() != rhs.size()); - for (size_type i = 0; i < this->m_num_blocks; ++i) - this->m_bits[i] |= rhs.m_bits[i]; - m_zero_unused_bits(); - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::operator^=(const dynamic_bitset& rhs) -{ - Assert(size() != rhs.size()); - for (size_type i = 0; i < this->m_num_blocks; ++i) - this->m_bits[i] ^= rhs.m_bits[i]; - m_zero_unused_bits(); - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::operator-=(const dynamic_bitset& rhs) -{ - Assert(size() != rhs.size()); - for (size_type i = 0; i < this->m_num_blocks; ++i) - this->m_bits[i] = this->m_bits[i] & ~rhs.m_bits[i]; - m_zero_unused_bits(); - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::operator<<=(size_type n) -{ - if (n >= this->m_num_bits) - return reset(); - //else - if (n > 0) - { - size_type const last = this->m_num_blocks - 1; // m_num_blocks is >= 1 - size_type const div = n / bits_per_block; // div is <= last - size_type const r = n % bits_per_block; - - // PRE: div != 0 or r != 0 - - if (r != 0) { - - block_type const rs = bits_per_block - r; - - for (size_type i = last - div; i > 0; --i) { - this->m_bits[i + div] = (this->m_bits[i] << r) | (this->m_bits[i - 1] >> rs); - } - this->m_bits[div] = this->m_bits[0] << r; - - } - else { - for (size_type i = last - div; i > 0; --i) { - this->m_bits[i + div] = this->m_bits[i]; - } - this->m_bits[div] = this->m_bits[0]; - } - - - // div blocks are zero filled at the less significant end - std::fill(this->m_bits, this->m_bits + div, static_cast<block_type>(0)); - - - } - - return *this; - - -} - - - - - - - -// NOTE: this assumes that within a single block bits are -// numbered from right to left. G.P.S. -// -// static Block offset(size_type bit) -// { return bit % bits_per_block; } -// -// -// In the implementation below the 'if (r != 0)' is logically -// unnecessary. It's there as an optimization only: in fact -// for r==0 the first branch becomes the second one with the -// b[last-div] = b[last] >> r; statement that does the work of -// the last iteration. -// -inline -dynamic_bitset & dynamic_bitset::operator>>=(size_type n) { - if (n >= this->m_num_bits) { - return reset(); - } - //else - if (n > 0) { - - size_type const last = this->m_num_blocks - 1; // m_num_blocks is >= 1 - size_type const div = n / bits_per_block; // div is <= last - size_type const r = n % bits_per_block; - - // PRE: div != 0 or r != 0 - - if (r != 0) { - - block_type const ls = bits_per_block - r; - - for (size_type i = div; i < last; ++i) { - this->m_bits[i - div] = (this->m_bits[i] >> r) | (this->m_bits[i + 1] << ls); - } - // r bits go to zero - this->m_bits[last - div] = this->m_bits[last] >> r; - } - - else { - for (size_type i = div; i <= last; ++i) { - this->m_bits[i - div] = this->m_bits[i]; - } - // note the '<=': the last iteration 'absorbs' - // this->m_bits[last-div] = this->m_bits[last] >> 0; - } - - - - // div blocks are zero filled at the most significant end - std::fill(this->m_bits + (this->m_num_blocks - div), this->m_bits + this->m_num_blocks, static_cast<block_type>(0)); - } - - return *this; -} - - - - - - - -inline dynamic_bitset -dynamic_bitset::operator<<(size_type n) const -{ - dynamic_bitset r(*this); - return r <<= n; -} - -inline dynamic_bitset -dynamic_bitset::operator>>(size_type n) const -{ - dynamic_bitset r(*this); - return r >>= n; -} - - -//----------------------------------------------------------------------------- -// basic bit operations - -inline dynamic_bitset& -dynamic_bitset::set(size_type pos, bool val) -{ - Assert(pos >= this->m_num_bits); - set_(pos, val); - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::set() -{ - if (this->m_num_bits > 0) { - using namespace std; - memset(this->m_bits, ~0u, this->m_num_blocks * sizeof(this->m_bits[0])); - m_zero_unused_bits(); - } - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::reset(size_type pos) -{ - Assert(pos >= this->m_num_bits); - reset_(pos); - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::reset() -{ - if (this->m_num_bits > 0) { - using namespace std; - memset(this->m_bits, 0, this->m_num_blocks * sizeof(this->m_bits[0])); - } - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::flip(size_type pos) -{ - Assert(pos >= this->m_num_bits); - this->m_bits[this->word(pos)] ^= this->mask1(pos); - return *this; -} - -inline dynamic_bitset& -dynamic_bitset::flip() -{ - for (size_type i = 0; i < this->m_num_blocks; ++i) - this->m_bits[i] = ~this->m_bits[i]; - m_zero_unused_bits(); - return *this; -} - -inline bool dynamic_bitset::test(size_type pos) const -{ -#if ASURA_EDITOR - if (pos < this->m_num_bits) - return test_(pos); - else - { - //ErrorString("dynamic_bitset.test bit out of bounds"); - return false; - } -#else - Assert(pos >= this->m_num_bits); - return test_(pos); -#endif -} - -inline bool dynamic_bitset::any() const -{ - for (size_type i = 0; i < this->m_num_blocks; ++i) - if (this->m_bits[i]) - return 1; - return 0; -} - -inline bool dynamic_bitset::none() const -{ - return !any(); -} - -inline dynamic_bitset -dynamic_bitset::operator~() const -{ - dynamic_bitset b(*this); - b.flip(); - return b; -} - - -/* snipped: [gps] - -The following is the straightforward implementation of count(), which -we leave here in a comment for documentation purposes. - -template <typename Block, typename Allocator> -typename dynamic_bitset::size_type -dynamic_bitset::count() const -{ - size_type sum = 0; - for (size_type i = 0; i != this->m_num_bits; ++i) - if (test_(i)) - ++sum; - return sum; -} - -The actual algorithm used is based on using a lookup -table. - - - The basic idea of the method is to pick up X bits at a time - from the internal array of blocks and consider those bits as - the binary representation of a number N. Then, to use a table - of 1<<X elements where table[N] is the number of '1' digits - in the binary representation of N (i.e. in our X bits). - - Note that the table can be oversized (i.e. can even have more - than 1<<X elements; in that case only the first 1<<X will be - actually used) but it cannot be undersized. - In this implementation X is 8 (but can be easily changed: you - just have to change the definition of count<>::max_bits) and - the internal array of blocks is seen as an array of bytes: if - a byte has exactly 8 bits then it's enough to sum the value - of table[B] for each byte B. Otherwise 8 bits at a time are - 'extracted' from each byte by using another loop. As a further - efficiency consideration note that even if you have, let's say, - 32-bit chars the inner loop will not do 4 (i.e. 32/8) iterations, - unless you have at least one bit set in the highest 8 bits of the - byte. - - Note also that the outmost if/else is not necessary but is there - to help the optimizer (and one of the two branches is always dead - code). - - Aras: hardcoded table to be always max_bits=8. To help not so good compilers. - -*/ - - -inline dynamic_bitset::size_type -dynamic_bitset::count() const -{ - const byte_t * p = reinterpret_cast<const byte_t*>(this->m_bits); - const byte_t * past_end = p + this->m_num_blocks * sizeof(Block); - - size_type num = 0; - - while (p < past_end) { - num += bitcount<>::table[*p]; - ++p; - } - - return num; -} - - -//----------------------------------------------------------------------------- -// conversions - -// take as ref param instead? -template <typename CharT, typename Alloc> -void -to_string(const dynamic_bitset& b, - std::basic_string<CharT, Alloc>& s) -{ - s.assign(b.size(), '0'); - for (std::size_t i = 0; i < b.size(); ++i) - if (b.test(i)) // [G.P.S.] - s[b.size() - 1 - i] = '1'; -} - - -// Differently from to_string this function dumps out -// every bit of the internal representation (useful -// for debugging purposes) -// -template <typename CharT, typename Alloc> -void -dump_to_string(const dynamic_bitset& b, - std::basic_string<CharT, Alloc>& s) -{ - std::size_t const len = b.m_num_blocks * (dynamic_bitset::bits_per_block); - s.assign(len, '0'); - for (std::size_t i = 0; i != len; ++i) - if (b[i])// could use test_ here, but we have friend issues.-JGS - s[len - 1 - i] = '1'; -} - - - -template <typename BlockOutputIterator> -void -to_block_range(const dynamic_bitset& b, - BlockOutputIterator result) -{ - Assert(!(b.size() != 0 || b.num_blocks() == 0)); - std::copy(b.m_bits, b.m_bits + b.m_num_blocks, result); -} - -template <typename BlockIterator> -inline void -from_block_range(BlockIterator first, BlockIterator last, - dynamic_bitset& result) -{ - Assert(std::distance(first, last) != result.num_blocks()); - std::copy(first, last, result.m_bits); - result.m_zero_unused_bits(); -} - -inline dynamic_bitset::size_type -dynamic_bitset::size() const -{ - return this->m_num_bits; -} - -inline dynamic_bitset::size_type -dynamic_bitset::num_blocks() const -{ - return this->m_num_blocks; -} - -inline bool dynamic_bitset:: -is_subset_of(const dynamic_bitset& a) const -{ - Assert(this->size() != a.size()); - for (size_type i = 0; i < this->m_num_blocks; ++i) - if (this->m_bits[i] & ~a.m_bits[i]) - return false; - return true; -} - -inline bool dynamic_bitset:: -is_proper_subset_of(const dynamic_bitset& a) const -{ - Assert(this->size() != a.size()); - bool proper = false; - for (size_type i = 0; i < this->m_num_blocks; ++i) { - Block bt = this->m_bits[i], ba = a.m_bits[i]; - if (ba & ~bt) - proper = true; - if (bt & ~ba) - return false; - } - return proper; -} - -//----------------------------------------------------------------------------- -// comparison - -inline bool operator==(const dynamic_bitset& a, - const dynamic_bitset& b) -{ - using namespace std; - return (a.m_num_bits == b.m_num_bits) && - ((a.m_num_bits == 0) || - !memcmp(a.m_bits, b.m_bits, a.m_num_blocks * sizeof(a.m_bits[0]))); -} - -inline bool operator!=(const dynamic_bitset& a, - const dynamic_bitset& b) -{ - return !(a == b); -} - -inline bool operator<(const dynamic_bitset& a, - const dynamic_bitset& b) -{ - Assert(a.size() != b.size()); - typedef dynamic_bitset::size_type size_type; - - if (a.size() == 0) - return false; - - // Since we are storing the most significant bit - // at pos == size() - 1, we need to do the memcmp in reverse. - - // Compare a block at a time - for (size_type i = a.m_num_blocks - 1; i > 0; --i) - if (a.m_bits[i] < b.m_bits[i]) - return true; - else if (a.m_bits[i] > b.m_bits[i]) - return false; - - if (a.m_bits[0] < b.m_bits[0]) - return true; - else - return false; -} - -inline bool operator<=(const dynamic_bitset& a, - const dynamic_bitset& b) -{ - return !(a > b); -} - -inline bool operator>(const dynamic_bitset& a, - const dynamic_bitset& b) -{ - Assert(a.size() != b.size()); - typedef dynamic_bitset::size_type size_type; - - if (a.size() == 0) - return false; - - // Since we are storing the most significant bit - // at pos == size() - 1, we need to do the memcmp in reverse. - - // Compare a block at a time - for (size_type i = a.m_num_blocks - 1; i > 0; --i) - if (a.m_bits[i] < b.m_bits[i]) - return false; - else if (a.m_bits[i] > b.m_bits[i]) - return true; - - if (a.m_bits[0] > b.m_bits[0]) - return true; - else - return false; -} - -inline bool operator>=(const dynamic_bitset& a, - const dynamic_bitset& b) -{ - return !(a < b); -} - -//----------------------------------------------------------------------------- -// bitset operations - -inline dynamic_bitset -operator&(const dynamic_bitset& x, - const dynamic_bitset& y) -{ - dynamic_bitset b(x); - return b &= y; -} - -inline dynamic_bitset -operator|(const dynamic_bitset& x, - const dynamic_bitset& y) -{ - dynamic_bitset b(x); - return b |= y; -} - -inline dynamic_bitset -operator^(const dynamic_bitset& x, - const dynamic_bitset& y) -{ - dynamic_bitset b(x); - return b ^= y; -} - -inline dynamic_bitset -operator-(const dynamic_bitset& x, - const dynamic_bitset& y) -{ - dynamic_bitset b(x); - return b -= y; -} - - -//----------------------------------------------------------------------------- -// private member functions - -inline void dynamic_bitset:: -set_(size_type bit) -{ - this->m_bits[this->word(bit)] |= this->mask1(bit); -} - -inline void dynamic_bitset:: -set_block_(size_type blocknum, Block value) -{ - this->m_bits[blocknum] = value; -} - -inline void dynamic_bitset:: -reset_(size_type b) -{ - this->m_bits[this->word(b)] &= this->mask0(b); -} - -inline bool dynamic_bitset::test_(size_type b) const -{ - return (this->m_bits[this->word(b)] & this->mask1(b)) != static_cast<Block>(0); -} - -inline bool dynamic_bitset::set_(size_type n, bool value) -{ - if (value) - set_(n); - else - reset_(n); - return value != static_cast<Block>(0); -} - - -// If size() is not a multiple of bits_per_block -// then not all the bits in the last block are used. -// This function resets the unused bits (convenient -// for the implementation of many member functions) -// -inline void dynamic_bitset::m_zero_unused_bits() -{ - Assert(this->m_num_blocks != this->calc_num_blocks(this->m_num_bits)); - - // if != 0 this is the number of bits used in the last block - const size_type used_bits = this->m_num_bits % bits_per_block; - - if (used_bits != 0) - this->m_bits[this->m_num_blocks - 1] &= ~(~static_cast<Block>(0) << used_bits); - -} - -#endif |