Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:46

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_next(size_type pos) const;
0329 
0330 
0331 #if !defined BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
0332     // lexicographical comparison
0333     template <typename B, typename A>
0334     friend bool operator==(const dynamic_bitset<B, A>& a,
0335                            const dynamic_bitset<B, A>& b);
0336 
0337     template <typename B, typename A>
0338     friend bool operator<(const dynamic_bitset<B, A>& a,
0339                           const dynamic_bitset<B, A>& b);
0340 
0341     template <typename B, typename A>
0342     friend bool oplessthan(const dynamic_bitset<B, A>& a,
0343                           const dynamic_bitset<B, A>& b);
0344 
0345 
0346     template <typename B, typename A, typename BlockOutputIterator>
0347     friend void to_block_range(const dynamic_bitset<B, A>& b,
0348                                BlockOutputIterator result);
0349 
0350     template <typename BlockIterator, typename B, typename A>
0351     friend void from_block_range(BlockIterator first, BlockIterator last,
0352                                  dynamic_bitset<B, A>& result);
0353 
0354 
0355     template <typename CharT, typename Traits, typename B, typename A>
0356     friend std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& is,
0357                                                          dynamic_bitset<B, A>& b);
0358 
0359     template <typename B, typename A, typename stringT>
0360     friend void to_string_helper(const dynamic_bitset<B, A> & b, stringT & s, bool dump_all);
0361 
0362     template <typename B, typename A>
0363     friend std::size_t hash_value(const dynamic_bitset<B, A>& a);
0364 #endif
0365 
0366 public:
0367     // forward declaration for optional zero-copy serialization support
0368     class serialize_impl;
0369     friend class serialize_impl;
0370 
0371 private:
0372     BOOST_STATIC_CONSTANT(block_width_type, ulong_width = std::numeric_limits<unsigned long>::digits);
0373 
0374     dynamic_bitset& range_operation(size_type pos, size_type len,
0375         Block (*partial_block_operation)(Block, size_type, size_type),
0376         Block (*full_block_operation)(Block));
0377     void m_zero_unused_bits();
0378     bool m_check_invariants() const;
0379 
0380     static bool m_not_empty(Block x){ return x != Block(0); };
0381     size_type m_do_find_from(size_type first_block) const;
0382 
0383     block_width_type count_extra_bits() const BOOST_NOEXCEPT { return bit_index(size()); }
0384     static size_type block_index(size_type pos) BOOST_NOEXCEPT { return pos / bits_per_block; }
0385     static block_width_type bit_index(size_type pos) BOOST_NOEXCEPT { return static_cast<block_width_type>(pos % bits_per_block); }
0386     static Block bit_mask(size_type pos) BOOST_NOEXCEPT { return Block(1) << bit_index(pos); }
0387     static Block bit_mask(size_type first, size_type last) BOOST_NOEXCEPT
0388     {
0389         Block res = (last == bits_per_block - 1)
0390             ? detail::dynamic_bitset_impl::max_limit<Block>::value
0391             : ((Block(1) << (last + 1)) - 1);
0392         res ^= (Block(1) << first) - 1;
0393         return res;
0394     }
0395     static Block set_block_bits(Block block, size_type first,
0396         size_type last, bool val) BOOST_NOEXCEPT
0397     {
0398         if (val)
0399             return block | bit_mask(first, last);
0400         else
0401             return block & static_cast<Block>(~bit_mask(first, last));
0402     }
0403 
0404     // Functions for operations on ranges
0405     inline static Block set_block_partial(Block block, size_type first,
0406         size_type last) BOOST_NOEXCEPT
0407     {
0408         return set_block_bits(block, first, last, true);
0409     }
0410     inline static Block set_block_full(Block) BOOST_NOEXCEPT
0411     {
0412         return detail::dynamic_bitset_impl::max_limit<Block>::value;
0413     }
0414     inline static Block reset_block_partial(Block block, size_type first,
0415         size_type last) BOOST_NOEXCEPT
0416     {
0417         return set_block_bits(block, first, last, false);
0418     }
0419     inline static Block reset_block_full(Block) BOOST_NOEXCEPT
0420     {
0421         return 0;
0422     }
0423     inline static Block flip_block_partial(Block block, size_type first,
0424         size_type last) BOOST_NOEXCEPT
0425     {
0426         return block ^ bit_mask(first, last);
0427     }
0428     inline static Block flip_block_full(Block block) BOOST_NOEXCEPT
0429     {
0430         return ~block;
0431     }
0432 
0433     template <typename CharT, typename Traits, typename Alloc>
0434     void init_from_string(const std::basic_string<CharT, Traits, Alloc>& s,
0435         typename std::basic_string<CharT, Traits, Alloc>::size_type pos,
0436         typename std::basic_string<CharT, Traits, Alloc>::size_type n,
0437         size_type num_bits)
0438     {
0439         assert(pos <= s.size());
0440 
0441         typedef typename std::basic_string<CharT, Traits, Alloc> StrT;
0442         typedef typename StrT::traits_type Tr;
0443 
0444         const typename StrT::size_type rlen = (std::min)(n, s.size() - pos);
0445         const size_type sz = ( num_bits != npos? num_bits : rlen);
0446         m_bits.resize(calc_num_blocks(sz));
0447         m_num_bits = sz;
0448 
0449 
0450         BOOST_DYNAMIC_BITSET_CTYPE_FACET(CharT, fac, std::locale());
0451         const CharT one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
0452 
0453         const size_type m = num_bits < rlen ? num_bits : rlen;
0454         typename StrT::size_type i = 0;
0455         for( ; i < m; ++i) {
0456 
0457             const CharT c = s[(pos + m - 1) - i];
0458 
0459             assert( Tr::eq(c, one)
0460                     || Tr::eq(c, BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0')) );
0461 
0462             if (Tr::eq(c, one))
0463                 set(i);
0464 
0465         }
0466 
0467     }
0468 
0469     void init_from_unsigned_long(size_type num_bits,
0470                                  unsigned long value/*,
0471                                  const Allocator& alloc*/)
0472     {
0473 
0474         assert(m_bits.size() == 0);
0475 
0476         m_bits.resize(calc_num_blocks(num_bits));
0477         m_num_bits = num_bits;
0478 
0479         typedef unsigned long num_type;
0480         typedef boost::detail::dynamic_bitset_impl
0481             ::shifter<num_type, bits_per_block, ulong_width> shifter;
0482 
0483         //if (num_bits == 0)
0484         //    return;
0485 
0486         // zero out all bits at pos >= num_bits, if any;
0487         // note that: num_bits == 0 implies value == 0
0488         if (num_bits < static_cast<size_type>(ulong_width)) {
0489             const num_type mask = (num_type(1) << num_bits) - 1;
0490             value &= mask;
0491         }
0492 
0493         typename buffer_type::iterator it = m_bits.begin();
0494         for( ; value; shifter::left_shift(value), ++it) {
0495             *it = static_cast<block_type>(value);
0496         }
0497 
0498     }
0499 
0500 
0501 
0502 BOOST_DYNAMIC_BITSET_PRIVATE:
0503 
0504     bool m_unchecked_test(size_type pos) const;
0505     static size_type calc_num_blocks(size_type num_bits);
0506 
0507     Block&        m_highest_block();
0508     const Block&  m_highest_block() const;
0509 
0510     buffer_type m_bits;
0511     size_type   m_num_bits;
0512 
0513 
0514     class bit_appender;
0515     friend class bit_appender;
0516     class bit_appender {
0517       // helper for stream >>
0518       // Supplies to the lack of an efficient append at the less
0519       // significant end: bits are actually appended "at left" but
0520       // rearranged in the destructor. From the perspective of
0521       // client code everything works *as if* dynamic_bitset<> had
0522       // an append_at_right() function (eventually throwing the same
0523       // exceptions as push_back) except that the function is in fact
0524       // called bit_appender::do_append().
0525       //
0526       dynamic_bitset & bs;
0527       size_type n;
0528       Block mask;
0529       Block * current;
0530 
0531       // not implemented
0532       bit_appender(const bit_appender &);
0533       bit_appender & operator=(const bit_appender &);
0534 
0535     public:
0536         bit_appender(dynamic_bitset & r) : bs(r), n(0), mask(0), current(0) {}
0537         ~bit_appender() {
0538             // reverse the order of blocks, shift
0539             // if needed, and then resize
0540             //
0541             std::reverse(bs.m_bits.begin(), bs.m_bits.end());
0542             const block_width_type offs = bit_index(n);
0543             if (offs)
0544                 bs >>= (bits_per_block - offs);
0545             bs.resize(n); // doesn't enlarge, so can't throw
0546             assert(bs.m_check_invariants());
0547         }
0548         inline void do_append(bool value) {
0549 
0550             if (mask == 0) {
0551                 bs.append(Block(0));
0552                 current = &bs.m_highest_block();
0553                 mask = Block(1) << (bits_per_block - 1);
0554             }
0555 
0556             if(value)
0557                 *current |= mask;
0558 
0559             mask /= 2;
0560             ++n;
0561         }
0562         size_type get_count() const { return n; }
0563     };
0564 
0565 };
0566 
0567 #if !defined BOOST_NO_INCLASS_MEMBER_INITIALIZATION
0568 
0569 template <typename Block, typename Allocator>
0570 const typename dynamic_bitset<Block, Allocator>::block_width_type
0571 dynamic_bitset<Block, Allocator>::bits_per_block;
0572 
0573 template <typename Block, typename Allocator>
0574 const typename dynamic_bitset<Block, Allocator>::size_type
0575 dynamic_bitset<Block, Allocator>::npos;
0576 
0577 template <typename Block, typename Allocator>
0578 const typename dynamic_bitset<Block, Allocator>::block_width_type
0579 dynamic_bitset<Block, Allocator>::ulong_width;
0580 
0581 #endif
0582 
0583 // Global Functions:
0584 
0585 // comparison
0586 template <typename Block, typename Allocator>
0587 bool operator!=(const dynamic_bitset<Block, Allocator>& a,
0588                 const dynamic_bitset<Block, Allocator>& b);
0589 
0590 template <typename Block, typename Allocator>
0591 bool operator<=(const dynamic_bitset<Block, Allocator>& a,
0592                 const dynamic_bitset<Block, Allocator>& b);
0593 
0594 template <typename Block, typename Allocator>
0595 bool operator>(const dynamic_bitset<Block, Allocator>& a,
0596                const dynamic_bitset<Block, Allocator>& b);
0597 
0598 template <typename Block, typename Allocator>
0599 bool operator>=(const dynamic_bitset<Block, Allocator>& a,
0600                 const dynamic_bitset<Block, Allocator>& b);
0601 
0602 // stream operators
0603 #ifdef BOOST_OLD_IOSTREAMS
0604 template <typename Block, typename Allocator>
0605 std::ostream& operator<<(std::ostream& os,
0606                          const dynamic_bitset<Block, Allocator>& b);
0607 
0608 template <typename Block, typename Allocator>
0609 std::istream& operator>>(std::istream& is, dynamic_bitset<Block,Allocator>& b);
0610 #else
0611 template <typename CharT, typename Traits, typename Block, typename Allocator>
0612 std::basic_ostream<CharT, Traits>&
0613 operator<<(std::basic_ostream<CharT, Traits>& os,
0614            const dynamic_bitset<Block, Allocator>& b);
0615 
0616 template <typename CharT, typename Traits, typename Block, typename Allocator>
0617 std::basic_istream<CharT, Traits>&
0618 operator>>(std::basic_istream<CharT, Traits>& is,
0619            dynamic_bitset<Block, Allocator>& b);
0620 #endif
0621 
0622 // bitset operations
0623 template <typename Block, typename Allocator>
0624 dynamic_bitset<Block, Allocator>
0625 operator&(const dynamic_bitset<Block, Allocator>& b1,
0626           const dynamic_bitset<Block, Allocator>& b2);
0627 
0628 template <typename Block, typename Allocator>
0629 dynamic_bitset<Block, Allocator>
0630 operator|(const dynamic_bitset<Block, Allocator>& b1,
0631           const dynamic_bitset<Block, Allocator>& b2);
0632 
0633 template <typename Block, typename Allocator>
0634 dynamic_bitset<Block, Allocator>
0635 operator^(const dynamic_bitset<Block, Allocator>& b1,
0636           const dynamic_bitset<Block, Allocator>& b2);
0637 
0638 template <typename Block, typename Allocator>
0639 dynamic_bitset<Block, Allocator>
0640 operator-(const dynamic_bitset<Block, Allocator>& b1,
0641           const dynamic_bitset<Block, Allocator>& b2);
0642 
0643 // namespace scope swap
0644 template<typename Block, typename Allocator>
0645 void swap(dynamic_bitset<Block, Allocator>& b1,
0646           dynamic_bitset<Block, Allocator>& b2);
0647 
0648 
0649 template <typename Block, typename Allocator, typename stringT>
0650 void
0651 to_string(const dynamic_bitset<Block, Allocator>& b, stringT & s);
0652 
0653 template <typename Block, typename Allocator, typename BlockOutputIterator>
0654 void
0655 to_block_range(const dynamic_bitset<Block, Allocator>& b,
0656                BlockOutputIterator result);
0657 
0658 
0659 template <typename BlockIterator, typename B, typename A>
0660 inline void
0661 from_block_range(BlockIterator first, BlockIterator last,
0662                  dynamic_bitset<B, A>& result)
0663 {
0664     // PRE: distance(first, last) <= numblocks()
0665     std::copy (first, last, result.m_bits.begin());
0666 }
0667 
0668 //=============================================================================
0669 // dynamic_bitset implementation
0670 
0671 
0672 //-----------------------------------------------------------------------------
0673 // constructors, etc.
0674 
0675 template <typename Block, typename Allocator>
0676 dynamic_bitset<Block, Allocator>::dynamic_bitset(const Allocator& alloc)
0677   : m_bits(alloc), m_num_bits(0)
0678 {
0679 
0680 }
0681 
0682 template <typename Block, typename Allocator>
0683 dynamic_bitset<Block, Allocator>::
0684 dynamic_bitset(size_type num_bits, unsigned long value, const Allocator& alloc)
0685     : m_bits(alloc),
0686       m_num_bits(0)
0687 {
0688     init_from_unsigned_long(num_bits, value);
0689 }
0690 
0691 // copy constructor
0692 template <typename Block, typename Allocator>
0693 inline dynamic_bitset<Block, Allocator>::
0694 dynamic_bitset(const dynamic_bitset& b)
0695   : m_bits(b.m_bits), m_num_bits(b.m_num_bits)
0696 {
0697 
0698 }
0699 
0700 template <typename Block, typename Allocator>
0701 inline dynamic_bitset<Block, Allocator>::
0702 ~dynamic_bitset()
0703 {
0704     assert(m_check_invariants());
0705 }
0706 
0707 template <typename Block, typename Allocator>
0708 inline void dynamic_bitset<Block, Allocator>::
0709 swap(dynamic_bitset<Block, Allocator>& b) // no throw
0710 {
0711     std::swap(m_bits, b.m_bits);
0712     std::swap(m_num_bits, b.m_num_bits);
0713 }
0714 
0715 template <typename Block, typename Allocator>
0716 dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::
0717 operator=(const dynamic_bitset<Block, Allocator>& b)
0718 {
0719     m_bits = b.m_bits;
0720     m_num_bits = b.m_num_bits;
0721     return *this;
0722 }
0723 
0724 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
0725 
0726 template <typename Block, typename Allocator>
0727 inline dynamic_bitset<Block, Allocator>::
0728 dynamic_bitset(dynamic_bitset<Block, Allocator>&& b)
0729   : m_bits(boost::move(b.m_bits)), m_num_bits(boost::move(b.m_num_bits))
0730 {
0731     // Required so that assert(m_check_invariants()); works.
0732     assert((b.m_bits = buffer_type()).empty());
0733     b.m_num_bits = 0;
0734 }
0735 
0736 template <typename Block, typename Allocator>
0737 inline dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::
0738 operator=(dynamic_bitset<Block, Allocator>&& b)
0739 {
0740     if (boost::addressof(b) == this) { return *this; }
0741 
0742     m_bits = boost::move(b.m_bits);
0743     m_num_bits = boost::move(b.m_num_bits);
0744     // Required so that assert(m_check_invariants()); works.
0745     assert((b.m_bits = buffer_type()).empty());
0746     b.m_num_bits = 0;
0747     return *this;
0748 }
0749 
0750 #endif // BOOST_NO_CXX11_RVALUE_REFERENCES
0751 
0752 template <typename Block, typename Allocator>
0753 inline typename dynamic_bitset<Block, Allocator>::allocator_type
0754 dynamic_bitset<Block, Allocator>::get_allocator() const
0755 {
0756     return m_bits.get_allocator();
0757 }
0758 
0759 //-----------------------------------------------------------------------------
0760 // size changing operations
0761 
0762 template <typename Block, typename Allocator>
0763 void dynamic_bitset<Block, Allocator>::
0764 resize(size_type num_bits, bool value) // strong guarantee
0765 {
0766 
0767   const size_type old_num_blocks = num_blocks();
0768   const size_type required_blocks = calc_num_blocks(num_bits);
0769 
0770   const block_type v = value? detail::dynamic_bitset_impl::max_limit<Block>::value : Block(0);
0771 
0772   if (required_blocks != old_num_blocks) {
0773     m_bits.resize(required_blocks, v); // s.g. (copy)
0774   }
0775 
0776 
0777   // At this point:
0778   //
0779   //  - if the buffer was shrunk, we have nothing more to do,
0780   //    except a call to m_zero_unused_bits()
0781   //
0782   //  - if it was enlarged, all the (used) bits in the new blocks have
0783   //    the correct value, but we have not yet touched those bits, if
0784   //    any, that were 'unused bits' before enlarging: if value == true,
0785   //    they must be set.
0786 
0787   if (value && (num_bits > m_num_bits)) {
0788 
0789     const block_width_type extra_bits = count_extra_bits();
0790     if (extra_bits) {
0791         assert(old_num_blocks >= 1 && old_num_blocks <= m_bits.size());
0792 
0793         // Set them.
0794         m_bits[old_num_blocks - 1] |= (v << extra_bits);
0795     }
0796 
0797   }
0798 
0799   m_num_bits = num_bits;
0800   m_zero_unused_bits();
0801 
0802 }
0803 
0804 template <typename Block, typename Allocator>
0805 void dynamic_bitset<Block, Allocator>::
0806 clear() // no throw
0807 {
0808   m_bits.clear();
0809   m_num_bits = 0;
0810 }
0811 
0812 
0813 template <typename Block, typename Allocator>
0814 void dynamic_bitset<Block, Allocator>::
0815 push_back(bool bit)
0816 {
0817   const size_type sz = size();
0818   resize(sz + 1);
0819   set(sz, 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_next(ulong_width - 1) != 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 
1490 template <typename Block, typename Allocator>
1491 typename dynamic_bitset<Block, Allocator>::size_type
1492 dynamic_bitset<Block, Allocator>::find_next(size_type pos) const
1493 {
1494 
1495     const size_type sz = size();
1496     if (pos >= (sz-1) || sz == 0)
1497         return npos;
1498 
1499     ++pos;
1500 
1501     const size_type blk = block_index(pos);
1502     const block_width_type ind = bit_index(pos);
1503 
1504     // shift bits upto one immediately after current
1505     const Block fore = m_bits[blk] >> ind;
1506 
1507     return fore?
1508         pos + static_cast<size_type>(detail::lowest_bit(fore))
1509         :
1510         m_do_find_from(blk + 1);
1511 
1512 }
1513 
1514 
1515 
1516 //-----------------------------------------------------------------------------
1517 // comparison
1518 
1519 template <typename Block, typename Allocator>
1520 bool operator==(const dynamic_bitset<Block, Allocator>& a,
1521                 const dynamic_bitset<Block, Allocator>& b)
1522 {
1523     return (a.m_num_bits == b.m_num_bits)
1524            && (a.m_bits == b.m_bits);
1525 }
1526 
1527 template <typename Block, typename Allocator>
1528 inline bool operator!=(const dynamic_bitset<Block, Allocator>& a,
1529                        const dynamic_bitset<Block, Allocator>& b)
1530 {
1531     return !(a == b);
1532 }
1533 
1534 template <typename Block, typename Allocator>
1535 bool operator<(const dynamic_bitset<Block, Allocator>& a,
1536                const dynamic_bitset<Block, Allocator>& b)
1537 {
1538 //    assert(a.size() == b.size());
1539 
1540     typedef BOOST_DEDUCED_TYPENAME dynamic_bitset<Block, Allocator>::size_type size_type;
1541     
1542     size_type asize(a.size());
1543     size_type bsize(b.size());
1544 
1545     if (!bsize)
1546         {
1547         return false;
1548         }
1549     else if (!asize)
1550         {
1551         return true;
1552         }
1553     else if (asize == bsize)
1554         {
1555         for (size_type ii = a.num_blocks(); ii > 0; --ii) 
1556             {
1557             size_type i = ii-1;
1558             if (a.m_bits[i] < b.m_bits[i])
1559                 return true;
1560             else if (a.m_bits[i] > b.m_bits[i])
1561                 return false;
1562             }
1563         return false;
1564         }
1565     else
1566         {
1567         
1568         size_type leqsize(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(asize,bsize));
1569     
1570         for (size_type ii = 0; ii < leqsize; ++ii,--asize,--bsize)
1571             {
1572             size_type i = asize-1;
1573             size_type j = bsize-1;
1574             if (a[i] < b[j])
1575                 return true;
1576             else if (a[i] > b[j])
1577                 return false;
1578             }
1579         return (a.size() < b.size());
1580         }
1581 }
1582 
1583 template <typename Block, typename Allocator>
1584 bool oplessthan(const dynamic_bitset<Block, Allocator>& a,
1585                const dynamic_bitset<Block, Allocator>& b)
1586 {
1587 //    assert(a.size() == b.size());
1588 
1589     typedef BOOST_DEDUCED_TYPENAME dynamic_bitset<Block, Allocator>::size_type size_type;
1590     
1591     size_type asize(a.num_blocks());
1592     size_type bsize(b.num_blocks());
1593     assert(asize == 3);
1594     assert(bsize == 4);
1595 
1596     if (!bsize)
1597         {
1598         return false;
1599         }
1600     else if (!asize)
1601         {
1602         return true;
1603         }
1604     else
1605         {
1606         
1607         size_type leqsize(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(asize,bsize));
1608         assert(leqsize == 3);
1609     
1610         //if (a.size() == 0)
1611         //  return false;
1612     
1613         // Since we are storing the most significant bit
1614         // at pos == size() - 1, we need to do the comparisons in reverse.
1615         //
1616         for (size_type ii = 0; ii < leqsize; ++ii,--asize,--bsize)
1617             {
1618             size_type i = asize-1;
1619             size_type j = bsize-1;
1620             if (a.m_bits[i] < b.m_bits[j])
1621                 return true;
1622             else if (a.m_bits[i] > b.m_bits[j])
1623                 return false;
1624             }
1625         return (a.num_blocks() < b.num_blocks());
1626         }
1627 }
1628 
1629 template <typename Block, typename Allocator>
1630 inline bool operator<=(const dynamic_bitset<Block, Allocator>& a,
1631                        const dynamic_bitset<Block, Allocator>& b)
1632 {
1633     return !(a > b);
1634 }
1635 
1636 template <typename Block, typename Allocator>
1637 inline bool operator>(const dynamic_bitset<Block, Allocator>& a,
1638                       const dynamic_bitset<Block, Allocator>& b)
1639 {
1640     return b < a;
1641 }
1642 
1643 template <typename Block, typename Allocator>
1644 inline bool operator>=(const dynamic_bitset<Block, Allocator>& a,
1645                        const dynamic_bitset<Block, Allocator>& b)
1646 {
1647     return !(a < b);
1648 }
1649 
1650 //-----------------------------------------------------------------------------
1651 // hash operations
1652 
1653 template <typename Block, typename Allocator>
1654 inline std::size_t hash_value(const dynamic_bitset<Block, Allocator>& a)
1655 {
1656     std::size_t res = hash_value(a.m_num_bits);
1657     boost::hash_combine(res, a.m_bits);
1658     return res;
1659 }
1660 
1661 //-----------------------------------------------------------------------------
1662 // stream operations
1663 
1664 #ifdef BOOST_OLD_IOSTREAMS
1665 template < typename Block, typename Alloc>
1666 std::ostream&
1667 operator<<(std::ostream& os, const dynamic_bitset<Block, Alloc>& b)
1668 {
1669     // NOTE: since this is aimed at "classic" iostreams, exception
1670     // masks on the stream are not supported. The library that
1671     // ships with gcc 2.95 has an exceptions() member function but
1672     // nothing is actually implemented; not even the class ios::failure.
1673 
1674     using namespace std;
1675 
1676     const ios::iostate ok = ios::goodbit;
1677     ios::iostate err = ok;
1678 
1679     if (os.opfx()) {
1680 
1681         //try
1682         typedef typename dynamic_bitset<Block, Alloc>::size_type bitsetsize_type;
1683 
1684         const bitsetsize_type sz = b.size();
1685         std::streambuf * buf = os.rdbuf();
1686         size_t npad = os.width() <= 0  // careful: os.width() is signed (and can be < 0)
1687             || (bitsetsize_type) os.width() <= sz? 0 : os.width() - sz;
1688 
1689         const char fill_char = os.fill();
1690         const ios::fmtflags adjustfield = os.flags() & ios::adjustfield;
1691 
1692         // if needed fill at left; pad is decresed along the way
1693         if (adjustfield != ios::left) {
1694             for (; 0 < npad; --npad)
1695                 if (fill_char != buf->sputc(fill_char)) {
1696                     err |= ios::failbit;
1697                     break;
1698                 }
1699         }
1700 
1701         if (err == ok) {
1702             // output the bitset
1703             for (bitsetsize_type i = b.size(); 0 < i; --i) {
1704                 const char dig = b.test(i-1)? '1' : '0';
1705                 if (EOF == buf->sputc(dig)) {
1706                     err |= ios::failbit;
1707                     break;
1708                 }
1709             }
1710         }
1711 
1712         if (err == ok) {
1713             // if needed fill at right
1714             for (; 0 < npad; --npad) {
1715                 if (fill_char != buf->sputc(fill_char)) {
1716                     err |= ios::failbit;
1717                     break;
1718                 }
1719             }
1720         }
1721 
1722         os.osfx();
1723         os.width(0);
1724 
1725     } // if opfx
1726 
1727     if(err != ok)
1728         os.setstate(err); // assume this does NOT throw
1729     return os;
1730 
1731 }
1732 #else
1733 
1734 template <typename Ch, typename Tr, typename Block, typename Alloc>
1735 std::basic_ostream<Ch, Tr>&
1736 operator<<(std::basic_ostream<Ch, Tr>& os,
1737            const dynamic_bitset<Block, Alloc>& b)
1738 {
1739 
1740     using namespace std;
1741 
1742     const ios_base::iostate ok = ios_base::goodbit;
1743     ios_base::iostate err = ok;
1744 
1745     typename basic_ostream<Ch, Tr>::sentry cerberos(os);
1746     if (cerberos) {
1747 
1748         BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, os.getloc());
1749         const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
1750         const Ch one  = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
1751 
1752         BOOST_TRY {
1753 
1754             typedef typename dynamic_bitset<Block, Alloc>::size_type bitset_size_type;
1755             typedef basic_streambuf<Ch, Tr> buffer_type;
1756 
1757             buffer_type * buf = os.rdbuf();
1758             // careful: os.width() is signed (and can be < 0)
1759             const bitset_size_type width = (os.width() <= 0) ? 0 : static_cast<bitset_size_type>(os.width());
1760             streamsize npad = (width <= b.size()) ? 0 : width - b.size();
1761 
1762             const Ch fill_char = os.fill();
1763             const ios_base::fmtflags adjustfield = os.flags() & ios_base::adjustfield;
1764 
1765             // if needed fill at left; pad is decreased along the way
1766             if (adjustfield != ios_base::left) {
1767                 for (; 0 < npad; --npad)
1768                     if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) {
1769                           err |= ios_base::failbit;
1770                           break;
1771                     }
1772             }
1773 
1774             if (err == ok) {
1775                 // output the bitset
1776                 for (bitset_size_type i = b.size(); 0 < i; --i) {
1777                     typename buffer_type::int_type
1778                         ret = buf->sputc(b.test(i-1)? one : zero);
1779                     if (Tr::eq_int_type(Tr::eof(), ret)) {
1780                         err |= ios_base::failbit;
1781                         break;
1782                     }
1783                 }
1784             }
1785 
1786             if (err == ok) {
1787                 // if needed fill at right
1788                 for (; 0 < npad; --npad) {
1789                     if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) {
1790                         err |= ios_base::failbit;
1791                         break;
1792                     }
1793                 }
1794             }
1795 
1796 
1797             os.width(0);
1798 
1799         } BOOST_CATCH (...) { // see std 27.6.1.1/4
1800             bool rethrow = false;
1801             BOOST_TRY { os.setstate(ios_base::failbit); } BOOST_CATCH (...) { rethrow = true; } BOOST_CATCH_END
1802 
1803             if (rethrow)
1804                 BOOST_RETHROW;
1805         }
1806         BOOST_CATCH_END
1807     }
1808 
1809     if(err != ok)
1810         os.setstate(err); // may throw exception
1811     return os;
1812 
1813 }
1814 #endif
1815 
1816 
1817 #ifdef BOOST_OLD_IOSTREAMS
1818 
1819     // A sentry-like class that calls isfx in its destructor.
1820     // "Necessary" because bit_appender::do_append may throw.
1821     class pseudo_sentry {
1822         std::istream & m_r;
1823         const bool m_ok;
1824     public:
1825         explicit pseudo_sentry(std::istream & r) : m_r(r), m_ok(r.ipfx(0)) { }
1826         ~pseudo_sentry() { m_r.isfx(); }
1827         operator bool() const { return m_ok; }
1828     };
1829 
1830 template <typename Block, typename Alloc>
1831 std::istream&
1832 operator>>(std::istream& is, dynamic_bitset<Block, Alloc>& b)
1833 {
1834 
1835 // Extractor for classic IO streams (libstdc++ < 3.0)
1836 // ----------------------------------------------------//
1837 //  It's assumed that the stream buffer functions, and
1838 //  the stream's setstate() _cannot_ throw.
1839 
1840 
1841     typedef dynamic_bitset<Block, Alloc> bitset_type;
1842     typedef typename bitset_type::size_type size_type;
1843 
1844     std::ios::iostate err = std::ios::goodbit;
1845     pseudo_sentry cerberos(is); // skips whitespaces
1846     if(cerberos) {
1847 
1848         b.clear();
1849 
1850         const std::streamsize w = is.width();
1851         const size_type limit = w > 0 && static_cast<size_type>(w) < b.max_size()
1852                                                          ? static_cast<size_type>(w) : b.max_size();
1853         typename bitset_type::bit_appender appender(b);
1854         std::streambuf * buf = is.rdbuf();
1855         for(int c = buf->sgetc(); appender.get_count() < limit; c = buf->snextc() ) {
1856 
1857             if (c == EOF) {
1858                 err |= std::ios::eofbit;
1859                 break;
1860             }
1861             else if (char(c) != '0' && char(c) != '1')
1862                 break; // non digit character
1863 
1864             else {
1865                 BOOST_TRY {
1866                     appender.do_append(char(c) == '1');
1867                 }
1868                 BOOST_CATCH(...) {
1869                     is.setstate(std::ios::failbit); // assume this can't throw
1870                     BOOST_RETHROW;
1871                 }
1872                 BOOST_CATCH_END
1873             }
1874 
1875         } // for
1876     }
1877 
1878     is.width(0);
1879     if (b.size() == 0)
1880         err |= std::ios::failbit;
1881     if (err != std::ios::goodbit)
1882         is.setstate (err); // may throw
1883 
1884     return is;
1885 }
1886 
1887 #else // BOOST_OLD_IOSTREAMS
1888 
1889 template <typename Ch, typename Tr, typename Block, typename Alloc>
1890 std::basic_istream<Ch, Tr>&
1891 operator>>(std::basic_istream<Ch, Tr>& is, dynamic_bitset<Block, Alloc>& b)
1892 {
1893 
1894     using namespace std;
1895 
1896     typedef dynamic_bitset<Block, Alloc> bitset_type;
1897     typedef typename bitset_type::size_type size_type;
1898 
1899     const streamsize w = is.width();
1900     const size_type limit = 0 < w && static_cast<size_type>(w) < b.max_size()?
1901                                          static_cast<size_type>(w) : b.max_size();
1902 
1903     ios_base::iostate err = ios_base::goodbit;
1904     typename basic_istream<Ch, Tr>::sentry cerberos(is); // skips whitespaces
1905     if(cerberos) {
1906 
1907         // in accordance with prop. resol. of lib DR 303 [last checked 4 Feb 2004]
1908         BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, is.getloc());
1909         const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
1910         const Ch one  = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
1911 
1912         b.clear();
1913         BOOST_TRY {
1914             typename bitset_type::bit_appender appender(b);
1915             basic_streambuf <Ch, Tr> * buf = is.rdbuf();
1916             typename Tr::int_type c = buf->sgetc();
1917             for( ; appender.get_count() < limit; c = buf->snextc() ) {
1918 
1919                 if (Tr::eq_int_type(Tr::eof(), c)) {
1920                     err |= ios_base::eofbit;
1921                     break;
1922                 }
1923                 else {
1924                     const Ch to_c = Tr::to_char_type(c);
1925                     const bool is_one = Tr::eq(to_c, one);
1926 
1927                     if (!is_one && !Tr::eq(to_c, zero))
1928                         break; // non digit character
1929 
1930                     appender.do_append(is_one);
1931 
1932                 }
1933 
1934             } // for
1935         }
1936         BOOST_CATCH (...) {
1937             // catches from stream buf, or from vector:
1938             //
1939             // bits_stored bits have been extracted and stored, and
1940             // either no further character is extractable or we can't
1941             // append to the underlying vector (out of memory)
1942 
1943             bool rethrow = false;   // see std 27.6.1.1/4
1944             BOOST_TRY { is.setstate(ios_base::badbit); }
1945             BOOST_CATCH(...) { rethrow = true; }
1946             BOOST_CATCH_END
1947 
1948             if (rethrow)
1949                 BOOST_RETHROW;
1950 
1951         }
1952         BOOST_CATCH_END
1953     }
1954 
1955     is.width(0);
1956     if (b.size() == 0 /*|| !cerberos*/)
1957         err |= ios_base::failbit;
1958     if (err != ios_base::goodbit)
1959         is.setstate (err); // may throw
1960 
1961     return is;
1962 
1963 }
1964 
1965 
1966 #endif
1967 
1968 
1969 //-----------------------------------------------------------------------------
1970 // bitset operations
1971 
1972 template <typename Block, typename Allocator>
1973 dynamic_bitset<Block, Allocator>
1974 operator&(const dynamic_bitset<Block, Allocator>& x,
1975           const dynamic_bitset<Block, Allocator>& y)
1976 {
1977     dynamic_bitset<Block, Allocator> b(x);
1978     return b &= y;
1979 }
1980 
1981 template <typename Block, typename Allocator>
1982 dynamic_bitset<Block, Allocator>
1983 operator|(const dynamic_bitset<Block, Allocator>& x,
1984           const dynamic_bitset<Block, Allocator>& y)
1985 {
1986     dynamic_bitset<Block, Allocator> b(x);
1987     return b |= y;
1988 }
1989 
1990 template <typename Block, typename Allocator>
1991 dynamic_bitset<Block, Allocator>
1992 operator^(const dynamic_bitset<Block, Allocator>& x,
1993           const dynamic_bitset<Block, Allocator>& y)
1994 {
1995     dynamic_bitset<Block, Allocator> b(x);
1996     return b ^= y;
1997 }
1998 
1999 template <typename Block, typename Allocator>
2000 dynamic_bitset<Block, Allocator>
2001 operator-(const dynamic_bitset<Block, Allocator>& x,
2002           const dynamic_bitset<Block, Allocator>& y)
2003 {
2004     dynamic_bitset<Block, Allocator> b(x);
2005     return b -= y;
2006 }
2007 
2008 //-----------------------------------------------------------------------------
2009 // namespace scope swap
2010 
2011 template<typename Block, typename Allocator>
2012 inline void
2013 swap(dynamic_bitset<Block, Allocator>& left,
2014      dynamic_bitset<Block, Allocator>& right) // no throw
2015 {
2016     left.swap(right);
2017 }
2018 
2019 
2020 //-----------------------------------------------------------------------------
2021 // private (on conforming compilers) member functions
2022 
2023 
2024 template <typename Block, typename Allocator>
2025 inline typename dynamic_bitset<Block, Allocator>::size_type
2026 dynamic_bitset<Block, Allocator>::calc_num_blocks(size_type num_bits)
2027 {
2028     return num_bits / bits_per_block
2029            + static_cast<size_type>( num_bits % bits_per_block != 0 );
2030 }
2031 
2032 // gives a reference to the highest block
2033 //
2034 template <typename Block, typename Allocator>
2035 inline Block& dynamic_bitset<Block, Allocator>::m_highest_block()
2036 {
2037     return const_cast<Block &>
2038            (static_cast<const dynamic_bitset *>(this)->m_highest_block());
2039 }
2040 
2041 // gives a const-reference to the highest block
2042 //
2043 template <typename Block, typename Allocator>
2044 inline const Block& dynamic_bitset<Block, Allocator>::m_highest_block() const
2045 {
2046     assert(size() > 0 && num_blocks() > 0);
2047     return m_bits.back();
2048 }
2049 
2050 template <typename Block, typename Allocator>
2051 dynamic_bitset<Block, Allocator>& dynamic_bitset<Block, Allocator>::range_operation(
2052     size_type pos, size_type len,
2053     Block (*partial_block_operation)(Block, size_type, size_type),
2054     Block (*full_block_operation)(Block))
2055 {
2056     assert(pos + len <= m_num_bits);
2057 
2058     // Do nothing in case of zero length
2059     if (!len)
2060         return *this;
2061 
2062     // Use an additional asserts in order to detect size_type overflow
2063     // For example: pos = 10, len = size_type_limit - 2, pos + len = 7
2064     // In case of overflow, 'pos + len' is always smaller than 'len'
2065     assert(pos + len >= len);
2066 
2067     // Start and end blocks of the [pos; pos + len - 1] sequence
2068     const size_type first_block = block_index(pos);
2069     const size_type last_block = block_index(pos + len - 1);
2070 
2071     const size_type first_bit_index = bit_index(pos);
2072     const size_type last_bit_index = bit_index(pos + len - 1);
2073 
2074     if (first_block == last_block) {
2075         // Filling only a sub-block of a block
2076         m_bits[first_block] = partial_block_operation(m_bits[first_block],
2077             first_bit_index, last_bit_index);
2078     } else {
2079         // Check if the corner blocks won't be fully filled with 'val'
2080         const size_type first_block_shift = bit_index(pos) ? 1 : 0;
2081         const size_type last_block_shift = (bit_index(pos + len - 1)
2082             == bits_per_block - 1) ? 0 : 1;
2083 
2084         // Blocks that will be filled with ~0 or 0 at once
2085         const size_type first_full_block = first_block + first_block_shift;
2086         const size_type last_full_block = last_block - last_block_shift;
2087 
2088         for (size_type i = first_full_block; i <= last_full_block; ++i) {
2089             m_bits[i] = full_block_operation(m_bits[i]);
2090         }
2091 
2092         // Fill the first block from the 'first' bit index to the end
2093         if (first_block_shift) {
2094             m_bits[first_block] = partial_block_operation(m_bits[first_block],
2095                 first_bit_index, bits_per_block - 1);
2096         }
2097 
2098         // Fill the last block from the start to the 'last' bit index
2099         if (last_block_shift) {
2100             m_bits[last_block] = partial_block_operation(m_bits[last_block],
2101                 0, last_bit_index);
2102         }
2103     }
2104 
2105     return *this;
2106 }
2107 
2108 // If size() is not a multiple of bits_per_block
2109 // then not all the bits in the last block are used.
2110 // This function resets the unused bits (convenient
2111 // for the implementation of many member functions)
2112 //
2113 template <typename Block, typename Allocator>
2114 inline void dynamic_bitset<Block, Allocator>::m_zero_unused_bits()
2115 {
2116     assert (num_blocks() == calc_num_blocks(m_num_bits));
2117 
2118     // if != 0 this is the number of bits used in the last block
2119     const block_width_type extra_bits = count_extra_bits();
2120 
2121     if (extra_bits != 0)
2122         m_highest_block() &= (Block(1) << extra_bits) - 1;
2123 }
2124 
2125 // check class invariants
2126 template <typename Block, typename Allocator>
2127 bool dynamic_bitset<Block, Allocator>::m_check_invariants() const
2128 {
2129     const block_width_type extra_bits = count_extra_bits();
2130     if (extra_bits > 0) {
2131         const block_type mask = detail::dynamic_bitset_impl::max_limit<Block>::value << extra_bits;
2132         if ((m_highest_block() & mask) != 0)
2133             return false;
2134     }
2135     if (m_bits.size() > m_bits.capacity() || num_blocks() != calc_num_blocks(size()))
2136         return false;
2137 
2138     return true;
2139 
2140 }
2141 
2142 
2143 } // namespace boost
2144 
2145 #undef BOOST_BITSET_CHAR
2146 
2147 // std::hash support
2148 #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL) && !defined(BOOST_DYNAMIC_BITSET_NO_STD_HASH)
2149 #include <functional>
2150 namespace std
2151 {
2152     template<typename Block, typename Allocator>
2153     struct hash< boost::dynamic_bitset<Block, Allocator> >
2154     {
2155         typedef boost::dynamic_bitset<Block, Allocator> argument_type;
2156         typedef std::size_t result_type;
2157         result_type operator()(const argument_type& a) const BOOST_NOEXCEPT
2158         {
2159             boost::hash<argument_type> hasher;
2160             return hasher(a);
2161         }
2162     };
2163 }
2164 #endif
2165 
2166 #endif // include guard
2167