x
Yes
No
Do you want to visit DriveHQ English website?
首页
产品服务
价格
免费试用
下载客户端
关于我们
云文件服务
|
云备份服务
|
FTP服务
|
企业邮箱服务
|
网站托管
|
客户端软件
云文件服务
云备份服务
FTP服务
企业级邮箱服务
网站托管
客户端软件
dynamic_bitset.hpp - Hosted on DriveHQ Cloud IT Platform
返回上层目录
上传
下载
共享
发布
新建文件夹
新建文件
复制
剪切
删除
粘贴
评论
升级服务
路径: \\game3dprogramming\materials\GameFactory\GameFactoryDemo\references\boost_1_35_0\boost\dynamic_bitset\dynamic_bitset.hpp
旋转
特效
属性
历史版本
// -------------------------------------------------- // // (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002. // (C) Copyright Gennaro Prota 2003 - 2006. // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // ----------------------------------------------------------- // See http://www.boost.org/libs/dynamic_bitset/ for documentation. // // $Revision: 41959 $ $Date: 2007-12-10 13:51:19 -0500 (Mon, 10 Dec 2007) $ - $Name$ #ifndef BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP #define BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP #include
#include
#include
// for std::overflow_error #include
// for std::swap, min, copy, fill #include
#include
// for CHAR_BIT #include "boost/dynamic_bitset/config.hpp" #ifndef BOOST_NO_STD_LOCALE # include
#endif #if defined(BOOST_OLD_IOSTREAMS) # include
# include
// for isspace #else # include
# include
#endif #include "boost/dynamic_bitset_fwd.hpp" #include "boost/detail/dynamic_bitset.hpp" #include "boost/detail/iterator.hpp" // used to implement append(Iter, Iter) #include "boost/static_assert.hpp" #include "boost/limits.hpp" #include "boost/pending/lowest_bit.hpp" // used by find_first/next namespace boost { template #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1300) // 1300 == VC++ 7.0 // VC++ (up to 7.0) wants the default arguments again
> # else
# endif class dynamic_bitset { // Portability note: member function templates are defined inside // this class definition to avoid problems with VC++. Similarly, // with the member functions of nested classes. BOOST_STATIC_ASSERT(detail::dynamic_bitset_allowed_block_type
::value); public: typedef Block block_type; typedef Allocator allocator_type; typedef std::size_t size_type; typedef int block_width_type; BOOST_STATIC_CONSTANT(block_width_type, bits_per_block = (std::numeric_limits
::digits)); BOOST_STATIC_CONSTANT(size_type, npos = static_cast
(-1)); public: // A proxy class to simulate lvalues of bit type. // class reference { friend class dynamic_bitset
; // the one and only non-copy ctor reference(block_type & b, int pos) :m_block(b), m_mask(block_type(1) << pos) { assert(pos >= 0 && pos < bits_per_block); } void operator&(); // left undefined public: // copy constructor: compiler generated operator bool() const { return (m_block & m_mask) != 0; } bool operator~() const { return (m_block & m_mask) == 0; } reference& flip() { do_flip(); return *this; } reference& operator=(bool x) { do_assign(x); return *this; } // for b[i] = x reference& operator=(const reference& rhs) { do_assign(rhs); return *this; } // for b[i] = b[j] reference& operator|=(bool x) { if (x) do_set(); return *this; } reference& operator&=(bool x) { if (!x) do_reset(); return *this; } reference& operator^=(bool x) { if (x) do_flip(); return *this; } reference& operator-=(bool x) { if (x) do_reset(); return *this; } private: block_type & m_block; const block_type m_mask; void do_set() { m_block |= m_mask; } void do_reset() { m_block &= ~m_mask; } void do_flip() { m_block ^= m_mask; } void do_assign(bool x) { x? do_set() : do_reset(); } }; typedef bool const_reference; // constructors, etc. explicit dynamic_bitset(const Allocator& alloc = Allocator()); explicit dynamic_bitset(size_type num_bits, unsigned long value = 0, const Allocator& alloc = Allocator()); // WARNING: you should avoid using this constructor. // // A conversion from string is, in most cases, formatting, // and should be performed by using operator>>. // // NOTE: // Leave the parentheses around std::basic_string
::npos. // g++ 3.2 requires them and probably the standard will - see core issue 325 // NOTE 2: // split into two constructors because of bugs in MSVC 6.0sp5 with STLport template
dynamic_bitset(const std::basic_string
& s, typename std::basic_string
::size_type pos, typename std::basic_string
::size_type n, size_type num_bits = npos, const Allocator& alloc = Allocator()) :m_bits(alloc), m_num_bits(0) { init_from_string(s, pos, n, num_bits); } template
explicit dynamic_bitset(const std::basic_string
& s, typename std::basic_string
::size_type pos = 0) :m_bits(Allocator()), m_num_bits(0) { init_from_string(s, pos, (std::basic_string
::npos), npos); } // 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
dynamic_bitset(BlockInputIterator first, BlockInputIterator last, const Allocator& alloc = Allocator()) :m_bits(first, last, alloc), m_num_bits(m_bits.size() * bits_per_block) {} // copy constructor dynamic_bitset(const dynamic_bitset& b); ~dynamic_bitset(); void swap(dynamic_bitset& b); dynamic_bitset& operator=(const dynamic_bitset& b); allocator_type get_allocator() const; // size changing operations void resize(size_type num_bits, bool value = false); void clear(); void push_back(bool bit); void append(Block block); template
void m_append(BlockInputIterator first, BlockInputIterator last, std::input_iterator_tag) { std::vector
v(first, last); m_append(v.begin(), v.end(), std::random_access_iterator_tag()); } template
void m_append(BlockInputIterator first, BlockInputIterator last, std::forward_iterator_tag) { assert(first != last); block_width_type r = count_extra_bits(); std::size_t d = boost::detail::distance(first, last); m_bits.reserve(num_blocks() + d); if (r == 0) { for( ; first != last; ++first) m_bits.push_back(*first); // could use vector<>::insert() } else { m_highest_block() |= (*first << r); do { Block b = *first >> (bits_per_block - r); ++first; m_bits.push_back(b | (first==last? 0 : *first << r)); } while (first != last); } m_num_bits += bits_per_block * d; } template
void append(BlockInputIterator first, BlockInputIterator last) // strong guarantee { if (first != last) { typename detail::iterator_traits
::iterator_category cat; m_append(first, last, cat); } } // 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(m_bits[block_index(pos)], bit_index(pos)); } bool operator[](size_type pos) const { return test(pos); } unsigned long to_ulong() const; size_type size() const; size_type num_blocks() const; size_type max_size() const; bool empty() const; bool is_subset_of(const dynamic_bitset& a) const; bool is_proper_subset_of(const dynamic_bitset& a) const; bool intersects(const dynamic_bitset & a) const; // lookup size_type find_first() const; size_type find_next(size_type pos) const; #if !defined BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS // lexicographical comparison template
friend bool operator==(const dynamic_bitset
& a, const dynamic_bitset
& b); template
friend bool operator<(const dynamic_bitset
& a, const dynamic_bitset
& b); template
friend void to_block_range(const dynamic_bitset
& b, BlockOutputIterator result); template
friend void from_block_range(BlockIterator first, BlockIterator last, dynamic_bitset
& result); template
friend std::basic_istream
& operator>>(std::basic_istream
& is, dynamic_bitset
& b); template
friend void to_string_helper(const dynamic_bitset
& b, stringT & s, bool dump_all); #endif private: BOOST_STATIC_CONSTANT(block_width_type, ulong_width = std::numeric_limits
::digits); typedef std::vector
buffer_type; void m_zero_unused_bits(); bool m_check_invariants() const; size_type m_do_find_from(size_type first_block) const; block_width_type count_extra_bits() const { return bit_index(size()); } static size_type block_index(size_type pos) { return pos / bits_per_block; } static block_width_type bit_index(size_type pos) { return static_cast
(pos % bits_per_block); } static Block bit_mask(size_type pos) { return Block(1) << bit_index(pos); } template
void init_from_string(const std::basic_string
& s, typename std::basic_string
::size_type pos, typename std::basic_string
::size_type n, size_type num_bits) { assert(pos <= s.size()); typedef typename std::basic_string
StrT; typedef typename StrT::traits_type Tr; const typename StrT::size_type rlen = (std::min)(n, s.size() - pos); const size_type sz = ( num_bits != npos? num_bits : rlen); m_bits.resize(calc_num_blocks(sz)); m_num_bits = sz; BOOST_DYNAMIC_BITSET_CTYPE_FACET(CharT, fac, std::locale()); const CharT one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1'); const size_type m = num_bits < rlen ? num_bits : rlen; typename StrT::size_type i = 0; for( ; i < m; ++i) { const CharT c = s[(pos + m - 1) - i]; assert( Tr::eq(c, one) || Tr::eq(c, BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0')) ); if (Tr::eq(c, one)) set(i); } } BOOST_DYNAMIC_BITSET_PRIVATE: bool m_unchecked_test(size_type pos) const; static size_type calc_num_blocks(size_type num_bits); Block& m_highest_block(); const Block& m_highest_block() const; buffer_type m_bits; size_type m_num_bits; class bit_appender; friend class bit_appender; class bit_appender { // helper for stream >> // Supplies to the lack of an efficient append at the less // significant end: bits are actually appended "at left" but // rearranged in the destructor. From the perspective of // client code everything works *as if* dynamic_bitset<> had // an append_at_right() function (eventually throwing the same // exceptions as push_back) except that the function is in fact // called bit_appender::do_append(). // dynamic_bitset & bs; size_type n; Block mask; Block * current; public: bit_appender(dynamic_bitset & r) : bs(r), n(0), mask(0), current(0) {} ~bit_appender() { // reverse the order of blocks, shift // if needed, and then resize // std::reverse(bs.m_bits.begin(), bs.m_bits.end()); const block_width_type offs = bit_index(n); if (offs) bs >>= (bits_per_block - offs); bs.resize(n); // doesn't enlarge, so can't throw assert(bs.m_check_invariants()); } inline void do_append(bool value) { if (mask == 0) { bs.append(Block(0)); current = &bs.m_highest_block(); mask = Block(1) << (bits_per_block - 1); } if(value) *current |= mask; mask /= 2; ++n; } size_type get_count() const { return n; } }; }; #if defined(__IBMCPP__) && BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600)) // Workaround for IBM's AIX platform. // See http://comments.gmane.org/gmane.comp.lib.boost.user/15331 // // NOTE: // The compiler is actually right, until core issue 454 will be settled: // http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active.html#454 // // It's arguable whether we want to mark this with BOOST_WORKAROUND or not. template
dynamic_bitset
::block_width_type const dynamic_bitset
::bits_per_block; template
dynamic_bitset
::block_width_type const dynamic_bitset
::ulong_width; #endif // Global Functions: // comparison template
bool operator!=(const dynamic_bitset
& a, const dynamic_bitset
& b); template
bool operator<=(const dynamic_bitset
& a, const dynamic_bitset
& b); template
bool operator>(const dynamic_bitset
& a, const dynamic_bitset
& b); template
bool operator>=(const dynamic_bitset
& a, const dynamic_bitset
& b); // stream operators #ifdef BOOST_OLD_IOSTREAMS template
std::ostream& operator<<(std::ostream& os, const dynamic_bitset
& b); template
std::istream& operator>>(std::istream& is, dynamic_bitset
& b); #else template
std::basic_ostream
& operator<<(std::basic_ostream
& os, const dynamic_bitset
& b); template
std::basic_istream
& operator>>(std::basic_istream
& is, dynamic_bitset
& b); #endif // bitset operations template
dynamic_bitset
operator&(const dynamic_bitset
& b1, const dynamic_bitset
& b2); template
dynamic_bitset
operator|(const dynamic_bitset
& b1, const dynamic_bitset
& b2); template
dynamic_bitset
operator^(const dynamic_bitset
& b1, const dynamic_bitset
& b2); template
dynamic_bitset
operator-(const dynamic_bitset
& b1, const dynamic_bitset
& b2); // namespace scope swap template
void swap(dynamic_bitset
& b1, dynamic_bitset
& b2); template
void to_string(const dynamic_bitset
& b, stringT & s); template
void to_block_range(const dynamic_bitset
& b, BlockOutputIterator result); template
inline void from_block_range(BlockIterator first, BlockIterator last, dynamic_bitset
& result) { // PRE: distance(first, last) <= numblocks() std::copy (first, last, result.m_bits.begin()); } //============================================================================= // dynamic_bitset implementation //----------------------------------------------------------------------------- // constructors, etc. template
dynamic_bitset
::dynamic_bitset(const Allocator& alloc) : m_bits(alloc), m_num_bits(0) { } template
dynamic_bitset
:: dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc) : m_bits(calc_num_blocks(num_bits), Block(0), alloc), m_num_bits(num_bits) { typedef unsigned long num_type; typedef boost::detail::shifter
shifter; //if (num_bits == 0) // return; // zero out all bits at pos >= num_bits, if any; // note that: num_bits == 0 implies value == 0 if (num_bits < static_cast
(ulong_width)) { const num_type mask = (num_type(1) << num_bits) - 1; value &= mask; } typename buffer_type::iterator it = m_bits.begin(); for( ; value; shifter::left_shift(value), ++it) { *it = static_cast
(value); } } // copy constructor template
inline dynamic_bitset
:: dynamic_bitset(const dynamic_bitset& b) : m_bits(b.m_bits), m_num_bits(b.m_num_bits) { } template
inline dynamic_bitset
:: ~dynamic_bitset() { assert(m_check_invariants()); } template
inline void dynamic_bitset
:: swap(dynamic_bitset
& b) // no throw { std::swap(m_bits, b.m_bits); std::swap(m_num_bits, b.m_num_bits); } template
dynamic_bitset
& dynamic_bitset
:: operator=(const dynamic_bitset
& b) { m_bits = b.m_bits; m_num_bits = b.m_num_bits; return *this; } template
inline typename dynamic_bitset
::allocator_type dynamic_bitset
::get_allocator() const { return m_bits.get_allocator(); } //----------------------------------------------------------------------------- // size changing operations template
void dynamic_bitset
:: resize(size_type num_bits, bool value) // strong guarantee { const size_type old_num_blocks = num_blocks(); const size_type required_blocks = calc_num_blocks(num_bits); const block_type v = value? ~Block(0) : Block(0); if (required_blocks != old_num_blocks) { m_bits.resize(required_blocks, v); // s.g. (copy) } // At this point: // // - if the buffer was shrunk, we have nothing more to do, // except a call to m_zero_unused_bits() // // - if it was enlarged, all the (used) bits in the new blocks have // the correct value, but we have not yet touched those bits, if // any, that were 'unused bits' before enlarging: if value == true, // they must be set. if (value && (num_bits > m_num_bits)) { const size_type extra_bits = count_extra_bits(); if (extra_bits) { assert(old_num_blocks >= 1 && old_num_blocks <= m_bits.size()); // Set them. m_bits[old_num_blocks - 1] |= (v << extra_bits); } } m_num_bits = num_bits; m_zero_unused_bits(); } template
void dynamic_bitset
:: clear() // no throw { m_bits.clear(); m_num_bits = 0; } template
void dynamic_bitset
:: push_back(bool bit) { const size_type sz = size(); resize(sz + 1); set(sz, bit); } template
void dynamic_bitset
:: append(Block value) // strong guarantee { const block_width_type r = count_extra_bits(); if (r == 0) { // the buffer is empty, or all blocks are filled m_bits.push_back(value); } else { m_bits.push_back(value >> (bits_per_block - r)); m_bits[m_bits.size() - 2] |= (value << r); // m_bits.size() >= 2 } m_num_bits += bits_per_block; assert(m_check_invariants()); } //----------------------------------------------------------------------------- // bitset operations template
dynamic_bitset
& dynamic_bitset
::operator&=(const dynamic_bitset& rhs) { assert(size() == rhs.size()); for (size_type i = 0; i < num_blocks(); ++i) m_bits[i] &= rhs.m_bits[i]; return *this; } template
dynamic_bitset
& dynamic_bitset
::operator|=(const dynamic_bitset& rhs) { assert(size() == rhs.size()); for (size_type i = 0; i < num_blocks(); ++i) m_bits[i] |= rhs.m_bits[i]; //m_zero_unused_bits(); return *this; } template
dynamic_bitset
& dynamic_bitset
::operator^=(const dynamic_bitset& rhs) { assert(size() == rhs.size()); for (size_type i = 0; i < this->num_blocks(); ++i) m_bits[i] ^= rhs.m_bits[i]; //m_zero_unused_bits(); return *this; } template
dynamic_bitset
& dynamic_bitset
::operator-=(const dynamic_bitset& rhs) { assert(size() == rhs.size()); for (size_type i = 0; i < num_blocks(); ++i) m_bits[i] &= ~rhs.m_bits[i]; //m_zero_unused_bits(); return *this; } // // NOTE: // Note that the 'if (r != 0)' is crucial to avoid undefined // behavior when the left hand operand of >> isn't promoted to a // wider type (because rs would be too large). // template
dynamic_bitset
& dynamic_bitset
::operator<<=(size_type n) { if (n >= m_num_bits) return reset(); //else if (n > 0) { size_type const last = num_blocks() - 1; // num_blocks() is >= 1 size_type const div = n / bits_per_block; // div is <= last block_width_type const r = bit_index(n); block_type * const b = &m_bits[0]; if (r != 0) { block_width_type const rs = bits_per_block - r; for (size_type i = last-div; i>0; --i) { b[i+div] = (b[i] << r) | (b[i-1] >> rs); } b[div] = b[0] << r; } else { for (size_type i = last-div; i>0; --i) { b[i+div] = b[i]; } b[div] = b[0]; } // disable std::fill_n deprecated warning in MSVC++ 8.0 (warning C4996) // This will only work in MSVC++ 8.0 SP1, which brings up the warning // in the line of user code; otherwise, the warning will come up // in the line in the header itself, so if the user includes stdlib // headers before dynamic_bitset, he will still get the warning. #if defined(_MSC_VER) && _MSC_VER >= 1400 #pragma warning(push) #pragma warning(disable:4996) #endif // zero out div blocks at the less significant end std::fill_n(b, div, static_cast
(0)); #if defined(_MSC_VER) && _MSC_VER >= 1400 #pragma warning(pop) #endif // zero out any 1 bit that flowed into the unused part m_zero_unused_bits(); // thanks to Lester Gong } return *this; } // // NOTE: // see the comments to operator <<= // template
dynamic_bitset
& dynamic_bitset
::operator>>=(size_type n) { if (n >= m_num_bits) { return reset(); } //else if (n>0) { size_type const last = num_blocks() - 1; // num_blocks() is >= 1 size_type const div = n / bits_per_block; // div is <= last block_width_type const r = bit_index(n); block_type * const b = &m_bits[0]; if (r != 0) { block_width_type const ls = bits_per_block - r; for (size_type i = div; i < last; ++i) { b[i-div] = (b[i] >> r) | (b[i+1] << ls); } // r bits go to zero b[last-div] = b[last] >> r; } else { for (size_type i = div; i <= last; ++i) { b[i-div] = b[i]; } // note the '<=': the last iteration 'absorbs' // b[last-div] = b[last] >> 0; } // div blocks are zero filled at the most significant end std::fill_n(b + (num_blocks()-div), div, static_cast
(0)); } return *this; } template
dynamic_bitset
dynamic_bitset
::operator<<(size_type n) const { dynamic_bitset r(*this); return r <<= n; } template
dynamic_bitset
dynamic_bitset
::operator>>(size_type n) const { dynamic_bitset r(*this); return r >>= n; } //----------------------------------------------------------------------------- // basic bit operations template
dynamic_bitset
& dynamic_bitset
::set(size_type pos, bool val) { assert(pos < m_num_bits); if (val) m_bits[block_index(pos)] |= bit_mask(pos); else reset(pos); return *this; } template
dynamic_bitset
& dynamic_bitset
::set() { std::fill(m_bits.begin(), m_bits.end(), ~Block(0)); m_zero_unused_bits(); return *this; } template
dynamic_bitset
& dynamic_bitset
::reset(size_type pos) { assert(pos < m_num_bits); #if defined __MWERKS__ && BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x // CodeWarrior 8 generates incorrect code when the &=~ is compiled, // use the |^ variation instead..
m_bits[block_index(pos)] |= bit_mask(pos); m_bits[block_index(pos)] ^= bit_mask(pos); #else m_bits[block_index(pos)] &= ~bit_mask(pos); #endif return *this; } template
dynamic_bitset
& dynamic_bitset
::reset() { std::fill(m_bits.begin(), m_bits.end(), Block(0)); return *this; } template
dynamic_bitset
& dynamic_bitset
::flip(size_type pos) { assert(pos < m_num_bits); m_bits[block_index(pos)] ^= bit_mask(pos); return *this; } template
dynamic_bitset
& dynamic_bitset
::flip() { for (size_type i = 0; i < num_blocks(); ++i) m_bits[i] = ~m_bits[i]; m_zero_unused_bits(); return *this; } template
bool dynamic_bitset
::m_unchecked_test(size_type pos) const { return (m_bits[block_index(pos)] & bit_mask(pos)) != 0; } template
bool dynamic_bitset
::test(size_type pos) const { assert(pos < m_num_bits); return m_unchecked_test(pos); } template
bool dynamic_bitset
::any() const { for (size_type i = 0; i < num_blocks(); ++i) if (m_bits[i]) return true; return false; } template
inline bool dynamic_bitset
::none() const { return !any(); } template
dynamic_bitset
dynamic_bitset
::operator~() const { dynamic_bitset b(*this); b.flip(); return b; } template
typename dynamic_bitset
::size_type dynamic_bitset
::count() const { using namespace detail::dynamic_bitset_count_impl; const bool no_padding = bits_per_block == CHAR_BIT * sizeof(Block); const bool enough_table_width = table_width >= CHAR_BIT; typedef mode_to_type< (no_padding && enough_table_width ? access_by_bytes : access_by_blocks) > m; return do_count(m_bits.begin(), num_blocks(), Block(0), static_cast
(0)); } //----------------------------------------------------------------------------- // conversions template
void to_string_helper(const dynamic_bitset
& b, stringT & s, bool dump_all) { typedef typename stringT::traits_type Tr; typedef typename stringT::value_type Ch; BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, std::locale()); const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0'); const Ch one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1'); // Note that this function may access (when // dump_all == true) bits beyond position size() - 1 typedef typename dynamic_bitset
::size_type size_type; const size_type len = dump_all? dynamic_bitset
::bits_per_block * b.num_blocks(): b.size(); s.assign (len, zero); for (size_type i = 0; i < len; ++i) { if (b.m_unchecked_test(i)) Tr::assign(s[len - 1 - i], one); } } // A comment similar to the one about the constructor from // basic_string can be done here. Thanks to James Kanze for // making me (Gennaro) realize this important separation of // concerns issue, as well as many things about i18n. // template
inline void to_string(const dynamic_bitset
& b, stringT& s) { to_string_helper(b, s, false); } // Differently from to_string this function dumps out // every bit of the internal representation (may be // useful for debugging purposes) // template
inline void dump_to_string(const dynamic_bitset
& b, stringT& s) { to_string_helper(b, s, true /* =dump_all*/); } template
inline void to_block_range(const dynamic_bitset
& b, BlockOutputIterator result) { // note how this copies *all* bits, including the // unused ones in the last block (which are zero) std::copy(b.m_bits.begin(), b.m_bits.end(), result); } template
unsigned long dynamic_bitset
:: to_ulong() const { if (m_num_bits == 0) return 0; // convention // Check for overflows. This may be a performance burden on very // large bitsets but is required by the specification, sorry if (find_next(ulong_width - 1) != npos) throw std::overflow_error("boost::dynamic_bitset::to_ulong overflow"); // Ok, from now on we can be sure there's no "on" bit // beyond the "allowed" positions typedef unsigned long result_type; /* if find_next() did its job correctly we don't need the if below, because all bits we care about are in the first block if (bits_per_block >= ulong_width) return static_cast
(m_bits[0]); */ size_type last_block = block_index( (std::min)( m_num_bits, (size_type)ulong_width ) - 1 ); result_type result = 0; for (size_type i = 0; i <= last_block; ++i) { assert((size_type)bits_per_block * i < (size_type)ulong_width); unsigned long piece = m_bits[i]; result |= (piece << (bits_per_block * i)); } return result; } template
inline typename dynamic_bitset
::size_type dynamic_bitset
::size() const { return m_num_bits; } template
inline typename dynamic_bitset
::size_type dynamic_bitset
::num_blocks() const { return m_bits.size(); } template
inline typename dynamic_bitset
::size_type dynamic_bitset
::max_size() const { // Semantics of vector<>::max_size() aren't very clear // (see lib issue 197) and many library implementations // simply return dummy values, _unrelated_ to the underlying // allocator. // // Given these problems, I was tempted to not provide this // function at all but the user could need it if he provides // his own allocator. // const size_type m = detail::vector_max_size_workaround(m_bits); return m <= (size_type(-1)/bits_per_block) ? m * bits_per_block : size_type(-1); } template
inline bool dynamic_bitset
::empty() const { return size() == 0; } template
bool dynamic_bitset
:: is_subset_of(const dynamic_bitset
& a) const { assert(size() == a.size()); for (size_type i = 0; i < num_blocks(); ++i) if (m_bits[i] & ~a.m_bits[i]) return false; return true; } template
bool dynamic_bitset
:: is_proper_subset_of(const dynamic_bitset
& a) const { assert(size() == a.size()); assert(num_blocks() == a.num_blocks()); bool proper = false; for (size_type i = 0; i < num_blocks(); ++i) { const Block & bt = m_bits[i]; const Block & ba = a.m_bits[i]; if (bt & ~ba) return false; // not a subset at all if (ba & ~bt) proper = true; } return proper; } template
bool dynamic_bitset
::intersects(const dynamic_bitset & b) const { size_type common_blocks = num_blocks() < b.num_blocks() ? num_blocks() : b.num_blocks(); for(size_type i = 0; i < common_blocks; ++i) { if(m_bits[i] & b.m_bits[i]) return true; } return false; } // -------------------------------- // lookup // look for the first bit "on", starting // from the block with index first_block // template
typename dynamic_bitset
::size_type dynamic_bitset
::m_do_find_from(size_type first_block) const { size_type i = first_block; // skip null blocks while (i < num_blocks() && m_bits[i] == 0) ++i; if (i >= num_blocks()) return npos; // not found return i * bits_per_block + boost::lowest_bit(m_bits[i]); } template
typename dynamic_bitset
::size_type dynamic_bitset
::find_first() const { return m_do_find_from(0); } template
typename dynamic_bitset
::size_type dynamic_bitset
::find_next(size_type pos) const { const size_type sz = size(); if (pos >= (sz-1) || sz == 0) return npos; ++pos; const size_type blk = block_index(pos); const block_width_type ind = bit_index(pos); // mask out bits before pos const Block fore = m_bits[blk] & ( ~Block(0) << ind ); return fore? blk * bits_per_block + lowest_bit(fore) : m_do_find_from(blk + 1); } //----------------------------------------------------------------------------- // comparison template
bool operator==(const dynamic_bitset
& a, const dynamic_bitset
& b) { return (a.m_num_bits == b.m_num_bits) && (a.m_bits == b.m_bits); } template
inline bool operator!=(const dynamic_bitset