ossrv_pub/boost_apis/boost/dynamic_bitset/dynamic_bitset.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     1 // --------------------------------------------------
       
     2 //
       
     3 // (C) Copyright Chuck Allison and Jeremy Siek 2001 - 2002.
       
     4 // (C) Copyright Gennaro Prota                 2003 - 2004.
       
     5 //
       
     6 // Distributed under the Boost Software License, Version 1.0.
       
     7 //    (See accompanying file LICENSE_1_0.txt or copy at
       
     8 //          http://www.boost.org/LICENSE_1_0.txt)
       
     9 //
       
    10 // -----------------------------------------------------------
       
    11 
       
    12 //  See http://www.boost.org/libs/dynamic_bitset for documentation.
       
    13 
       
    14 
       
    15 
       
    16 #ifndef BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP
       
    17 #define BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP
       
    18 
       
    19 #include <cassert>
       
    20 #include <string>
       
    21 #include <stdexcept>           // for std::overflow_error
       
    22 #include <algorithm>           // for std::swap, std::min, std::copy, std::fill
       
    23 #include <vector>
       
    24 #include <climits>             // for CHAR_BIT
       
    25 
       
    26 #include "boost/dynamic_bitset/config.hpp"
       
    27 
       
    28 #ifndef BOOST_NO_STD_LOCALE
       
    29 # include <locale> // G.P.S
       
    30 #endif
       
    31 
       
    32 #if defined(BOOST_OLD_IOSTREAMS)
       
    33 #  include <iostream.h>
       
    34 #  include <ctype.h> // for isspace
       
    35 #else
       
    36 #  include <istream>
       
    37 #  include <ostream>
       
    38 #endif
       
    39 
       
    40 #include "boost/dynamic_bitset_fwd.hpp"
       
    41 #include "boost/detail/dynamic_bitset.hpp"
       
    42 #include "boost/detail/iterator.hpp" // used to implement append(Iter, Iter)
       
    43 #include "boost/static_assert.hpp"
       
    44 #include "boost/limits.hpp"
       
    45 #include "boost/pending/lowest_bit.hpp" // used by find_first/next
       
    46 
       
    47 
       
    48 namespace boost {
       
    49 
       
    50 template
       
    51 
       
    52 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1300)  // 1300 == VC++ 7.0
       
    53    // VC++ (up to 7.0) wants the default arguments again
       
    54    <typename Block = unsigned long, typename Allocator = std::allocator<Block> >
       
    55 # else
       
    56    <typename Block, typename Allocator>
       
    57 # endif
       
    58 
       
    59 class dynamic_bitset
       
    60 {
       
    61   // Portability note: member function templates are defined inside
       
    62   // this class definition to avoid problems with VC++. Similarly,
       
    63   // with the member functions of nested classes.
       
    64 
       
    65   BOOST_STATIC_ASSERT(detail::dynamic_bitset_allowed_block_type<Block>::value);
       
    66 
       
    67 public:
       
    68     typedef Block block_type;
       
    69     typedef Allocator allocator_type;
       
    70     typedef std::size_t size_type;
       
    71     typedef int block_width_type; // gps
       
    72 
       
    73     BOOST_STATIC_CONSTANT(block_width_type, bits_per_block = (std::numeric_limits<Block>::digits));
       
    74     BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
       
    75 
       
    76 
       
    77 public:
       
    78 
       
    79     // A proxy class to simulate lvalues of bit type.
       
    80     // Shouldn't it be private? [gps]
       
    81     //
       
    82     class reference
       
    83     {
       
    84         friend class dynamic_bitset<Block, Allocator>;
       
    85 
       
    86 
       
    87         // the one and only non-copy ctor
       
    88         reference(block_type & b, int pos)
       
    89             :m_block(b), m_mask(block_type(1) << pos)
       
    90         {}
       
    91 
       
    92         void operator&(); // left undefined
       
    93 
       
    94     public:
       
    95 
       
    96         // copy constructor: compiler generated
       
    97 
       
    98         operator bool() const { return (m_block & m_mask) != 0; }
       
    99         bool operator~() const { return (m_block & m_mask) == 0; }
       
   100 
       
   101         reference& flip() { do_flip(); return *this; }
       
   102 
       
   103         reference& operator=(bool x)               { do_assign(x);   return *this; } // for b[i] = x
       
   104         reference& operator=(const reference& rhs) { do_assign(rhs); return *this; } // for b[i] = b[j]
       
   105 
       
   106         reference& operator|=(bool x) { if  (x) do_set();   return *this; }
       
   107         reference& operator&=(bool x) { if (!x) do_reset(); return *this; }
       
   108         reference& operator^=(bool x) { if  (x) do_flip();  return *this; }
       
   109         reference& operator-=(bool x) { if  (x) do_reset(); return *this; }
       
   110 
       
   111      private:
       
   112         block_type & m_block;
       
   113         const block_type m_mask;
       
   114 
       
   115         void do_set() { m_block |= m_mask; }
       
   116         void do_reset() { m_block &= ~m_mask; }
       
   117         void do_flip() { m_block ^= m_mask; }
       
   118         void do_assign(bool x) { x? do_set() : do_reset(); }
       
   119     };
       
   120 
       
   121     typedef bool const_reference;
       
   122 
       
   123     // constructors, etc.
       
   124     explicit
       
   125     dynamic_bitset(const Allocator& alloc = Allocator());
       
   126 
       
   127     explicit
       
   128     dynamic_bitset(size_type num_bits, unsigned long value = 0,
       
   129                const Allocator& alloc = Allocator());
       
   130 
       
   131 
       
   132     // The presence of this constructor is a concession to ease of
       
   133     // use, especially for the novice user. A conversion from string
       
   134     // is, in most cases, formatting, and should be done by the standard
       
   135     // formatting convention: operator>>.
       
   136     //
       
   137     // NOTE:
       
   138     // Leave the parentheses around std::basic_string<CharT, Traits, Alloc>::npos.
       
   139     // g++ 3.2 requires them and probably the standard will - see core issue 325
       
   140     // NOTE 2: 
       
   141     // split into two constructors because of bugs in MSVC 6.0sp5 with STLport
       
   142 
       
   143     template <typename CharT, typename Traits, typename Alloc>
       
   144     dynamic_bitset(const std::basic_string<CharT, Traits, Alloc>& s,
       
   145         typename std::basic_string<CharT, Traits, Alloc>::size_type pos,
       
   146         typename std::basic_string<CharT, Traits, Alloc>::size_type n,
       
   147         size_type num_bits = npos,
       
   148         const Allocator& alloc = Allocator())
       
   149 
       
   150     :m_bits(alloc),
       
   151      m_num_bits(0)
       
   152     {
       
   153       init_from_string(s, pos, n, num_bits, alloc);
       
   154     }
       
   155 
       
   156     template <typename CharT, typename Traits, typename Alloc>
       
   157     explicit
       
   158     dynamic_bitset(const std::basic_string<CharT, Traits, Alloc>& s,
       
   159       typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0)
       
   160 
       
   161     :m_bits(Allocator()),
       
   162      m_num_bits(0)
       
   163     {
       
   164       init_from_string(s, pos, (std::basic_string<CharT, Traits, Alloc>::npos),
       
   165                        npos, Allocator());
       
   166     }
       
   167 
       
   168     // The first bit in *first is the least significant bit, and the
       
   169     // last bit in the block just before *last is the most significant bit.
       
   170     template <typename BlockInputIterator>
       
   171     dynamic_bitset(BlockInputIterator first, BlockInputIterator last,
       
   172                    const Allocator& alloc = Allocator())
       
   173 
       
   174     :m_bits(first, last, alloc),
       
   175      m_num_bits(m_bits.size() * bits_per_block)
       
   176     {}
       
   177 
       
   178 
       
   179     // copy constructor
       
   180     dynamic_bitset(const dynamic_bitset& b);
       
   181 
       
   182     ~dynamic_bitset();
       
   183 
       
   184     void swap(dynamic_bitset& b);
       
   185     dynamic_bitset& operator=(const dynamic_bitset& b);
       
   186 
       
   187     allocator_type get_allocator() const;
       
   188 
       
   189     // size changing operations
       
   190     void resize(size_type num_bits, bool value = false);
       
   191     void clear();
       
   192     void push_back(bool bit);
       
   193     void append(Block block);
       
   194 
       
   195     template <typename BlockInputIterator>
       
   196     void m_append(BlockInputIterator first, BlockInputIterator last, std::input_iterator_tag)
       
   197     {
       
   198         std::vector<Block, Allocator> v(first, last);
       
   199         m_append(v.begin(), v.end(), std::random_access_iterator_tag());
       
   200     }
       
   201     template <typename BlockInputIterator>
       
   202     void m_append(BlockInputIterator first, BlockInputIterator last, std::forward_iterator_tag)
       
   203     {
       
   204         assert(first != last);
       
   205         block_width_type r = count_extra_bits();
       
   206         std::size_t d = boost::detail::distance(first, last);
       
   207         m_bits.reserve(num_blocks() + d);
       
   208         if (r == 0) {
       
   209             for( ; first != last; ++first)
       
   210                 m_bits.push_back(*first); // could use vector<>::insert()
       
   211         }
       
   212         else {
       
   213             m_highest_block() |= (*first << r);
       
   214             do {
       
   215                 Block b = *first >> (bits_per_block - r);
       
   216                 ++first;
       
   217                 m_bits.push_back(b | (first==last? 0 : *first << r));
       
   218             } while (first != last);
       
   219         }
       
   220         m_num_bits += bits_per_block * d;
       
   221     }
       
   222     template <typename BlockInputIterator>
       
   223     void append(BlockInputIterator first, BlockInputIterator last) // strong guarantee
       
   224     {
       
   225         if (first != last) {
       
   226             typename detail::iterator_traits<BlockInputIterator>::iterator_category cat;
       
   227             m_append(first, last, cat);
       
   228         }
       
   229     }
       
   230 
       
   231 
       
   232     // bitset operations
       
   233     dynamic_bitset& operator&=(const dynamic_bitset& b);
       
   234     dynamic_bitset& operator|=(const dynamic_bitset& b);
       
   235     dynamic_bitset& operator^=(const dynamic_bitset& b);
       
   236     dynamic_bitset& operator-=(const dynamic_bitset& b);
       
   237     dynamic_bitset& operator<<=(size_type n);
       
   238     dynamic_bitset& operator>>=(size_type n);
       
   239     dynamic_bitset operator<<(size_type n) const;
       
   240     dynamic_bitset operator>>(size_type n) const;
       
   241 
       
   242     // basic bit operations
       
   243     dynamic_bitset& set(size_type n, bool val = true);
       
   244     dynamic_bitset& set();
       
   245     dynamic_bitset& reset(size_type n);
       
   246     dynamic_bitset& reset();
       
   247     dynamic_bitset& flip(size_type n);
       
   248     dynamic_bitset& flip();
       
   249     bool test(size_type n) const;
       
   250     bool any() const;
       
   251     bool none() const;
       
   252     dynamic_bitset operator~() const;
       
   253     size_type count() const;
       
   254 
       
   255     // subscript
       
   256     reference operator[](size_type pos) {
       
   257         return reference(m_bits[block_index(pos)], bit_index(pos));
       
   258     }
       
   259     bool operator[](size_type pos) const { return test(pos); }
       
   260 
       
   261     unsigned long to_ulong() const;
       
   262 
       
   263     size_type size() const;
       
   264     size_type num_blocks() const;
       
   265     size_type max_size() const;
       
   266     bool empty() const;
       
   267 #if 0 // gps
       
   268     void reserve(size_type n);
       
   269     size_type capacity() const;
       
   270 #endif
       
   271 
       
   272     bool is_subset_of(const dynamic_bitset& a) const;
       
   273     bool is_proper_subset_of(const dynamic_bitset& a) const;
       
   274     bool intersects(const dynamic_bitset & a) const;
       
   275 
       
   276     // lookup
       
   277     size_type find_first() const;
       
   278     size_type find_next(size_type pos) const;
       
   279 
       
   280 
       
   281 #if !defined BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
       
   282     // lexicographical comparison
       
   283     template <typename B, typename A>
       
   284     friend bool operator==(const dynamic_bitset<B, A>& a,
       
   285                            const dynamic_bitset<B, A>& b);
       
   286 
       
   287     template <typename B, typename A>
       
   288     friend bool operator<(const dynamic_bitset<B, A>& a,
       
   289                           const dynamic_bitset<B, A>& b);
       
   290 
       
   291 
       
   292     template <typename B, typename A, typename BlockOutputIterator>
       
   293     friend void to_block_range(const dynamic_bitset<B, A>& b,
       
   294                                BlockOutputIterator result);
       
   295 
       
   296     template <typename BlockIterator, typename B, typename A>
       
   297     friend void from_block_range(BlockIterator first, BlockIterator last,
       
   298                                  dynamic_bitset<B, A>& result);
       
   299 
       
   300 
       
   301     template <typename CharT, typename Traits, typename B, typename A>
       
   302     friend std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is,
       
   303                                                          dynamic_bitset<B, A>& b);
       
   304 
       
   305     template <typename B, typename A, typename stringT>
       
   306     friend void to_string_helper(const dynamic_bitset<B, A> & b, stringT & s, bool dump_all);
       
   307 
       
   308 
       
   309 #endif
       
   310 
       
   311 
       
   312 private:
       
   313     BOOST_STATIC_CONSTANT(block_width_type, ulong_width = std::numeric_limits<unsigned long>::digits);
       
   314     typedef std::vector<block_type, allocator_type> buffer_type;
       
   315 
       
   316     void m_zero_unused_bits();
       
   317     bool m_check_invariants() const;
       
   318 
       
   319     size_type m_do_find_from(size_type first_block) const;
       
   320 
       
   321     block_width_type count_extra_bits() const { return bit_index(size()); }
       
   322     static size_type block_index(size_type pos) { return pos / bits_per_block; }
       
   323     static block_width_type bit_index(size_type pos) { return static_cast<int>(pos % bits_per_block); }
       
   324     static Block bit_mask(size_type pos) { return Block(1) << bit_index(pos); }
       
   325 
       
   326     template <typename CharT, typename Traits, typename Alloc>
       
   327     void init_from_string(const std::basic_string<CharT, Traits, Alloc>& s,
       
   328         typename std::basic_string<CharT, Traits, Alloc>::size_type pos,
       
   329         typename std::basic_string<CharT, Traits, Alloc>::size_type n,
       
   330         size_type num_bits,
       
   331         const Allocator& alloc)
       
   332     {
       
   333         assert(pos <= s.size());
       
   334 
       
   335         typedef typename std::basic_string<CharT, Traits, Alloc> StrT;
       
   336         typedef typename StrT::traits_type Tr;
       
   337 
       
   338         const typename StrT::size_type rlen = (std::min)(n, s.size() - pos); // gps
       
   339         const size_type sz = ( num_bits != npos? num_bits : rlen);
       
   340         m_bits.resize(calc_num_blocks(sz));
       
   341         m_num_bits = sz;
       
   342 
       
   343 
       
   344         BOOST_DYNAMIC_BITSET_CTYPE_FACET(CharT, fac, std::locale());
       
   345         const CharT one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
       
   346 
       
   347         const size_type m = num_bits < rlen ? num_bits : rlen; // [gps]
       
   348         typename StrT::size_type i = 0;
       
   349         for( ; i < m; ++i) {
       
   350 
       
   351             const CharT c = s[(pos + m - 1) - i];
       
   352 
       
   353             assert( Tr::eq(c, one)
       
   354                     || Tr::eq(c, BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0')) );
       
   355 
       
   356             if (Tr::eq(c, one))
       
   357                 set(i);
       
   358 
       
   359         }
       
   360 
       
   361     }
       
   362 
       
   363 BOOST_DYNAMIC_BITSET_PRIVATE:
       
   364 
       
   365     bool m_unchecked_test(size_type pos) const;
       
   366     static size_type calc_num_blocks(size_type num_bits);
       
   367 
       
   368     Block&        m_highest_block();
       
   369     const Block&  m_highest_block() const;
       
   370 
       
   371     buffer_type m_bits; // [gps] to be renamed
       
   372     size_type   m_num_bits;
       
   373 
       
   374 
       
   375     class bit_appender;
       
   376     friend class bit_appender;
       
   377     class bit_appender {
       
   378       // helper for stream >>
       
   379       // Supplies to the lack of an efficient append at the less
       
   380       // significant end: bits are actually appended "at left" but
       
   381       // rearranged in the destructor. Everything works just as if
       
   382       // dynamic_bitset<> had an append_at_right() function (which
       
   383       // threw, in case, the same exceptions as push_back) except
       
   384       // that the function is actually called bit_appender::do_append().
       
   385       //
       
   386       dynamic_bitset & bs;
       
   387       size_type n;
       
   388       Block mask;
       
   389       Block * current;
       
   390     public:
       
   391         bit_appender(dynamic_bitset & r) : bs(r), n(0), mask(0), current(0) {}
       
   392         ~bit_appender() {
       
   393             // reverse the order of blocks, shift
       
   394             // if needed, and then resize
       
   395             //
       
   396             std::reverse(bs.m_bits.begin(), bs.m_bits.end());
       
   397             const block_width_type offs = bit_index(n);
       
   398             if (offs)
       
   399                 bs >>= (bits_per_block - offs);
       
   400             bs.resize(n); // doesn't enlarge, so can't throw
       
   401             assert(bs.m_check_invariants());
       
   402         }
       
   403         inline void do_append(bool value) {
       
   404 
       
   405             if (mask == 0) {
       
   406                 bs.append(Block(0));
       
   407                 current = &bs.m_highest_block();
       
   408                 mask = Block(1) << (bits_per_block - 1);
       
   409             }
       
   410 
       
   411             if(value)
       
   412                 *current |= mask;
       
   413 
       
   414             mask /= 2;
       
   415             ++n;
       
   416         }
       
   417         size_type get_count() const { return n; }
       
   418     };
       
   419 
       
   420 };
       
   421 
       
   422 #if BOOST_WORKAROUND( __IBMCPP__, <=600 )
       
   423 
       
   424 // Workaround for IBM's AIX platform.
       
   425 // See http://comments.gmane.org/gmane.comp.lib.boost.user/15331
       
   426 
       
   427 template<typename Block, typename Allocator>
       
   428 dynamic_bitset<Block, Allocator>::block_width_type const
       
   429 dynamic_bitset<Block, Allocator>::bits_per_block;
       
   430 
       
   431 template<typename Block, typename Allocator>
       
   432 dynamic_bitset<Block, Allocator>::block_width_type const
       
   433 dynamic_bitset<Block, Allocator>::ulong_width;
       
   434 
       
   435 #endif
       
   436 
       
   437 // Global Functions:
       
   438 
       
   439 // comparison
       
   440 template <typename Block, typename Allocator>
       
   441 bool operator!=(const dynamic_bitset<Block, Allocator>& a,
       
   442                 const dynamic_bitset<Block, Allocator>& b);
       
   443 
       
   444 template <typename Block, typename Allocator>
       
   445 bool operator<=(const dynamic_bitset<Block, Allocator>& a,
       
   446                 const dynamic_bitset<Block, Allocator>& b);
       
   447 
       
   448 template <typename Block, typename Allocator>
       
   449 bool operator>(const dynamic_bitset<Block, Allocator>& a,
       
   450                const dynamic_bitset<Block, Allocator>& b);
       
   451 
       
   452 template <typename Block, typename Allocator>
       
   453 bool operator>=(const dynamic_bitset<Block, Allocator>& a,
       
   454                 const dynamic_bitset<Block, Allocator>& b);
       
   455 
       
   456 // stream operators
       
   457 #ifdef BOOST_OLD_IOSTREAMS
       
   458 template <typename Block, typename Allocator>
       
   459 std::ostream& operator<<(std::ostream& os,
       
   460                          const dynamic_bitset<Block, Allocator>& b);
       
   461 
       
   462 template <typename Block, typename Allocator>
       
   463 std::istream& operator>>(std::istream& is, dynamic_bitset<Block,Allocator>& b);
       
   464 #else
       
   465 // NOTE: Digital Mars wants the same template parameter names
       
   466 //       here and in the definition! [last tested: 8.48.10]
       
   467 //
       
   468 template <typename Ch, typename Tr, typename Block, typename Alloc>
       
   469 std::basic_ostream<Ch, Tr>&
       
   470 operator<<(std::basic_ostream<Ch, Tr>& os,
       
   471            const dynamic_bitset<Block, Alloc>& b);
       
   472 
       
   473 template <typename Ch, typename Tr, typename Block, typename Alloc>
       
   474 std::basic_istream<Ch, Tr>&
       
   475 operator>>(std::basic_istream<Ch, Tr>& is,
       
   476            dynamic_bitset<Block, Alloc>& b);
       
   477 #endif
       
   478 
       
   479 // bitset operations
       
   480 template <typename Block, typename Allocator>
       
   481 dynamic_bitset<Block, Allocator>
       
   482 operator&(const dynamic_bitset<Block, Allocator>& b1,
       
   483           const dynamic_bitset<Block, Allocator>& b2);
       
   484 
       
   485 template <typename Block, typename Allocator>
       
   486 dynamic_bitset<Block, Allocator>
       
   487 operator|(const dynamic_bitset<Block, Allocator>& b1,
       
   488           const dynamic_bitset<Block, Allocator>& b2);
       
   489 
       
   490 template <typename Block, typename Allocator>
       
   491 dynamic_bitset<Block, Allocator>
       
   492 operator^(const dynamic_bitset<Block, Allocator>& b1,
       
   493           const dynamic_bitset<Block, Allocator>& b2);
       
   494 
       
   495 template <typename Block, typename Allocator>
       
   496 dynamic_bitset<Block, Allocator>
       
   497 operator-(const dynamic_bitset<Block, Allocator>& b1,
       
   498           const dynamic_bitset<Block, Allocator>& b2);
       
   499 
       
   500 // namespace scope swap
       
   501 template<typename Block, typename Allocator>
       
   502 void swap(dynamic_bitset<Block, Allocator>& b1,
       
   503           dynamic_bitset<Block, Allocator>& b2);
       
   504 
       
   505 
       
   506 template <typename Block, typename Allocator, typename stringT>
       
   507 void
       
   508 to_string(const dynamic_bitset<Block, Allocator>& b, stringT & s); // gps
       
   509 
       
   510 template <typename Block, typename Allocator, typename BlockOutputIterator>
       
   511 void
       
   512 to_block_range(const dynamic_bitset<Block, Allocator>& b,
       
   513                BlockOutputIterator result);
       
   514 
       
   515 
       
   516 // gps - check docs with Jeremy
       
   517 //
       
   518 template <typename BlockIterator, typename B, typename A>
       
   519 inline void
       
   520 from_block_range(BlockIterator first, BlockIterator last,
       
   521                  dynamic_bitset<B, A>& result)
       
   522 {
       
   523     // PRE: distance(first, last) <= numblocks()
       
   524     std::copy (first, last, result.m_bits.begin()); //[gps]
       
   525 }
       
   526 
       
   527 //=============================================================================
       
   528 // dynamic_bitset implementation
       
   529 
       
   530 
       
   531 //-----------------------------------------------------------------------------
       
   532 // constructors, etc.
       
   533 
       
   534 template <typename Block, typename Allocator>
       
   535 dynamic_bitset<Block, Allocator>::dynamic_bitset(const Allocator& alloc)
       
   536   : m_bits(alloc), m_num_bits(0)
       
   537 {
       
   538 
       
   539 }
       
   540 
       
   541 template <typename Block, typename Allocator>
       
   542 dynamic_bitset<Block, Allocator>::
       
   543 dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc)
       
   544   : m_bits(calc_num_blocks(num_bits), Block(0), alloc),
       
   545     m_num_bits(num_bits)
       
   546 {
       
   547 
       
   548   if (num_bits == 0)
       
   549       return;
       
   550 
       
   551   typedef unsigned long num_type;
       
   552 
       
   553   // cut off all bits in value that have pos >= num_bits, if any
       
   554   if (num_bits < static_cast<size_type>(ulong_width)) {
       
   555       const num_type mask = (num_type(1) << num_bits) - 1;
       
   556       value &= mask;
       
   557   }
       
   558 
       
   559   if (bits_per_block >= ulong_width) {
       
   560       m_bits[0] = static_cast<block_type>(value);
       
   561   }
       
   562   else {
       
   563       for(size_type i = 0; value != 0; ++i) {
       
   564 
       
   565           m_bits[i] = static_cast<block_type>(value);
       
   566           value >>= BOOST_DYNAMIC_BITSET_WRAP_CONSTANT(bits_per_block);
       
   567       }
       
   568   }
       
   569 
       
   570 }
       
   571 
       
   572 // copy constructor
       
   573 template <typename Block, typename Allocator>
       
   574 inline dynamic_bitset<Block, Allocator>::
       
   575 dynamic_bitset(const dynamic_bitset& b)
       
   576   : m_bits(b.m_bits), m_num_bits(b.m_num_bits)  // [gps]
       
   577 {
       
   578 
       
   579 }
       
   580 
       
   581 template <typename Block, typename Allocator>
       
   582 inline dynamic_bitset<Block, Allocator>::
       
   583 ~dynamic_bitset()
       
   584 {
       
   585     assert(m_check_invariants());
       
   586 }
       
   587 
       
   588 template <typename Block, typename Allocator>
       
   589 inline void dynamic_bitset<Block, Allocator>::
       
   590 swap(dynamic_bitset<Block, Allocator>& b) // no throw
       
   591 {
       
   592     std::swap(m_bits, b.m_bits);
       
   593     std::swap(m_num_bits, b.m_num_bits);
       
   594 }
       
   595 
       
   596 template <typename Block, typename Allocator>
       
   597 dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::
       
   598 operator=(const dynamic_bitset<Block, Allocator>& b)
       
   599 {
       
   600 #if 0 // gps
       
   601     dynamic_bitset<Block, Allocator> tmp(b);
       
   602     this->swap(tmp);
       
   603     return *this;
       
   604 #else
       
   605     m_bits = b.m_bits;
       
   606     m_num_bits = b.m_num_bits;
       
   607     return *this;
       
   608 #endif
       
   609 }
       
   610 
       
   611 template <typename Block, typename Allocator>
       
   612 inline typename dynamic_bitset<Block, Allocator>::allocator_type
       
   613 dynamic_bitset<Block, Allocator>::get_allocator() const
       
   614 {
       
   615     return m_bits.get_allocator();
       
   616 }
       
   617 
       
   618 //-----------------------------------------------------------------------------
       
   619 // size changing operations
       
   620 
       
   621 template <typename Block, typename Allocator>
       
   622 void dynamic_bitset<Block, Allocator>::
       
   623 resize(size_type num_bits, bool value) // strong guarantee
       
   624 {
       
   625 
       
   626   const size_type old_num_blocks = num_blocks();
       
   627   const size_type required_blocks = calc_num_blocks(num_bits);
       
   628 
       
   629   const block_type v = value? ~Block(0) : Block(0);
       
   630 
       
   631   if (required_blocks != old_num_blocks) {
       
   632     m_bits.resize(required_blocks, v); // s.g. (copy) [gps]
       
   633   }
       
   634 
       
   635 
       
   636   // At this point:
       
   637   //
       
   638   //  - if the buffer was shrunk, there's nothing to do, except
       
   639   //    a call to m_zero_unused_bits()
       
   640   //
       
   641   //  - if it it is enlarged, all the (used) bits in the new blocks have
       
   642   //    the correct value, but we should also take care of the bits,
       
   643   //    if any, that were 'unused bits' before enlarging: if value == true,
       
   644   //    they must be set.
       
   645 
       
   646   if (value && (num_bits > m_num_bits)) {
       
   647 
       
   648     const size_type extra_bits = count_extra_bits(); // gps
       
   649     if (extra_bits) {
       
   650         assert(old_num_blocks >= 1 && old_num_blocks <= m_bits.size());
       
   651 
       
   652         // Set them.
       
   653         m_bits[old_num_blocks - 1] |= (v << extra_bits); // gps
       
   654     }
       
   655 
       
   656   }
       
   657 
       
   658 
       
   659 
       
   660   m_num_bits = num_bits;
       
   661   m_zero_unused_bits();
       
   662 
       
   663 }
       
   664 
       
   665 template <typename Block, typename Allocator>
       
   666 void dynamic_bitset<Block, Allocator>::
       
   667 clear() // no throw
       
   668 {
       
   669   m_bits.clear();
       
   670   m_num_bits = 0;
       
   671 }
       
   672 
       
   673 
       
   674 template <typename Block, typename Allocator>
       
   675 void dynamic_bitset<Block, Allocator>::
       
   676 push_back(bool bit)
       
   677 {
       
   678   resize(size() + 1);
       
   679   set(size() - 1, bit);
       
   680 }
       
   681 
       
   682 template <typename Block, typename Allocator>
       
   683 void dynamic_bitset<Block, Allocator>::
       
   684 append(Block value) // strong guarantee
       
   685 {
       
   686     // G.P.S. to be reviewed...
       
   687 
       
   688     const block_width_type r = count_extra_bits();
       
   689 
       
   690     if (r == 0) {
       
   691         // the buffer is empty, or all blocks are filled
       
   692         m_bits.push_back(value);
       
   693     }
       
   694     else {
       
   695         m_bits.push_back(value >> (bits_per_block - r));
       
   696         m_bits[m_bits.size() - 2] |= (value << r); // m_bits.size() >= 2
       
   697     }
       
   698 
       
   699     m_num_bits += bits_per_block;
       
   700     assert(m_check_invariants());
       
   701 
       
   702 }
       
   703 
       
   704 
       
   705 //-----------------------------------------------------------------------------
       
   706 // bitset operations
       
   707 template <typename Block, typename Allocator>
       
   708 dynamic_bitset<Block, Allocator>&
       
   709 dynamic_bitset<Block, Allocator>::operator&=(const dynamic_bitset& rhs)
       
   710 {
       
   711     assert(size() == rhs.size());
       
   712     for (size_type i = 0; i < num_blocks(); ++i)
       
   713         m_bits[i] &= rhs.m_bits[i];
       
   714     return *this;
       
   715 }
       
   716 
       
   717 template <typename Block, typename Allocator>
       
   718 dynamic_bitset<Block, Allocator>&
       
   719 dynamic_bitset<Block, Allocator>::operator|=(const dynamic_bitset& rhs)
       
   720 {
       
   721     assert(size() == rhs.size());
       
   722     for (size_type i = 0; i < num_blocks(); ++i)
       
   723         m_bits[i] |= rhs.m_bits[i];
       
   724     //m_zero_unused_bits();
       
   725     return *this;
       
   726 }
       
   727 
       
   728 template <typename Block, typename Allocator>
       
   729 dynamic_bitset<Block, Allocator>&
       
   730 dynamic_bitset<Block, Allocator>::operator^=(const dynamic_bitset& rhs)
       
   731 {
       
   732     assert(size() == rhs.size());
       
   733     for (size_type i = 0; i < this->num_blocks(); ++i)
       
   734         m_bits[i] ^= rhs.m_bits[i];
       
   735     //m_zero_unused_bits();
       
   736     return *this;
       
   737 }
       
   738 
       
   739 template <typename Block, typename Allocator>
       
   740 dynamic_bitset<Block, Allocator>&
       
   741 dynamic_bitset<Block, Allocator>::operator-=(const dynamic_bitset& rhs)
       
   742 {
       
   743     assert(size() == rhs.size());
       
   744     for (size_type i = 0; i < num_blocks(); ++i)
       
   745         m_bits[i] &= ~rhs.m_bits[i];
       
   746     //m_zero_unused_bits();
       
   747     return *this;
       
   748 }
       
   749 
       
   750 //
       
   751 // NOTE:
       
   752 //  Note that the 'if (r != 0)' is crucial to avoid undefined
       
   753 //  behavior when the left hand operand of >> isn't promoted to a
       
   754 //  wider type (because rs would be too large).
       
   755 //
       
   756 template <typename Block, typename Allocator>
       
   757 dynamic_bitset<Block, Allocator>&
       
   758 dynamic_bitset<Block, Allocator>::operator<<=(size_type n)
       
   759 {
       
   760     if (n >= m_num_bits)
       
   761         return reset();
       
   762     //else
       
   763     if (n > 0) {
       
   764 
       
   765         size_type    const last = num_blocks() - 1;  // num_blocks() is >= 1
       
   766         size_type    const div  = n / bits_per_block; // div is <= last
       
   767         block_width_type const r = bit_index(n);
       
   768         block_type * const b    = &m_bits[0];
       
   769 
       
   770         if (r != 0) {
       
   771 
       
   772             block_width_type const rs = bits_per_block - r;
       
   773 
       
   774             for (size_type i = last-div; i>0; --i) {
       
   775                 b[i+div] = (b[i] << r) | (b[i-1] >> rs);
       
   776             }
       
   777             b[div] = b[0] << r;
       
   778 
       
   779         }
       
   780         else {
       
   781             for (size_type i = last-div; i>0; --i) {
       
   782                 b[i+div] = b[i];
       
   783             }
       
   784             b[div] = b[0];
       
   785         }
       
   786 
       
   787 
       
   788         // zero out div blocks at the less significant end
       
   789         std::fill_n(b, div, static_cast<block_type>(0));
       
   790 
       
   791         // zero out any 1 bit that flowed into the unused part
       
   792         m_zero_unused_bits(); // thanks to Lester Gong
       
   793 
       
   794 
       
   795     }
       
   796 
       
   797     return *this;
       
   798 
       
   799 
       
   800 }
       
   801 
       
   802 
       
   803 //
       
   804 // NOTE:
       
   805 //  see the comments to operator <<=
       
   806 //
       
   807 template <typename B, typename A>
       
   808 dynamic_bitset<B, A> & dynamic_bitset<B, A>::operator>>=(size_type n) {
       
   809     if (n >= m_num_bits) {
       
   810         return reset();
       
   811     }
       
   812     //else
       
   813     if (n>0) {
       
   814 
       
   815         size_type  const last  = num_blocks() - 1; // num_blocks() is >= 1
       
   816         size_type  const div   = n / bits_per_block;   // div is <= last
       
   817         block_width_type const r     = bit_index(n);
       
   818         block_type * const b   = &m_bits[0];
       
   819 
       
   820 
       
   821         if (r != 0) {
       
   822 
       
   823             block_width_type const ls = bits_per_block - r;
       
   824 
       
   825             for (size_type i = div; i < last; ++i) {
       
   826                 b[i-div] = (b[i] >> r) | (b[i+1]  << ls);
       
   827             }
       
   828             // r bits go to zero
       
   829             b[last-div] = b[last] >> r;
       
   830         }
       
   831 
       
   832         else {
       
   833             for (size_type i = div; i <= last; ++i) {
       
   834                 b[i-div] = b[i];
       
   835             }
       
   836             // note the '<=': the last iteration 'absorbs'
       
   837             // b[last-div] = b[last] >> 0;
       
   838         }
       
   839 
       
   840 
       
   841 
       
   842         // div blocks are zero filled at the most significant end
       
   843         std::fill_n(b + (num_blocks()-div), div, static_cast<block_type>(0));
       
   844     }
       
   845 
       
   846     return *this;
       
   847 }
       
   848 
       
   849 
       
   850 template <typename Block, typename Allocator>
       
   851 dynamic_bitset<Block, Allocator>
       
   852 dynamic_bitset<Block, Allocator>::operator<<(size_type n) const
       
   853 {
       
   854     dynamic_bitset r(*this);
       
   855     return r <<= n;
       
   856 }
       
   857 
       
   858 template <typename Block, typename Allocator>
       
   859 dynamic_bitset<Block, Allocator>
       
   860 dynamic_bitset<Block, Allocator>::operator>>(size_type n) const
       
   861 {
       
   862     dynamic_bitset r(*this);
       
   863     return r >>= n;
       
   864 }
       
   865 
       
   866 
       
   867 //-----------------------------------------------------------------------------
       
   868 // basic bit operations
       
   869 
       
   870 template <typename Block, typename Allocator>
       
   871 dynamic_bitset<Block, Allocator>&
       
   872 dynamic_bitset<Block, Allocator>::set(size_type pos, bool val)
       
   873 {
       
   874     // [gps]
       
   875     //
       
   876     // Below we have no set(size_type) function to call when
       
   877     // value == true; instead of using a helper, I think
       
   878     // overloading set (rather than giving it a default bool
       
   879     // argument) would be more elegant.
       
   880 
       
   881     assert(pos < m_num_bits);
       
   882 
       
   883     if (val)
       
   884         m_bits[block_index(pos)] |= bit_mask(pos);
       
   885     else
       
   886         reset(pos);
       
   887 
       
   888     return *this;
       
   889 }
       
   890 
       
   891 template <typename Block, typename Allocator>
       
   892 dynamic_bitset<Block, Allocator>&
       
   893 dynamic_bitset<Block, Allocator>::set()
       
   894 {
       
   895   std::fill(m_bits.begin(), m_bits.end(), ~Block(0));
       
   896   m_zero_unused_bits();
       
   897   return *this;
       
   898 }
       
   899 
       
   900 template <typename Block, typename Allocator>
       
   901 dynamic_bitset<Block, Allocator>&
       
   902 dynamic_bitset<Block, Allocator>::reset(size_type pos)
       
   903 {
       
   904     assert(pos < m_num_bits);
       
   905     #if BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
       
   906     // CodeWarrior 8 generates incorrect code when the &=~ is compiled,
       
   907     // use the |^ variation instead.. <grafik>
       
   908     m_bits[block_index(pos)] |= bit_mask(pos);
       
   909     m_bits[block_index(pos)] ^= bit_mask(pos);
       
   910     #else
       
   911     m_bits[block_index(pos)] &= ~bit_mask(pos);
       
   912     #endif
       
   913     return *this;
       
   914 }
       
   915 
       
   916 template <typename Block, typename Allocator>
       
   917 dynamic_bitset<Block, Allocator>&
       
   918 dynamic_bitset<Block, Allocator>::reset()
       
   919 {
       
   920   std::fill(m_bits.begin(), m_bits.end(), Block(0));
       
   921   return *this;
       
   922 }
       
   923 
       
   924 template <typename Block, typename Allocator>
       
   925 dynamic_bitset<Block, Allocator>&
       
   926 dynamic_bitset<Block, Allocator>::flip(size_type pos)
       
   927 {
       
   928     assert(pos < m_num_bits);
       
   929     m_bits[block_index(pos)] ^= bit_mask(pos);
       
   930     return *this;
       
   931 }
       
   932 
       
   933 template <typename Block, typename Allocator>
       
   934 dynamic_bitset<Block, Allocator>&
       
   935 dynamic_bitset<Block, Allocator>::flip()
       
   936 {
       
   937     for (size_type i = 0; i < num_blocks(); ++i)
       
   938         m_bits[i] = ~m_bits[i];
       
   939     m_zero_unused_bits();
       
   940     return *this;
       
   941 }
       
   942 
       
   943 template <typename Block, typename Allocator>
       
   944 bool dynamic_bitset<Block, Allocator>::m_unchecked_test(size_type pos) const
       
   945 {
       
   946     return (m_bits[block_index(pos)] & bit_mask(pos)) != 0;
       
   947 }
       
   948 
       
   949 template <typename Block, typename Allocator>
       
   950 bool dynamic_bitset<Block, Allocator>::test(size_type pos) const
       
   951 {
       
   952     assert(pos < m_num_bits);
       
   953     return m_unchecked_test(pos);
       
   954 }
       
   955 
       
   956 template <typename Block, typename Allocator>
       
   957 bool dynamic_bitset<Block, Allocator>::any() const
       
   958 {
       
   959     for (size_type i = 0; i < num_blocks(); ++i)
       
   960         if (m_bits[i])
       
   961             return true;
       
   962     return false;
       
   963 }
       
   964 
       
   965 template <typename Block, typename Allocator>
       
   966 inline bool dynamic_bitset<Block, Allocator>::none() const
       
   967 {
       
   968     return !any();
       
   969 }
       
   970 
       
   971 template <typename Block, typename Allocator>
       
   972 dynamic_bitset<Block, Allocator>
       
   973 dynamic_bitset<Block, Allocator>::operator~() const
       
   974 {
       
   975     dynamic_bitset b(*this);
       
   976     b.flip();
       
   977     return b;
       
   978 }
       
   979 
       
   980 
       
   981 /*
       
   982 
       
   983 The following is the straightforward implementation of count(), which
       
   984 we leave here in a comment for documentation purposes.
       
   985 
       
   986 template <typename Block, typename Allocator>
       
   987 typename dynamic_bitset<Block, Allocator>::size_type
       
   988 dynamic_bitset<Block, Allocator>::count() const
       
   989 {
       
   990     size_type sum = 0;
       
   991     for (size_type i = 0; i != this->m_num_bits; ++i)
       
   992         if (test(i))
       
   993             ++sum;
       
   994     return sum;
       
   995 }
       
   996 
       
   997 The actual algorithm uses a lookup table.
       
   998 
       
   999 
       
  1000   The basic idea of the method is to pick up X bits at a time
       
  1001   from the internal array of blocks and consider those bits as
       
  1002   the binary representation of a number N. Then, to use a table
       
  1003   of 1<<X elements where table[N] is the number of '1' digits
       
  1004   in the binary representation of N (i.e. in our X bits).
       
  1005 
       
  1006 
       
  1007   In this implementation X is 8 (but can be easily changed: you
       
  1008   just have to modify the definition of table_width and shrink/enlarge
       
  1009   the table accordingly - it could be useful, for instance, to expand
       
  1010   the table to 512 elements on an implementation with 9-bit bytes) and
       
  1011   the internal array of blocks is seen, if possible, as an array of bytes.
       
  1012   In practice the "reinterpretation" as array of bytes is possible if and
       
  1013   only if X >= CHAR_BIT and Block has no padding bits (that would be counted
       
  1014   together with the "real ones" if we saw the array as array of bytes).
       
  1015   Otherwise we simply 'extract' X bits at a time from each Block.
       
  1016 
       
  1017 */
       
  1018 
       
  1019 
       
  1020 template <typename Block, typename Allocator>
       
  1021 typename dynamic_bitset<Block, Allocator>::size_type
       
  1022 dynamic_bitset<Block, Allocator>::count() const
       
  1023 {
       
  1024     using namespace detail::dynamic_bitset_count_impl;
       
  1025 
       
  1026     const bool no_padding = bits_per_block == CHAR_BIT * sizeof(Block);
       
  1027     const bool enough_table_width = table_width >= CHAR_BIT;
       
  1028 
       
  1029     typedef mode_to_type< (no_padding && enough_table_width ?
       
  1030                           access_by_bytes : access_by_blocks) > m;
       
  1031 
       
  1032     return do_count(m_bits.begin(), num_blocks(), Block(0), static_cast<m*>(0));
       
  1033 
       
  1034 }
       
  1035 
       
  1036 
       
  1037 //-----------------------------------------------------------------------------
       
  1038 // conversions
       
  1039 
       
  1040 
       
  1041 template <typename B, typename A, typename stringT>
       
  1042 void to_string_helper(const dynamic_bitset<B, A> & b, stringT & s,
       
  1043                       bool dump_all)
       
  1044 {
       
  1045     typedef typename stringT::traits_type Tr;
       
  1046     typedef typename stringT::value_type  Ch;
       
  1047 
       
  1048     BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, std::locale());
       
  1049     const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
       
  1050     const Ch one  = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
       
  1051 
       
  1052     // Note that this function may access (when
       
  1053     // dump_all == true) bits beyond position size() - 1
       
  1054 
       
  1055     typedef typename dynamic_bitset<B, A>::size_type size_type;
       
  1056 
       
  1057     const size_type len = dump_all?
       
  1058          dynamic_bitset<B, A>::bits_per_block * b.num_blocks():
       
  1059          b.size();
       
  1060     s.assign (len, zero);
       
  1061 
       
  1062     for (size_type i = 0; i < len; ++i) {
       
  1063         if (b.m_unchecked_test(i))
       
  1064             Tr::assign(s[len - 1 - i], one);
       
  1065 
       
  1066     }
       
  1067 
       
  1068 }
       
  1069 
       
  1070 
       
  1071 // A comment similar to the one about the constructor from
       
  1072 // basic_string can be done here. Thanks to James Kanze for
       
  1073 // making me (Gennaro) realize this important separation of
       
  1074 // concerns issue, as well as many things about i18n.
       
  1075 //
       
  1076 template <typename Block, typename Allocator, typename stringT> // G.P.S.
       
  1077 inline void
       
  1078 to_string(const dynamic_bitset<Block, Allocator>& b, stringT& s)
       
  1079 {
       
  1080     to_string_helper(b, s, false);
       
  1081 }
       
  1082 
       
  1083 
       
  1084 // Differently from to_string this function dumps out
       
  1085 // every bit of the internal representation (may be
       
  1086 // useful for debugging purposes)
       
  1087 //
       
  1088 template <typename B, typename A, typename stringT>
       
  1089 inline void
       
  1090 dump_to_string(const dynamic_bitset<B, A>& b, stringT& s) // G.P.S.
       
  1091 {
       
  1092     to_string_helper(b, s, true /* =dump_all*/);
       
  1093 }
       
  1094 
       
  1095 template <typename Block, typename Allocator, typename BlockOutputIterator>
       
  1096 inline void
       
  1097 to_block_range(const dynamic_bitset<Block, Allocator>& b,
       
  1098                BlockOutputIterator result)
       
  1099 {
       
  1100     // note how this copies *all* bits, including the
       
  1101     // unused ones in the last block (which are zero)
       
  1102     std::copy(b.m_bits.begin(), b.m_bits.end(), result); // [gps]
       
  1103 }
       
  1104 
       
  1105 template <typename Block, typename Allocator>
       
  1106 unsigned long dynamic_bitset<Block, Allocator>::
       
  1107 to_ulong() const
       
  1108 {
       
  1109 
       
  1110   if (m_num_bits == 0)
       
  1111       return 0; // convention
       
  1112 
       
  1113   // Check for overflows. This may be a performance burden on very
       
  1114   // large bitsets but is required by the specification, sorry
       
  1115   if (find_next(ulong_width - 1) != npos)
       
  1116     throw std::overflow_error("boost::dynamic_bitset::to_ulong overflow");
       
  1117 
       
  1118 
       
  1119   // Ok, from now on we can be sure there's no "on" bit beyond
       
  1120   // the allowed positions
       
  1121 
       
  1122   if (bits_per_block >= ulong_width)
       
  1123       return m_bits[0];
       
  1124 
       
  1125 
       
  1126   size_type last_block = block_index((std::min)(m_num_bits-1, // gps
       
  1127                                     (size_type)(ulong_width-1)));
       
  1128   unsigned long result = 0;
       
  1129   for (size_type i = 0; i <= last_block; ++i) {
       
  1130 
       
  1131     assert((size_type)bits_per_block * i < (size_type)ulong_width); // gps
       
  1132 
       
  1133     unsigned long piece = m_bits[i];
       
  1134     result |= (piece << (bits_per_block * i));
       
  1135   }
       
  1136 
       
  1137   return result;
       
  1138 
       
  1139 }
       
  1140 
       
  1141 
       
  1142 template <typename Block, typename Allocator>
       
  1143 inline typename dynamic_bitset<Block, Allocator>::size_type
       
  1144 dynamic_bitset<Block, Allocator>::size() const
       
  1145 {
       
  1146     return m_num_bits;
       
  1147 }
       
  1148 
       
  1149 template <typename Block, typename Allocator>
       
  1150 inline typename dynamic_bitset<Block, Allocator>::size_type
       
  1151 dynamic_bitset<Block, Allocator>::num_blocks() const
       
  1152 {
       
  1153     return m_bits.size();
       
  1154 }
       
  1155 
       
  1156 template <typename Block, typename Allocator>
       
  1157 inline typename dynamic_bitset<Block, Allocator>::size_type
       
  1158 dynamic_bitset<Block, Allocator>::max_size() const
       
  1159 {
       
  1160     // Semantics of vector<>::max_size() aren't very clear
       
  1161     // (see lib issue 197) and many library implementations
       
  1162     // simply return dummy values, _unrelated_ to the underlying
       
  1163     // allocator.
       
  1164     //
       
  1165     // Given these problems, I was tempted to not provide this
       
  1166     // function at all but the user could need it if he provides
       
  1167     // his own allocator.
       
  1168     //
       
  1169 
       
  1170     const size_type m = detail::vector_max_size_workaround(m_bits);
       
  1171 
       
  1172     return m <= (size_type(-1)/bits_per_block) ?
       
  1173         m * bits_per_block :
       
  1174         size_type(-1);
       
  1175 }
       
  1176 
       
  1177 template <typename Block, typename Allocator>
       
  1178 inline bool dynamic_bitset<Block, Allocator>::empty() const
       
  1179 {
       
  1180   return size() == 0;
       
  1181 }
       
  1182 
       
  1183 #if 0 // gps
       
  1184 template <typename Block, typename Allocator>
       
  1185 inline void dynamic_bitset<Block, Allocator>::reserve(size_type n)
       
  1186 {
       
  1187     assert(n <= max_size()); // PRE - G.P.S.
       
  1188     m_bits.reserve(calc_num_blocks(n));
       
  1189 }
       
  1190 
       
  1191 template <typename Block, typename Allocator>
       
  1192 typename dynamic_bitset<Block, Allocator>::size_type
       
  1193 dynamic_bitset<Block, Allocator>::capacity() const
       
  1194 {
       
  1195     // capacity is m_bits.capacity() * bits_per_block
       
  1196     // unless that one overflows
       
  1197     const size_type m = static_cast<size_type>(-1);
       
  1198     const size_type q = m / bits_per_block;
       
  1199 
       
  1200     const size_type c = m_bits.capacity();
       
  1201 
       
  1202     return c <= q ?
       
  1203         c * bits_per_block :
       
  1204         m;
       
  1205 }
       
  1206 #endif
       
  1207 
       
  1208 template <typename Block, typename Allocator>
       
  1209 bool dynamic_bitset<Block, Allocator>::
       
  1210 is_subset_of(const dynamic_bitset<Block, Allocator>& a) const
       
  1211 {
       
  1212     assert(size() == a.size());
       
  1213     for (size_type i = 0; i < num_blocks(); ++i)
       
  1214         if (m_bits[i] & ~a.m_bits[i])
       
  1215             return false;
       
  1216     return true;
       
  1217 }
       
  1218 
       
  1219 template <typename Block, typename Allocator>
       
  1220 bool dynamic_bitset<Block, Allocator>::
       
  1221 is_proper_subset_of(const dynamic_bitset<Block, Allocator>& a) const
       
  1222 {
       
  1223     assert(size() == a.size());
       
  1224     bool proper = false;
       
  1225     for (size_type i = 0; i < num_blocks(); ++i) {
       
  1226         Block bt = m_bits[i], ba = a.m_bits[i];
       
  1227         if (ba & ~bt)
       
  1228             proper = true;
       
  1229         if (bt & ~ba)
       
  1230             return false;
       
  1231     }
       
  1232     return proper;
       
  1233 }
       
  1234 
       
  1235 template <typename Block, typename Allocator>
       
  1236 bool dynamic_bitset<Block, Allocator>::intersects(const dynamic_bitset & b) const
       
  1237 {
       
  1238     size_type common_blocks = num_blocks() < b.num_blocks()
       
  1239                               ? num_blocks() : b.num_blocks();
       
  1240 
       
  1241     for(size_type i = 0; i < common_blocks; ++i) {
       
  1242         if(m_bits[i] & b.m_bits[i])
       
  1243             return true;
       
  1244     }
       
  1245     return false;
       
  1246 }
       
  1247 
       
  1248 // --------------------------------
       
  1249 // lookup
       
  1250 
       
  1251 
       
  1252 // look for the first bit "on", starting
       
  1253 // from the block with index first_block
       
  1254 //
       
  1255 template <typename Block, typename Allocator>
       
  1256 typename dynamic_bitset<Block, Allocator>::size_type
       
  1257 dynamic_bitset<Block, Allocator>::m_do_find_from(size_type first_block) const
       
  1258 {
       
  1259     size_type i = first_block;
       
  1260 
       
  1261     // skip null blocks
       
  1262     while (i < num_blocks() && m_bits[i] == 0)
       
  1263         ++i;
       
  1264 
       
  1265     if (i >= num_blocks())
       
  1266         return npos; // not found
       
  1267 
       
  1268     return i * bits_per_block + boost::lowest_bit(m_bits[i]);
       
  1269 
       
  1270 }
       
  1271 
       
  1272 
       
  1273 template <typename Block, typename Allocator>
       
  1274 typename dynamic_bitset<Block, Allocator>::size_type
       
  1275 dynamic_bitset<Block, Allocator>::find_first() const
       
  1276 {
       
  1277     return m_do_find_from(0);
       
  1278 }
       
  1279 
       
  1280 
       
  1281 template <typename Block, typename Allocator>
       
  1282 typename dynamic_bitset<Block, Allocator>::size_type
       
  1283 dynamic_bitset<Block, Allocator>::find_next(size_type pos) const
       
  1284 {
       
  1285 
       
  1286     const size_type sz = size();
       
  1287     if (pos >= (sz-1) || sz == 0)
       
  1288         return npos;
       
  1289 
       
  1290     ++pos;
       
  1291 
       
  1292     const size_type blk = block_index(pos);
       
  1293     const block_width_type ind = bit_index(pos);
       
  1294 
       
  1295     // mask out bits before pos
       
  1296     const Block fore = m_bits[blk] & ( ~Block(0) << ind );
       
  1297 
       
  1298     return fore?
       
  1299         blk * bits_per_block + lowest_bit(fore)
       
  1300         :
       
  1301         m_do_find_from(blk + 1);
       
  1302 
       
  1303 }
       
  1304 
       
  1305 
       
  1306 
       
  1307 //-----------------------------------------------------------------------------
       
  1308 // comparison
       
  1309 
       
  1310 template <typename Block, typename Allocator>
       
  1311 bool operator==(const dynamic_bitset<Block, Allocator>& a,
       
  1312                 const dynamic_bitset<Block, Allocator>& b)
       
  1313 {
       
  1314     return (a.m_num_bits == b.m_num_bits)
       
  1315            && (a.m_bits == b.m_bits); // [gps]
       
  1316 }
       
  1317 
       
  1318 template <typename Block, typename Allocator>
       
  1319 inline bool operator!=(const dynamic_bitset<Block, Allocator>& a,
       
  1320                        const dynamic_bitset<Block, Allocator>& b)
       
  1321 {
       
  1322     return !(a == b);
       
  1323 }
       
  1324 
       
  1325 template <typename Block, typename Allocator>
       
  1326 bool operator<(const dynamic_bitset<Block, Allocator>& a,
       
  1327                const dynamic_bitset<Block, Allocator>& b)
       
  1328 {
       
  1329     assert(a.size() == b.size());
       
  1330     typedef typename dynamic_bitset<Block, Allocator>::size_type size_type;
       
  1331 
       
  1332     if (a.size() == 0)
       
  1333       return false;
       
  1334 
       
  1335     // Since we are storing the most significant bit
       
  1336     // at pos == size() - 1, we need to do the comparisons in reverse.
       
  1337 
       
  1338     // Compare a block at a time
       
  1339     for (size_type i = a.num_blocks() - 1; i > 0; --i)
       
  1340       if (a.m_bits[i] < b.m_bits[i])
       
  1341         return true;
       
  1342       else if (a.m_bits[i] > b.m_bits[i])
       
  1343         return false;
       
  1344 
       
  1345     if (a.m_bits[0] < b.m_bits[0])
       
  1346       return true;
       
  1347     else
       
  1348       return false;
       
  1349 }
       
  1350 
       
  1351 template <typename Block, typename Allocator>
       
  1352 inline bool operator<=(const dynamic_bitset<Block, Allocator>& a,
       
  1353                        const dynamic_bitset<Block, Allocator>& b)
       
  1354 {
       
  1355     return !(a > b);
       
  1356 }
       
  1357 
       
  1358 template <typename Block, typename Allocator>
       
  1359 inline bool operator>(const dynamic_bitset<Block, Allocator>& a,
       
  1360                       const dynamic_bitset<Block, Allocator>& b)
       
  1361 {
       
  1362     return b < a;
       
  1363 }
       
  1364 
       
  1365 template <typename Block, typename Allocator>
       
  1366 inline bool operator>=(const dynamic_bitset<Block, Allocator>& a,
       
  1367                        const dynamic_bitset<Block, Allocator>& b)
       
  1368 {
       
  1369     return !(a < b);
       
  1370 }
       
  1371 
       
  1372 //-----------------------------------------------------------------------------
       
  1373 // stream operations
       
  1374 
       
  1375 #ifdef BOOST_OLD_IOSTREAMS
       
  1376 template < typename Block, typename Alloc>
       
  1377 std::ostream&
       
  1378 operator<<(std::ostream& os, const dynamic_bitset<Block, Alloc>& b)
       
  1379 {
       
  1380     // NOTE: since this is aimed at "classic" iostreams, exception
       
  1381     // masks on the stream are not supported. The library that
       
  1382     // ships with gcc 2.95 has an exceptions() member function but
       
  1383     // nothing is actually implemented; not even the class ios::failure.
       
  1384 
       
  1385     using namespace std;
       
  1386 
       
  1387     const ios::iostate ok = ios::goodbit;
       
  1388     ios::iostate err = ok;
       
  1389 
       
  1390     if (os.opfx()) { // gps
       
  1391 
       
  1392         //try
       
  1393         typedef typename dynamic_bitset<Block, Alloc>::size_type bitsetsize_type;
       
  1394 
       
  1395         const bitsetsize_type sz = b.size();
       
  1396         std::streambuf * buf = os.rdbuf();
       
  1397         size_t npad = os.width() <= 0  // careful: os.width() is signed (and can be < 0)
       
  1398             || (bitsetsize_type) os.width() <= sz? 0 : os.width() - sz; //- gps
       
  1399 
       
  1400         const char fill_char = os.fill();
       
  1401         const ios::fmtflags adjustfield = os.flags() & ios::adjustfield;
       
  1402 
       
  1403         // if needed fill at left; pad is decresed along the way
       
  1404         if (adjustfield != ios::left) {
       
  1405             for (; 0 < npad; --npad)
       
  1406                 if (fill_char != buf->sputc(fill_char)) {
       
  1407                     err |= ios::failbit;   // gps
       
  1408                     break;
       
  1409                 }
       
  1410         }
       
  1411 
       
  1412         if (err == ok) {
       
  1413             // output the bitset
       
  1414             for (bitsetsize_type i = b.size(); 0 < i; --i) {// G.P.S.
       
  1415                 const char dig = b.test(i-1)? '1' : '0';
       
  1416                 if (EOF == buf->sputc(dig)) { // ok?? gps
       
  1417                     err |= ios::failbit;
       
  1418                     break;
       
  1419                 }
       
  1420             }
       
  1421         }
       
  1422 
       
  1423         if (err == ok) {
       
  1424             // if needed fill at right
       
  1425             for (; 0 < npad; --npad) {
       
  1426                 if (fill_char != buf->sputc(fill_char)) {
       
  1427                     err |= ios::failbit;
       
  1428                     break;
       
  1429                 }
       
  1430             }
       
  1431         }
       
  1432 
       
  1433         os.osfx();
       
  1434         os.width(0);
       
  1435 
       
  1436     } // if opfx
       
  1437 
       
  1438     if(err != ok)
       
  1439         os.setstate(err); // assume this does NOT throw - gps
       
  1440     return os;
       
  1441 
       
  1442 }
       
  1443 #else
       
  1444 
       
  1445 template <typename Ch, typename Tr, typename Block, typename Alloc>
       
  1446 std::basic_ostream<Ch, Tr>&
       
  1447 operator<<(std::basic_ostream<Ch, Tr>& os,
       
  1448            const dynamic_bitset<Block, Alloc>& b)
       
  1449 {
       
  1450 
       
  1451     using namespace std;
       
  1452 
       
  1453     const ios_base::iostate ok = ios_base::goodbit;
       
  1454     ios_base::iostate err = ok;
       
  1455 
       
  1456     typename basic_ostream<Ch, Tr>::sentry cerberos(os);
       
  1457     if (cerberos) {
       
  1458 
       
  1459         BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, os.getloc());
       
  1460         const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
       
  1461         const Ch one  = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
       
  1462 
       
  1463         try {
       
  1464 
       
  1465             typedef typename dynamic_bitset<Block, Alloc>::size_type bitsetsize_type;
       
  1466             typedef basic_streambuf<Ch, Tr> buffer_type; // G.P.S.
       
  1467 
       
  1468             buffer_type * buf = os.rdbuf();
       
  1469             size_t npad = os.width() <= 0  // careful: os.width() is signed (and can be < 0)
       
  1470                 || (bitsetsize_type) os.width() <= b.size()? 0 : os.width() - b.size(); //- G.P.S.
       
  1471 
       
  1472             const Ch fill_char = os.fill();
       
  1473             const ios_base::fmtflags adjustfield = os.flags() & ios_base::adjustfield;
       
  1474 
       
  1475             // if needed fill at left; pad is decresed along the way
       
  1476             if (adjustfield != ios_base::left) {
       
  1477                 for (; 0 < npad; --npad)
       
  1478                     if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) {
       
  1479                           err |= ios_base::failbit;   // G.P.S.
       
  1480                           break;
       
  1481                     }
       
  1482             }
       
  1483 
       
  1484             if (err == ok) {
       
  1485                 // output the bitset
       
  1486                 for (bitsetsize_type i = b.size(); 0 < i; --i) {// G.P.S.
       
  1487                     typename buffer_type::int_type
       
  1488                         ret = buf->sputc(b.test(i-1)? one : zero);
       
  1489                     if (Tr::eq_int_type(Tr::eof(), ret)) {
       
  1490                         err |= ios_base::failbit;
       
  1491                         break;
       
  1492                     }
       
  1493                 }
       
  1494             }
       
  1495 
       
  1496             if (err == ok) {
       
  1497                 // if needed fill at right
       
  1498                 for (; 0 < npad; --npad) {
       
  1499                     if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) {
       
  1500                         err |= ios_base::failbit;
       
  1501                         break;
       
  1502                     }
       
  1503                 }
       
  1504             }
       
  1505 
       
  1506 
       
  1507             os.width(0);
       
  1508 
       
  1509         } catch (...) { // see std 27.6.1.1/4
       
  1510             bool rethrow = false;
       
  1511             try { os.setstate(ios_base::failbit); } catch (...) { rethrow = true; }
       
  1512 
       
  1513             if (rethrow)
       
  1514                 throw;
       
  1515         }
       
  1516     }
       
  1517 
       
  1518     if(err != ok)
       
  1519         os.setstate(err); // may throw exception
       
  1520     return os;
       
  1521 
       
  1522 }
       
  1523 #endif
       
  1524 
       
  1525 
       
  1526 #ifdef BOOST_OLD_IOSTREAMS
       
  1527 
       
  1528     // gps - A sentry-like class that calls isfx in its
       
  1529     // destructor. Necessary because bit_appender::do_append may throw.
       
  1530     class pseudo_sentry {
       
  1531         std::istream & m_r;
       
  1532         const bool m_ok;
       
  1533     public:
       
  1534         explicit pseudo_sentry(std::istream & r) : m_r(r), m_ok(r.ipfx(0)) { }
       
  1535         ~pseudo_sentry() { m_r.isfx(); }
       
  1536         operator bool() const { return m_ok; }
       
  1537     };
       
  1538 
       
  1539 template <typename Block, typename Alloc>
       
  1540 std::istream&
       
  1541 operator>>(std::istream& is, dynamic_bitset<Block, Alloc>& b)
       
  1542 {
       
  1543 
       
  1544 // Extractor for classic IO streams (libstdc++ < 3.0)
       
  1545 // ----------------------------------------------------//
       
  1546 //  It's assumed that the stream buffer functions, and
       
  1547 //  the stream's setstate() _cannot_ throw.
       
  1548 
       
  1549 
       
  1550     typedef dynamic_bitset<Block, Alloc> bitset_type;
       
  1551     typedef typename bitset_type::size_type size_type;
       
  1552 
       
  1553     std::ios::iostate err = std::ios::goodbit; // gps
       
  1554     pseudo_sentry cerberos(is); // skips whitespaces
       
  1555     if(cerberos) {
       
  1556 
       
  1557         b.clear();
       
  1558 
       
  1559         const std::streamsize w = is.width();
       
  1560         const size_type limit = w > 0 && static_cast<size_type>(w) < b.max_size()// gps
       
  1561                                                          ? w : b.max_size();
       
  1562         typename bitset_type::bit_appender appender(b);
       
  1563         std::streambuf * buf = is.rdbuf();
       
  1564         for(int c = buf->sgetc(); appender.get_count() < limit; c = buf->snextc() ) {
       
  1565 
       
  1566             if (c == EOF) {
       
  1567                 err |= std::ios::eofbit; // G.P.S.
       
  1568                 break;
       
  1569             }
       
  1570             else if (char(c) != '0' && char(c) != '1')
       
  1571                 break; // non digit character
       
  1572 
       
  1573             else {
       
  1574                 try {
       
  1575                     //throw std::bad_alloc(); // gps
       
  1576                     appender.do_append(char(c) == '1');
       
  1577                 }
       
  1578                 catch(...) {
       
  1579                     is.setstate(std::ios::failbit); // assume this can't throw
       
  1580                     throw;
       
  1581                 }
       
  1582             }
       
  1583 
       
  1584         } // for
       
  1585     }
       
  1586 
       
  1587     is.width(0); // gps
       
  1588     if (b.size() == 0)
       
  1589         err |= std::ios::failbit;
       
  1590     if (err != std::ios::goodbit) // gps
       
  1591         is.setstate (err); // may throw
       
  1592 
       
  1593     return is;
       
  1594 }
       
  1595 
       
  1596 #else // BOOST_OLD_IOSTREAMS
       
  1597 
       
  1598 template <typename Ch, typename Tr, typename Block, typename Alloc>
       
  1599 std::basic_istream<Ch, Tr>&
       
  1600 operator>>(std::basic_istream<Ch, Tr>& is, dynamic_bitset<Block, Alloc>& b)
       
  1601 {
       
  1602 
       
  1603     using namespace std;
       
  1604 
       
  1605     typedef dynamic_bitset<Block, Alloc> bitset_type;
       
  1606     typedef typename bitset_type::size_type size_type;
       
  1607 
       
  1608     const streamsize w = is.width();
       
  1609     const size_type limit = 0 < w && static_cast<size_type>(w) < b.max_size()? // gps
       
  1610                                          w : b.max_size();
       
  1611 
       
  1612     ios_base::iostate err = ios_base::goodbit; // gps
       
  1613     typename basic_istream<Ch, Tr>::sentry cerberos(is); // skips whitespaces
       
  1614     if(cerberos) {
       
  1615 
       
  1616         // in accordance with prop. resol. of lib DR 303 [last checked 4 Feb 2004]
       
  1617         BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, is.getloc());
       
  1618         const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
       
  1619         const Ch one  = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
       
  1620 
       
  1621         b.clear();
       
  1622         try {
       
  1623             typename bitset_type::bit_appender appender(b);
       
  1624             basic_streambuf <Ch, Tr> * buf = is.rdbuf();
       
  1625             typename Tr::int_type c = buf->sgetc(); // G.P.S.
       
  1626             for( ; appender.get_count() < limit; c = buf->snextc() ) {
       
  1627 
       
  1628                 if (Tr::eq_int_type(Tr::eof(), c)) {
       
  1629                     err |= ios_base::eofbit; // G.P.S.
       
  1630                     break;
       
  1631                 }
       
  1632                 else {
       
  1633                     const Ch to_c = Tr::to_char_type(c);
       
  1634                     const bool is_one = Tr::eq(to_c, one);
       
  1635 
       
  1636                     if (!is_one && !Tr::eq(to_c, zero))
       
  1637                         break; // non digit character
       
  1638 
       
  1639                     appender.do_append(is_one);
       
  1640 
       
  1641                 }
       
  1642 
       
  1643             } // for
       
  1644         }
       
  1645         catch (...) {
       
  1646             // catches from stream buf, or from vector:
       
  1647             //
       
  1648             // bits_stored bits have been extracted and stored, and
       
  1649             // either no further character is extractable or we can't
       
  1650             // append to the underlying vector (out of memory) gps
       
  1651 
       
  1652             bool rethrow = false;   // see std 27.6.1.1/4
       
  1653             try { is.setstate(ios_base::badbit); }
       
  1654             catch(...) { rethrow = true; }
       
  1655 
       
  1656             if (rethrow)
       
  1657                 throw;
       
  1658 
       
  1659         }
       
  1660     }
       
  1661 
       
  1662     is.width(0); // gps
       
  1663     if (b.size() == 0 /*|| !cerberos*/)
       
  1664         err |= ios_base::failbit;
       
  1665     if (err != ios_base::goodbit) // gps
       
  1666         is.setstate (err); // may throw
       
  1667 
       
  1668     return is;
       
  1669 
       
  1670 }
       
  1671 
       
  1672 
       
  1673 #endif
       
  1674 
       
  1675 
       
  1676 //-----------------------------------------------------------------------------
       
  1677 // bitset operations
       
  1678 
       
  1679 template <typename Block, typename Allocator>
       
  1680 dynamic_bitset<Block, Allocator>
       
  1681 operator&(const dynamic_bitset<Block, Allocator>& x,
       
  1682           const dynamic_bitset<Block, Allocator>& y)
       
  1683 {
       
  1684     dynamic_bitset<Block, Allocator> b(x);
       
  1685     return b &= y;
       
  1686 }
       
  1687 
       
  1688 template <typename Block, typename Allocator>
       
  1689 dynamic_bitset<Block, Allocator>
       
  1690 operator|(const dynamic_bitset<Block, Allocator>& x,
       
  1691           const dynamic_bitset<Block, Allocator>& y)
       
  1692 {
       
  1693     dynamic_bitset<Block, Allocator> b(x);
       
  1694     return b |= y;
       
  1695 }
       
  1696 
       
  1697 template <typename Block, typename Allocator>
       
  1698 dynamic_bitset<Block, Allocator>
       
  1699 operator^(const dynamic_bitset<Block, Allocator>& x,
       
  1700           const dynamic_bitset<Block, Allocator>& y)
       
  1701 {
       
  1702     dynamic_bitset<Block, Allocator> b(x);
       
  1703     return b ^= y;
       
  1704 }
       
  1705 
       
  1706 template <typename Block, typename Allocator>
       
  1707 dynamic_bitset<Block, Allocator>
       
  1708 operator-(const dynamic_bitset<Block, Allocator>& x,
       
  1709           const dynamic_bitset<Block, Allocator>& y)
       
  1710 {
       
  1711     dynamic_bitset<Block, Allocator> b(x);
       
  1712     return b -= y;
       
  1713 }
       
  1714 
       
  1715 //-----------------------------------------------------------------------------
       
  1716 // namespace scope swap
       
  1717 
       
  1718 template<typename Block, typename Allocator>
       
  1719 inline void
       
  1720 swap(dynamic_bitset<Block, Allocator>& left,
       
  1721      dynamic_bitset<Block, Allocator>& right) // no throw
       
  1722 {
       
  1723     left.swap(right); // gps
       
  1724 }
       
  1725 
       
  1726 
       
  1727 //-----------------------------------------------------------------------------
       
  1728 // private (on conforming compilers) member functions
       
  1729 
       
  1730 
       
  1731 template <typename Block, typename Allocator>
       
  1732 inline typename dynamic_bitset<Block, Allocator>::size_type
       
  1733 dynamic_bitset<Block, Allocator>::calc_num_blocks(size_type num_bits)
       
  1734 {
       
  1735     return num_bits / bits_per_block
       
  1736            + static_cast<int>( num_bits % bits_per_block != 0 );
       
  1737 }
       
  1738 
       
  1739 // gives a reference to the highest block
       
  1740 //
       
  1741 template <typename Block, typename Allocator>
       
  1742 inline Block& dynamic_bitset<Block, Allocator>::m_highest_block()
       
  1743 {
       
  1744     return const_cast<Block &>
       
  1745            (static_cast<const dynamic_bitset *>(this)->m_highest_block());
       
  1746 }
       
  1747 
       
  1748 // gives a const-reference to the highest block
       
  1749 //
       
  1750 template <typename Block, typename Allocator>
       
  1751 inline const Block& dynamic_bitset<Block, Allocator>::m_highest_block() const
       
  1752 {
       
  1753     assert(size() > 0 && num_blocks() > 0);
       
  1754     return m_bits.back();
       
  1755 }
       
  1756 
       
  1757 
       
  1758 // If size() is not a multiple of bits_per_block
       
  1759 // then not all the bits in the last block are used.
       
  1760 // This function resets the unused bits (convenient
       
  1761 // for the implementation of many member functions)
       
  1762 //
       
  1763 template <typename Block, typename Allocator>
       
  1764 inline void dynamic_bitset<Block, Allocator>::m_zero_unused_bits()
       
  1765 {
       
  1766     assert (num_blocks() == calc_num_blocks(m_num_bits));
       
  1767 
       
  1768     // if != 0 this is the number of bits used in the last block
       
  1769     const block_width_type extra_bits = count_extra_bits();
       
  1770 
       
  1771     if (extra_bits != 0)
       
  1772         m_highest_block() &= ~(~static_cast<Block>(0) << extra_bits);
       
  1773 
       
  1774 }
       
  1775 
       
  1776 // check class invariants
       
  1777 template <typename Block, typename Allocator>
       
  1778 bool dynamic_bitset<Block, Allocator>::m_check_invariants() const
       
  1779 {
       
  1780     const block_width_type extra_bits = count_extra_bits();
       
  1781     if (extra_bits > 0) {
       
  1782         block_type const mask = (~static_cast<Block>(0) << extra_bits);
       
  1783         if ((m_highest_block() & mask) != 0)
       
  1784             return false;
       
  1785     }
       
  1786     if (m_bits.size() > m_bits.capacity() || num_blocks() != calc_num_blocks(size()))
       
  1787         return false;
       
  1788 
       
  1789     return true;
       
  1790 
       
  1791 }
       
  1792 
       
  1793 
       
  1794 } // namespace boost
       
  1795 
       
  1796 
       
  1797 #undef BOOST_BITSET_CHAR
       
  1798 
       
  1799 #endif // include guard
       
  1800