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