| // TR2 <dynamic_bitset> -*- C++ -*- |
| |
| // Copyright (C) 2009-2014 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // Under Section 7 of GPL version 3, you are granted additional |
| // permissions described in the GCC Runtime Library Exception, version |
| // 3.1, as published by the Free Software Foundation. |
| |
| // You should have received a copy of the GNU General Public License and |
| // a copy of the GCC Runtime Library Exception along with this program; |
| // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| // <http://www.gnu.org/licenses/>. |
| |
| /** @file tr2/dynamic_bitset |
| * This is a TR2 C++ Library header. |
| */ |
| |
| #ifndef _GLIBCXX_TR2_DYNAMIC_BITSET |
| #define _GLIBCXX_TR2_DYNAMIC_BITSET 1 |
| |
| #pragma GCC system_header |
| |
| #include <limits> |
| #include <vector> |
| #include <string> |
| #include <memory> // For std::allocator |
| #include <bits/functexcept.h> // For invalid_argument, out_of_range, |
| // overflow_error |
| #include <iosfwd> |
| #include <bits/cxxabi_forced.h> |
| |
| namespace std _GLIBCXX_VISIBILITY(default) |
| { |
| namespace tr2 |
| { |
| _GLIBCXX_BEGIN_NAMESPACE_VERSION |
| |
| /** |
| * Dynamic Bitset. |
| * |
| * See N2050, |
| * Proposal to Add a Dynamically Sizeable Bitset to the Standard Library. |
| */ |
| namespace __detail |
| { |
| |
| template<typename T> |
| class _Bool2UChar |
| { |
| typedef T type; |
| }; |
| |
| template<> |
| class _Bool2UChar<bool> |
| { |
| public: |
| typedef unsigned char type; |
| }; |
| |
| } |
| |
| /** |
| * Base class, general case. |
| * |
| * See documentation for dynamic_bitset. |
| */ |
| template<typename _WordT = unsigned long long, |
| typename _Alloc = std::allocator<_WordT>> |
| struct __dynamic_bitset_base |
| { |
| static_assert(std::is_unsigned<_WordT>::value, "template argument " |
| "_WordT not an unsigned integral type"); |
| |
| typedef _WordT block_type; |
| typedef _Alloc allocator_type; |
| typedef size_t size_type; |
| |
| static const size_type _S_bits_per_block = __CHAR_BIT__ * sizeof(block_type); |
| static const size_type npos = static_cast<size_type>(-1); |
| |
| /// 0 is the least significant word. |
| std::vector<block_type, allocator_type> _M_w; |
| |
| explicit |
| __dynamic_bitset_base(const allocator_type& __alloc = allocator_type()) |
| : _M_w(__alloc) |
| { } |
| |
| explicit |
| __dynamic_bitset_base(__dynamic_bitset_base&& __b) |
| { this->_M_w.swap(__b._M_w); } |
| |
| explicit |
| __dynamic_bitset_base(size_type __nbits, unsigned long long __val = 0ULL, |
| const allocator_type& __alloc = allocator_type()) |
| : _M_w(__nbits / _S_bits_per_block |
| + (__nbits % _S_bits_per_block > 0), |
| __val, __alloc) |
| { |
| unsigned long long __mask = ~static_cast<block_type>(0); |
| size_t __n = std::min(this->_M_w.size(), |
| sizeof(unsigned long long) / sizeof(block_type)); |
| for (size_t __i = 0; __i < __n; ++__i) |
| { |
| this->_M_w[__i] = (__val & __mask) >> (__i * _S_bits_per_block); |
| __mask <<= _S_bits_per_block; |
| } |
| } |
| |
| void |
| _M_assign(const __dynamic_bitset_base& __b) |
| { this->_M_w = __b._M_w; } |
| |
| void |
| _M_swap(__dynamic_bitset_base& __b) |
| { this->_M_w.swap(__b._M_w); } |
| |
| void |
| _M_clear() |
| { this->_M_w.clear(); } |
| |
| void |
| _M_resize(size_t __nbits, bool __value) |
| { |
| size_t __sz = __nbits / _S_bits_per_block; |
| if (__nbits % _S_bits_per_block > 0) |
| ++__sz; |
| if (__sz != this->_M_w.size()) |
| { |
| block_type __val = 0; |
| if (__value) |
| __val = std::numeric_limits<block_type>::max(); |
| this->_M_w.resize(__sz, __val); |
| } |
| } |
| |
| allocator_type |
| _M_get_allocator() const |
| { return this->_M_w.get_allocator(); } |
| |
| static size_type |
| _S_whichword(size_type __pos) noexcept |
| { return __pos / _S_bits_per_block; } |
| |
| static size_type |
| _S_whichbyte(size_type __pos) noexcept |
| { return (__pos % _S_bits_per_block) / __CHAR_BIT__; } |
| |
| static size_type |
| _S_whichbit(size_type __pos) noexcept |
| { return __pos % _S_bits_per_block; } |
| |
| static block_type |
| _S_maskbit(size_type __pos) noexcept |
| { return (static_cast<block_type>(1)) << _S_whichbit(__pos); } |
| |
| block_type& |
| _M_getword(size_type __pos) |
| { return this->_M_w[_S_whichword(__pos)]; } |
| |
| block_type |
| _M_getword(size_type __pos) const |
| { return this->_M_w[_S_whichword(__pos)]; } |
| |
| block_type& |
| _M_hiword() |
| { return this->_M_w[_M_w.size() - 1]; } |
| |
| block_type |
| _M_hiword() const |
| { return this->_M_w[_M_w.size() - 1]; } |
| |
| void |
| _M_do_and(const __dynamic_bitset_base& __x) |
| { |
| if (__x._M_w.size() == this->_M_w.size()) |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| this->_M_w[__i] &= __x._M_w[__i]; |
| else |
| return; |
| } |
| |
| void |
| _M_do_or(const __dynamic_bitset_base& __x) |
| { |
| if (__x._M_w.size() == this->_M_w.size()) |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| this->_M_w[__i] |= __x._M_w[__i]; |
| else |
| return; |
| } |
| |
| void |
| _M_do_xor(const __dynamic_bitset_base& __x) |
| { |
| if (__x._M_w.size() == this->_M_w.size()) |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| this->_M_w[__i] ^= __x._M_w[__i]; |
| else |
| return; |
| } |
| |
| void |
| _M_do_dif(const __dynamic_bitset_base& __x) |
| { |
| if (__x._M_w.size() == this->_M_w.size()) |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| this->_M_w[__i] &= ~__x._M_w[__i]; |
| else |
| return; |
| } |
| |
| void |
| _M_do_left_shift(size_t __shift); |
| |
| void |
| _M_do_right_shift(size_t __shift); |
| |
| void |
| _M_do_flip() |
| { |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| this->_M_w[__i] = ~this->_M_w[__i]; |
| } |
| |
| void |
| _M_do_set() |
| { |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| this->_M_w[__i] = ~static_cast<block_type>(0); |
| } |
| |
| void |
| _M_do_reset() |
| { |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| this->_M_w[__i] = static_cast<block_type>(0); |
| } |
| |
| bool |
| _M_is_equal(const __dynamic_bitset_base& __x) const |
| { |
| if (__x._M_w.size() == this->_M_w.size()) |
| { |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| if (this->_M_w[__i] != __x._M_w[__i]) |
| return false; |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| bool |
| _M_is_less(const __dynamic_bitset_base& __x) const |
| { |
| if (__x._M_w.size() == this->_M_w.size()) |
| { |
| for (size_t __i = this->_M_w.size(); __i > 0; --__i) |
| { |
| if (this->_M_w[__i-1] < __x._M_w[__i-1]) |
| return true; |
| else if (this->_M_w[__i-1] > __x._M_w[__i-1]) |
| return false; |
| } |
| return false; |
| } |
| else |
| return false; |
| } |
| |
| size_t |
| _M_are_all_aux() const |
| { |
| for (size_t __i = 0; __i < this->_M_w.size() - 1; ++__i) |
| if (_M_w[__i] != ~static_cast<block_type>(0)) |
| return 0; |
| return ((this->_M_w.size() - 1) * _S_bits_per_block |
| + __builtin_popcountll(this->_M_hiword())); |
| } |
| |
| bool |
| _M_is_any() const |
| { |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| if (this->_M_w[__i] != static_cast<block_type>(0)) |
| return true; |
| return false; |
| } |
| |
| bool |
| _M_is_subset_of(const __dynamic_bitset_base& __b) |
| { |
| if (__b._M_w.size() == this->_M_w.size()) |
| { |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| if (this->_M_w[__i] != (this->_M_w[__i] | __b._M_w[__i])) |
| return false; |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| bool |
| _M_is_proper_subset_of(const __dynamic_bitset_base& __b) const |
| { |
| if (this->is_subset_of(__b)) |
| { |
| if (*this == __b) |
| return false; |
| else |
| return true; |
| } |
| else |
| return false; |
| } |
| |
| size_t |
| _M_do_count() const |
| { |
| size_t __result = 0; |
| for (size_t __i = 0; __i < this->_M_w.size(); ++__i) |
| __result += __builtin_popcountll(this->_M_w[__i]); |
| return __result; |
| } |
| |
| size_type |
| _M_size() const noexcept |
| { return this->_M_w.size(); } |
| |
| unsigned long |
| _M_do_to_ulong() const; |
| |
| unsigned long long |
| _M_do_to_ullong() const; |
| |
| // find first "on" bit |
| size_type |
| _M_do_find_first(size_t __not_found) const; |
| |
| // find the next "on" bit that follows "prev" |
| size_type |
| _M_do_find_next(size_t __prev, size_t __not_found) const; |
| |
| // do append of block |
| void |
| _M_do_append_block(block_type __block, size_type __pos) |
| { |
| size_t __offset = __pos % _S_bits_per_block; |
| if (__offset == 0) |
| this->_M_w.push_back(__block); |
| else |
| { |
| this->_M_hiword() |= (__block << __offset); |
| this->_M_w.push_back(__block >> (_S_bits_per_block - __offset)); |
| } |
| } |
| }; |
| |
| /** |
| * @brief The %dynamic_bitset class represents a sequence of bits. |
| * |
| * @ingroup containers |
| * |
| * (Note that %dynamic_bitset does @e not meet the formal |
| * requirements of a <a href="tables.html#65">container</a>. |
| * Mainly, it lacks iterators.) |
| * |
| * The template argument, @a Nb, may be any non-negative number, |
| * specifying the number of bits (e.g., "0", "12", "1024*1024"). |
| * |
| * In the general unoptimized case, storage is allocated in |
| * word-sized blocks. Let B be the number of bits in a word, then |
| * (Nb+(B-1))/B words will be used for storage. B - Nb%B bits are |
| * unused. (They are the high-order bits in the highest word.) It |
| * is a class invariant that those unused bits are always zero. |
| * |
| * If you think of %dynamic_bitset as "a simple array of bits," be |
| * aware that your mental picture is reversed: a %dynamic_bitset |
| * behaves the same way as bits in integers do, with the bit at |
| * index 0 in the "least significant / right-hand" position, and |
| * the bit at index Nb-1 in the "most significant / left-hand" |
| * position. Thus, unlike other containers, a %dynamic_bitset's |
| * index "counts from right to left," to put it very loosely. |
| * |
| * This behavior is preserved when translating to and from strings. |
| * For example, the first line of the following program probably |
| * prints "b('a') is 0001100001" on a modern ASCII system. |
| * |
| * @code |
| * #include <dynamic_bitset> |
| * #include <iostream> |
| * #include <sstream> |
| * |
| * using namespace std; |
| * |
| * int main() |
| * { |
| * long a = 'a'; |
| * dynamic_bitset b(a); |
| * |
| * cout << "b('a') is " << b << endl; |
| * |
| * ostringstream s; |
| * s << b; |
| * string str = s.str(); |
| * cout << "index 3 in the string is " << str[3] << " but\n" |
| * << "index 3 in the bitset is " << b[3] << endl; |
| * } |
| * @endcode |
| * |
| * Also see: |
| * http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch33s02.html |
| * for a description of extensions. |
| * |
| * Most of the actual code isn't contained in %dynamic_bitset<> |
| * itself, but in the base class __dynamic_bitset_base. The base |
| * class works with whole words, not with individual bits. This |
| * allows us to specialize __dynamic_bitset_base for the important |
| * special case where the %dynamic_bitset is only a single word. |
| * |
| * Extra confusion can result due to the fact that the storage for |
| * __dynamic_bitset_base @e is a vector, and is indexed as such. This is |
| * carefully encapsulated. |
| */ |
| template<typename _WordT = unsigned long long, |
| typename _Alloc = std::allocator<_WordT>> |
| class dynamic_bitset |
| : private __dynamic_bitset_base<_WordT, _Alloc> |
| { |
| static_assert(std::is_unsigned<_WordT>::value, "template argument " |
| "_WordT not an unsigned integral type"); |
| |
| public: |
| |
| typedef __dynamic_bitset_base<_WordT, _Alloc> _Base; |
| typedef _WordT block_type; |
| typedef _Alloc allocator_type; |
| typedef size_t size_type; |
| |
| static const size_type bits_per_block = __CHAR_BIT__ * sizeof(block_type); |
| // Use this: constexpr size_type std::numeric_limits<size_type>::max(). |
| static const size_type npos = static_cast<size_type>(-1); |
| |
| private: |
| |
| // Clear the unused bits in the uppermost word. |
| void |
| _M_do_sanitize() |
| { |
| size_type __shift = this->_M_Nb % bits_per_block; |
| if (__shift > 0) |
| this->_M_hiword() &= ~((~static_cast<block_type>(0)) << __shift); |
| } |
| |
| // Set the unused bits in the uppermost word. |
| void |
| _M_do_fill() |
| { |
| size_type __shift = this->_M_Nb % bits_per_block; |
| if (__shift > 0) |
| this->_M_hiword() |= ((~static_cast<block_type>(0)) << __shift); |
| } |
| |
| /** |
| * These versions of single-bit set, reset, flip, and test |
| * do no range checking. |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| _M_unchecked_set(size_type __pos) |
| { |
| this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); |
| return *this; |
| } |
| |
| dynamic_bitset<_WordT, _Alloc>& |
| _M_unchecked_set(size_type __pos, int __val) |
| { |
| if (__val) |
| this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); |
| else |
| this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); |
| return *this; |
| } |
| |
| dynamic_bitset<_WordT, _Alloc>& |
| _M_unchecked_reset(size_type __pos) |
| { |
| this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); |
| return *this; |
| } |
| |
| dynamic_bitset<_WordT, _Alloc>& |
| _M_unchecked_flip(size_type __pos) |
| { |
| this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos); |
| return *this; |
| } |
| |
| bool |
| _M_unchecked_test(size_type __pos) const |
| { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos)) |
| != static_cast<_WordT>(0)); } |
| |
| size_type _M_Nb; |
| |
| public: |
| /** |
| * This encapsulates the concept of a single bit. An instance |
| * of this class is a proxy for an actual bit; this way the |
| * individual bit operations are done as faster word-size |
| * bitwise instructions. |
| * |
| * Most users will never need to use this class directly; |
| * conversions to and from bool are automatic and should be |
| * transparent. Overloaded operators help to preserve the |
| * illusion. |
| * |
| * (On a typical system, this "bit %reference" is 64 times the |
| * size of an actual bit. Ha.) |
| */ |
| class reference |
| { |
| friend class dynamic_bitset; |
| |
| block_type *_M_wp; |
| size_type _M_bpos; |
| |
| // left undefined |
| reference(); |
| |
| public: |
| reference(dynamic_bitset& __b, size_type __pos) |
| { |
| this->_M_wp = &__b._M_getword(__pos); |
| this->_M_bpos = _Base::_S_whichbit(__pos); |
| } |
| |
| ~reference() |
| { } |
| |
| // For b[i] = __x; |
| reference& |
| operator=(bool __x) |
| { |
| if (__x) |
| *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos); |
| else |
| *this->_M_wp &= ~_Base::_S_maskbit(this->_M_bpos); |
| return *this; |
| } |
| |
| // For b[i] = b[__j]; |
| reference& |
| operator=(const reference& __j) |
| { |
| if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos))) |
| *this->_M_wp |= _Base::_S_maskbit(this->_M_bpos); |
| else |
| *this->_M_wp &= ~_Base::_S_maskbit(this->_M_bpos); |
| return *this; |
| } |
| |
| // Flips the bit |
| bool |
| operator~() const |
| { return (*(_M_wp) & _Base::_S_maskbit(this->_M_bpos)) == 0; } |
| |
| // For __x = b[i]; |
| operator bool() const |
| { return (*(this->_M_wp) & _Base::_S_maskbit(this->_M_bpos)) != 0; } |
| |
| // For b[i].flip(); |
| reference& |
| flip() |
| { |
| *this->_M_wp ^= _Base::_S_maskbit(this->_M_bpos); |
| return *this; |
| } |
| }; |
| |
| friend class reference; |
| |
| typedef bool const_reference; |
| |
| // 23.3.5.1 constructors: |
| /// All bits set to zero. |
| explicit |
| dynamic_bitset(const allocator_type& __alloc = allocator_type()) |
| : _Base(__alloc), _M_Nb(0) |
| { } |
| |
| /// Initial bits bitwise-copied from a single word (others set to zero). |
| explicit |
| dynamic_bitset(size_type __nbits, unsigned long long __val = 0ULL, |
| const allocator_type& __alloc = allocator_type()) |
| : _Base(__nbits, __val, __alloc), |
| _M_Nb(__nbits) |
| { } |
| |
| dynamic_bitset(initializer_list<block_type> __il, |
| const allocator_type& __alloc = allocator_type()) |
| : _Base(__alloc), _M_Nb(0) |
| { this->append(__il); } |
| |
| /** |
| * @brief Use a subset of a string. |
| * @param __str A string of '0' and '1' characters. |
| * @param __pos Index of the first character in @p __str to use. |
| * @param __n The number of characters to copy. |
| * @throw std::out_of_range If @p __pos is bigger the size of @p __str. |
| * @throw std::invalid_argument If a character appears in the string |
| * which is neither '0' nor '1'. |
| */ |
| template<typename _CharT, typename _Traits, typename _Alloc1> |
| explicit |
| dynamic_bitset(const std::basic_string<_CharT, _Traits, _Alloc1>& __str, |
| typename basic_string<_CharT,_Traits,_Alloc1>::size_type |
| __pos = 0, |
| typename basic_string<_CharT,_Traits,_Alloc1>::size_type |
| __n = std::basic_string<_CharT, _Traits, _Alloc1>::npos, |
| _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'), |
| const allocator_type& __alloc = allocator_type()) |
| : _Base(__alloc), |
| _M_Nb(0) // Watch for npos. |
| { |
| if (__pos > __str.size()) |
| __throw_out_of_range(__N("dynamic_bitset::bitset initial position " |
| "not valid")); |
| |
| // Watch for npos. |
| this->_M_Nb = (__n > __str.size() ? __str.size() - __pos : __n); |
| this->resize(this->_M_Nb); |
| this->_M_copy_from_string(__str, __pos, __n, |
| _CharT('0'), _CharT('1')); |
| } |
| |
| /** |
| * @brief Construct from a string. |
| * @param __str A string of '0' and '1' characters. |
| * @throw std::invalid_argument If a character appears in the string |
| * which is neither '0' nor '1'. |
| */ |
| explicit |
| dynamic_bitset(const char* __str, |
| const allocator_type& __alloc = allocator_type()) |
| : _Base(__alloc) |
| { |
| size_t __len = 0; |
| if (__str) |
| while (__str[__len] != '\0') |
| ++__len; |
| this->resize(__len); |
| this->_M_copy_from_ptr<char,std::char_traits<char>> |
| (__str, __len, 0, __len, '0', '1'); |
| } |
| |
| /** |
| * @brief Copy constructor. |
| */ |
| dynamic_bitset(const dynamic_bitset& __b) |
| : _Base(__b), _M_Nb(__b.size()) |
| { } |
| |
| /** |
| * @brief Move constructor. |
| */ |
| dynamic_bitset(dynamic_bitset&& __b) |
| : _Base(std::forward<_Base>(__b)), _M_Nb(__b.size()) |
| { } |
| |
| /** |
| * @brief Swap with another bitset. |
| */ |
| void |
| swap(dynamic_bitset& __b) |
| { |
| this->_M_swap(__b); |
| std::swap(this->_M_Nb, __b._M_Nb); |
| } |
| |
| /** |
| * @brief Assignment. |
| */ |
| dynamic_bitset& |
| operator=(const dynamic_bitset& __b) |
| { |
| if (&__b != this) |
| { |
| this->_M_assign(__b); |
| this->_M_Nb = __b._M_Nb; |
| } |
| } |
| |
| /** |
| * @brief Move assignment. |
| */ |
| dynamic_bitset& |
| operator=(dynamic_bitset&& __b) |
| { |
| this->swap(__b); |
| return *this; |
| } |
| |
| /** |
| * @brief Return the allocator for the bitset. |
| */ |
| allocator_type |
| get_allocator() const |
| { return this->_M_get_allocator(); } |
| |
| /** |
| * @brief Resize the bitset. |
| */ |
| void |
| resize(size_type __nbits, bool __value = false) |
| { |
| if (__value) |
| this->_M_do_fill(); |
| this->_M_resize(__nbits, __value); |
| this->_M_Nb = __nbits; |
| this->_M_do_sanitize(); |
| } |
| |
| /** |
| * @brief Clear the bitset. |
| */ |
| void |
| clear() |
| { |
| this->_M_clear(); |
| this->_M_Nb = 0; |
| } |
| |
| /** |
| * @brief Push a bit onto the high end of the bitset. |
| */ |
| void |
| push_back(bool __bit) |
| { |
| if (size_t __offset = this->size() % bits_per_block == 0) |
| this->_M_do_append_block(block_type(0), this->_M_Nb); |
| ++this->_M_Nb; |
| this->_M_unchecked_set(this->_M_Nb, __bit); |
| } |
| |
| /** |
| * @brief Append a block. |
| */ |
| void |
| append(block_type __block) |
| { |
| this->_M_do_append_block(__block, this->_M_Nb); |
| this->_M_Nb += bits_per_block; |
| } |
| |
| /** |
| * @brief |
| */ |
| void |
| append(initializer_list<block_type> __il) |
| { this->append(__il.begin(), __il.end()); } |
| |
| /** |
| * @brief Append an iterator range of blocks. |
| */ |
| template <typename _BlockInputIterator> |
| void |
| append(_BlockInputIterator __first, _BlockInputIterator __last) |
| { |
| for (; __first != __last; ++__first) |
| this->append(*__first); |
| } |
| |
| // 23.3.5.2 dynamic_bitset operations: |
| //@{ |
| /** |
| * @brief Operations on dynamic_bitsets. |
| * @param __rhs A same-sized dynamic_bitset. |
| * |
| * These should be self-explanatory. |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| operator&=(const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { |
| this->_M_do_and(__rhs); |
| return *this; |
| } |
| |
| dynamic_bitset<_WordT, _Alloc>& |
| operator&=(dynamic_bitset<_WordT, _Alloc>&& __rhs) |
| { |
| this->_M_do_and(std::move(__rhs)); |
| return *this; |
| } |
| |
| dynamic_bitset<_WordT, _Alloc>& |
| operator|=(const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { |
| this->_M_do_or(__rhs); |
| return *this; |
| } |
| |
| dynamic_bitset<_WordT, _Alloc>& |
| operator^=(const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { |
| this->_M_do_xor(__rhs); |
| return *this; |
| } |
| |
| dynamic_bitset<_WordT, _Alloc>& |
| operator-=(const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { |
| this->_M_do_dif(__rhs); |
| return *this; |
| } |
| //@} |
| |
| //@{ |
| /** |
| * @brief Operations on dynamic_bitsets. |
| * @param __pos The number of places to shift. |
| * |
| * These should be self-explanatory. |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| operator<<=(size_type __pos) |
| { |
| if (__builtin_expect(__pos < this->_M_Nb, 1)) |
| { |
| this->_M_do_left_shift(__pos); |
| this->_M_do_sanitize(); |
| } |
| else |
| this->_M_do_reset(); |
| return *this; |
| } |
| |
| dynamic_bitset<_WordT, _Alloc>& |
| operator>>=(size_type __pos) |
| { |
| if (__builtin_expect(__pos < this->_M_Nb, 1)) |
| { |
| this->_M_do_right_shift(__pos); |
| this->_M_do_sanitize(); |
| } |
| else |
| this->_M_do_reset(); |
| return *this; |
| } |
| //@} |
| |
| // Set, reset, and flip. |
| /** |
| * @brief Sets every bit to true. |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| set() |
| { |
| this->_M_do_set(); |
| this->_M_do_sanitize(); |
| return *this; |
| } |
| |
| /** |
| * @brief Sets a given bit to a particular value. |
| * @param __pos The index of the bit. |
| * @param __val Either true or false, defaults to true. |
| * @throw std::out_of_range If @a __pos is bigger the size of the %set. |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| set(size_type __pos, bool __val = true) |
| { |
| if (__pos >= _M_Nb) |
| __throw_out_of_range(__N("dynamic_bitset::set")); |
| return this->_M_unchecked_set(__pos, __val); |
| } |
| |
| /** |
| * @brief Sets every bit to false. |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| reset() |
| { |
| this->_M_do_reset(); |
| return *this; |
| } |
| |
| /** |
| * @brief Sets a given bit to false. |
| * @param __pos The index of the bit. |
| * @throw std::out_of_range If @a __pos is bigger the size of the %set. |
| * |
| * Same as writing @c set(__pos, false). |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| reset(size_type __pos) |
| { |
| if (__pos >= _M_Nb) |
| __throw_out_of_range(__N("dynamic_bitset::reset")); |
| return this->_M_unchecked_reset(__pos); |
| } |
| |
| /** |
| * @brief Toggles every bit to its opposite value. |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| flip() |
| { |
| this->_M_do_flip(); |
| this->_M_do_sanitize(); |
| return *this; |
| } |
| |
| /** |
| * @brief Toggles a given bit to its opposite value. |
| * @param __pos The index of the bit. |
| * @throw std::out_of_range If @a __pos is bigger the size of the %set. |
| */ |
| dynamic_bitset<_WordT, _Alloc>& |
| flip(size_type __pos) |
| { |
| if (__pos >= _M_Nb) |
| __throw_out_of_range(__N("dynamic_bitset::flip")); |
| return this->_M_unchecked_flip(__pos); |
| } |
| |
| /// See the no-argument flip(). |
| dynamic_bitset<_WordT, _Alloc> |
| operator~() const |
| { return dynamic_bitset<_WordT, _Alloc>(*this).flip(); } |
| |
| //@{ |
| /** |
| * @brief Array-indexing support. |
| * @param __pos Index into the %dynamic_bitset. |
| * @return A bool for a 'const %dynamic_bitset'. For non-const |
| * bitsets, an instance of the reference proxy class. |
| * @note These operators do no range checking and throw no |
| * exceptions, as required by DR 11 to the standard. |
| */ |
| reference |
| operator[](size_type __pos) |
| { return reference(*this,__pos); } |
| |
| const_reference |
| operator[](size_type __pos) const |
| { return _M_unchecked_test(__pos); } |
| //@} |
| |
| /** |
| * @brief Returns a numerical interpretation of the %dynamic_bitset. |
| * @return The integral equivalent of the bits. |
| * @throw std::overflow_error If there are too many bits to be |
| * represented in an @c unsigned @c long. |
| */ |
| unsigned long |
| to_ulong() const |
| { return this->_M_do_to_ulong(); } |
| |
| /** |
| * @brief Returns a numerical interpretation of the %dynamic_bitset. |
| * @return The integral equivalent of the bits. |
| * @throw std::overflow_error If there are too many bits to be |
| * represented in an @c unsigned @c long. |
| */ |
| unsigned long long |
| to_ullong() const |
| { return this->_M_do_to_ullong(); } |
| |
| /** |
| * @brief Returns a character interpretation of the %dynamic_bitset. |
| * @return The string equivalent of the bits. |
| * |
| * Note the ordering of the bits: decreasing character positions |
| * correspond to increasing bit positions (see the main class notes for |
| * an example). |
| */ |
| template<typename _CharT = char, |
| typename _Traits = std::char_traits<_CharT>, |
| typename _Alloc1 = std::allocator<_CharT>> |
| std::basic_string<_CharT, _Traits, _Alloc1> |
| to_string(_CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) const |
| { |
| std::basic_string<_CharT, _Traits, _Alloc1> __result; |
| _M_copy_to_string(__result, __zero, __one); |
| return __result; |
| } |
| |
| // Helper functions for string operations. |
| template<typename _CharT, typename _Traits> |
| void |
| _M_copy_from_ptr(const _CharT*, size_t, size_t, size_t, |
| _CharT, _CharT); |
| |
| template<typename _CharT, typename _Traits, typename _Alloc1> |
| void |
| _M_copy_from_string(const std::basic_string<_CharT, |
| _Traits, _Alloc1>& __str, size_t __pos, size_t __n, |
| _CharT __zero = _CharT('0'), |
| _CharT __one = _CharT('1')) |
| { _M_copy_from_ptr<_CharT, _Traits>(__str.data(), __str.size(), |
| __pos, __n, __zero, __one); } |
| |
| template<typename _CharT, typename _Traits, typename _Alloc1> |
| void |
| _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc1>& __str, |
| _CharT __zero = _CharT('0'), |
| _CharT __one = _CharT('1')) const; |
| |
| /// Returns the number of bits which are set. |
| size_type |
| count() const noexcept |
| { return this->_M_do_count(); } |
| |
| /// Returns the total number of bits. |
| size_type |
| size() const noexcept |
| { return this->_M_Nb; } |
| |
| /// Returns the total number of blocks. |
| size_type |
| num_blocks() const noexcept |
| { return this->_M_size(); } |
| |
| /// Returns true if the dynamic_bitset is empty. |
| bool |
| empty() const noexcept |
| { return (this->_M_Nb == 0); } |
| |
| /// Returns the maximum size of a dynamic_bitset object having the same |
| /// type as *this. |
| /// The real answer is max() * bits_per_block but is likely to overflow. |
| constexpr size_type |
| max_size() noexcept |
| { return std::numeric_limits<block_type>::max(); } |
| |
| /** |
| * @brief Tests the value of a bit. |
| * @param __pos The index of a bit. |
| * @return The value at @a __pos. |
| * @throw std::out_of_range If @a __pos is bigger the size of the %set. |
| */ |
| bool |
| test(size_type __pos) const |
| { |
| if (__pos >= _M_Nb) |
| __throw_out_of_range(__N("dynamic_bitset::test")); |
| return _M_unchecked_test(__pos); |
| } |
| |
| /** |
| * @brief Tests whether all the bits are on. |
| * @return True if all the bits are set. |
| */ |
| bool |
| all() const |
| { return this->_M_are_all_aux() == _M_Nb; } |
| |
| /** |
| * @brief Tests whether any of the bits are on. |
| * @return True if at least one bit is set. |
| */ |
| bool |
| any() const |
| { return this->_M_is_any(); } |
| |
| /** |
| * @brief Tests whether any of the bits are on. |
| * @return True if none of the bits are set. |
| */ |
| bool |
| none() const |
| { return !this->_M_is_any(); } |
| |
| //@{ |
| /// Self-explanatory. |
| dynamic_bitset<_WordT, _Alloc> |
| operator<<(size_type __pos) const |
| { return dynamic_bitset<_WordT, _Alloc>(*this) <<= __pos; } |
| |
| dynamic_bitset<_WordT, _Alloc> |
| operator>>(size_type __pos) const |
| { return dynamic_bitset<_WordT, _Alloc>(*this) >>= __pos; } |
| //@} |
| |
| /** |
| * @brief Finds the index of the first "on" bit. |
| * @return The index of the first bit set, or size() if not found. |
| * @sa find_next |
| */ |
| size_type |
| find_first() const |
| { return this->_M_do_find_first(this->_M_Nb); } |
| |
| /** |
| * @brief Finds the index of the next "on" bit after prev. |
| * @return The index of the next bit set, or size() if not found. |
| * @param __prev Where to start searching. |
| * @sa find_first |
| */ |
| size_type |
| find_next(size_t __prev) const |
| { return this->_M_do_find_next(__prev, this->_M_Nb); } |
| |
| bool |
| is_subset_of(const dynamic_bitset& __b) const |
| { return this->_M_is_subset_of(__b); } |
| |
| bool |
| is_proper_subset_of(const dynamic_bitset& __b) const |
| { return this->_M_is_proper_subset_of(__b); } |
| |
| friend bool |
| operator==(const dynamic_bitset<_WordT, _Alloc>& __lhs, |
| const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { return __lhs._M_is_equal(__rhs); } |
| |
| friend bool |
| operator<(const dynamic_bitset<_WordT, _Alloc>& __lhs, |
| const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { return __lhs._M_is_less(__rhs); } |
| }; |
| |
| template<typename _WordT, typename _Alloc> |
| template<typename _CharT, typename _Traits, typename _Alloc1> |
| inline void |
| dynamic_bitset<_WordT, _Alloc>:: |
| _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc1>& __str, |
| _CharT __zero, _CharT __one) const |
| { |
| __str.assign(_M_Nb, __zero); |
| for (size_t __i = _M_Nb; __i > 0; --__i) |
| if (_M_unchecked_test(__i - 1)) |
| _Traits::assign(__str[_M_Nb - __i], __one); |
| } |
| |
| |
| //@{ |
| /// These comparisons for equality/inequality are, well, @e bitwise. |
| |
| template<typename _WordT, typename _Alloc> |
| inline bool |
| operator!=(const dynamic_bitset<_WordT, _Alloc>& __lhs, |
| const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { return !(__lhs == __rhs); } |
| |
| template<typename _WordT, typename _Alloc> |
| inline bool |
| operator<=(const dynamic_bitset<_WordT, _Alloc>& __lhs, |
| const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { return !(__lhs > __rhs); } |
| |
| template<typename _WordT, typename _Alloc> |
| inline bool |
| operator>(const dynamic_bitset<_WordT, _Alloc>& __lhs, |
| const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { return __rhs < __lhs; } |
| |
| template<typename _WordT, typename _Alloc> |
| inline bool |
| operator>=(const dynamic_bitset<_WordT, _Alloc>& __lhs, |
| const dynamic_bitset<_WordT, _Alloc>& __rhs) |
| { return !(__lhs < __rhs); } |
| //@} |
| |
| // 23.3.5.3 bitset operations: |
| //@{ |
| /** |
| * @brief Global bitwise operations on bitsets. |
| * @param __x A bitset. |
| * @param __y A bitset of the same size as @a __x. |
| * @return A new bitset. |
| * |
| * These should be self-explanatory. |
| */ |
| template<typename _WordT, typename _Alloc> |
| inline dynamic_bitset<_WordT, _Alloc> |
| operator&(const dynamic_bitset<_WordT, _Alloc>& __x, |
| const dynamic_bitset<_WordT, _Alloc>& __y) |
| { |
| dynamic_bitset<_WordT, _Alloc> __result(__x); |
| __result &= __y; |
| return __result; |
| } |
| |
| template<typename _WordT, typename _Alloc> |
| inline dynamic_bitset<_WordT, _Alloc> |
| operator|(const dynamic_bitset<_WordT, _Alloc>& __x, |
| const dynamic_bitset<_WordT, _Alloc>& __y) |
| { |
| dynamic_bitset<_WordT, _Alloc> __result(__x); |
| __result |= __y; |
| return __result; |
| } |
| |
| template <typename _WordT, typename _Alloc> |
| inline dynamic_bitset<_WordT, _Alloc> |
| operator^(const dynamic_bitset<_WordT, _Alloc>& __x, |
| const dynamic_bitset<_WordT, _Alloc>& __y) |
| { |
| dynamic_bitset<_WordT, _Alloc> __result(__x); |
| __result ^= __y; |
| return __result; |
| } |
| |
| template <typename _WordT, typename _Alloc> |
| inline dynamic_bitset<_WordT, _Alloc> |
| operator-(const dynamic_bitset<_WordT, _Alloc>& __x, |
| const dynamic_bitset<_WordT, _Alloc>& __y) |
| { |
| dynamic_bitset<_WordT, _Alloc> __result(__x); |
| __result -= __y; |
| return __result; |
| } |
| //@} |
| |
| /** |
| * @defgroup Global I/O operators for bitsets. |
| * @{ |
| * @brief Global I/O operators for bitsets. |
| * |
| * Direct I/O between streams and bitsets is supported. Output is |
| * straightforward. Input will skip whitespace and only accept '0' |
| * and '1' characters. The %dynamic_bitset will grow as necessary |
| * to hold the string of bits. |
| */ |
| template <typename _CharT, typename _Traits, |
| typename _WordT, typename _Alloc> |
| inline std::basic_ostream<_CharT, _Traits>& |
| operator<<(std::basic_ostream<_CharT, _Traits>& __os, |
| const dynamic_bitset<_WordT, _Alloc>& __x) |
| { |
| std::basic_string<_CharT, _Traits> __tmp; |
| |
| const ctype<_CharT>& __ct = use_facet<ctype<_CharT>>(__os.getloc()); |
| __x._M_copy_to_string(__tmp, __ct.widen('0'), __ct.widen('1')); |
| return __os << __tmp; |
| } |
| /** |
| * @} |
| */ |
| |
| _GLIBCXX_END_NAMESPACE_VERSION |
| } // tr2 |
| } // std |
| |
| #include <tr2/dynamic_bitset.tcc> |
| |
| #endif /* _GLIBCXX_TR2_DYNAMIC_BITSET */ |