File indexing completed on 2025-01-18 09:30:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
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
0062
0063
0064
0065
0066
0067
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
0085
0086 class reference
0087 {
0088 friend class dynamic_bitset<Block, Allocator>;
0089
0090
0091
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&();
0100
0101 public:
0102
0103
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; }
0111 reference& operator=(const reference& rhs) { do_assign(rhs); return *this; }
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
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
0142
0143
0144
0145
0146
0147
0148
0149
0150
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
0178
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
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
0229
0230 allocator_type get_allocator() const;
0231
0232
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);
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)
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
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
0287 dynamic_bitset& set(size_type n, size_type len, bool val );
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
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
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
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
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
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 )
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
0484
0485
0486
0487
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
0518
0519
0520
0521
0522
0523
0524
0525
0526 dynamic_bitset & bs;
0527 size_type n;
0528 Block mask;
0529 Block * current;
0530
0531
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
0539
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);
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
0584
0585
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
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
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
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
0665 std::copy (first, last, result.m_bits.begin());
0666 }
0667
0668
0669
0670
0671
0672
0673
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
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)
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
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
0745 assert((b.m_bits = buffer_type()).empty());
0746 b.m_num_bits = 0;
0747 return *this;
0748 }
0749
0750 #endif
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
0761
0762 template <typename Block, typename Allocator>
0763 void dynamic_bitset<Block, Allocator>::
0764 resize(size_type num_bits, bool value)
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);
0774 }
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
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
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()
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)
0841 {
0842 const block_width_type r = count_extra_bits();
0843
0844 if (r == 0) {
0845
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);
0851 }
0852
0853 m_num_bits += bits_per_block;
0854 assert(m_check_invariants());
0855
0856 }
0857
0858
0859
0860
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
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
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
0901 return *this;
0902 }
0903
0904
0905
0906
0907
0908
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
0917 if (n > 0) {
0918
0919 size_type const last = num_blocks() - 1;
0920 size_type const div = n / bits_per_block;
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
0942 std::fill_n(m_bits.begin(), div, static_cast<block_type>(0));
0943
0944
0945 m_zero_unused_bits();
0946
0947 }
0948
0949 return *this;
0950
0951
0952 }
0953
0954
0955
0956
0957
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
0965 if (n>0) {
0966
0967 size_type const last = num_blocks() - 1;
0968 size_type const div = n / bits_per_block;
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
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
0989
0990 }
0991
0992
0993
0994
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
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)
1069
1070
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
1220
1221 enum { no_padding = bits_per_block == CHAR_BIT * sizeof(Block) };
1222 #else
1223
1224
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
1234 enum { uneffective_popcount = sizeof(Block) < sizeof(unsigned short) };
1235 #elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
1236
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
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
1267
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
1286
1287
1288
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
1299
1300
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 );
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
1315
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;
1326
1327
1328
1329 if (find_next(ulong_width - 1) != npos)
1330 BOOST_THROW_EXCEPTION(std::overflow_error("boost::dynamic_bitset::to_ulong overflow"));
1331
1332
1333
1334
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
1372
1373
1374
1375
1376
1377
1378
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;
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
1462
1463
1464
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;
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
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
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
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
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
1611
1612
1613
1614
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
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
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
1670
1671
1672
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
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
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
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
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
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 }
1726
1727 if(err != ok)
1728 os.setstate(err);
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
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
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
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
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 (...) {
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);
1811 return os;
1812
1813 }
1814 #endif
1815
1816
1817 #ifdef BOOST_OLD_IOSTREAMS
1818
1819
1820
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
1836
1837
1838
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);
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;
1863
1864 else {
1865 BOOST_TRY {
1866 appender.do_append(char(c) == '1');
1867 }
1868 BOOST_CATCH(...) {
1869 is.setstate(std::ios::failbit);
1870 BOOST_RETHROW;
1871 }
1872 BOOST_CATCH_END
1873 }
1874
1875 }
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);
1883
1884 return is;
1885 }
1886
1887 #else
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);
1905 if(cerberos) {
1906
1907
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;
1929
1930 appender.do_append(is_one);
1931
1932 }
1933
1934 }
1935 }
1936 BOOST_CATCH (...) {
1937
1938
1939
1940
1941
1942
1943 bool rethrow = false;
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 )
1957 err |= ios_base::failbit;
1958 if (err != ios_base::goodbit)
1959 is.setstate (err);
1960
1961 return is;
1962
1963 }
1964
1965
1966 #endif
1967
1968
1969
1970
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
2010
2011 template<typename Block, typename Allocator>
2012 inline void
2013 swap(dynamic_bitset<Block, Allocator>& left,
2014 dynamic_bitset<Block, Allocator>& right)
2015 {
2016 left.swap(right);
2017 }
2018
2019
2020
2021
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
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
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
2059 if (!len)
2060 return *this;
2061
2062
2063
2064
2065 assert(pos + len >= len);
2066
2067
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
2076 m_bits[first_block] = partial_block_operation(m_bits[first_block],
2077 first_bit_index, last_bit_index);
2078 } else {
2079
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
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
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
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
2109
2110
2111
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
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
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 }
2144
2145 #undef BOOST_BITSET_CHAR
2146
2147
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
2167