Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-18 08:37:34

0001 // -----------------------------------------------------------
0002 //
0003 //   Copyright (c) 2001-2002 Chuck Allison and Jeremy Siek
0004 //        Copyright (c) 2003-2006, 2008 Gennaro Prota
0005 //             Copyright (c) 2014 Ahmed Charles
0006 //
0007 // Copyright (c) 2014 Glen Joseph Fernandes
0008 // (glenjofe@gmail.com)
0009 //
0010 // Copyright (c) 2014 Riccardo Marcangelo
0011 //             Copyright (c) 2018 Evgeny Shulgin
0012 //
0013 // Distributed under the Boost Software License, Version 1.0.
0014 //    (See accompanying file LICENSE_1_0.txt or copy at
0015 //          http://www.boost.org/LICENSE_1_0.txt)
0016 //
0017 // -----------------------------------------------------------
0018 
0019 #ifndef BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP
0020 #define BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP
0021 
0022 #include <assert.h>
0023 #include <string>
0024 #include <stdexcept>
0025 #include <algorithm>
0026 #include <iterator>     // used to implement append(Iter, Iter)
0027 #include <vector>
0028 #include <climits>      // for CHAR_BIT
0029 
0030 #include "boost/dynamic_bitset/config.hpp"
0031 
0032 #ifndef BOOST_NO_STD_LOCALE
0033 #  include <locale>
0034 #endif
0035 
0036 #if defined(BOOST_OLD_IOSTREAMS)
0037 #  include <iostream.h>
0038 #  include <ctype.h> // for isspace
0039 #else
0040 #  include <istream>
0041 #  include <ostream>
0042 #endif
0043 
0044 #include "boost/dynamic_bitset_fwd.hpp"
0045 #include "boost/dynamic_bitset/detail/dynamic_bitset.hpp"
0046 #include "boost/dynamic_bitset/detail/lowest_bit.hpp"
0047 #include "boost/move/move.hpp"
0048 #include "boost/limits.hpp"
0049 #include "boost/static_assert.hpp"
0050 #include "boost/core/addressof.hpp"
0051 #include "boost/core/no_exceptions_support.hpp"
0052 #include "boost/throw_exception.hpp"
0053 #include "boost/functional/hash/hash.hpp"
0054 
0055 
0056 namespace boost {
0057 
0058 template <typename Block, typename Allocator>
0059 class dynamic_bitset
0060 {
0061     // Portability note: member function templates are defined inside
0062     // this class definition to avoid problems with VC++. Similarly,
0063     // with the member functions of nested classes.
0064     //
0065     // [October 2008: the note above is mostly historical; new versions
0066     // of VC++ are likely able to digest a more drinking form of the
0067     // code; but changing it now is probably not worth the risks...]
0068 
0069     BOOST_STATIC_ASSERT((bool)detail::dynamic_bitset_impl::allowed_block_type<Block>::value);
0070     typedef std::vector<Block, Allocator> buffer_type;
0071 
0072 public:
0073     typedef Block block_type;
0074     typedef Allocator allocator_type;
0075     typedef std::size_t size_type;
0076     typedef typename buffer_type::size_type block_width_type;
0077 
0078     BOOST_STATIC_CONSTANT(block_width_type, bits_per_block = (std::numeric_limits<Block>::digits));
0079     BOOST_STATIC_CONSTANT(size_type, npos = static_cast<size_type>(-1));
0080 
0081 
0082 public:
0083 
0084     // A proxy class to simulate lvalues of bit type.
0085     //
0086     class reference
0087     {
0088         friend class dynamic_bitset<Block, Allocator>;
0089 
0090 
0091         // the one and only non-copy ctor
0092         reference(block_type & b, block_width_type pos)
0093             :m_block(b),
0094              m_mask( (assert(pos < bits_per_block),
0095                       block_type(1) << pos )
0096                    )
0097         { }
0098 
0099         void operator&(); // left undefined
0100 
0101     public:
0102 
0103         // copy constructor: compiler generated
0104 
0105         operator bool() const { return (m_block & m_mask) != 0; }
0106         bool operator~() const { return (m_block & m_mask) == 0; }
0107 
0108         reference& flip() { do_flip(); return *this; }
0109 
0110         reference& operator=(bool x)               { do_assign(x);   return *this; } // for b[i] = x
0111         reference& operator=(const reference& rhs) { do_assign(rhs); return *this; } // for b[i] = b[j]
0112 
0113         reference& operator|=(bool x) { if  (x) do_set();   return *this; }
0114         reference& operator&=(bool x) { if (!x) do_reset(); return *this; }
0115         reference& operator^=(bool x) { if  (x) do_flip();  return *this; }
0116         reference& operator-=(bool x) { if  (x) do_reset(); return *this; }
0117 
0118      private:
0119         block_type & m_block;
0120         const block_type m_mask;
0121 
0122         void do_set() { m_block |= m_mask; }
0123         void do_reset() { m_block &= ~m_mask; }
0124         void do_flip() { m_block ^= m_mask; }
0125         void do_assign(bool x) { x? do_set() : do_reset(); }
0126     };
0127 
0128     typedef bool const_reference;
0129 
0130     // constructors, etc.
0131     dynamic_bitset() : m_num_bits(0) {}
0132 
0133     explicit
0134     dynamic_bitset(const Allocator& alloc);
0135 
0136     explicit
0137     dynamic_bitset(size_type num_bits, unsigned long value = 0,
0138                const Allocator& alloc = Allocator());
0139 
0140 
0141     // WARNING: you should avoid using this constructor.
0142     //
0143     //  A conversion from string is, in most cases, formatting,
0144     //  and should be performed by using operator>>.
0145     //
0146     // NOTE:
0147     //  Leave the parentheses around std::basic_string<CharT, Traits, Alloc>::npos.
0148     //  g++ 3.2 requires them and probably the standard will - see core issue 325
0149     // NOTE 2:
0150     //  split into two constructors because of bugs in MSVC 6.0sp5 with STLport
0151 
0152     template <typename CharT, typename Traits, typename Alloc>
0153     dynamic_bitset(const std::basic_string<CharT, Traits, Alloc>& s,
0154         typename std::basic_string<CharT, Traits, Alloc>::size_type pos,
0155         typename std::basic_string<CharT, Traits, Alloc>::size_type n,
0156         size_type num_bits = npos,
0157         const Allocator& alloc = Allocator())
0158 
0159     :m_bits(alloc),
0160      m_num_bits(0)
0161     {
0162       init_from_string(s, pos, n, num_bits);
0163     }
0164 
0165     template <typename CharT, typename Traits, typename Alloc>
0166     explicit
0167     dynamic_bitset(const std::basic_string<CharT, Traits, Alloc>& s,
0168       typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0)
0169 
0170     :m_bits(Allocator()),
0171      m_num_bits(0)
0172     {
0173       init_from_string(s, pos, (std::basic_string<CharT, Traits, Alloc>::npos),
0174                        npos);
0175     }
0176 
0177     // The first bit in *first is the least significant bit, and the
0178     // last bit in the block just before *last is the most significant bit.
0179     template <typename BlockInputIterator>
0180     dynamic_bitset(BlockInputIterator first, BlockInputIterator last,
0181                    const Allocator& alloc = Allocator())
0182 
0183     :m_bits(alloc),
0184      m_num_bits(0)
0185     {
0186         using boost::detail::dynamic_bitset_impl::value_to_type;
0187         using boost::detail::dynamic_bitset_impl::is_numeric;
0188 
0189         const value_to_type<
0190             is_numeric<BlockInputIterator>::value> selector;
0191 
0192         dispatch_init(first, last, selector);
0193     }
0194 
0195     template <typename T>
0196     void dispatch_init(T num_bits, unsigned long value,
0197                        detail::dynamic_bitset_impl::value_to_type<true>)
0198     {
0199         init_from_unsigned_long(static_cast<size_type>(num_bits), value);
0200     }
0201 
0202     template <typename T>
0203     void dispatch_init(T first, T last,
0204                        detail::dynamic_bitset_impl::value_to_type<false>)
0205     {
0206         init_from_block_range(first, last);
0207     }
0208 
0209     template <typename BlockIter>
0210     void init_from_block_range(BlockIter first, BlockIter last)
0211     {
0212         assert(m_bits.size() == 0);
0213         m_bits.insert(m_bits.end(), first, last);
0214         m_num_bits = m_bits.size() * bits_per_block;
0215     }
0216 
0217     // copy constructor
0218     dynamic_bitset(const dynamic_bitset& b);
0219 
0220     ~dynamic_bitset();
0221 
0222     void swap(dynamic_bitset& b);
0223     dynamic_bitset& operator=(const dynamic_bitset& b);
0224 
0225 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0226     dynamic_bitset(dynamic_bitset&& src);
0227     dynamic_bitset& operator=(dynamic_bitset&& src);
0228 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
0229 
0230     allocator_type get_allocator() const;
0231 
0232     // size changing operations
0233     void resize(size_type num_bits, bool value = false);
0234     void clear();
0235     void push_back(bool bit);
0236     void pop_back();
0237     void append(Block block);
0238 
0239     template <typename BlockInputIterator>
0240     void m_append(BlockInputIterator first, BlockInputIterator last, std::input_iterator_tag)
0241     {
0242         std::vector<Block, Allocator> v(first, last);
0243         m_append(v.begin(), v.end(), std::random_access_iterator_tag());
0244     }
0245     template <typename BlockInputIterator>
0246     void m_append(BlockInputIterator first, BlockInputIterator last, std::forward_iterator_tag)
0247     {
0248         assert(first != last);
0249         block_width_type r = count_extra_bits();
0250         std::size_t d = std::distance(first, last);
0251         m_bits.reserve(num_blocks() + d);
0252         if (r == 0) {
0253             for( ; first != last; ++first)
0254                 m_bits.push_back(*first); // could use vector<>::insert()
0255         }
0256         else {
0257             m_highest_block() |= (*first << r);
0258             do {
0259                 Block b = *first >> (bits_per_block - r);
0260                 ++first;
0261                 m_bits.push_back(b | (first==last? 0 : *first << r));
0262             } while (first != last);
0263         }
0264         m_num_bits += bits_per_block * d;
0265     }
0266     template <typename BlockInputIterator>
0267     void append(BlockInputIterator first, BlockInputIterator last) // strong guarantee
0268     {
0269         if (first != last) {
0270             typename std::iterator_traits<BlockInputIterator>::iterator_category cat;
0271             m_append(first, last, cat);
0272         }
0273     }
0274 
0275 
0276     // bitset operations
0277     dynamic_bitset& operator&=(const dynamic_bitset& b);
0278     dynamic_bitset& operator|=(const dynamic_bitset& b);
0279     dynamic_bitset& operator^=(const dynamic_bitset& b);
0280     dynamic_bitset& operator-=(const dynamic_bitset& b);
0281     dynamic_bitset& operator<<=(size_type n);
0282     dynamic_bitset& operator>>=(size_type n);
0283     dynamic_bitset operator<<(size_type n) const;
0284     dynamic_bitset operator>>(size_type n) const;
0285 
0286     // basic bit operations
0287     dynamic_bitset& set(size_type n, size_type len, bool val /* = true */); // default would make it ambiguous
0288     dynamic_bitset& set(size_type n, bool val = true);
0289     dynamic_bitset& set();
0290     dynamic_bitset& reset(size_type n, size_type len);
0291     dynamic_bitset& reset(size_type n);
0292     dynamic_bitset& reset();
0293     dynamic_bitset& flip(size_type n, size_type len);
0294     dynamic_bitset& flip(size_type n);
0295     dynamic_bitset& flip();
0296     reference at(size_type n);
0297     bool at(size_type n) const;
0298     bool test(size_type n) const;
0299     bool test_set(size_type n, bool val = true);
0300     bool all() const;
0301     bool any() const;
0302     bool none() const;
0303     dynamic_bitset operator~() const;
0304     size_type count() const BOOST_NOEXCEPT;
0305 
0306     // subscript
0307     reference operator[](size_type pos) {
0308         return reference(m_bits[block_index(pos)], bit_index(pos));
0309     }
0310     bool operator[](size_type pos) const { return test(pos); }
0311 
0312     unsigned long to_ulong() const;
0313 
0314     size_type size() const BOOST_NOEXCEPT;
0315     size_type num_blocks() const BOOST_NOEXCEPT;
0316     size_type max_size() const BOOST_NOEXCEPT;
0317     bool empty() const BOOST_NOEXCEPT;
0318     size_type capacity() const BOOST_NOEXCEPT;
0319     void reserve(size_type num_bits);
0320     void shrink_to_fit();
0321 
0322     bool is_subset_of(const dynamic_bitset& a) const;
0323     bool is_proper_subset_of(const dynamic_bitset& a) const;
0324     bool intersects(const dynamic_bitset & a) const;
0325 
0326     // lookup
0327     size_type find_first() const;
0328     size_type find_first(size_type pos) const;
0329     size_type find_next(size_type pos) const;
0330 
0331 
0332 #if !defined BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
0333     // lexicographical comparison
0334     template <typename B, typename A>
0335     friend bool operator==(const dynamic_bitset<B, A>& a,
0336                            const dynamic_bitset<B, A>& b);
0337 
0338     template <typename B, typename A>
0339     friend bool operator<(const dynamic_bitset<B, A>& a,
0340                           const dynamic_bitset<B, A>& b);
0341 
0342     template <typename B, typename A>
0343     friend bool oplessthan(const dynamic_bitset<B, A>& a,
0344                           const dynamic_bitset<B, A>& b);
0345 
0346 
0347     template <typename B, typename A, typename BlockOutputIterator>
0348     friend void to_block_range(const dynamic_bitset<B, A>& b,
0349                                BlockOutputIterator result);
0350 
0351     template <typename BlockIterator, typename B, typename A>
0352     friend void from_block_range(BlockIterator first, BlockIterator last,
0353                                  dynamic_bitset<B, A>& result);
0354 
0355 
0356     template <typename CharT, typename Traits, typename B, typename A>
0357     friend std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is,
0358                                                          dynamic_bitset<B, A>& b);
0359 
0360     template <typename B, typename A, typename stringT>
0361     friend void to_string_helper(const dynamic_bitset<B, A> & b, stringT & s, bool dump_all);
0362 
0363     template <typename B, typename A>
0364     friend std::size_t hash_value(const dynamic_bitset<B, A>& a);
0365 #endif
0366 
0367 public:
0368     // forward declaration for optional zero-copy serialization support
0369     class serialize_impl;
0370     friend class serialize_impl;
0371 
0372 private:
0373     BOOST_STATIC_CONSTANT(block_width_type, ulong_width = std::numeric_limits<unsigned long>::digits);
0374 
0375     dynamic_bitset& range_operation(size_type pos, size_type len,
0376         Block (*partial_block_operation)(Block, size_type, size_type),
0377         Block (*full_block_operation)(Block));
0378     void m_zero_unused_bits();
0379     bool m_check_invariants() const;
0380 
0381     static bool m_not_empty(Block x){ return x != Block(0); };
0382     size_type m_do_find_from(size_type first_block) const;
0383 
0384     block_width_type count_extra_bits() const BOOST_NOEXCEPT { return bit_index(size()); }
0385     static size_type block_index(size_type pos) BOOST_NOEXCEPT { return pos / bits_per_block; }
0386     static block_width_type bit_index(size_type pos) BOOST_NOEXCEPT { return static_cast<block_width_type>(pos % bits_per_block); }
0387     static Block bit_mask(size_type pos) BOOST_NOEXCEPT { return Block(1) << bit_index(pos); }
0388     static Block bit_mask(size_type first, size_type last) BOOST_NOEXCEPT
0389     {
0390         Block res = (last == bits_per_block - 1)
0391             ? detail::dynamic_bitset_impl::max_limit<Block>::value
0392             : ((Block(1) << (last + 1)) - 1);
0393         res ^= (Block(1) << first) - 1;
0394         return res;
0395     }
0396     static Block set_block_bits(Block block, size_type first,
0397         size_type last, bool val) BOOST_NOEXCEPT
0398     {
0399         if (val)
0400             return block | bit_mask(first, last);
0401         else
0402             return block & static_cast<Block>(~bit_mask(first, last));
0403     }
0404 
0405     // Functions for operations on ranges
0406     inline static Block set_block_partial(Block block, size_type first,
0407         size_type last) BOOST_NOEXCEPT
0408     {
0409         return set_block_bits(block, first, last, true);
0410     }
0411     inline static Block set_block_full(Block) BOOST_NOEXCEPT
0412     {
0413         return detail::dynamic_bitset_impl::max_limit<Block>::value;
0414     }
0415     inline static Block reset_block_partial(Block block, size_type first,
0416         size_type last) BOOST_NOEXCEPT
0417     {
0418         return set_block_bits(block, first, last, false);
0419     }
0420     inline static Block reset_block_full(Block) BOOST_NOEXCEPT
0421     {
0422         return 0;
0423     }
0424     inline static Block flip_block_partial(Block block, size_type first,
0425         size_type last) BOOST_NOEXCEPT
0426     {
0427         return block ^ bit_mask(first, last);
0428     }
0429     inline static Block flip_block_full(Block block) BOOST_NOEXCEPT
0430     {
0431         return ~block;
0432     }
0433 
0434     template <typename CharT, typename Traits, typename Alloc>
0435     void init_from_string(const std::basic_string<CharT, Traits, Alloc>& s,
0436         typename std::basic_string<CharT, Traits, Alloc>::size_type pos,
0437         typename std::basic_string<CharT, Traits, Alloc>::size_type n,
0438         size_type num_bits)
0439     {
0440         assert(pos <= s.size());
0441 
0442         typedef typename std::basic_string<CharT, Traits, Alloc> StrT;
0443         typedef typename StrT::traits_type Tr;
0444 
0445         const typename StrT::size_type rlen = (std::min)(n, s.size() - pos);
0446         const size_type sz = ( num_bits != npos? num_bits : rlen);
0447         m_bits.resize(calc_num_blocks(sz));
0448         m_num_bits = sz;
0449 
0450 
0451         BOOST_DYNAMIC_BITSET_CTYPE_FACET(CharT, fac, std::locale());
0452         const CharT one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
0453 
0454         const size_type m = num_bits < rlen ? num_bits : rlen;
0455         typename StrT::size_type i = 0;
0456         for( ; i < m; ++i) {
0457 
0458             const CharT c = s[(pos + m - 1) - i];
0459 
0460             assert( Tr::eq(c, one)
0461                     || Tr::eq(c, BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0')) );
0462 
0463             if (Tr::eq(c, one))
0464                 set(i);
0465 
0466         }
0467 
0468     }
0469 
0470     void init_from_unsigned_long(size_type num_bits,
0471                                  unsigned long value/*,
0472                                  const Allocator& alloc*/)
0473     {
0474 
0475         assert(m_bits.size() == 0);
0476 
0477         m_bits.resize(calc_num_blocks(num_bits));
0478         m_num_bits = num_bits;
0479 
0480         typedef unsigned long num_type;
0481         typedef boost::detail::dynamic_bitset_impl
0482             ::shifter<num_type, bits_per_block, ulong_width> shifter;
0483 
0484         //if (num_bits == 0)
0485         //    return;
0486 
0487         // zero out all bits at pos >= num_bits, if any;
0488         // note that: num_bits == 0 implies value == 0
0489         if (num_bits < static_cast<size_type>(ulong_width)) {
0490             const num_type mask = (num_type(1) << num_bits) - 1;
0491             value &= mask;
0492         }
0493 
0494         typename buffer_type::iterator it = m_bits.begin();
0495         for( ; value; shifter::left_shift(value), ++it) {
0496             *it = static_cast<block_type>(value);
0497         }
0498 
0499     }
0500 
0501 
0502 
0503 BOOST_DYNAMIC_BITSET_PRIVATE:
0504 
0505     bool m_unchecked_test(size_type pos) const;
0506     static size_type calc_num_blocks(size_type num_bits);
0507 
0508     Block&        m_highest_block();
0509     const Block&  m_highest_block() const;
0510 
0511     buffer_type m_bits;
0512     size_type   m_num_bits;
0513 
0514 
0515     class bit_appender;
0516     friend class bit_appender;
0517     class bit_appender {
0518       // helper for stream >>
0519       // Supplies to the lack of an efficient append at the less
0520       // significant end: bits are actually appended "at left" but
0521       // rearranged in the destructor. From the perspective of
0522       // client code everything works *as if* dynamic_bitset<> had
0523       // an append_at_right() function (eventually throwing the same
0524       // exceptions as push_back) except that the function is in fact
0525       // called bit_appender::do_append().
0526       //
0527       dynamic_bitset & bs;
0528       size_type n;
0529       Block mask;
0530       Block * current;
0531 
0532       // not implemented
0533       bit_appender(const bit_appender &);
0534       bit_appender & operator=(const bit_appender &);
0535 
0536     public:
0537         bit_appender(dynamic_bitset & r) : bs(r), n(0), mask(0), current(0) {}
0538         ~bit_appender() {
0539             // reverse the order of blocks, shift
0540             // if needed, and then resize
0541             //
0542             std::reverse(bs.m_bits.begin(), bs.m_bits.end());
0543             const block_width_type offs = bit_index(n);
0544             if (offs)
0545                 bs >>= (bits_per_block - offs);
0546             bs.resize(n); // doesn't enlarge, so can't throw
0547             assert(bs.m_check_invariants());
0548         }
0549         inline void do_append(bool value) {
0550 
0551             if (mask == 0) {
0552                 bs.append(Block(0));
0553                 current = &bs.m_highest_block();
0554                 mask = Block(1) << (bits_per_block - 1);
0555             }
0556 
0557             if(value)
0558                 *current |= mask;
0559 
0560             mask /= 2;
0561             ++n;
0562         }
0563         size_type get_count() const { return n; }
0564     };
0565 
0566 };
0567 
0568 #if !defined BOOST_NO_INCLASS_MEMBER_INITIALIZATION
0569 
0570 template <typename Block, typename Allocator>
0571 const typename dynamic_bitset<Block, Allocator>::block_width_type
0572 dynamic_bitset<Block, Allocator>::bits_per_block;
0573 
0574 template <typename Block, typename Allocator>
0575 const typename dynamic_bitset<Block, Allocator>::size_type
0576 dynamic_bitset<Block, Allocator>::npos;
0577 
0578 template <typename Block, typename Allocator>
0579 const typename dynamic_bitset<Block, Allocator>::block_width_type
0580 dynamic_bitset<Block, Allocator>::ulong_width;
0581 
0582 #endif
0583 
0584 // Global Functions:
0585 
0586 // comparison
0587 template <typename Block, typename Allocator>
0588 bool operator!=(const dynamic_bitset<Block, Allocator>& a,
0589                 const dynamic_bitset<Block, Allocator>& b);
0590 
0591 template <typename Block, typename Allocator>
0592 bool operator<=(const dynamic_bitset<Block, Allocator>& a,
0593                 const dynamic_bitset<Block, Allocator>& b);
0594 
0595 template <typename Block, typename Allocator>
0596 bool operator>(const dynamic_bitset<Block, Allocator>& a,
0597                const dynamic_bitset<Block, Allocator>& b);
0598 
0599 template <typename Block, typename Allocator>
0600 bool operator>=(const dynamic_bitset<Block, Allocator>& a,
0601                 const dynamic_bitset<Block, Allocator>& b);
0602 
0603 // stream operators
0604 #ifdef BOOST_OLD_IOSTREAMS
0605 template <typename Block, typename Allocator>
0606 std::ostream& operator<<(std::ostream& os,
0607                          const dynamic_bitset<Block, Allocator>& b);
0608 
0609 template <typename Block, typename Allocator>
0610 std::istream& operator>>(std::istream& is, dynamic_bitset<Block,Allocator>& b);
0611 #else
0612 template <typename CharT, typename Traits, typename Block, typename Allocator>
0613 std::basic_ostream<CharT, Traits>&
0614 operator<<(std::basic_ostream<CharT, Traits>& os,
0615            const dynamic_bitset<Block, Allocator>& b);
0616 
0617 template <typename CharT, typename Traits, typename Block, typename Allocator>
0618 std::basic_istream<CharT, Traits>&
0619 operator>>(std::basic_istream<CharT, Traits>& is,
0620            dynamic_bitset<Block, Allocator>& b);
0621 #endif
0622 
0623 // bitset operations
0624 template <typename Block, typename Allocator>
0625 dynamic_bitset<Block, Allocator>
0626 operator&(const dynamic_bitset<Block, Allocator>& b1,
0627           const dynamic_bitset<Block, Allocator>& b2);
0628 
0629 template <typename Block, typename Allocator>
0630 dynamic_bitset<Block, Allocator>
0631 operator|(const dynamic_bitset<Block, Allocator>& b1,
0632           const dynamic_bitset<Block, Allocator>& b2);
0633 
0634 template <typename Block, typename Allocator>
0635 dynamic_bitset<Block, Allocator>
0636 operator^(const dynamic_bitset<Block, Allocator>& b1,
0637           const dynamic_bitset<Block, Allocator>& b2);
0638 
0639 template <typename Block, typename Allocator>
0640 dynamic_bitset<Block, Allocator>
0641 operator-(const dynamic_bitset<Block, Allocator>& b1,
0642           const dynamic_bitset<Block, Allocator>& b2);
0643 
0644 // namespace scope swap
0645 template<typename Block, typename Allocator>
0646 void swap(dynamic_bitset<Block, Allocator>& b1,
0647           dynamic_bitset<Block, Allocator>& b2);
0648 
0649 
0650 template <typename Block, typename Allocator, typename stringT>
0651 void
0652 to_string(const dynamic_bitset<Block, Allocator>& b, stringT & s);
0653 
0654 template <typename Block, typename Allocator, typename BlockOutputIterator>
0655 void
0656 to_block_range(const dynamic_bitset<Block, Allocator>& b,
0657                BlockOutputIterator result);
0658 
0659 
0660 template <typename BlockIterator, typename B, typename A>
0661 inline void
0662 from_block_range(BlockIterator first, BlockIterator last,
0663                  dynamic_bitset<B, A>& result)
0664 {
0665     // PRE: distance(first, last) <= numblocks()
0666     std::copy (first, last, result.m_bits.begin());
0667 }
0668 
0669 //=============================================================================
0670 // dynamic_bitset implementation
0671 
0672 
0673 //-----------------------------------------------------------------------------
0674 // constructors, etc.
0675 
0676 template <typename Block, typename Allocator>
0677 dynamic_bitset<Block, Allocator>::dynamic_bitset(const Allocator& alloc)
0678   : m_bits(alloc), m_num_bits(0)
0679 {
0680 
0681 }
0682 
0683 template <typename Block, typename Allocator>
0684 dynamic_bitset<Block, Allocator>::
0685 dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc)
0686     : m_bits(alloc),
0687       m_num_bits(0)
0688 {
0689     init_from_unsigned_long(num_bits, value);
0690 }
0691 
0692 // copy constructor
0693 template <typename Block, typename Allocator>
0694 inline dynamic_bitset<Block, Allocator>::
0695 dynamic_bitset(const dynamic_bitset& b)
0696   : m_bits(b.m_bits), m_num_bits(b.m_num_bits)
0697 {
0698 
0699 }
0700 
0701 template <typename Block, typename Allocator>
0702 inline dynamic_bitset<Block, Allocator>::
0703 ~dynamic_bitset()
0704 {
0705     assert(m_check_invariants());
0706 }
0707 
0708 template <typename Block, typename Allocator>
0709 inline void dynamic_bitset<Block, Allocator>::
0710 swap(dynamic_bitset<Block, Allocator>& b) // no throw
0711 {
0712     std::swap(m_bits, b.m_bits);
0713     std::swap(m_num_bits, b.m_num_bits);
0714 }
0715 
0716 template <typename Block, typename Allocator>
0717 dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::
0718 operator=(const dynamic_bitset<Block, Allocator>& b)
0719 {
0720     m_bits = b.m_bits;
0721     m_num_bits = b.m_num_bits;
0722     return *this;
0723 }
0724 
0725 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0726 
0727 template <typename Block, typename Allocator>
0728 inline dynamic_bitset<Block, Allocator>::
0729 dynamic_bitset(dynamic_bitset<Block, Allocator>&& b)
0730   : m_bits(boost::move(b.m_bits)), m_num_bits(boost::move(b.m_num_bits))
0731 {
0732     // Required so that assert(m_check_invariants()); works.
0733     assert((b.m_bits = buffer_type(get_allocator())).empty());
0734     b.m_num_bits = 0;
0735 }
0736 
0737 template <typename Block, typename Allocator>
0738 inline dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::
0739 operator=(dynamic_bitset<Block, Allocator>&& b)
0740 {
0741     if (boost::addressof(b) == this) { return *this; }
0742 
0743     m_bits = boost::move(b.m_bits);
0744     m_num_bits = boost::move(b.m_num_bits);
0745     // Required so that assert(m_check_invariants()); works.
0746     assert((b.m_bits = buffer_type(get_allocator())).empty());
0747     b.m_num_bits = 0;
0748     return *this;
0749 }
0750 
0751 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
0752 
0753 template <typename Block, typename Allocator>
0754 inline typename dynamic_bitset<Block, Allocator>::allocator_type
0755 dynamic_bitset<Block, Allocator>::get_allocator() const
0756 {
0757     return m_bits.get_allocator();
0758 }
0759 
0760 //-----------------------------------------------------------------------------
0761 // size changing operations
0762 
0763 template <typename Block, typename Allocator>
0764 void dynamic_bitset<Block, Allocator>::
0765 resize(size_type num_bits, bool value) // strong guarantee
0766 {
0767 
0768   const size_type old_num_blocks = num_blocks();
0769   const size_type required_blocks = calc_num_blocks(num_bits);
0770 
0771   const block_type v = value? detail::dynamic_bitset_impl::max_limit<Block>::value : Block(0);
0772 
0773   if (required_blocks != old_num_blocks) {
0774     m_bits.resize(required_blocks, v); // s.g. (copy)
0775   }
0776 
0777 
0778   // At this point:
0779   //
0780   //  - if the buffer was shrunk, we have nothing more to do,
0781   //    except a call to m_zero_unused_bits()
0782   //
0783   //  - if it was enlarged, all the (used) bits in the new blocks have
0784   //    the correct value, but we have not yet touched those bits, if
0785   //    any, that were 'unused bits' before enlarging: if value == true,
0786   //    they must be set.
0787 
0788   if (value && (num_bits > m_num_bits)) {
0789 
0790     const block_width_type extra_bits = count_extra_bits();
0791     if (extra_bits) {
0792         assert(old_num_blocks >= 1 && old_num_blocks <= m_bits.size());
0793 
0794         // Set them.
0795         m_bits[old_num_blocks - 1] |= (v << extra_bits);
0796     }
0797 
0798   }
0799 
0800   m_num_bits = num_bits;
0801   m_zero_unused_bits();
0802 
0803 }
0804 
0805 template <typename Block, typename Allocator>
0806 void dynamic_bitset<Block, Allocator>::
0807 clear() // no throw
0808 {
0809   m_bits.clear();
0810   m_num_bits = 0;
0811 }
0812 
0813 
0814 template <typename Block, typename Allocator>
0815 void dynamic_bitset<Block, Allocator>::
0816 push_back(bool bit)
0817 {
0818   const size_type sz = size();
0819   resize(sz + 1, bit);
0820 }
0821 
0822 template <typename Block, typename Allocator>
0823 void dynamic_bitset<Block, Allocator>::
0824 pop_back()
0825 {
0826   const size_type old_num_blocks = num_blocks();
0827   const size_type required_blocks = calc_num_blocks(m_num_bits - 1);
0828 
0829   if (required_blocks != old_num_blocks) {
0830     m_bits.pop_back();
0831   }
0832 
0833   --m_num_bits;
0834   m_zero_unused_bits();
0835 }
0836 
0837 
0838 template <typename Block, typename Allocator>
0839 void dynamic_bitset<Block, Allocator>::
0840 append(Block value) // strong guarantee
0841 {
0842     const block_width_type r = count_extra_bits();
0843 
0844     if (r == 0) {
0845         // the buffer is empty, or all blocks are filled
0846         m_bits.push_back(value);
0847     }
0848     else {
0849         m_bits.push_back(value >> (bits_per_block - r));
0850         m_bits[m_bits.size() - 2] |= (value << r); // m_bits.size() >= 2
0851     }
0852 
0853     m_num_bits += bits_per_block;
0854     assert(m_check_invariants());
0855 
0856 }
0857 
0858 
0859 //-----------------------------------------------------------------------------
0860 // bitset operations
0861 template <typename Block, typename Allocator>
0862 dynamic_bitset<Block, Allocator>&
0863 dynamic_bitset<Block, Allocator>::operator&=(const dynamic_bitset& rhs)
0864 {
0865     assert(size() == rhs.size());
0866     for (size_type i = 0; i < num_blocks(); ++i)
0867         m_bits[i] &= rhs.m_bits[i];
0868     return *this;
0869 }
0870 
0871 template <typename Block, typename Allocator>
0872 dynamic_bitset<Block, Allocator>&
0873 dynamic_bitset<Block, Allocator>::operator|=(const dynamic_bitset& rhs)
0874 {
0875     assert(size() == rhs.size());
0876     for (size_type i = 0; i < num_blocks(); ++i)
0877         m_bits[i] |= rhs.m_bits[i];
0878     //m_zero_unused_bits();
0879     return *this;
0880 }
0881 
0882 template <typename Block, typename Allocator>
0883 dynamic_bitset<Block, Allocator>&
0884 dynamic_bitset<Block, Allocator>::operator^=(const dynamic_bitset& rhs)
0885 {
0886     assert(size() == rhs.size());
0887     for (size_type i = 0; i < this->num_blocks(); ++i)
0888         m_bits[i] ^= rhs.m_bits[i];
0889     //m_zero_unused_bits();
0890     return *this;
0891 }
0892 
0893 template <typename Block, typename Allocator>
0894 dynamic_bitset<Block, Allocator>&
0895 dynamic_bitset<Block, Allocator>::operator-=(const dynamic_bitset& rhs)
0896 {
0897     assert(size() == rhs.size());
0898     for (size_type i = 0; i < num_blocks(); ++i)
0899         m_bits[i] &= ~rhs.m_bits[i];
0900     //m_zero_unused_bits();
0901     return *this;
0902 }
0903 
0904 //
0905 // NOTE:
0906 //  Note that the 'if (r != 0)' is crucial to avoid undefined
0907 //  behavior when the left hand operand of >> isn't promoted to a
0908 //  wider type (because rs would be too large).
0909 //
0910 template <typename Block, typename Allocator>
0911 dynamic_bitset<Block, Allocator>&
0912 dynamic_bitset<Block, Allocator>::operator<<=(size_type n)
0913 {
0914     if (n >= m_num_bits)
0915         return reset();
0916     //else
0917     if (n > 0) {
0918 
0919         size_type    const last = num_blocks() - 1;  // num_blocks() is >= 1
0920         size_type    const div  = n / bits_per_block; // div is <= last
0921         block_width_type const r = bit_index(n);
0922         block_type * const b    = &m_bits[0];
0923 
0924         if (r != 0) {
0925 
0926             block_width_type const rs = bits_per_block - r;
0927 
0928             for (size_type i = last-div; i>0; --i) {
0929                 b[i+div] = (b[i] << r) | (b[i-1] >> rs);
0930             }
0931             b[div] = b[0] << r;
0932 
0933         }
0934         else {
0935             for (size_type i = last-div; i>0; --i) {
0936                 b[i+div] = b[i];
0937             }
0938             b[div] = b[0];
0939         }
0940 
0941         // zero out div blocks at the less significant end
0942         std::fill_n(m_bits.begin(), div, static_cast<block_type>(0));
0943 
0944         // zero out any 1 bit that flowed into the unused part
0945         m_zero_unused_bits(); // thanks to Lester Gong
0946 
0947     }
0948 
0949     return *this;
0950 
0951 
0952 }
0953 
0954 
0955 //
0956 // NOTE:
0957 //  see the comments to operator <<=
0958 //
0959 template <typename B, typename A>
0960 dynamic_bitset<B, A> & dynamic_bitset<B, A>::operator>>=(size_type n) {
0961     if (n >= m_num_bits) {
0962         return reset();
0963     }
0964     //else
0965     if (n>0) {
0966 
0967         size_type  const last  = num_blocks() - 1; // num_blocks() is >= 1
0968         size_type  const div   = n / bits_per_block;   // div is <= last
0969         block_width_type const r     = bit_index(n);
0970         block_type * const b   = &m_bits[0];
0971 
0972 
0973         if (r != 0) {
0974 
0975             block_width_type const ls = bits_per_block - r;
0976 
0977             for (size_type i = div; i < last; ++i) {
0978                 b[i-div] = (b[i] >> r) | (b[i+1]  << ls);
0979             }
0980             // r bits go to zero
0981             b[last-div] = b[last] >> r;
0982         }
0983 
0984         else {
0985             for (size_type i = div; i <= last; ++i) {
0986                 b[i-div] = b[i];
0987             }
0988             // note the '<=': the last iteration 'absorbs'
0989             // b[last-div] = b[last] >> 0;
0990         }
0991 
0992 
0993 
0994         // div blocks are zero filled at the most significant end
0995         std::fill_n(m_bits.begin() + (num_blocks()-div), div, static_cast<block_type>(0));
0996     }
0997 
0998     return *this;
0999 }
1000 
1001 
1002 template <typename Block, typename Allocator>
1003 dynamic_bitset<Block, Allocator>
1004 dynamic_bitset<Block, Allocator>::operator<<(size_type n) const
1005 {
1006     dynamic_bitset r(*this);
1007     return r <<= n;
1008 }
1009 
1010 template <typename Block, typename Allocator>
1011 dynamic_bitset<Block, Allocator>
1012 dynamic_bitset<Block, Allocator>::operator>>(size_type n) const
1013 {
1014     dynamic_bitset r(*this);
1015     return r >>= n;
1016 }
1017 
1018 
1019 //-----------------------------------------------------------------------------
1020 // basic bit operations
1021 
1022 template <typename Block, typename Allocator>
1023 dynamic_bitset<Block, Allocator>&
1024 dynamic_bitset<Block, Allocator>::set(size_type pos,
1025         size_type len, bool val)
1026 {
1027     if (val)
1028         return range_operation(pos, len, set_block_partial, set_block_full);
1029     else
1030         return range_operation(pos, len, reset_block_partial, reset_block_full);
1031 }
1032 
1033 template <typename Block, typename Allocator>
1034 dynamic_bitset<Block, Allocator>&
1035 dynamic_bitset<Block, Allocator>::set(size_type pos, bool val)
1036 {
1037     assert(pos < m_num_bits);
1038 
1039     if (val)
1040         m_bits[block_index(pos)] |= bit_mask(pos);
1041     else
1042         reset(pos);
1043 
1044     return *this;
1045 }
1046 
1047 template <typename Block, typename Allocator>
1048 dynamic_bitset<Block, Allocator>&
1049 dynamic_bitset<Block, Allocator>::set()
1050 {
1051   std::fill(m_bits.begin(), m_bits.end(), detail::dynamic_bitset_impl::max_limit<Block>::value);
1052   m_zero_unused_bits();
1053   return *this;
1054 }
1055 
1056 template <typename Block, typename Allocator>
1057 inline dynamic_bitset<Block, Allocator>&
1058 dynamic_bitset<Block, Allocator>::reset(size_type pos, size_type len)
1059 {
1060     return range_operation(pos, len, reset_block_partial, reset_block_full);
1061 }
1062 
1063 template <typename Block, typename Allocator>
1064 dynamic_bitset<Block, Allocator>&
1065 dynamic_bitset<Block, Allocator>::reset(size_type pos)
1066 {
1067     assert(pos < m_num_bits);
1068 #if defined __MWERKS__ && BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
1069     // CodeWarrior 8 generates incorrect code when the &=~ is compiled,
1070     // use the |^ variation instead.. <grafik>
1071     m_bits[block_index(pos)] |= bit_mask(pos);
1072     m_bits[block_index(pos)] ^= bit_mask(pos);
1073 #else
1074     m_bits[block_index(pos)] &= ~bit_mask(pos);
1075 #endif
1076     return *this;
1077 }
1078 
1079 template <typename Block, typename Allocator>
1080 dynamic_bitset<Block, Allocator>&
1081 dynamic_bitset<Block, Allocator>::reset()
1082 {
1083   std::fill(m_bits.begin(), m_bits.end(), Block(0));
1084   return *this;
1085 }
1086 
1087 template <typename Block, typename Allocator>
1088 dynamic_bitset<Block, Allocator>&
1089 dynamic_bitset<Block, Allocator>::flip(size_type pos, size_type len)
1090 {
1091     return range_operation(pos, len, flip_block_partial, flip_block_full);
1092 }
1093 
1094 template <typename Block, typename Allocator>
1095 dynamic_bitset<Block, Allocator>&
1096 dynamic_bitset<Block, Allocator>::flip(size_type pos)
1097 {
1098     assert(pos < m_num_bits);
1099     m_bits[block_index(pos)] ^= bit_mask(pos);
1100     return *this;
1101 }
1102 
1103 template <typename Block, typename Allocator>
1104 dynamic_bitset<Block, Allocator>&
1105 dynamic_bitset<Block, Allocator>::flip()
1106 {
1107     for (size_type i = 0; i < num_blocks(); ++i)
1108         m_bits[i] = ~m_bits[i];
1109     m_zero_unused_bits();
1110     return *this;
1111 }
1112 
1113 template <typename Block, typename Allocator>
1114 bool dynamic_bitset<Block, Allocator>::m_unchecked_test(size_type pos) const
1115 {
1116     return (m_bits[block_index(pos)] & bit_mask(pos)) != 0;
1117 }
1118 
1119 template <typename Block, typename Allocator>
1120 typename dynamic_bitset<Block, Allocator>::reference
1121 dynamic_bitset<Block, Allocator>::at(size_type pos)
1122 {
1123     if (pos >= m_num_bits)
1124         BOOST_THROW_EXCEPTION(std::out_of_range("boost::dynamic_bitset::at out_of_range"));
1125 
1126     return (*this)[pos];
1127 }
1128 
1129 template <typename Block, typename Allocator>
1130 bool dynamic_bitset<Block, Allocator>::at(size_type pos) const
1131 {
1132     if (pos >= m_num_bits)
1133         BOOST_THROW_EXCEPTION(std::out_of_range("boost::dynamic_bitset::at out_of_range"));
1134 
1135     return (*this)[pos];
1136 }
1137 
1138 template <typename Block, typename Allocator>
1139 bool dynamic_bitset<Block, Allocator>::test(size_type pos) const
1140 {
1141     assert(pos < m_num_bits);
1142     return m_unchecked_test(pos);
1143 }
1144 
1145 template <typename Block, typename Allocator>
1146 bool dynamic_bitset<Block, Allocator>::test_set(size_type pos, bool val)
1147 {
1148     bool const b = test(pos);
1149     if (b != val) {
1150         set(pos, val);
1151     }
1152     return b;
1153 }
1154 
1155 template <typename Block, typename Allocator>
1156 bool dynamic_bitset<Block, Allocator>::all() const
1157 {
1158     if (empty()) {
1159         return true;
1160     }
1161 
1162     const block_width_type extra_bits = count_extra_bits();
1163     block_type const all_ones = detail::dynamic_bitset_impl::max_limit<Block>::value;
1164 
1165     if (extra_bits == 0) {
1166         for (size_type i = 0, e = num_blocks(); i < e; ++i) {
1167             if (m_bits[i] != all_ones) {
1168                 return false;
1169             }
1170         }
1171     } else {
1172         for (size_type i = 0, e = num_blocks() - 1; i < e; ++i) {
1173             if (m_bits[i] != all_ones) {
1174                 return false;
1175             }
1176         }
1177         const block_type mask = (block_type(1) << extra_bits) - 1;
1178         if (m_highest_block() != mask) {
1179             return false;
1180         }
1181     }
1182     return true;
1183 }
1184 
1185 template <typename Block, typename Allocator>
1186 bool dynamic_bitset<Block, Allocator>::any() const
1187 {
1188     for (size_type i = 0; i < num_blocks(); ++i)
1189         if (m_bits[i])
1190             return true;
1191     return false;
1192 }
1193 
1194 template <typename Block, typename Allocator>
1195 inline bool dynamic_bitset<Block, Allocator>::none() const
1196 {
1197     return !any();
1198 }
1199 
1200 template <typename Block, typename Allocator>
1201 dynamic_bitset<Block, Allocator>
1202 dynamic_bitset<Block, Allocator>::operator~() const
1203 {
1204     dynamic_bitset b(*this);
1205     b.flip();
1206     return b;
1207 }
1208 
1209 template <typename Block, typename Allocator>
1210 typename dynamic_bitset<Block, Allocator>::size_type
1211 dynamic_bitset<Block, Allocator>::count() const BOOST_NOEXCEPT
1212 {
1213     using detail::dynamic_bitset_impl::table_width;
1214     using detail::dynamic_bitset_impl::access_by_bytes;
1215     using detail::dynamic_bitset_impl::access_by_blocks;
1216     using detail::dynamic_bitset_impl::value_to_type;
1217 
1218 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 3) && (__GNUC_PATCHLEVEL__ == 3)
1219     // NOTE: Explicit qualification of "bits_per_block"
1220     //       breaks compilation on gcc 4.3.3
1221     enum { no_padding = bits_per_block == CHAR_BIT * sizeof(Block) };
1222 #else
1223     // NOTE: Explicitly qualifying "bits_per_block" to workaround
1224     //       regressions of gcc 3.4.x
1225     enum { no_padding =
1226         dynamic_bitset<Block, Allocator>::bits_per_block
1227         == CHAR_BIT * sizeof(Block) };
1228 #endif
1229 
1230     enum { enough_table_width = table_width >= CHAR_BIT };
1231 
1232 #if ((defined(BOOST_MSVC) && (BOOST_MSVC >= 1600)) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
1233     // Windows popcount is effective starting from the unsigned short type
1234     enum { uneffective_popcount = sizeof(Block) < sizeof(unsigned short) };
1235 #elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
1236     // GCC popcount is effective starting from the unsigned int type
1237     enum { uneffective_popcount = sizeof(Block) < sizeof(unsigned int) };
1238 #else
1239     enum { uneffective_popcount = true };
1240 #endif
1241 
1242     enum { mode = (no_padding && enough_table_width && uneffective_popcount)
1243                           ? access_by_bytes
1244                           : access_by_blocks };
1245 
1246     return do_count(m_bits.begin(), num_blocks(), Block(0),
1247                     static_cast<value_to_type<(bool)mode> *>(0));
1248 }
1249 
1250 
1251 //-----------------------------------------------------------------------------
1252 // conversions
1253 
1254 
1255 template <typename B, typename A, typename stringT>
1256 void to_string_helper(const dynamic_bitset<B, A> & b, stringT & s,
1257                       bool dump_all)
1258 {
1259     typedef typename stringT::traits_type Tr;
1260     typedef typename stringT::value_type  Ch;
1261 
1262     BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, std::locale());
1263     const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
1264     const Ch one  = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
1265 
1266     // Note that this function may access (when
1267     // dump_all == true) bits beyond position size() - 1
1268 
1269     typedef typename dynamic_bitset<B, A>::size_type size_type;
1270 
1271     const size_type len = dump_all?
1272          dynamic_bitset<B, A>::bits_per_block * b.num_blocks():
1273          b.size();
1274     s.assign (len, zero);
1275 
1276     for (size_type i = 0; i < len; ++i) {
1277         if (b.m_unchecked_test(i))
1278             Tr::assign(s[len - 1 - i], one);
1279 
1280     }
1281 
1282 }
1283 
1284 
1285 // A comment similar to the one about the constructor from
1286 // basic_string can be done here. Thanks to James Kanze for
1287 // making me (Gennaro) realize this important separation of
1288 // concerns issue, as well as many things about i18n.
1289 //
1290 template <typename Block, typename Allocator, typename stringT>
1291 inline void
1292 to_string(const dynamic_bitset<Block, Allocator>& b, stringT& s)
1293 {
1294     to_string_helper(b, s, false);
1295 }
1296 
1297 
1298 // Differently from to_string this function dumps out
1299 // every bit of the internal representation (may be
1300 // useful for debugging purposes)
1301 //
1302 template <typename B, typename A, typename stringT>
1303 inline void
1304 dump_to_string(const dynamic_bitset<B, A>& b, stringT& s)
1305 {
1306     to_string_helper(b, s, true /* =dump_all*/);
1307 }
1308 
1309 template <typename Block, typename Allocator, typename BlockOutputIterator>
1310 inline void
1311 to_block_range(const dynamic_bitset<Block, Allocator>& b,
1312                BlockOutputIterator result)
1313 {
1314     // note how this copies *all* bits, including the
1315     // unused ones in the last block (which are zero)
1316     std::copy(b.m_bits.begin(), b.m_bits.end(), result);
1317 }
1318 
1319 template <typename Block, typename Allocator>
1320 unsigned long dynamic_bitset<Block, Allocator>::
1321 to_ulong() const
1322 {
1323 
1324   if (m_num_bits == 0)
1325       return 0; // convention
1326 
1327   // Check for overflows. This may be a performance burden on very
1328   // large bitsets but is required by the specification, sorry
1329   if (find_first(ulong_width) != npos)
1330     BOOST_THROW_EXCEPTION(std::overflow_error("boost::dynamic_bitset::to_ulong overflow"));
1331 
1332 
1333   // Ok, from now on we can be sure there's no "on" bit
1334   // beyond the "allowed" positions
1335   typedef unsigned long result_type;
1336 
1337   const size_type maximum_size =
1338             (std::min)(m_num_bits, static_cast<size_type>(ulong_width));
1339 
1340   const size_type last_block = block_index( maximum_size - 1 );
1341 
1342   assert((last_block * bits_per_block) < static_cast<size_type>(ulong_width));
1343 
1344   result_type result = 0;
1345   for (size_type i = 0; i <= last_block; ++i) {
1346     const size_type offset = i * bits_per_block;
1347     result |= (static_cast<result_type>(m_bits[i]) << offset);
1348   }
1349 
1350   return result;
1351 }
1352 
1353 template <typename Block, typename Allocator>
1354 inline typename dynamic_bitset<Block, Allocator>::size_type
1355 dynamic_bitset<Block, Allocator>::size() const BOOST_NOEXCEPT
1356 {
1357     return m_num_bits;
1358 }
1359 
1360 template <typename Block, typename Allocator>
1361 inline typename dynamic_bitset<Block, Allocator>::size_type
1362 dynamic_bitset<Block, Allocator>::num_blocks() const BOOST_NOEXCEPT
1363 {
1364     return m_bits.size();
1365 }
1366 
1367 template <typename Block, typename Allocator>
1368 inline typename dynamic_bitset<Block, Allocator>::size_type
1369 dynamic_bitset<Block, Allocator>::max_size() const BOOST_NOEXCEPT
1370 {
1371     // Semantics of vector<>::max_size() aren't very clear
1372     // (see lib issue 197) and many library implementations
1373     // simply return dummy values, _unrelated_ to the underlying
1374     // allocator.
1375     //
1376     // Given these problems, I was tempted to not provide this
1377     // function at all but the user could need it if he provides
1378     // his own allocator.
1379     //
1380 
1381     const size_type m = detail::dynamic_bitset_impl::
1382                         vector_max_size_workaround(m_bits);
1383 
1384     return m <= (size_type(-1)/bits_per_block) ?
1385         m * bits_per_block :
1386         size_type(-1);
1387 }
1388 
1389 template <typename Block, typename Allocator>
1390 inline bool dynamic_bitset<Block, Allocator>::empty() const BOOST_NOEXCEPT
1391 {
1392   return size() == 0;
1393 }
1394 
1395 template <typename Block, typename Allocator>
1396 inline typename dynamic_bitset<Block, Allocator>::size_type
1397 dynamic_bitset<Block, Allocator>::capacity() const BOOST_NOEXCEPT
1398 {
1399     return m_bits.capacity() * bits_per_block;
1400 }
1401 
1402 template <typename Block, typename Allocator>
1403 inline void dynamic_bitset<Block, Allocator>::reserve(size_type num_bits)
1404 {
1405     m_bits.reserve(calc_num_blocks(num_bits));
1406 }
1407 
1408 template <typename Block, typename Allocator>
1409 void dynamic_bitset<Block, Allocator>::shrink_to_fit()
1410 {
1411     if (m_bits.size() < m_bits.capacity()) {
1412       buffer_type(m_bits).swap(m_bits);
1413     }
1414 }
1415 
1416 template <typename Block, typename Allocator>
1417 bool dynamic_bitset<Block, Allocator>::
1418 is_subset_of(const dynamic_bitset<Block, Allocator>& a) const
1419 {
1420     assert(size() == a.size());
1421     for (size_type i = 0; i < num_blocks(); ++i)
1422         if (m_bits[i] & ~a.m_bits[i])
1423             return false;
1424     return true;
1425 }
1426 
1427 template <typename Block, typename Allocator>
1428 bool dynamic_bitset<Block, Allocator>::
1429 is_proper_subset_of(const dynamic_bitset<Block, Allocator>& a) const
1430 {
1431     assert(size() == a.size());
1432     assert(num_blocks() == a.num_blocks());
1433 
1434     bool proper = false;
1435     for (size_type i = 0; i < num_blocks(); ++i) {
1436         const Block & bt =   m_bits[i];
1437         const Block & ba = a.m_bits[i];
1438 
1439         if (bt & ~ba)
1440             return false; // not a subset at all
1441         if (ba & ~bt)
1442             proper = true;
1443     }
1444     return proper;
1445 }
1446 
1447 template <typename Block, typename Allocator>
1448 bool dynamic_bitset<Block, Allocator>::intersects(const dynamic_bitset & b) const
1449 {
1450     size_type common_blocks = num_blocks() < b.num_blocks()
1451                               ? num_blocks() : b.num_blocks();
1452 
1453     for(size_type i = 0; i < common_blocks; ++i) {
1454         if(m_bits[i] & b.m_bits[i])
1455             return true;
1456     }
1457     return false;
1458 }
1459 
1460 // --------------------------------
1461 // lookup
1462 
1463 // look for the first bit "on", starting
1464 // from the block with index first_block
1465 //
1466 
1467 template <typename Block, typename Allocator>
1468 typename dynamic_bitset<Block, Allocator>::size_type
1469 dynamic_bitset<Block, Allocator>::m_do_find_from(size_type first_block) const
1470 {
1471 
1472     size_type i = std::distance(m_bits.begin(),
1473         std::find_if(m_bits.begin() + first_block, m_bits.end(), m_not_empty) );
1474 
1475     if (i >= num_blocks())
1476         return npos; // not found
1477 
1478     return i * bits_per_block + static_cast<size_type>(detail::lowest_bit(m_bits[i]));
1479 }
1480 
1481 
1482 template <typename Block, typename Allocator>
1483 typename dynamic_bitset<Block, Allocator>::size_type
1484 dynamic_bitset<Block, Allocator>::find_first() const
1485 {
1486     return m_do_find_from(0);
1487 }
1488 
1489 template <typename Block, typename Allocator>
1490 typename dynamic_bitset<Block, Allocator>::size_type
1491 dynamic_bitset<Block, Allocator>::find_first(size_type pos) const
1492 {
1493     const size_type sz = size();
1494     if (pos >= sz) return npos;
1495 
1496     const size_type blk = block_index(pos);
1497     const block_width_type ind = bit_index(pos);
1498 
1499     // shift bits upto one immediately after current
1500     const Block fore = m_bits[blk] >> ind;
1501 
1502     return fore?
1503         pos + static_cast<size_type>(detail::lowest_bit(fore))
1504         :
1505         m_do_find_from(blk + 1);
1506 }
1507 
1508 
1509 template <typename Block, typename Allocator>
1510 typename dynamic_bitset<Block, Allocator>::size_type
1511 dynamic_bitset<Block, Allocator>::find_next(size_type pos) const
1512 {
1513     if (pos == npos) return npos;
1514     return find_first(pos + 1);
1515 }
1516 
1517 
1518 
1519 //-----------------------------------------------------------------------------
1520 // comparison
1521 
1522 template <typename Block, typename Allocator>
1523 bool operator==(const dynamic_bitset<Block, Allocator>& a,
1524                 const dynamic_bitset<Block, Allocator>& b)
1525 {
1526     return (a.m_num_bits == b.m_num_bits)
1527            && (a.m_bits == b.m_bits);
1528 }
1529 
1530 template <typename Block, typename Allocator>
1531 inline bool operator!=(const dynamic_bitset<Block, Allocator>& a,
1532                        const dynamic_bitset<Block, Allocator>& b)
1533 {
1534     return !(a == b);
1535 }
1536 
1537 template <typename Block, typename Allocator>
1538 bool operator<(const dynamic_bitset<Block, Allocator>& a,
1539                const dynamic_bitset<Block, Allocator>& b)
1540 {
1541 //    assert(a.size() == b.size());
1542 
1543     typedef BOOST_DEDUCED_TYPENAME dynamic_bitset<Block, Allocator>::size_type size_type;
1544     
1545     size_type asize(a.size());
1546     size_type bsize(b.size());
1547 
1548     if (!bsize)
1549         {
1550         return false;
1551         }
1552     else if (!asize)
1553         {
1554         return true;
1555         }
1556     else if (asize == bsize)
1557         {
1558         for (size_type ii = a.num_blocks(); ii > 0; --ii) 
1559             {
1560             size_type i = ii-1;
1561             if (a.m_bits[i] < b.m_bits[i])
1562                 return true;
1563             else if (a.m_bits[i] > b.m_bits[i])
1564                 return false;
1565             }
1566         return false;
1567         }
1568     else
1569         {
1570         
1571         size_type leqsize(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(asize,bsize));
1572     
1573         for (size_type ii = 0; ii < leqsize; ++ii,--asize,--bsize)
1574             {
1575             size_type i = asize-1;
1576             size_type j = bsize-1;
1577             if (a[i] < b[j])
1578                 return true;
1579             else if (a[i] > b[j])
1580                 return false;
1581             }
1582         return (a.size() < b.size());
1583         }
1584 }
1585 
1586 template <typename Block, typename Allocator>
1587 bool oplessthan(const dynamic_bitset<Block, Allocator>& a,
1588                const dynamic_bitset<Block, Allocator>& b)
1589 {
1590 //    assert(a.size() == b.size());
1591 
1592     typedef BOOST_DEDUCED_TYPENAME dynamic_bitset<Block, Allocator>::size_type size_type;
1593     
1594     size_type asize(a.num_blocks());
1595     size_type bsize(b.num_blocks());
1596     assert(asize == 3);
1597     assert(bsize == 4);
1598 
1599     if (!bsize)
1600         {
1601         return false;
1602         }
1603     else if (!asize)
1604         {
1605         return true;
1606         }
1607     else
1608         {
1609         
1610         size_type leqsize(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(asize,bsize));
1611         assert(leqsize == 3);
1612     
1613         //if (a.size() == 0)
1614         //  return false;
1615     
1616         // Since we are storing the most significant bit
1617         // at pos == size() - 1, we need to do the comparisons in reverse.
1618         //
1619         for (size_type ii = 0; ii < leqsize; ++ii,--asize,--bsize)
1620             {
1621             size_type i = asize-1;
1622             size_type j = bsize-1;
1623             if (a.m_bits[i] < b.m_bits[j])
1624                 return true;
1625             else if (a.m_bits[i] > b.m_bits[j])
1626                 return false;
1627             }
1628         return (a.num_blocks() < b.num_blocks());
1629         }
1630 }
1631 
1632 template <typename Block, typename Allocator>
1633 inline bool operator<=(const dynamic_bitset<Block, Allocator>& a,
1634                        const dynamic_bitset<Block, Allocator>& b)
1635 {
1636     return !(a > b);
1637 }
1638 
1639 template <typename Block, typename Allocator>
1640 inline bool operator>(const dynamic_bitset<Block, Allocator>& a,
1641                       const dynamic_bitset<Block, Allocator>& b)
1642 {
1643     return b < a;
1644 }
1645 
1646 template <typename Block, typename Allocator>
1647 inline bool operator>=(const dynamic_bitset<Block, Allocator>& a,
1648                        const dynamic_bitset<Block, Allocator>& b)
1649 {
1650     return !(a < b);
1651 }
1652 
1653 //-----------------------------------------------------------------------------
1654 // hash operations
1655 
1656 template <typename Block, typename Allocator>
1657 inline std::size_t hash_value(const dynamic_bitset<Block, Allocator>& a)
1658 {
1659     std::size_t res = hash_value(a.m_num_bits);
1660     boost::hash_combine(res, a.m_bits);
1661     return res;
1662 }
1663 
1664 //-----------------------------------------------------------------------------
1665 // stream operations
1666 
1667 #ifdef BOOST_OLD_IOSTREAMS
1668 template < typename Block, typename Alloc>
1669 std::ostream&
1670 operator<<(std::ostream& os, const dynamic_bitset<Block, Alloc>& b)
1671 {
1672     // NOTE: since this is aimed at "classic" iostreams, exception
1673     // masks on the stream are not supported. The library that
1674     // ships with gcc 2.95 has an exceptions() member function but
1675     // nothing is actually implemented; not even the class ios::failure.
1676 
1677     using namespace std;
1678 
1679     const ios::iostate ok = ios::goodbit;
1680     ios::iostate err = ok;
1681 
1682     if (os.opfx()) {
1683 
1684         //try
1685         typedef typename dynamic_bitset<Block, Alloc>::size_type bitsetsize_type;
1686 
1687         const bitsetsize_type sz = b.size();
1688         std::streambuf * buf = os.rdbuf();
1689         size_t npad = os.width() <= 0  // careful: os.width() is signed (and can be < 0)
1690             || (bitsetsize_type) os.width() <= sz? 0 : os.width() - sz;
1691 
1692         const char fill_char = os.fill();
1693         const ios::fmtflags adjustfield = os.flags() & ios::adjustfield;
1694 
1695         // if needed fill at left; pad is decresed along the way
1696         if (adjustfield != ios::left) {
1697             for (; 0 < npad; --npad)
1698                 if (fill_char != buf->sputc(fill_char)) {
1699                     err |= ios::failbit;
1700                     break;
1701                 }
1702         }
1703 
1704         if (err == ok) {
1705             // output the bitset
1706             for (bitsetsize_type i = b.size(); 0 < i; --i) {
1707                 const char dig = b.test(i-1)? '1' : '0';
1708                 if (EOF == buf->sputc(dig)) {
1709                     err |= ios::failbit;
1710                     break;
1711                 }
1712             }
1713         }
1714 
1715         if (err == ok) {
1716             // if needed fill at right
1717             for (; 0 < npad; --npad) {
1718                 if (fill_char != buf->sputc(fill_char)) {
1719                     err |= ios::failbit;
1720                     break;
1721                 }
1722             }
1723         }
1724 
1725         os.osfx();
1726         os.width(0);
1727 
1728     } // if opfx
1729 
1730     if(err != ok)
1731         os.setstate(err); // assume this does NOT throw
1732     return os;
1733 
1734 }
1735 #else
1736 
1737 template <typename Ch, typename Tr, typename Block, typename Alloc>
1738 std::basic_ostream<Ch, Tr>&
1739 operator<<(std::basic_ostream<Ch, Tr>& os,
1740            const dynamic_bitset<Block, Alloc>& b)
1741 {
1742 
1743     using namespace std;
1744 
1745     const ios_base::iostate ok = ios_base::goodbit;
1746     ios_base::iostate err = ok;
1747 
1748     typename basic_ostream<Ch, Tr>::sentry cerberos(os);
1749     if (cerberos) {
1750 
1751         BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, os.getloc());
1752         const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
1753         const Ch one  = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
1754 
1755         BOOST_TRY {
1756 
1757             typedef typename dynamic_bitset<Block, Alloc>::size_type bitset_size_type;
1758             typedef basic_streambuf<Ch, Tr> buffer_type;
1759 
1760             buffer_type * buf = os.rdbuf();
1761             // careful: os.width() is signed (and can be < 0)
1762             const bitset_size_type width = (os.width() <= 0) ? 0 : static_cast<bitset_size_type>(os.width());
1763             streamsize npad = (width <= b.size()) ? 0 : width - b.size();
1764 
1765             const Ch fill_char = os.fill();
1766             const ios_base::fmtflags adjustfield = os.flags() & ios_base::adjustfield;
1767 
1768             // if needed fill at left; pad is decreased along the way
1769             if (adjustfield != ios_base::left) {
1770                 for (; 0 < npad; --npad)
1771                     if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) {
1772                           err |= ios_base::failbit;
1773                           break;
1774                     }
1775             }
1776 
1777             if (err == ok) {
1778                 // output the bitset
1779                 for (bitset_size_type i = b.size(); 0 < i; --i) {
1780                     typename buffer_type::int_type
1781                         ret = buf->sputc(b.test(i-1)? one : zero);
1782                     if (Tr::eq_int_type(Tr::eof(), ret)) {
1783                         err |= ios_base::failbit;
1784                         break;
1785                     }
1786                 }
1787             }
1788 
1789             if (err == ok) {
1790                 // if needed fill at right
1791                 for (; 0 < npad; --npad) {
1792                     if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) {
1793                         err |= ios_base::failbit;
1794                         break;
1795                     }
1796                 }
1797             }
1798 
1799 
1800             os.width(0);
1801 
1802         } BOOST_CATCH (...) { // see std 27.6.1.1/4
1803             bool rethrow = false;
1804             BOOST_TRY { os.setstate(ios_base::failbit); } BOOST_CATCH (...) { rethrow = true; } BOOST_CATCH_END
1805 
1806             if (rethrow)
1807                 BOOST_RETHROW;
1808         }
1809         BOOST_CATCH_END
1810     }
1811 
1812     if(err != ok)
1813         os.setstate(err); // may throw exception
1814     return os;
1815 
1816 }
1817 #endif
1818 
1819 
1820 #ifdef BOOST_OLD_IOSTREAMS
1821 
1822     // A sentry-like class that calls isfx in its destructor.
1823     // "Necessary" because bit_appender::do_append may throw.
1824     class pseudo_sentry {
1825         std::istream & m_r;
1826         const bool m_ok;
1827     public:
1828         explicit pseudo_sentry(std::istream & r) : m_r(r), m_ok(r.ipfx(0)) { }
1829         ~pseudo_sentry() { m_r.isfx(); }
1830         operator bool() const { return m_ok; }
1831     };
1832 
1833 template <typename Block, typename Alloc>
1834 std::istream&
1835 operator>>(std::istream& is, dynamic_bitset<Block, Alloc>& b)
1836 {
1837 
1838 // Extractor for classic IO streams (libstdc++ < 3.0)
1839 // ----------------------------------------------------//
1840 //  It's assumed that the stream buffer functions, and
1841 //  the stream's setstate() _cannot_ throw.
1842 
1843 
1844     typedef dynamic_bitset<Block, Alloc> bitset_type;
1845     typedef typename bitset_type::size_type size_type;
1846 
1847     std::ios::iostate err = std::ios::goodbit;
1848     pseudo_sentry cerberos(is); // skips whitespaces
1849     if(cerberos) {
1850 
1851         b.clear();
1852 
1853         const std::streamsize w = is.width();
1854         const size_type limit = w > 0 && static_cast<size_type>(w) < b.max_size()
1855                                                          ? static_cast<size_type>(w) : b.max_size();
1856         typename bitset_type::bit_appender appender(b);
1857         std::streambuf * buf = is.rdbuf();
1858         for(int c = buf->sgetc(); appender.get_count() < limit; c = buf->snextc() ) {
1859 
1860             if (c == EOF) {
1861                 err |= std::ios::eofbit;
1862                 break;
1863             }
1864             else if (char(c) != '0' && char(c) != '1')
1865                 break; // non digit character
1866 
1867             else {
1868                 BOOST_TRY {
1869                     appender.do_append(char(c) == '1');
1870                 }
1871                 BOOST_CATCH(...) {
1872                     is.setstate(std::ios::failbit); // assume this can't throw
1873                     BOOST_RETHROW;
1874                 }
1875                 BOOST_CATCH_END
1876             }
1877 
1878         } // for
1879     }
1880 
1881     is.width(0);
1882     if (b.size() == 0)
1883         err |= std::ios::failbit;
1884     if (err != std::ios::goodbit)
1885         is.setstate (err); // may throw
1886 
1887     return is;
1888 }
1889 
1890 #else // BOOST_OLD_IOSTREAMS
1891 
1892 template <typename Ch, typename Tr, typename Block, typename Alloc>
1893 std::basic_istream<Ch, Tr>&
1894 operator>>(std::basic_istream<Ch, Tr>& is, dynamic_bitset<Block, Alloc>& b)
1895 {
1896 
1897     using namespace std;
1898 
1899     typedef dynamic_bitset<Block, Alloc> bitset_type;
1900     typedef typename bitset_type::size_type size_type;
1901 
1902     const streamsize w = is.width();
1903     const size_type limit = 0 < w && static_cast<size_type>(w) < b.max_size()?
1904                                          static_cast<size_type>(w) : b.max_size();
1905 
1906     ios_base::iostate err = ios_base::goodbit;
1907     typename basic_istream<Ch, Tr>::sentry cerberos(is); // skips whitespaces
1908     if(cerberos) {
1909 
1910         // in accordance with prop. resol. of lib DR 303 [last checked 4 Feb 2004]
1911         BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, is.getloc());
1912         const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
1913         const Ch one  = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
1914 
1915         b.clear();
1916         BOOST_TRY {
1917             typename bitset_type::bit_appender appender(b);
1918             basic_streambuf <Ch, Tr> * buf = is.rdbuf();
1919             typename Tr::int_type c = buf->sgetc();
1920             for( ; appender.get_count() < limit; c = buf->snextc() ) {
1921 
1922                 if (Tr::eq_int_type(Tr::eof(), c)) {
1923                     err |= ios_base::eofbit;
1924                     break;
1925                 }
1926                 else {
1927                     const Ch to_c = Tr::to_char_type(c);
1928                     const bool is_one = Tr::eq(to_c, one);
1929 
1930                     if (!is_one && !Tr::eq(to_c, zero))
1931                         break; // non digit character
1932 
1933                     appender.do_append(is_one);
1934 
1935                 }
1936 
1937             } // for
1938         }
1939         BOOST_CATCH (...) {
1940             // catches from stream buf, or from vector:
1941             //
1942             // bits_stored bits have been extracted and stored, and
1943             // either no further character is extractable or we can't
1944             // append to the underlying vector (out of memory)
1945 
1946             bool rethrow = false;   // see std 27.6.1.1/4
1947             BOOST_TRY { is.setstate(ios_base::badbit); }
1948             BOOST_CATCH(...) { rethrow = true; }
1949             BOOST_CATCH_END
1950 
1951             if (rethrow)
1952                 BOOST_RETHROW;
1953 
1954         }
1955         BOOST_CATCH_END
1956     }
1957 
1958     is.width(0);
1959     if (b.size() == 0 /*|| !cerberos*/)
1960         err |= ios_base::failbit;
1961     if (err != ios_base::goodbit)
1962         is.setstate (err); // may throw
1963 
1964     return is;
1965 
1966 }
1967 
1968 
1969 #endif
1970 
1971 
1972 //-----------------------------------------------------------------------------
1973 // bitset operations
1974 
1975 template <typename Block, typename Allocator>
1976 dynamic_bitset<Block, Allocator>
1977 operator&(const dynamic_bitset<Block, Allocator>& x,
1978           const dynamic_bitset<Block, Allocator>& y)
1979 {
1980     dynamic_bitset<Block, Allocator> b(x);
1981     return b &= y;
1982 }
1983 
1984 template <typename Block, typename Allocator>
1985 dynamic_bitset<Block, Allocator>
1986 operator|(const dynamic_bitset<Block, Allocator>& x,
1987           const dynamic_bitset<Block, Allocator>& y)
1988 {
1989     dynamic_bitset<Block, Allocator> b(x);
1990     return b |= y;
1991 }
1992 
1993 template <typename Block, typename Allocator>
1994 dynamic_bitset<Block, Allocator>
1995 operator^(const dynamic_bitset<Block, Allocator>& x,
1996           const dynamic_bitset<Block, Allocator>& y)
1997 {
1998     dynamic_bitset<Block, Allocator> b(x);
1999     return b ^= y;
2000 }
2001 
2002 template <typename Block, typename Allocator>
2003 dynamic_bitset<Block, Allocator>
2004 operator-(const dynamic_bitset<Block, Allocator>& x,
2005           const dynamic_bitset<Block, Allocator>& y)
2006 {
2007     dynamic_bitset<Block, Allocator> b(x);
2008     return b -= y;
2009 }
2010 
2011 //-----------------------------------------------------------------------------
2012 // namespace scope swap
2013 
2014 template<typename Block, typename Allocator>
2015 inline void
2016 swap(dynamic_bitset<Block, Allocator>& left,
2017      dynamic_bitset<Block, Allocator>& right) // no throw
2018 {
2019     left.swap(right);
2020 }
2021 
2022 
2023 //-----------------------------------------------------------------------------
2024 // private (on conforming compilers) member functions
2025 
2026 
2027 template <typename Block, typename Allocator>
2028 inline typename dynamic_bitset<Block, Allocator>::size_type
2029 dynamic_bitset<Block, Allocator>::calc_num_blocks(size_type num_bits)
2030 {
2031     return num_bits / bits_per_block
2032            + static_cast<size_type>( num_bits % bits_per_block != 0 );
2033 }
2034 
2035 // gives a reference to the highest block
2036 //
2037 template <typename Block, typename Allocator>
2038 inline Block& dynamic_bitset<Block, Allocator>::m_highest_block()
2039 {
2040     return const_cast<Block &>
2041            (static_cast<const dynamic_bitset *>(this)->m_highest_block());
2042 }
2043 
2044 // gives a const-reference to the highest block
2045 //
2046 template <typename Block, typename Allocator>
2047 inline const Block& dynamic_bitset<Block, Allocator>::m_highest_block() const
2048 {
2049     assert(size() > 0 && num_blocks() > 0);
2050     return m_bits.back();
2051 }
2052 
2053 template <typename Block, typename Allocator>
2054 dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::range_operation(
2055     size_type pos, size_type len,
2056     Block (*partial_block_operation)(Block, size_type, size_type),
2057     Block (*full_block_operation)(Block))
2058 {
2059     assert(pos + len <= m_num_bits);
2060 
2061     // Do nothing in case of zero length
2062     if (!len)
2063         return *this;
2064 
2065     // Use an additional asserts in order to detect size_type overflow
2066     // For example: pos = 10, len = size_type_limit - 2, pos + len = 7
2067     // In case of overflow, 'pos + len' is always smaller than 'len'
2068     assert(pos + len >= len);
2069 
2070     // Start and end blocks of the [pos; pos + len - 1] sequence
2071     const size_type first_block = block_index(pos);
2072     const size_type last_block = block_index(pos + len - 1);
2073 
2074     const size_type first_bit_index = bit_index(pos);
2075     const size_type last_bit_index = bit_index(pos + len - 1);
2076 
2077     if (first_block == last_block) {
2078         // Filling only a sub-block of a block
2079         m_bits[first_block] = partial_block_operation(m_bits[first_block],
2080             first_bit_index, last_bit_index);
2081     } else {
2082         // Check if the corner blocks won't be fully filled with 'val'
2083         const size_type first_block_shift = bit_index(pos) ? 1 : 0;
2084         const size_type last_block_shift = (bit_index(pos + len - 1)
2085             == bits_per_block - 1) ? 0 : 1;
2086 
2087         // Blocks that will be filled with ~0 or 0 at once
2088         const size_type first_full_block = first_block + first_block_shift;
2089         const size_type last_full_block = last_block - last_block_shift;
2090 
2091         for (size_type i = first_full_block; i <= last_full_block; ++i) {
2092             m_bits[i] = full_block_operation(m_bits[i]);
2093         }
2094 
2095         // Fill the first block from the 'first' bit index to the end
2096         if (first_block_shift) {
2097             m_bits[first_block] = partial_block_operation(m_bits[first_block],
2098                 first_bit_index, bits_per_block - 1);
2099         }
2100 
2101         // Fill the last block from the start to the 'last' bit index
2102         if (last_block_shift) {
2103             m_bits[last_block] = partial_block_operation(m_bits[last_block],
2104                 0, last_bit_index);
2105         }
2106     }
2107 
2108     return *this;
2109 }
2110 
2111 // If size() is not a multiple of bits_per_block
2112 // then not all the bits in the last block are used.
2113 // This function resets the unused bits (convenient
2114 // for the implementation of many member functions)
2115 //
2116 template <typename Block, typename Allocator>
2117 inline void dynamic_bitset<Block, Allocator>::m_zero_unused_bits()
2118 {
2119     assert (num_blocks() == calc_num_blocks(m_num_bits));
2120 
2121     // if != 0 this is the number of bits used in the last block
2122     const block_width_type extra_bits = count_extra_bits();
2123 
2124     if (extra_bits != 0)
2125         m_highest_block() &= (Block(1) << extra_bits) - 1;
2126 }
2127 
2128 // check class invariants
2129 template <typename Block, typename Allocator>
2130 bool dynamic_bitset<Block, Allocator>::m_check_invariants() const
2131 {
2132     const block_width_type extra_bits = count_extra_bits();
2133     if (extra_bits > 0) {
2134         const block_type mask = detail::dynamic_bitset_impl::max_limit<Block>::value << extra_bits;
2135         if ((m_highest_block() & mask) != 0)
2136             return false;
2137     }
2138     if (m_bits.size() > m_bits.capacity() || num_blocks() != calc_num_blocks(size()))
2139         return false;
2140 
2141     return true;
2142 
2143 }
2144 
2145 
2146 } // namespace boost
2147 
2148 #undef BOOST_BITSET_CHAR
2149 
2150 // std::hash support
2151 #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) && !defined(BOOST_DYNAMIC_BITSET_NO_STD_HASH)
2152 #include <functional>
2153 namespace std
2154 {
2155     template<typename Block, typename Allocator>
2156     struct hash< boost::dynamic_bitset<Block, Allocator> >
2157     {
2158         typedef boost::dynamic_bitset<Block, Allocator> argument_type;
2159         typedef std::size_t result_type;
2160         result_type operator()(const argument_type& a) const BOOST_NOEXCEPT
2161         {
2162             boost::hash<argument_type> hasher;
2163             return hasher(a);
2164         }
2165     };
2166 }
2167 #endif
2168 
2169 #endif // include guard
2170