100db7afdSDavid E. O'Brien // <bitset> -*- C++ -*- 200db7afdSDavid E. O'Brien 3*f8a1b7d9SAlexander Kabaev // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 4*f8a1b7d9SAlexander Kabaev // Free Software Foundation, Inc. 500db7afdSDavid E. O'Brien // 600db7afdSDavid E. O'Brien // This file is part of the GNU ISO C++ Library. This library is free 700db7afdSDavid E. O'Brien // software; you can redistribute it and/or modify it under the 800db7afdSDavid E. O'Brien // terms of the GNU General Public License as published by the 900db7afdSDavid E. O'Brien // Free Software Foundation; either version 2, or (at your option) 1000db7afdSDavid E. O'Brien // any later version. 1100db7afdSDavid E. O'Brien 1200db7afdSDavid E. O'Brien // This library is distributed in the hope that it will be useful, 1300db7afdSDavid E. O'Brien // but WITHOUT ANY WARRANTY; without even the implied warranty of 1400db7afdSDavid E. O'Brien // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1500db7afdSDavid E. O'Brien // GNU General Public License for more details. 1600db7afdSDavid E. O'Brien 1700db7afdSDavid E. O'Brien // You should have received a copy of the GNU General Public License along 1800db7afdSDavid E. O'Brien // with this library; see the file COPYING. If not, write to the Free 19*f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 2000db7afdSDavid E. O'Brien // USA. 2100db7afdSDavid E. O'Brien 2200db7afdSDavid E. O'Brien // As a special exception, you may use this file as part of a free software 2300db7afdSDavid E. O'Brien // library without restriction. Specifically, if other files instantiate 2400db7afdSDavid E. O'Brien // templates or use macros or inline functions from this file, or you compile 2500db7afdSDavid E. O'Brien // this file and link it with other files to produce an executable, this 2600db7afdSDavid E. O'Brien // file does not by itself cause the resulting executable to be covered by 2700db7afdSDavid E. O'Brien // the GNU General Public License. This exception does not however 2800db7afdSDavid E. O'Brien // invalidate any other reasons why the executable file might be covered by 2900db7afdSDavid E. O'Brien // the GNU General Public License. 3000db7afdSDavid E. O'Brien 3100db7afdSDavid E. O'Brien /* 3200db7afdSDavid E. O'Brien * Copyright (c) 1998 3300db7afdSDavid E. O'Brien * Silicon Graphics Computer Systems, Inc. 3400db7afdSDavid E. O'Brien * 3500db7afdSDavid E. O'Brien * Permission to use, copy, modify, distribute and sell this software 3600db7afdSDavid E. O'Brien * and its documentation for any purpose is hereby granted without fee, 3700db7afdSDavid E. O'Brien * provided that the above copyright notice appear in all copies and 3800db7afdSDavid E. O'Brien * that both that copyright notice and this permission notice appear 3900db7afdSDavid E. O'Brien * in supporting documentation. Silicon Graphics makes no 4000db7afdSDavid E. O'Brien * representations about the suitability of this software for any 4100db7afdSDavid E. O'Brien * purpose. It is provided "as is" without express or implied warranty. 4200db7afdSDavid E. O'Brien */ 4300db7afdSDavid E. O'Brien 44*f8a1b7d9SAlexander Kabaev /** @file include/bitset 45*f8a1b7d9SAlexander Kabaev * This is a Standard C++ Library header. 4600db7afdSDavid E. O'Brien */ 4700db7afdSDavid E. O'Brien 48ffeaf689SAlexander Kabaev #ifndef _GLIBCXX_BITSET 49ffeaf689SAlexander Kabaev #define _GLIBCXX_BITSET 1 5000db7afdSDavid E. O'Brien 5100db7afdSDavid E. O'Brien #pragma GCC system_header 5200db7afdSDavid E. O'Brien 53ffeaf689SAlexander Kabaev #include <cstddef> // For size_t 54ffeaf689SAlexander Kabaev #include <cstring> // For memset 55ffeaf689SAlexander Kabaev #include <limits> // For numeric_limits 5600db7afdSDavid E. O'Brien #include <string> 57ffeaf689SAlexander Kabaev #include <bits/functexcept.h> // For invalid_argument, out_of_range, 5800db7afdSDavid E. O'Brien // overflow_error 59ffeaf689SAlexander Kabaev #include <ostream> // For ostream (operator<<) 60ffeaf689SAlexander Kabaev #include <istream> // For istream (operator>>) 6100db7afdSDavid E. O'Brien 62ffeaf689SAlexander Kabaev #define _GLIBCXX_BITSET_BITS_PER_WORD numeric_limits<unsigned long>::digits 63ffeaf689SAlexander Kabaev #define _GLIBCXX_BITSET_WORDS(__n) \ 64*f8a1b7d9SAlexander Kabaev ((__n) < 1 ? 0 : ((__n) + _GLIBCXX_BITSET_BITS_PER_WORD - 1) \ 65*f8a1b7d9SAlexander Kabaev / _GLIBCXX_BITSET_BITS_PER_WORD) 6600db7afdSDavid E. O'Brien 67*f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NESTED_NAMESPACE(std, _GLIBCXX_STD) 68*f8a1b7d9SAlexander Kabaev 6900db7afdSDavid E. O'Brien /** 7000db7afdSDavid E. O'Brien * @if maint 7100db7afdSDavid E. O'Brien * Base class, general case. It is a class inveriant that _Nw will be 7200db7afdSDavid E. O'Brien * nonnegative. 7300db7afdSDavid E. O'Brien * 7400db7afdSDavid E. O'Brien * See documentation for bitset. 7500db7afdSDavid E. O'Brien * @endif 7600db7afdSDavid E. O'Brien */ 7700db7afdSDavid E. O'Brien template<size_t _Nw> 7800db7afdSDavid E. O'Brien struct _Base_bitset 7900db7afdSDavid E. O'Brien { 8000db7afdSDavid E. O'Brien typedef unsigned long _WordT; 8100db7afdSDavid E. O'Brien 8200db7afdSDavid E. O'Brien /// 0 is the least significant word. 8300db7afdSDavid E. O'Brien _WordT _M_w[_Nw]; 8400db7afdSDavid E. O'Brien _Base_bitset_Base_bitset85*f8a1b7d9SAlexander Kabaev _Base_bitset() 86*f8a1b7d9SAlexander Kabaev { _M_do_reset(); } 87*f8a1b7d9SAlexander Kabaev _Base_bitset_Base_bitset8800db7afdSDavid E. O'Brien _Base_bitset(unsigned long __val) 8900db7afdSDavid E. O'Brien { 9000db7afdSDavid E. O'Brien _M_do_reset(); 9100db7afdSDavid E. O'Brien _M_w[0] = __val; 9200db7afdSDavid E. O'Brien } 9300db7afdSDavid E. O'Brien 9400db7afdSDavid E. O'Brien static size_t _S_whichword_Base_bitset9500db7afdSDavid E. O'Brien _S_whichword(size_t __pos ) 96ffeaf689SAlexander Kabaev { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } 9700db7afdSDavid E. O'Brien 9800db7afdSDavid E. O'Brien static size_t _S_whichbyte_Base_bitset9900db7afdSDavid E. O'Brien _S_whichbyte(size_t __pos ) 100ffeaf689SAlexander Kabaev { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } 10100db7afdSDavid E. O'Brien 10200db7afdSDavid E. O'Brien static size_t _S_whichbit_Base_bitset10300db7afdSDavid E. O'Brien _S_whichbit(size_t __pos ) 104ffeaf689SAlexander Kabaev { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } 10500db7afdSDavid E. O'Brien 10600db7afdSDavid E. O'Brien static _WordT _S_maskbit_Base_bitset10700db7afdSDavid E. O'Brien _S_maskbit(size_t __pos ) 10800db7afdSDavid E. O'Brien { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } 10900db7afdSDavid E. O'Brien 11000db7afdSDavid E. O'Brien _WordT& _M_getword_Base_bitset11100db7afdSDavid E. O'Brien _M_getword(size_t __pos) 11200db7afdSDavid E. O'Brien { return _M_w[_S_whichword(__pos)]; } 11300db7afdSDavid E. O'Brien 11400db7afdSDavid E. O'Brien _WordT _M_getword_Base_bitset11500db7afdSDavid E. O'Brien _M_getword(size_t __pos) const 11600db7afdSDavid E. O'Brien { return _M_w[_S_whichword(__pos)]; } 11700db7afdSDavid E. O'Brien 11800db7afdSDavid E. O'Brien _WordT& _M_hiword_Base_bitset119*f8a1b7d9SAlexander Kabaev _M_hiword() 120*f8a1b7d9SAlexander Kabaev { return _M_w[_Nw - 1]; } 12100db7afdSDavid E. O'Brien 12200db7afdSDavid E. O'Brien _WordT _M_hiword_Base_bitset123*f8a1b7d9SAlexander Kabaev _M_hiword() const 124*f8a1b7d9SAlexander Kabaev { return _M_w[_Nw - 1]; } 12500db7afdSDavid E. O'Brien 12600db7afdSDavid E. O'Brien void _M_do_and_Base_bitset12700db7afdSDavid E. O'Brien _M_do_and(const _Base_bitset<_Nw>& __x) 12800db7afdSDavid E. O'Brien { 12900db7afdSDavid E. O'Brien for (size_t __i = 0; __i < _Nw; __i++) 13000db7afdSDavid E. O'Brien _M_w[__i] &= __x._M_w[__i]; 13100db7afdSDavid E. O'Brien } 13200db7afdSDavid E. O'Brien 13300db7afdSDavid E. O'Brien void _M_do_or_Base_bitset13400db7afdSDavid E. O'Brien _M_do_or(const _Base_bitset<_Nw>& __x) 13500db7afdSDavid E. O'Brien { 13600db7afdSDavid E. O'Brien for (size_t __i = 0; __i < _Nw; __i++) 13700db7afdSDavid E. O'Brien _M_w[__i] |= __x._M_w[__i]; 13800db7afdSDavid E. O'Brien } 13900db7afdSDavid E. O'Brien 14000db7afdSDavid E. O'Brien void _M_do_xor_Base_bitset14100db7afdSDavid E. O'Brien _M_do_xor(const _Base_bitset<_Nw>& __x) 14200db7afdSDavid E. O'Brien { 14300db7afdSDavid E. O'Brien for (size_t __i = 0; __i < _Nw; __i++) 14400db7afdSDavid E. O'Brien _M_w[__i] ^= __x._M_w[__i]; 14500db7afdSDavid E. O'Brien } 14600db7afdSDavid E. O'Brien 14700db7afdSDavid E. O'Brien void 14800db7afdSDavid E. O'Brien _M_do_left_shift(size_t __shift); 14900db7afdSDavid E. O'Brien 15000db7afdSDavid E. O'Brien void 15100db7afdSDavid E. O'Brien _M_do_right_shift(size_t __shift); 15200db7afdSDavid E. O'Brien 15300db7afdSDavid E. O'Brien void _M_do_flip_Base_bitset15400db7afdSDavid E. O'Brien _M_do_flip() 15500db7afdSDavid E. O'Brien { 15600db7afdSDavid E. O'Brien for (size_t __i = 0; __i < _Nw; __i++) 15700db7afdSDavid E. O'Brien _M_w[__i] = ~_M_w[__i]; 15800db7afdSDavid E. O'Brien } 15900db7afdSDavid E. O'Brien 16000db7afdSDavid E. O'Brien void _M_do_set_Base_bitset16100db7afdSDavid E. O'Brien _M_do_set() 16200db7afdSDavid E. O'Brien { 16300db7afdSDavid E. O'Brien for (size_t __i = 0; __i < _Nw; __i++) 16400db7afdSDavid E. O'Brien _M_w[__i] = ~static_cast<_WordT>(0); 16500db7afdSDavid E. O'Brien } 16600db7afdSDavid E. O'Brien 16700db7afdSDavid E. O'Brien void _M_do_reset_Base_bitset168*f8a1b7d9SAlexander Kabaev _M_do_reset() 169*f8a1b7d9SAlexander Kabaev { std::memset(_M_w, 0, _Nw * sizeof(_WordT)); } 17000db7afdSDavid E. O'Brien 17100db7afdSDavid E. O'Brien bool _M_is_equal_Base_bitset17200db7afdSDavid E. O'Brien _M_is_equal(const _Base_bitset<_Nw>& __x) const 17300db7afdSDavid E. O'Brien { 17400db7afdSDavid E. O'Brien for (size_t __i = 0; __i < _Nw; ++__i) 17500db7afdSDavid E. O'Brien { 17600db7afdSDavid E. O'Brien if (_M_w[__i] != __x._M_w[__i]) 17700db7afdSDavid E. O'Brien return false; 17800db7afdSDavid E. O'Brien } 17900db7afdSDavid E. O'Brien return true; 18000db7afdSDavid E. O'Brien } 18100db7afdSDavid E. O'Brien 18200db7afdSDavid E. O'Brien bool _M_is_any_Base_bitset18300db7afdSDavid E. O'Brien _M_is_any() const 18400db7afdSDavid E. O'Brien { 18500db7afdSDavid E. O'Brien for (size_t __i = 0; __i < _Nw; __i++) 18600db7afdSDavid E. O'Brien { 18700db7afdSDavid E. O'Brien if (_M_w[__i] != static_cast<_WordT>(0)) 18800db7afdSDavid E. O'Brien return true; 18900db7afdSDavid E. O'Brien } 19000db7afdSDavid E. O'Brien return false; 19100db7afdSDavid E. O'Brien } 19200db7afdSDavid E. O'Brien 19300db7afdSDavid E. O'Brien size_t _M_do_count_Base_bitset19400db7afdSDavid E. O'Brien _M_do_count() const 19500db7afdSDavid E. O'Brien { 19600db7afdSDavid E. O'Brien size_t __result = 0; 197ffeaf689SAlexander Kabaev for (size_t __i = 0; __i < _Nw; __i++) 198ffeaf689SAlexander Kabaev __result += __builtin_popcountl(_M_w[__i]); 19900db7afdSDavid E. O'Brien return __result; 20000db7afdSDavid E. O'Brien } 20100db7afdSDavid E. O'Brien 20200db7afdSDavid E. O'Brien unsigned long 20300db7afdSDavid E. O'Brien _M_do_to_ulong() const; 20400db7afdSDavid E. O'Brien 20500db7afdSDavid E. O'Brien // find first "on" bit 20600db7afdSDavid E. O'Brien size_t 20700db7afdSDavid E. O'Brien _M_do_find_first(size_t __not_found) const; 20800db7afdSDavid E. O'Brien 20900db7afdSDavid E. O'Brien // find the next "on" bit that follows "prev" 21000db7afdSDavid E. O'Brien size_t 21100db7afdSDavid E. O'Brien _M_do_find_next(size_t __prev, size_t __not_found) const; 21200db7afdSDavid E. O'Brien }; 21300db7afdSDavid E. O'Brien 21400db7afdSDavid E. O'Brien // Definitions of non-inline functions from _Base_bitset. 21500db7afdSDavid E. O'Brien template<size_t _Nw> 21600db7afdSDavid E. O'Brien void _M_do_left_shift(size_t __shift)21700db7afdSDavid E. O'Brien _Base_bitset<_Nw>::_M_do_left_shift(size_t __shift) 21800db7afdSDavid E. O'Brien { 2191b86b14eSAlexander Kabaev if (__builtin_expect(__shift != 0, 1)) 22000db7afdSDavid E. O'Brien { 221ffeaf689SAlexander Kabaev const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; 222ffeaf689SAlexander Kabaev const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; 22300db7afdSDavid E. O'Brien 22400db7afdSDavid E. O'Brien if (__offset == 0) 22500db7afdSDavid E. O'Brien for (size_t __n = _Nw - 1; __n >= __wshift; --__n) 22600db7afdSDavid E. O'Brien _M_w[__n] = _M_w[__n - __wshift]; 22700db7afdSDavid E. O'Brien else 22800db7afdSDavid E. O'Brien { 229*f8a1b7d9SAlexander Kabaev const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD 230*f8a1b7d9SAlexander Kabaev - __offset); 23100db7afdSDavid E. O'Brien for (size_t __n = _Nw - 1; __n > __wshift; --__n) 232*f8a1b7d9SAlexander Kabaev _M_w[__n] = ((_M_w[__n - __wshift] << __offset) 233*f8a1b7d9SAlexander Kabaev | (_M_w[__n - __wshift - 1] >> __sub_offset)); 23400db7afdSDavid E. O'Brien _M_w[__wshift] = _M_w[0] << __offset; 23500db7afdSDavid E. O'Brien } 23600db7afdSDavid E. O'Brien 237ffeaf689SAlexander Kabaev std::fill(_M_w + 0, _M_w + __wshift, static_cast<_WordT>(0)); 23800db7afdSDavid E. O'Brien } 23900db7afdSDavid E. O'Brien } 24000db7afdSDavid E. O'Brien 24100db7afdSDavid E. O'Brien template<size_t _Nw> 24200db7afdSDavid E. O'Brien void _M_do_right_shift(size_t __shift)24300db7afdSDavid E. O'Brien _Base_bitset<_Nw>::_M_do_right_shift(size_t __shift) 24400db7afdSDavid E. O'Brien { 2451b86b14eSAlexander Kabaev if (__builtin_expect(__shift != 0, 1)) 24600db7afdSDavid E. O'Brien { 247ffeaf689SAlexander Kabaev const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; 248ffeaf689SAlexander Kabaev const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; 24900db7afdSDavid E. O'Brien const size_t __limit = _Nw - __wshift - 1; 25000db7afdSDavid E. O'Brien 25100db7afdSDavid E. O'Brien if (__offset == 0) 25200db7afdSDavid E. O'Brien for (size_t __n = 0; __n <= __limit; ++__n) 25300db7afdSDavid E. O'Brien _M_w[__n] = _M_w[__n + __wshift]; 25400db7afdSDavid E. O'Brien else 25500db7afdSDavid E. O'Brien { 256*f8a1b7d9SAlexander Kabaev const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD 257*f8a1b7d9SAlexander Kabaev - __offset); 25800db7afdSDavid E. O'Brien for (size_t __n = 0; __n < __limit; ++__n) 259*f8a1b7d9SAlexander Kabaev _M_w[__n] = ((_M_w[__n + __wshift] >> __offset) 260*f8a1b7d9SAlexander Kabaev | (_M_w[__n + __wshift + 1] << __sub_offset)); 26100db7afdSDavid E. O'Brien _M_w[__limit] = _M_w[_Nw-1] >> __offset; 26200db7afdSDavid E. O'Brien } 26300db7afdSDavid E. O'Brien 264ffeaf689SAlexander Kabaev std::fill(_M_w + __limit + 1, _M_w + _Nw, static_cast<_WordT>(0)); 26500db7afdSDavid E. O'Brien } 26600db7afdSDavid E. O'Brien } 26700db7afdSDavid E. O'Brien 26800db7afdSDavid E. O'Brien template<size_t _Nw> 26900db7afdSDavid E. O'Brien unsigned long _M_do_to_ulong()27000db7afdSDavid E. O'Brien _Base_bitset<_Nw>::_M_do_to_ulong() const 27100db7afdSDavid E. O'Brien { 27200db7afdSDavid E. O'Brien for (size_t __i = 1; __i < _Nw; ++__i) 27300db7afdSDavid E. O'Brien if (_M_w[__i]) 274ffeaf689SAlexander Kabaev __throw_overflow_error(__N("_Base_bitset::_M_do_to_ulong")); 27500db7afdSDavid E. O'Brien return _M_w[0]; 27600db7afdSDavid E. O'Brien } 27700db7afdSDavid E. O'Brien 27800db7afdSDavid E. O'Brien template<size_t _Nw> 27900db7afdSDavid E. O'Brien size_t _M_do_find_first(size_t __not_found)28000db7afdSDavid E. O'Brien _Base_bitset<_Nw>::_M_do_find_first(size_t __not_found) const 28100db7afdSDavid E. O'Brien { 28200db7afdSDavid E. O'Brien for (size_t __i = 0; __i < _Nw; __i++) 28300db7afdSDavid E. O'Brien { 28400db7afdSDavid E. O'Brien _WordT __thisword = _M_w[__i]; 28500db7afdSDavid E. O'Brien if (__thisword != static_cast<_WordT>(0)) 286*f8a1b7d9SAlexander Kabaev return (__i * _GLIBCXX_BITSET_BITS_PER_WORD 287*f8a1b7d9SAlexander Kabaev + __builtin_ctzl(__thisword)); 28800db7afdSDavid E. O'Brien } 28900db7afdSDavid E. O'Brien // not found, so return an indication of failure. 29000db7afdSDavid E. O'Brien return __not_found; 29100db7afdSDavid E. O'Brien } 29200db7afdSDavid E. O'Brien 29300db7afdSDavid E. O'Brien template<size_t _Nw> 29400db7afdSDavid E. O'Brien size_t _M_do_find_next(size_t __prev,size_t __not_found)29500db7afdSDavid E. O'Brien _Base_bitset<_Nw>::_M_do_find_next(size_t __prev, size_t __not_found) const 29600db7afdSDavid E. O'Brien { 29700db7afdSDavid E. O'Brien // make bound inclusive 29800db7afdSDavid E. O'Brien ++__prev; 29900db7afdSDavid E. O'Brien 30000db7afdSDavid E. O'Brien // check out of bounds 301ffeaf689SAlexander Kabaev if (__prev >= _Nw * _GLIBCXX_BITSET_BITS_PER_WORD) 30200db7afdSDavid E. O'Brien return __not_found; 30300db7afdSDavid E. O'Brien 30400db7afdSDavid E. O'Brien // search first word 30500db7afdSDavid E. O'Brien size_t __i = _S_whichword(__prev); 30600db7afdSDavid E. O'Brien _WordT __thisword = _M_w[__i]; 30700db7afdSDavid E. O'Brien 30800db7afdSDavid E. O'Brien // mask off bits below bound 30900db7afdSDavid E. O'Brien __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev); 31000db7afdSDavid E. O'Brien 31100db7afdSDavid E. O'Brien if (__thisword != static_cast<_WordT>(0)) 312*f8a1b7d9SAlexander Kabaev return (__i * _GLIBCXX_BITSET_BITS_PER_WORD 313*f8a1b7d9SAlexander Kabaev + __builtin_ctzl(__thisword)); 31400db7afdSDavid E. O'Brien 31500db7afdSDavid E. O'Brien // check subsequent words 31600db7afdSDavid E. O'Brien __i++; 31700db7afdSDavid E. O'Brien for (; __i < _Nw; __i++) 31800db7afdSDavid E. O'Brien { 31900db7afdSDavid E. O'Brien __thisword = _M_w[__i]; 32000db7afdSDavid E. O'Brien if (__thisword != static_cast<_WordT>(0)) 321*f8a1b7d9SAlexander Kabaev return (__i * _GLIBCXX_BITSET_BITS_PER_WORD 322*f8a1b7d9SAlexander Kabaev + __builtin_ctzl(__thisword)); 32300db7afdSDavid E. O'Brien } 32400db7afdSDavid E. O'Brien // not found, so return an indication of failure. 32500db7afdSDavid E. O'Brien return __not_found; 32600db7afdSDavid E. O'Brien } // end _M_do_find_next 32700db7afdSDavid E. O'Brien 32800db7afdSDavid E. O'Brien /** 32900db7afdSDavid E. O'Brien * @if maint 33000db7afdSDavid E. O'Brien * Base class, specialization for a single word. 33100db7afdSDavid E. O'Brien * 33200db7afdSDavid E. O'Brien * See documentation for bitset. 33300db7afdSDavid E. O'Brien * @endif 33400db7afdSDavid E. O'Brien */ 33500db7afdSDavid E. O'Brien template<> 33600db7afdSDavid E. O'Brien struct _Base_bitset<1> 33700db7afdSDavid E. O'Brien { 33800db7afdSDavid E. O'Brien typedef unsigned long _WordT; 33900db7afdSDavid E. O'Brien _WordT _M_w; 34000db7afdSDavid E. O'Brien 341*f8a1b7d9SAlexander Kabaev _Base_bitset(void) 342*f8a1b7d9SAlexander Kabaev : _M_w(0) 343*f8a1b7d9SAlexander Kabaev { } 344*f8a1b7d9SAlexander Kabaev 345*f8a1b7d9SAlexander Kabaev _Base_bitset(unsigned long __val) 346*f8a1b7d9SAlexander Kabaev : _M_w(__val) 347*f8a1b7d9SAlexander Kabaev { } 34800db7afdSDavid E. O'Brien 34900db7afdSDavid E. O'Brien static size_t 35000db7afdSDavid E. O'Brien _S_whichword(size_t __pos ) 351ffeaf689SAlexander Kabaev { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } 35200db7afdSDavid E. O'Brien 35300db7afdSDavid E. O'Brien static size_t 35400db7afdSDavid E. O'Brien _S_whichbyte(size_t __pos ) 355ffeaf689SAlexander Kabaev { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } 35600db7afdSDavid E. O'Brien 35700db7afdSDavid E. O'Brien static size_t 35800db7afdSDavid E. O'Brien _S_whichbit(size_t __pos ) 359ffeaf689SAlexander Kabaev { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } 36000db7afdSDavid E. O'Brien 36100db7afdSDavid E. O'Brien static _WordT 36200db7afdSDavid E. O'Brien _S_maskbit(size_t __pos ) 36300db7afdSDavid E. O'Brien { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } 36400db7afdSDavid E. O'Brien 36500db7afdSDavid E. O'Brien _WordT& 366*f8a1b7d9SAlexander Kabaev _M_getword(size_t) 367*f8a1b7d9SAlexander Kabaev { return _M_w; } 36800db7afdSDavid E. O'Brien 36900db7afdSDavid E. O'Brien _WordT 370*f8a1b7d9SAlexander Kabaev _M_getword(size_t) const 371*f8a1b7d9SAlexander Kabaev { return _M_w; } 37200db7afdSDavid E. O'Brien 37300db7afdSDavid E. O'Brien _WordT& 374*f8a1b7d9SAlexander Kabaev _M_hiword() 375*f8a1b7d9SAlexander Kabaev { return _M_w; } 37600db7afdSDavid E. O'Brien 37700db7afdSDavid E. O'Brien _WordT 378*f8a1b7d9SAlexander Kabaev _M_hiword() const 379*f8a1b7d9SAlexander Kabaev { return _M_w; } 38000db7afdSDavid E. O'Brien 38100db7afdSDavid E. O'Brien void 382*f8a1b7d9SAlexander Kabaev _M_do_and(const _Base_bitset<1>& __x) 383*f8a1b7d9SAlexander Kabaev { _M_w &= __x._M_w; } 38400db7afdSDavid E. O'Brien 38500db7afdSDavid E. O'Brien void 386*f8a1b7d9SAlexander Kabaev _M_do_or(const _Base_bitset<1>& __x) 387*f8a1b7d9SAlexander Kabaev { _M_w |= __x._M_w; } 38800db7afdSDavid E. O'Brien 38900db7afdSDavid E. O'Brien void 390*f8a1b7d9SAlexander Kabaev _M_do_xor(const _Base_bitset<1>& __x) 391*f8a1b7d9SAlexander Kabaev { _M_w ^= __x._M_w; } 39200db7afdSDavid E. O'Brien 39300db7afdSDavid E. O'Brien void 394*f8a1b7d9SAlexander Kabaev _M_do_left_shift(size_t __shift) 395*f8a1b7d9SAlexander Kabaev { _M_w <<= __shift; } 39600db7afdSDavid E. O'Brien 39700db7afdSDavid E. O'Brien void 398*f8a1b7d9SAlexander Kabaev _M_do_right_shift(size_t __shift) 399*f8a1b7d9SAlexander Kabaev { _M_w >>= __shift; } 40000db7afdSDavid E. O'Brien 40100db7afdSDavid E. O'Brien void 402*f8a1b7d9SAlexander Kabaev _M_do_flip() 403*f8a1b7d9SAlexander Kabaev { _M_w = ~_M_w; } 40400db7afdSDavid E. O'Brien 40500db7afdSDavid E. O'Brien void 406*f8a1b7d9SAlexander Kabaev _M_do_set() 407*f8a1b7d9SAlexander Kabaev { _M_w = ~static_cast<_WordT>(0); } 40800db7afdSDavid E. O'Brien 40900db7afdSDavid E. O'Brien void 410*f8a1b7d9SAlexander Kabaev _M_do_reset() 411*f8a1b7d9SAlexander Kabaev { _M_w = 0; } 41200db7afdSDavid E. O'Brien 41300db7afdSDavid E. O'Brien bool 41400db7afdSDavid E. O'Brien _M_is_equal(const _Base_bitset<1>& __x) const 41500db7afdSDavid E. O'Brien { return _M_w == __x._M_w; } 41600db7afdSDavid E. O'Brien 41700db7afdSDavid E. O'Brien bool 418*f8a1b7d9SAlexander Kabaev _M_is_any() const 419*f8a1b7d9SAlexander Kabaev { return _M_w != 0; } 42000db7afdSDavid E. O'Brien 42100db7afdSDavid E. O'Brien size_t 422*f8a1b7d9SAlexander Kabaev _M_do_count() const 423*f8a1b7d9SAlexander Kabaev { return __builtin_popcountl(_M_w); } 42400db7afdSDavid E. O'Brien 42500db7afdSDavid E. O'Brien unsigned long 426*f8a1b7d9SAlexander Kabaev _M_do_to_ulong() const 427*f8a1b7d9SAlexander Kabaev { return _M_w; } 42800db7afdSDavid E. O'Brien 42900db7afdSDavid E. O'Brien size_t 430ffeaf689SAlexander Kabaev _M_do_find_first(size_t __not_found) const 431ffeaf689SAlexander Kabaev { 432ffeaf689SAlexander Kabaev if (_M_w != 0) 433ffeaf689SAlexander Kabaev return __builtin_ctzl(_M_w); 434ffeaf689SAlexander Kabaev else 435ffeaf689SAlexander Kabaev return __not_found; 436ffeaf689SAlexander Kabaev } 43700db7afdSDavid E. O'Brien 43800db7afdSDavid E. O'Brien // find the next "on" bit that follows "prev" 43900db7afdSDavid E. O'Brien size_t 440ffeaf689SAlexander Kabaev _M_do_find_next(size_t __prev, size_t __not_found) const 441ffeaf689SAlexander Kabaev { 442ffeaf689SAlexander Kabaev ++__prev; 443ffeaf689SAlexander Kabaev if (__prev >= ((size_t) _GLIBCXX_BITSET_BITS_PER_WORD)) 444ffeaf689SAlexander Kabaev return __not_found; 445ffeaf689SAlexander Kabaev 446ffeaf689SAlexander Kabaev _WordT __x = _M_w >> __prev; 447ffeaf689SAlexander Kabaev if (__x != 0) 448ffeaf689SAlexander Kabaev return __builtin_ctzl(__x) + __prev; 449ffeaf689SAlexander Kabaev else 450ffeaf689SAlexander Kabaev return __not_found; 451ffeaf689SAlexander Kabaev } 45200db7afdSDavid E. O'Brien }; 45300db7afdSDavid E. O'Brien 454ca6500fcSAlexander Kabaev /** 455ca6500fcSAlexander Kabaev * @if maint 456ca6500fcSAlexander Kabaev * Base class, specialization for no storage (zero-length %bitset). 457ca6500fcSAlexander Kabaev * 458ca6500fcSAlexander Kabaev * See documentation for bitset. 459ca6500fcSAlexander Kabaev * @endif 460ca6500fcSAlexander Kabaev */ 461ca6500fcSAlexander Kabaev template<> 462ca6500fcSAlexander Kabaev struct _Base_bitset<0> 463ca6500fcSAlexander Kabaev { 464ca6500fcSAlexander Kabaev typedef unsigned long _WordT; 465ca6500fcSAlexander Kabaev 466*f8a1b7d9SAlexander Kabaev _Base_bitset() 467*f8a1b7d9SAlexander Kabaev { } 468*f8a1b7d9SAlexander Kabaev 469*f8a1b7d9SAlexander Kabaev _Base_bitset(unsigned long) 470*f8a1b7d9SAlexander Kabaev { } 471ca6500fcSAlexander Kabaev 472ca6500fcSAlexander Kabaev static size_t 473ca6500fcSAlexander Kabaev _S_whichword(size_t __pos ) 474ffeaf689SAlexander Kabaev { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } 475ca6500fcSAlexander Kabaev 476ca6500fcSAlexander Kabaev static size_t 477ca6500fcSAlexander Kabaev _S_whichbyte(size_t __pos ) 478ffeaf689SAlexander Kabaev { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } 479ca6500fcSAlexander Kabaev 480ca6500fcSAlexander Kabaev static size_t 481ca6500fcSAlexander Kabaev _S_whichbit(size_t __pos ) 482ffeaf689SAlexander Kabaev { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } 483ca6500fcSAlexander Kabaev 484ca6500fcSAlexander Kabaev static _WordT 485ca6500fcSAlexander Kabaev _S_maskbit(size_t __pos ) 486ca6500fcSAlexander Kabaev { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } 487ca6500fcSAlexander Kabaev 488ca6500fcSAlexander Kabaev // This would normally give access to the data. The bounds-checking 489ca6500fcSAlexander Kabaev // in the bitset class will prevent the user from getting this far, 490ca6500fcSAlexander Kabaev // but (1) it must still return an lvalue to compile, and (2) the 491ca6500fcSAlexander Kabaev // user might call _Unchecked_set directly, in which case this /needs/ 492ca6500fcSAlexander Kabaev // to fail. Let's not penalize zero-length users unless they actually 493ca6500fcSAlexander Kabaev // make an unchecked call; all the memory ugliness is therefore 494ca6500fcSAlexander Kabaev // localized to this single should-never-get-this-far function. 495ca6500fcSAlexander Kabaev _WordT& 496ca6500fcSAlexander Kabaev _M_getword(size_t) const 497ffeaf689SAlexander Kabaev { 498ffeaf689SAlexander Kabaev __throw_out_of_range(__N("_Base_bitset::_M_getword")); 499ffeaf689SAlexander Kabaev return *new _WordT; 500ffeaf689SAlexander Kabaev } 501ca6500fcSAlexander Kabaev 502ca6500fcSAlexander Kabaev _WordT 503*f8a1b7d9SAlexander Kabaev _M_hiword() const 504*f8a1b7d9SAlexander Kabaev { return 0; } 505ca6500fcSAlexander Kabaev 506ca6500fcSAlexander Kabaev void 507*f8a1b7d9SAlexander Kabaev _M_do_and(const _Base_bitset<0>&) 508*f8a1b7d9SAlexander Kabaev { } 509ca6500fcSAlexander Kabaev 510ca6500fcSAlexander Kabaev void 511*f8a1b7d9SAlexander Kabaev _M_do_or(const _Base_bitset<0>&) 512*f8a1b7d9SAlexander Kabaev { } 513ca6500fcSAlexander Kabaev 514ca6500fcSAlexander Kabaev void 515*f8a1b7d9SAlexander Kabaev _M_do_xor(const _Base_bitset<0>&) 516*f8a1b7d9SAlexander Kabaev { } 517ca6500fcSAlexander Kabaev 518ca6500fcSAlexander Kabaev void 519*f8a1b7d9SAlexander Kabaev _M_do_left_shift(size_t) 520*f8a1b7d9SAlexander Kabaev { } 521ca6500fcSAlexander Kabaev 522ca6500fcSAlexander Kabaev void 523*f8a1b7d9SAlexander Kabaev _M_do_right_shift(size_t) 524*f8a1b7d9SAlexander Kabaev { } 525ca6500fcSAlexander Kabaev 526ca6500fcSAlexander Kabaev void 527*f8a1b7d9SAlexander Kabaev _M_do_flip() 528*f8a1b7d9SAlexander Kabaev { } 529ca6500fcSAlexander Kabaev 530ca6500fcSAlexander Kabaev void 531*f8a1b7d9SAlexander Kabaev _M_do_set() 532*f8a1b7d9SAlexander Kabaev { } 533ca6500fcSAlexander Kabaev 534ca6500fcSAlexander Kabaev void 535*f8a1b7d9SAlexander Kabaev _M_do_reset() 536*f8a1b7d9SAlexander Kabaev { } 537ca6500fcSAlexander Kabaev 538ca6500fcSAlexander Kabaev // Are all empty bitsets equal to each other? Are they equal to 539ca6500fcSAlexander Kabaev // themselves? How to compare a thing which has no state? What is 540ca6500fcSAlexander Kabaev // the sound of one zero-length bitset clapping? 541ca6500fcSAlexander Kabaev bool 542*f8a1b7d9SAlexander Kabaev _M_is_equal(const _Base_bitset<0>&) const 543*f8a1b7d9SAlexander Kabaev { return true; } 544ca6500fcSAlexander Kabaev 545ca6500fcSAlexander Kabaev bool 546*f8a1b7d9SAlexander Kabaev _M_is_any() const 547*f8a1b7d9SAlexander Kabaev { return false; } 548ca6500fcSAlexander Kabaev 549ca6500fcSAlexander Kabaev size_t 550*f8a1b7d9SAlexander Kabaev _M_do_count() const 551*f8a1b7d9SAlexander Kabaev { return 0; } 552ca6500fcSAlexander Kabaev 553ca6500fcSAlexander Kabaev unsigned long 554*f8a1b7d9SAlexander Kabaev _M_do_to_ulong() const 555*f8a1b7d9SAlexander Kabaev { return 0; } 556ca6500fcSAlexander Kabaev 557ca6500fcSAlexander Kabaev // Normally "not found" is the size, but that could also be 558ca6500fcSAlexander Kabaev // misinterpreted as an index in this corner case. Oh well. 559ca6500fcSAlexander Kabaev size_t 560*f8a1b7d9SAlexander Kabaev _M_do_find_first(size_t) const 561*f8a1b7d9SAlexander Kabaev { return 0; } 562ca6500fcSAlexander Kabaev 563ca6500fcSAlexander Kabaev size_t 564*f8a1b7d9SAlexander Kabaev _M_do_find_next(size_t, size_t) const 565*f8a1b7d9SAlexander Kabaev { return 0; } 566ca6500fcSAlexander Kabaev }; 567ca6500fcSAlexander Kabaev 568ca6500fcSAlexander Kabaev 56900db7afdSDavid E. O'Brien // Helper class to zero out the unused high-order bits in the highest word. 57000db7afdSDavid E. O'Brien template<size_t _Extrabits> 57100db7afdSDavid E. O'Brien struct _Sanitize 57200db7afdSDavid E. O'Brien { 57300db7afdSDavid E. O'Brien static void _S_do_sanitize(unsigned long& __val) 57400db7afdSDavid E. O'Brien { __val &= ~((~static_cast<unsigned long>(0)) << _Extrabits); } 57500db7afdSDavid E. O'Brien }; 57600db7afdSDavid E. O'Brien 57700db7afdSDavid E. O'Brien template<> 57800db7afdSDavid E. O'Brien struct _Sanitize<0> 57900db7afdSDavid E. O'Brien { static void _S_do_sanitize(unsigned long) {} }; 58000db7afdSDavid E. O'Brien 58100db7afdSDavid E. O'Brien /** 58200db7afdSDavid E. O'Brien * @brief The %bitset class represents a @e fixed-size sequence of bits. 58300db7afdSDavid E. O'Brien * 58400db7afdSDavid E. O'Brien * @ingroup Containers 58500db7afdSDavid E. O'Brien * 58600db7afdSDavid E. O'Brien * (Note that %bitset does @e not meet the formal requirements of a 58700db7afdSDavid E. O'Brien * <a href="tables.html#65">container</a>. Mainly, it lacks iterators.) 58800db7afdSDavid E. O'Brien * 5891b86b14eSAlexander Kabaev * The template argument, @a Nb, may be any non-negative number, 5901b86b14eSAlexander Kabaev * specifying the number of bits (e.g., "0", "12", "1024*1024"). 59100db7afdSDavid E. O'Brien * 5921b86b14eSAlexander Kabaev * In the general unoptimized case, storage is allocated in word-sized 5931b86b14eSAlexander Kabaev * blocks. Let B be the number of bits in a word, then (Nb+(B-1))/B 5941b86b14eSAlexander Kabaev * words will be used for storage. B - Nb%B bits are unused. (They are 5951b86b14eSAlexander Kabaev * the high-order bits in the highest word.) It is a class invariant 5961b86b14eSAlexander Kabaev * that those unused bits are always zero. 59700db7afdSDavid E. O'Brien * 59800db7afdSDavid E. O'Brien * If you think of %bitset as "a simple array of bits," be aware that 59900db7afdSDavid E. O'Brien * your mental picture is reversed: a %bitset behaves the same way as 60000db7afdSDavid E. O'Brien * bits in integers do, with the bit at index 0 in the "least significant 6011b86b14eSAlexander Kabaev * / right-hand" position, and the bit at index Nb-1 in the "most 60200db7afdSDavid E. O'Brien * significant / left-hand" position. Thus, unlike other containers, a 60300db7afdSDavid E. O'Brien * %bitset's index "counts from right to left," to put it very loosely. 60400db7afdSDavid E. O'Brien * 60500db7afdSDavid E. O'Brien * This behavior is preserved when translating to and from strings. For 60600db7afdSDavid E. O'Brien * example, the first line of the following program probably prints 60700db7afdSDavid E. O'Brien * "b('a') is 0001100001" on a modern ASCII system. 60800db7afdSDavid E. O'Brien * 60900db7afdSDavid E. O'Brien * @code 61000db7afdSDavid E. O'Brien * #include <bitset> 61100db7afdSDavid E. O'Brien * #include <iostream> 61200db7afdSDavid E. O'Brien * #include <sstream> 61300db7afdSDavid E. O'Brien * 61400db7afdSDavid E. O'Brien * using namespace std; 61500db7afdSDavid E. O'Brien * 61600db7afdSDavid E. O'Brien * int main() 61700db7afdSDavid E. O'Brien * { 61800db7afdSDavid E. O'Brien * long a = 'a'; 61900db7afdSDavid E. O'Brien * bitset<10> b(a); 62000db7afdSDavid E. O'Brien * 62100db7afdSDavid E. O'Brien * cout << "b('a') is " << b << endl; 62200db7afdSDavid E. O'Brien * 62300db7afdSDavid E. O'Brien * ostringstream s; 62400db7afdSDavid E. O'Brien * s << b; 62500db7afdSDavid E. O'Brien * string str = s.str(); 62600db7afdSDavid E. O'Brien * cout << "index 3 in the string is " << str[3] << " but\n" 62700db7afdSDavid E. O'Brien * << "index 3 in the bitset is " << b[3] << endl; 62800db7afdSDavid E. O'Brien * } 62900db7afdSDavid E. O'Brien * @endcode 63000db7afdSDavid E. O'Brien * 63100db7afdSDavid E. O'Brien * Also see http://gcc.gnu.org/onlinedocs/libstdc++/ext/sgiexts.html#ch23 6321b86b14eSAlexander Kabaev * for a description of extensions. 63300db7afdSDavid E. O'Brien * 63400db7afdSDavid E. O'Brien * @if maint 63500db7afdSDavid E. O'Brien * Most of the actual code isn't contained in %bitset<> itself, but in the 63600db7afdSDavid E. O'Brien * base class _Base_bitset. The base class works with whole words, not with 63700db7afdSDavid E. O'Brien * individual bits. This allows us to specialize _Base_bitset for the 63800db7afdSDavid E. O'Brien * important special case where the %bitset is only a single word. 63900db7afdSDavid E. O'Brien * 64000db7afdSDavid E. O'Brien * Extra confusion can result due to the fact that the storage for 64100db7afdSDavid E. O'Brien * _Base_bitset @e is a regular array, and is indexed as such. This is 64200db7afdSDavid E. O'Brien * carefully encapsulated. 64300db7afdSDavid E. O'Brien * @endif 64400db7afdSDavid E. O'Brien */ 64500db7afdSDavid E. O'Brien template<size_t _Nb> 646*f8a1b7d9SAlexander Kabaev class bitset 647*f8a1b7d9SAlexander Kabaev : private _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> 64800db7afdSDavid E. O'Brien { 64900db7afdSDavid E. O'Brien private: 650ffeaf689SAlexander Kabaev typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base; 65100db7afdSDavid E. O'Brien typedef unsigned long _WordT; 65200db7afdSDavid E. O'Brien 65300db7afdSDavid E. O'Brien void 65400db7afdSDavid E. O'Brien _M_do_sanitize() 65500db7afdSDavid E. O'Brien { 656ffeaf689SAlexander Kabaev _Sanitize<_Nb % _GLIBCXX_BITSET_BITS_PER_WORD>:: 65700db7afdSDavid E. O'Brien _S_do_sanitize(this->_M_hiword()); 65800db7afdSDavid E. O'Brien } 65900db7afdSDavid E. O'Brien 66000db7afdSDavid E. O'Brien public: 66100db7afdSDavid E. O'Brien /** 66200db7afdSDavid E. O'Brien * This encapsulates the concept of a single bit. An instance of this 66300db7afdSDavid E. O'Brien * class is a proxy for an actual bit; this way the individual bit 66400db7afdSDavid E. O'Brien * operations are done as faster word-size bitwise instructions. 66500db7afdSDavid E. O'Brien * 66600db7afdSDavid E. O'Brien * Most users will never need to use this class directly; conversions 66700db7afdSDavid E. O'Brien * to and from bool are automatic and should be transparent. Overloaded 66800db7afdSDavid E. O'Brien * operators help to preserve the illusion. 66900db7afdSDavid E. O'Brien * 67000db7afdSDavid E. O'Brien * (On a typical system, this "bit %reference" is 64 times the size of 67100db7afdSDavid E. O'Brien * an actual bit. Ha.) 67200db7afdSDavid E. O'Brien */ 67300db7afdSDavid E. O'Brien class reference 67400db7afdSDavid E. O'Brien { 67500db7afdSDavid E. O'Brien friend class bitset; 67600db7afdSDavid E. O'Brien 67700db7afdSDavid E. O'Brien _WordT *_M_wp; 67800db7afdSDavid E. O'Brien size_t _M_bpos; 67900db7afdSDavid E. O'Brien 68000db7afdSDavid E. O'Brien // left undefined 68100db7afdSDavid E. O'Brien reference(); 68200db7afdSDavid E. O'Brien 68300db7afdSDavid E. O'Brien public: 68400db7afdSDavid E. O'Brien reference(bitset& __b, size_t __pos) 68500db7afdSDavid E. O'Brien { 68600db7afdSDavid E. O'Brien _M_wp = &__b._M_getword(__pos); 68700db7afdSDavid E. O'Brien _M_bpos = _Base::_S_whichbit(__pos); 68800db7afdSDavid E. O'Brien } 68900db7afdSDavid E. O'Brien 690*f8a1b7d9SAlexander Kabaev ~reference() 691*f8a1b7d9SAlexander Kabaev { } 69200db7afdSDavid E. O'Brien 693ffeaf689SAlexander Kabaev // For b[i] = __x; 69400db7afdSDavid E. O'Brien reference& 69500db7afdSDavid E. O'Brien operator=(bool __x) 69600db7afdSDavid E. O'Brien { 69700db7afdSDavid E. O'Brien if (__x) 69800db7afdSDavid E. O'Brien *_M_wp |= _Base::_S_maskbit(_M_bpos); 69900db7afdSDavid E. O'Brien else 70000db7afdSDavid E. O'Brien *_M_wp &= ~_Base::_S_maskbit(_M_bpos); 70100db7afdSDavid E. O'Brien return *this; 70200db7afdSDavid E. O'Brien } 70300db7afdSDavid E. O'Brien 704ffeaf689SAlexander Kabaev // For b[i] = b[__j]; 70500db7afdSDavid E. O'Brien reference& 70600db7afdSDavid E. O'Brien operator=(const reference& __j) 70700db7afdSDavid E. O'Brien { 70800db7afdSDavid E. O'Brien if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos))) 70900db7afdSDavid E. O'Brien *_M_wp |= _Base::_S_maskbit(_M_bpos); 71000db7afdSDavid E. O'Brien else 71100db7afdSDavid E. O'Brien *_M_wp &= ~_Base::_S_maskbit(_M_bpos); 71200db7afdSDavid E. O'Brien return *this; 71300db7afdSDavid E. O'Brien } 71400db7afdSDavid E. O'Brien 715ffeaf689SAlexander Kabaev // Flips the bit 71600db7afdSDavid E. O'Brien bool 71700db7afdSDavid E. O'Brien operator~() const 71800db7afdSDavid E. O'Brien { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) == 0; } 71900db7afdSDavid E. O'Brien 720ffeaf689SAlexander Kabaev // For __x = b[i]; 72100db7afdSDavid E. O'Brien operator bool() const 72200db7afdSDavid E. O'Brien { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; } 72300db7afdSDavid E. O'Brien 724ffeaf689SAlexander Kabaev // For b[i].flip(); 72500db7afdSDavid E. O'Brien reference& 72600db7afdSDavid E. O'Brien flip() 72700db7afdSDavid E. O'Brien { 72800db7afdSDavid E. O'Brien *_M_wp ^= _Base::_S_maskbit(_M_bpos); 72900db7afdSDavid E. O'Brien return *this; 73000db7afdSDavid E. O'Brien } 73100db7afdSDavid E. O'Brien }; 73200db7afdSDavid E. O'Brien friend class reference; 73300db7afdSDavid E. O'Brien 73400db7afdSDavid E. O'Brien // 23.3.5.1 constructors: 73500db7afdSDavid E. O'Brien /// All bits set to zero. 736*f8a1b7d9SAlexander Kabaev bitset() 737*f8a1b7d9SAlexander Kabaev { } 73800db7afdSDavid E. O'Brien 73900db7afdSDavid E. O'Brien /// Initial bits bitwise-copied from a single word (others set to zero). 740*f8a1b7d9SAlexander Kabaev bitset(unsigned long __val) 741*f8a1b7d9SAlexander Kabaev : _Base(__val) 74200db7afdSDavid E. O'Brien { _M_do_sanitize(); } 74300db7afdSDavid E. O'Brien 74400db7afdSDavid E. O'Brien /** 74500db7afdSDavid E. O'Brien * @brief Use a subset of a string. 74600db7afdSDavid E. O'Brien * @param s A string of '0' and '1' characters. 747*f8a1b7d9SAlexander Kabaev * @param position Index of the first character in @a s to use; 748*f8a1b7d9SAlexander Kabaev * defaults to zero. 74900db7afdSDavid E. O'Brien * @throw std::out_of_range If @a pos is bigger the size of @a s. 75000db7afdSDavid E. O'Brien * @throw std::invalid_argument If a character appears in the string 75100db7afdSDavid E. O'Brien * which is neither '0' nor '1'. 75200db7afdSDavid E. O'Brien */ 75300db7afdSDavid E. O'Brien template<class _CharT, class _Traits, class _Alloc> 754*f8a1b7d9SAlexander Kabaev explicit 755*f8a1b7d9SAlexander Kabaev bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s, 756*f8a1b7d9SAlexander Kabaev size_t __position = 0) 757*f8a1b7d9SAlexander Kabaev : _Base() 75800db7afdSDavid E. O'Brien { 759ffeaf689SAlexander Kabaev if (__position > __s.size()) 760ffeaf689SAlexander Kabaev __throw_out_of_range(__N("bitset::bitset initial position " 761ffeaf689SAlexander Kabaev "not valid")); 762ffeaf689SAlexander Kabaev _M_copy_from_string(__s, __position, 763*f8a1b7d9SAlexander Kabaev std::basic_string<_CharT, _Traits, _Alloc>::npos); 76400db7afdSDavid E. O'Brien } 76500db7afdSDavid E. O'Brien 76600db7afdSDavid E. O'Brien /** 76700db7afdSDavid E. O'Brien * @brief Use a subset of a string. 76800db7afdSDavid E. O'Brien * @param s A string of '0' and '1' characters. 769ffeaf689SAlexander Kabaev * @param position Index of the first character in @a s to use. 77000db7afdSDavid E. O'Brien * @param n The number of characters to copy. 77100db7afdSDavid E. O'Brien * @throw std::out_of_range If @a pos is bigger the size of @a s. 77200db7afdSDavid E. O'Brien * @throw std::invalid_argument If a character appears in the string 77300db7afdSDavid E. O'Brien * which is neither '0' nor '1'. 77400db7afdSDavid E. O'Brien */ 77500db7afdSDavid E. O'Brien template<class _CharT, class _Traits, class _Alloc> 776*f8a1b7d9SAlexander Kabaev bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __s, 777*f8a1b7d9SAlexander Kabaev size_t __position, size_t __n) 778*f8a1b7d9SAlexander Kabaev : _Base() 77900db7afdSDavid E. O'Brien { 780ffeaf689SAlexander Kabaev if (__position > __s.size()) 781ffeaf689SAlexander Kabaev __throw_out_of_range(__N("bitset::bitset initial position " 782ffeaf689SAlexander Kabaev "not valid")); 783ffeaf689SAlexander Kabaev _M_copy_from_string(__s, __position, __n); 78400db7afdSDavid E. O'Brien } 78500db7afdSDavid E. O'Brien 78600db7afdSDavid E. O'Brien // 23.3.5.2 bitset operations: 78700db7afdSDavid E. O'Brien //@{ 78800db7afdSDavid E. O'Brien /** 78900db7afdSDavid E. O'Brien * @brief Operations on bitsets. 79000db7afdSDavid E. O'Brien * @param rhs A same-sized bitset. 79100db7afdSDavid E. O'Brien * 79200db7afdSDavid E. O'Brien * These should be self-explanatory. 79300db7afdSDavid E. O'Brien */ 79400db7afdSDavid E. O'Brien bitset<_Nb>& 79500db7afdSDavid E. O'Brien operator&=(const bitset<_Nb>& __rhs) 79600db7afdSDavid E. O'Brien { 79700db7afdSDavid E. O'Brien this->_M_do_and(__rhs); 79800db7afdSDavid E. O'Brien return *this; 79900db7afdSDavid E. O'Brien } 80000db7afdSDavid E. O'Brien 80100db7afdSDavid E. O'Brien bitset<_Nb>& 80200db7afdSDavid E. O'Brien operator|=(const bitset<_Nb>& __rhs) 80300db7afdSDavid E. O'Brien { 80400db7afdSDavid E. O'Brien this->_M_do_or(__rhs); 80500db7afdSDavid E. O'Brien return *this; 80600db7afdSDavid E. O'Brien } 80700db7afdSDavid E. O'Brien 80800db7afdSDavid E. O'Brien bitset<_Nb>& 80900db7afdSDavid E. O'Brien operator^=(const bitset<_Nb>& __rhs) 81000db7afdSDavid E. O'Brien { 81100db7afdSDavid E. O'Brien this->_M_do_xor(__rhs); 81200db7afdSDavid E. O'Brien return *this; 81300db7afdSDavid E. O'Brien } 81400db7afdSDavid E. O'Brien //@} 81500db7afdSDavid E. O'Brien 81600db7afdSDavid E. O'Brien //@{ 81700db7afdSDavid E. O'Brien /** 81800db7afdSDavid E. O'Brien * @brief Operations on bitsets. 819ffeaf689SAlexander Kabaev * @param position The number of places to shift. 82000db7afdSDavid E. O'Brien * 82100db7afdSDavid E. O'Brien * These should be self-explanatory. 82200db7afdSDavid E. O'Brien */ 82300db7afdSDavid E. O'Brien bitset<_Nb>& 824ffeaf689SAlexander Kabaev operator<<=(size_t __position) 82500db7afdSDavid E. O'Brien { 826ffeaf689SAlexander Kabaev if (__builtin_expect(__position < _Nb, 1)) 8271b86b14eSAlexander Kabaev { 828ffeaf689SAlexander Kabaev this->_M_do_left_shift(__position); 82900db7afdSDavid E. O'Brien this->_M_do_sanitize(); 8301b86b14eSAlexander Kabaev } 8311b86b14eSAlexander Kabaev else 8321b86b14eSAlexander Kabaev this->_M_do_reset(); 83300db7afdSDavid E. O'Brien return *this; 83400db7afdSDavid E. O'Brien } 83500db7afdSDavid E. O'Brien 83600db7afdSDavid E. O'Brien bitset<_Nb>& 837ffeaf689SAlexander Kabaev operator>>=(size_t __position) 83800db7afdSDavid E. O'Brien { 839ffeaf689SAlexander Kabaev if (__builtin_expect(__position < _Nb, 1)) 8401b86b14eSAlexander Kabaev { 841ffeaf689SAlexander Kabaev this->_M_do_right_shift(__position); 84200db7afdSDavid E. O'Brien this->_M_do_sanitize(); 8431b86b14eSAlexander Kabaev } 8441b86b14eSAlexander Kabaev else 8451b86b14eSAlexander Kabaev this->_M_do_reset(); 84600db7afdSDavid E. O'Brien return *this; 84700db7afdSDavid E. O'Brien } 84800db7afdSDavid E. O'Brien //@} 84900db7afdSDavid E. O'Brien 85000db7afdSDavid E. O'Brien //@{ 85100db7afdSDavid E. O'Brien /** 85200db7afdSDavid E. O'Brien * These versions of single-bit set, reset, flip, and test are 85300db7afdSDavid E. O'Brien * extensions from the SGI version. They do no range checking. 85400db7afdSDavid E. O'Brien * @ingroup SGIextensions 85500db7afdSDavid E. O'Brien */ 85600db7afdSDavid E. O'Brien bitset<_Nb>& 85700db7afdSDavid E. O'Brien _Unchecked_set(size_t __pos) 85800db7afdSDavid E. O'Brien { 85900db7afdSDavid E. O'Brien this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); 86000db7afdSDavid E. O'Brien return *this; 86100db7afdSDavid E. O'Brien } 86200db7afdSDavid E. O'Brien 86300db7afdSDavid E. O'Brien bitset<_Nb>& 86400db7afdSDavid E. O'Brien _Unchecked_set(size_t __pos, int __val) 86500db7afdSDavid E. O'Brien { 86600db7afdSDavid E. O'Brien if (__val) 86700db7afdSDavid E. O'Brien this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); 86800db7afdSDavid E. O'Brien else 86900db7afdSDavid E. O'Brien this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); 87000db7afdSDavid E. O'Brien return *this; 87100db7afdSDavid E. O'Brien } 87200db7afdSDavid E. O'Brien 87300db7afdSDavid E. O'Brien bitset<_Nb>& 87400db7afdSDavid E. O'Brien _Unchecked_reset(size_t __pos) 87500db7afdSDavid E. O'Brien { 87600db7afdSDavid E. O'Brien this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); 87700db7afdSDavid E. O'Brien return *this; 87800db7afdSDavid E. O'Brien } 87900db7afdSDavid E. O'Brien 88000db7afdSDavid E. O'Brien bitset<_Nb>& 88100db7afdSDavid E. O'Brien _Unchecked_flip(size_t __pos) 88200db7afdSDavid E. O'Brien { 88300db7afdSDavid E. O'Brien this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos); 88400db7afdSDavid E. O'Brien return *this; 88500db7afdSDavid E. O'Brien } 88600db7afdSDavid E. O'Brien 88700db7afdSDavid E. O'Brien bool 88800db7afdSDavid E. O'Brien _Unchecked_test(size_t __pos) const 889*f8a1b7d9SAlexander Kabaev { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos)) 890*f8a1b7d9SAlexander Kabaev != static_cast<_WordT>(0)); } 89100db7afdSDavid E. O'Brien //@} 89200db7afdSDavid E. O'Brien 89300db7afdSDavid E. O'Brien // Set, reset, and flip. 89400db7afdSDavid E. O'Brien /** 89500db7afdSDavid E. O'Brien * @brief Sets every bit to true. 89600db7afdSDavid E. O'Brien */ 89700db7afdSDavid E. O'Brien bitset<_Nb>& 89800db7afdSDavid E. O'Brien set() 89900db7afdSDavid E. O'Brien { 90000db7afdSDavid E. O'Brien this->_M_do_set(); 90100db7afdSDavid E. O'Brien this->_M_do_sanitize(); 90200db7afdSDavid E. O'Brien return *this; 90300db7afdSDavid E. O'Brien } 90400db7afdSDavid E. O'Brien 90500db7afdSDavid E. O'Brien /** 90600db7afdSDavid E. O'Brien * @brief Sets a given bit to a particular value. 907ffeaf689SAlexander Kabaev * @param position The index of the bit. 90800db7afdSDavid E. O'Brien * @param val Either true or false, defaults to true. 90900db7afdSDavid E. O'Brien * @throw std::out_of_range If @a pos is bigger the size of the %set. 91000db7afdSDavid E. O'Brien */ 91100db7afdSDavid E. O'Brien bitset<_Nb>& 912ffeaf689SAlexander Kabaev set(size_t __position, bool __val = true) 91300db7afdSDavid E. O'Brien { 914ffeaf689SAlexander Kabaev if (__position >= _Nb) 915ffeaf689SAlexander Kabaev __throw_out_of_range(__N("bitset::set")); 916ffeaf689SAlexander Kabaev return _Unchecked_set(__position, __val); 91700db7afdSDavid E. O'Brien } 91800db7afdSDavid E. O'Brien 91900db7afdSDavid E. O'Brien /** 92000db7afdSDavid E. O'Brien * @brief Sets every bit to false. 92100db7afdSDavid E. O'Brien */ 92200db7afdSDavid E. O'Brien bitset<_Nb>& 92300db7afdSDavid E. O'Brien reset() 92400db7afdSDavid E. O'Brien { 92500db7afdSDavid E. O'Brien this->_M_do_reset(); 92600db7afdSDavid E. O'Brien return *this; 92700db7afdSDavid E. O'Brien } 92800db7afdSDavid E. O'Brien 92900db7afdSDavid E. O'Brien /** 93000db7afdSDavid E. O'Brien * @brief Sets a given bit to false. 931ffeaf689SAlexander Kabaev * @param position The index of the bit. 93200db7afdSDavid E. O'Brien * @throw std::out_of_range If @a pos is bigger the size of the %set. 93300db7afdSDavid E. O'Brien * 93400db7afdSDavid E. O'Brien * Same as writing @c set(pos,false). 93500db7afdSDavid E. O'Brien */ 93600db7afdSDavid E. O'Brien bitset<_Nb>& 937ffeaf689SAlexander Kabaev reset(size_t __position) 93800db7afdSDavid E. O'Brien { 939ffeaf689SAlexander Kabaev if (__position >= _Nb) 940ffeaf689SAlexander Kabaev __throw_out_of_range(__N("bitset::reset")); 941ffeaf689SAlexander Kabaev return _Unchecked_reset(__position); 94200db7afdSDavid E. O'Brien } 94300db7afdSDavid E. O'Brien 94400db7afdSDavid E. O'Brien /** 94500db7afdSDavid E. O'Brien * @brief Toggles every bit to its opposite value. 94600db7afdSDavid E. O'Brien */ 94700db7afdSDavid E. O'Brien bitset<_Nb>& 94800db7afdSDavid E. O'Brien flip() 94900db7afdSDavid E. O'Brien { 95000db7afdSDavid E. O'Brien this->_M_do_flip(); 95100db7afdSDavid E. O'Brien this->_M_do_sanitize(); 95200db7afdSDavid E. O'Brien return *this; 95300db7afdSDavid E. O'Brien } 95400db7afdSDavid E. O'Brien 95500db7afdSDavid E. O'Brien /** 95600db7afdSDavid E. O'Brien * @brief Toggles a given bit to its opposite value. 957ffeaf689SAlexander Kabaev * @param position The index of the bit. 95800db7afdSDavid E. O'Brien * @throw std::out_of_range If @a pos is bigger the size of the %set. 95900db7afdSDavid E. O'Brien */ 96000db7afdSDavid E. O'Brien bitset<_Nb>& 961ffeaf689SAlexander Kabaev flip(size_t __position) 96200db7afdSDavid E. O'Brien { 963ffeaf689SAlexander Kabaev if (__position >= _Nb) 964ffeaf689SAlexander Kabaev __throw_out_of_range(__N("bitset::flip")); 965ffeaf689SAlexander Kabaev return _Unchecked_flip(__position); 96600db7afdSDavid E. O'Brien } 96700db7afdSDavid E. O'Brien 96800db7afdSDavid E. O'Brien /// See the no-argument flip(). 96900db7afdSDavid E. O'Brien bitset<_Nb> 970*f8a1b7d9SAlexander Kabaev operator~() const 971*f8a1b7d9SAlexander Kabaev { return bitset<_Nb>(*this).flip(); } 97200db7afdSDavid E. O'Brien 97300db7afdSDavid E. O'Brien //@{ 97400db7afdSDavid E. O'Brien /** 97500db7afdSDavid E. O'Brien * @brief Array-indexing support. 976ffeaf689SAlexander Kabaev * @param position Index into the %bitset. 97700db7afdSDavid E. O'Brien * @return A bool for a 'const %bitset'. For non-const bitsets, an 97800db7afdSDavid E. O'Brien * instance of the reference proxy class. 97900db7afdSDavid E. O'Brien * @note These operators do no range checking and throw no exceptions, 98000db7afdSDavid E. O'Brien * as required by DR 11 to the standard. 98100db7afdSDavid E. O'Brien * 98200db7afdSDavid E. O'Brien * @if maint 983ffeaf689SAlexander Kabaev * _GLIBCXX_RESOLVE_LIB_DEFECTS Note that this implementation already 98400db7afdSDavid E. O'Brien * resolves DR 11 (items 1 and 2), but does not do the range-checking 98500db7afdSDavid E. O'Brien * required by that DR's resolution. -pme 98600db7afdSDavid E. O'Brien * The DR has since been changed: range-checking is a precondition 98700db7afdSDavid E. O'Brien * (users' responsibility), and these functions must not throw. -pme 98800db7afdSDavid E. O'Brien * @endif 98900db7afdSDavid E. O'Brien */ 99000db7afdSDavid E. O'Brien reference 991*f8a1b7d9SAlexander Kabaev operator[](size_t __position) 992*f8a1b7d9SAlexander Kabaev { return reference(*this,__position); } 99300db7afdSDavid E. O'Brien 99400db7afdSDavid E. O'Brien bool 995*f8a1b7d9SAlexander Kabaev operator[](size_t __position) const 996*f8a1b7d9SAlexander Kabaev { return _Unchecked_test(__position); } 99700db7afdSDavid E. O'Brien //@} 99800db7afdSDavid E. O'Brien 99900db7afdSDavid E. O'Brien /** 100000db7afdSDavid E. O'Brien * @brief Retuns a numerical interpretation of the %bitset. 100100db7afdSDavid E. O'Brien * @return The integral equivalent of the bits. 100200db7afdSDavid E. O'Brien * @throw std::overflow_error If there are too many bits to be 100300db7afdSDavid E. O'Brien * represented in an @c unsigned @c long. 100400db7afdSDavid E. O'Brien */ 100500db7afdSDavid E. O'Brien unsigned long 1006*f8a1b7d9SAlexander Kabaev to_ulong() const 1007*f8a1b7d9SAlexander Kabaev { return this->_M_do_to_ulong(); } 100800db7afdSDavid E. O'Brien 100900db7afdSDavid E. O'Brien /** 101000db7afdSDavid E. O'Brien * @brief Retuns a character interpretation of the %bitset. 101100db7afdSDavid E. O'Brien * @return The string equivalent of the bits. 101200db7afdSDavid E. O'Brien * 101300db7afdSDavid E. O'Brien * Note the ordering of the bits: decreasing character positions 101400db7afdSDavid E. O'Brien * correspond to increasing bit positions (see the main class notes for 101500db7afdSDavid E. O'Brien * an example). 101600db7afdSDavid E. O'Brien */ 101700db7afdSDavid E. O'Brien template<class _CharT, class _Traits, class _Alloc> 1018*f8a1b7d9SAlexander Kabaev std::basic_string<_CharT, _Traits, _Alloc> 101900db7afdSDavid E. O'Brien to_string() const 102000db7afdSDavid E. O'Brien { 1021*f8a1b7d9SAlexander Kabaev std::basic_string<_CharT, _Traits, _Alloc> __result; 102200db7afdSDavid E. O'Brien _M_copy_to_string(__result); 102300db7afdSDavid E. O'Brien return __result; 102400db7afdSDavid E. O'Brien } 102500db7afdSDavid E. O'Brien 1026*f8a1b7d9SAlexander Kabaev // _GLIBCXX_RESOLVE_LIB_DEFECTS 1027*f8a1b7d9SAlexander Kabaev // 434. bitset::to_string() hard to use. 1028*f8a1b7d9SAlexander Kabaev template<class _CharT, class _Traits> 1029*f8a1b7d9SAlexander Kabaev std::basic_string<_CharT, _Traits, std::allocator<_CharT> > 1030*f8a1b7d9SAlexander Kabaev to_string() const 1031*f8a1b7d9SAlexander Kabaev { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); } 1032*f8a1b7d9SAlexander Kabaev 1033*f8a1b7d9SAlexander Kabaev template<class _CharT> 1034*f8a1b7d9SAlexander Kabaev std::basic_string<_CharT, std::char_traits<_CharT>, 1035*f8a1b7d9SAlexander Kabaev std::allocator<_CharT> > 1036*f8a1b7d9SAlexander Kabaev to_string() const 1037*f8a1b7d9SAlexander Kabaev { 1038*f8a1b7d9SAlexander Kabaev return to_string<_CharT, std::char_traits<_CharT>, 1039*f8a1b7d9SAlexander Kabaev std::allocator<_CharT> >(); 1040*f8a1b7d9SAlexander Kabaev } 1041*f8a1b7d9SAlexander Kabaev 1042*f8a1b7d9SAlexander Kabaev std::basic_string<char, std::char_traits<char>, std::allocator<char> > 1043*f8a1b7d9SAlexander Kabaev to_string() const 1044*f8a1b7d9SAlexander Kabaev { 1045*f8a1b7d9SAlexander Kabaev return to_string<char, std::char_traits<char>, 1046*f8a1b7d9SAlexander Kabaev std::allocator<char> >(); 1047*f8a1b7d9SAlexander Kabaev } 1048*f8a1b7d9SAlexander Kabaev 104900db7afdSDavid E. O'Brien // Helper functions for string operations. 105000db7afdSDavid E. O'Brien template<class _CharT, class _Traits, class _Alloc> 105100db7afdSDavid E. O'Brien void 1052*f8a1b7d9SAlexander Kabaev _M_copy_from_string(const std::basic_string<_CharT, 1053*f8a1b7d9SAlexander Kabaev _Traits, _Alloc>& __s, 105400db7afdSDavid E. O'Brien size_t, size_t); 105500db7afdSDavid E. O'Brien 105600db7afdSDavid E. O'Brien template<class _CharT, class _Traits, class _Alloc> 105700db7afdSDavid E. O'Brien void 1058*f8a1b7d9SAlexander Kabaev _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>&) const; 105900db7afdSDavid E. O'Brien 106000db7afdSDavid E. O'Brien /// Returns the number of bits which are set. 106100db7afdSDavid E. O'Brien size_t 1062*f8a1b7d9SAlexander Kabaev count() const 1063*f8a1b7d9SAlexander Kabaev { return this->_M_do_count(); } 106400db7afdSDavid E. O'Brien 106500db7afdSDavid E. O'Brien /// Returns the total number of bits. 106600db7afdSDavid E. O'Brien size_t 1067*f8a1b7d9SAlexander Kabaev size() const 1068*f8a1b7d9SAlexander Kabaev { return _Nb; } 106900db7afdSDavid E. O'Brien 107000db7afdSDavid E. O'Brien //@{ 107100db7afdSDavid E. O'Brien /// These comparisons for equality/inequality are, well, @e bitwise. 107200db7afdSDavid E. O'Brien bool 107300db7afdSDavid E. O'Brien operator==(const bitset<_Nb>& __rhs) const 107400db7afdSDavid E. O'Brien { return this->_M_is_equal(__rhs); } 107500db7afdSDavid E. O'Brien 107600db7afdSDavid E. O'Brien bool 107700db7afdSDavid E. O'Brien operator!=(const bitset<_Nb>& __rhs) const 107800db7afdSDavid E. O'Brien { return !this->_M_is_equal(__rhs); } 107900db7afdSDavid E. O'Brien //@} 108000db7afdSDavid E. O'Brien 108100db7afdSDavid E. O'Brien /** 108200db7afdSDavid E. O'Brien * @brief Tests the value of a bit. 1083ffeaf689SAlexander Kabaev * @param position The index of a bit. 108400db7afdSDavid E. O'Brien * @return The value at @a pos. 108500db7afdSDavid E. O'Brien * @throw std::out_of_range If @a pos is bigger the size of the %set. 108600db7afdSDavid E. O'Brien */ 108700db7afdSDavid E. O'Brien bool 1088ffeaf689SAlexander Kabaev test(size_t __position) const 108900db7afdSDavid E. O'Brien { 1090ffeaf689SAlexander Kabaev if (__position >= _Nb) 1091ffeaf689SAlexander Kabaev __throw_out_of_range(__N("bitset::test")); 1092ffeaf689SAlexander Kabaev return _Unchecked_test(__position); 109300db7afdSDavid E. O'Brien } 109400db7afdSDavid E. O'Brien 109500db7afdSDavid E. O'Brien /** 109600db7afdSDavid E. O'Brien * @brief Tests whether any of the bits are on. 109700db7afdSDavid E. O'Brien * @return True if at least one bit is set. 109800db7afdSDavid E. O'Brien */ 109900db7afdSDavid E. O'Brien bool 1100*f8a1b7d9SAlexander Kabaev any() const 1101*f8a1b7d9SAlexander Kabaev { return this->_M_is_any(); } 110200db7afdSDavid E. O'Brien 110300db7afdSDavid E. O'Brien /** 110400db7afdSDavid E. O'Brien * @brief Tests whether any of the bits are on. 110500db7afdSDavid E. O'Brien * @return True if none of the bits are set. 110600db7afdSDavid E. O'Brien */ 110700db7afdSDavid E. O'Brien bool 1108*f8a1b7d9SAlexander Kabaev none() const 1109*f8a1b7d9SAlexander Kabaev { return !this->_M_is_any(); } 111000db7afdSDavid E. O'Brien 111100db7afdSDavid E. O'Brien //@{ 111200db7afdSDavid E. O'Brien /// Self-explanatory. 111300db7afdSDavid E. O'Brien bitset<_Nb> 1114ffeaf689SAlexander Kabaev operator<<(size_t __position) const 1115ffeaf689SAlexander Kabaev { return bitset<_Nb>(*this) <<= __position; } 111600db7afdSDavid E. O'Brien 111700db7afdSDavid E. O'Brien bitset<_Nb> 1118ffeaf689SAlexander Kabaev operator>>(size_t __position) const 1119ffeaf689SAlexander Kabaev { return bitset<_Nb>(*this) >>= __position; } 112000db7afdSDavid E. O'Brien //@} 112100db7afdSDavid E. O'Brien 112200db7afdSDavid E. O'Brien /** 112300db7afdSDavid E. O'Brien * @brief Finds the index of the first "on" bit. 112400db7afdSDavid E. O'Brien * @return The index of the first bit set, or size() if not found. 112500db7afdSDavid E. O'Brien * @ingroup SGIextensions 112600db7afdSDavid E. O'Brien * @sa _Find_next 112700db7afdSDavid E. O'Brien */ 112800db7afdSDavid E. O'Brien size_t 112900db7afdSDavid E. O'Brien _Find_first() const 113000db7afdSDavid E. O'Brien { return this->_M_do_find_first(_Nb); } 113100db7afdSDavid E. O'Brien 113200db7afdSDavid E. O'Brien /** 113300db7afdSDavid E. O'Brien * @brief Finds the index of the next "on" bit after prev. 113400db7afdSDavid E. O'Brien * @return The index of the next bit set, or size() if not found. 113500db7afdSDavid E. O'Brien * @param prev Where to start searching. 113600db7afdSDavid E. O'Brien * @ingroup SGIextensions 113700db7afdSDavid E. O'Brien * @sa _Find_first 113800db7afdSDavid E. O'Brien */ 113900db7afdSDavid E. O'Brien size_t 114000db7afdSDavid E. O'Brien _Find_next(size_t __prev ) const 114100db7afdSDavid E. O'Brien { return this->_M_do_find_next(__prev, _Nb); } 114200db7afdSDavid E. O'Brien }; 114300db7afdSDavid E. O'Brien 114400db7afdSDavid E. O'Brien // Definitions of non-inline member functions. 114500db7afdSDavid E. O'Brien template<size_t _Nb> 114600db7afdSDavid E. O'Brien template<class _CharT, class _Traits, class _Alloc> 114700db7afdSDavid E. O'Brien void 1148*f8a1b7d9SAlexander Kabaev bitset<_Nb>:: 1149*f8a1b7d9SAlexander Kabaev _M_copy_from_string(const std::basic_string<_CharT, _Traits, 1150ffeaf689SAlexander Kabaev _Alloc>& __s, size_t __pos, size_t __n) 115100db7afdSDavid E. O'Brien { 115200db7afdSDavid E. O'Brien reset(); 1153ffeaf689SAlexander Kabaev const size_t __nbits = std::min(_Nb, std::min(__n, __s.size() - __pos)); 1154*f8a1b7d9SAlexander Kabaev for (size_t __i = __nbits; __i > 0; --__i) 115500db7afdSDavid E. O'Brien { 1156*f8a1b7d9SAlexander Kabaev switch(__s[__pos + __nbits - __i]) 115700db7afdSDavid E. O'Brien { 115800db7afdSDavid E. O'Brien case '0': 115900db7afdSDavid E. O'Brien break; 116000db7afdSDavid E. O'Brien case '1': 1161*f8a1b7d9SAlexander Kabaev _Unchecked_set(__i - 1); 116200db7afdSDavid E. O'Brien break; 116300db7afdSDavid E. O'Brien default: 1164ffeaf689SAlexander Kabaev __throw_invalid_argument(__N("bitset::_M_copy_from_string")); 116500db7afdSDavid E. O'Brien } 116600db7afdSDavid E. O'Brien } 116700db7afdSDavid E. O'Brien } 116800db7afdSDavid E. O'Brien 116900db7afdSDavid E. O'Brien template<size_t _Nb> 117000db7afdSDavid E. O'Brien template<class _CharT, class _Traits, class _Alloc> 117100db7afdSDavid E. O'Brien void 1172*f8a1b7d9SAlexander Kabaev bitset<_Nb>:: 1173*f8a1b7d9SAlexander Kabaev _M_copy_to_string(std::basic_string<_CharT, _Traits, _Alloc>& __s) const 117400db7afdSDavid E. O'Brien { 117500db7afdSDavid E. O'Brien __s.assign(_Nb, '0'); 1176*f8a1b7d9SAlexander Kabaev for (size_t __i = _Nb; __i > 0; --__i) 1177*f8a1b7d9SAlexander Kabaev if (_Unchecked_test(__i - 1)) 1178*f8a1b7d9SAlexander Kabaev __s[_Nb - __i] = '1'; 117900db7afdSDavid E. O'Brien } 118000db7afdSDavid E. O'Brien 118100db7afdSDavid E. O'Brien // 23.3.5.3 bitset operations: 118200db7afdSDavid E. O'Brien //@{ 118300db7afdSDavid E. O'Brien /** 118400db7afdSDavid E. O'Brien * @brief Global bitwise operations on bitsets. 118500db7afdSDavid E. O'Brien * @param x A bitset. 118600db7afdSDavid E. O'Brien * @param y A bitset of the same size as @a x. 118700db7afdSDavid E. O'Brien * @return A new bitset. 118800db7afdSDavid E. O'Brien * 118900db7afdSDavid E. O'Brien * These should be self-explanatory. 119000db7afdSDavid E. O'Brien */ 119100db7afdSDavid E. O'Brien template<size_t _Nb> 119200db7afdSDavid E. O'Brien inline bitset<_Nb> 119300db7afdSDavid E. O'Brien operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) 119400db7afdSDavid E. O'Brien { 119500db7afdSDavid E. O'Brien bitset<_Nb> __result(__x); 119600db7afdSDavid E. O'Brien __result &= __y; 119700db7afdSDavid E. O'Brien return __result; 119800db7afdSDavid E. O'Brien } 119900db7afdSDavid E. O'Brien 120000db7afdSDavid E. O'Brien template<size_t _Nb> 120100db7afdSDavid E. O'Brien inline bitset<_Nb> 120200db7afdSDavid E. O'Brien operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) 120300db7afdSDavid E. O'Brien { 120400db7afdSDavid E. O'Brien bitset<_Nb> __result(__x); 120500db7afdSDavid E. O'Brien __result |= __y; 120600db7afdSDavid E. O'Brien return __result; 120700db7afdSDavid E. O'Brien } 120800db7afdSDavid E. O'Brien 120900db7afdSDavid E. O'Brien template <size_t _Nb> 121000db7afdSDavid E. O'Brien inline bitset<_Nb> 121100db7afdSDavid E. O'Brien operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) 121200db7afdSDavid E. O'Brien { 121300db7afdSDavid E. O'Brien bitset<_Nb> __result(__x); 121400db7afdSDavid E. O'Brien __result ^= __y; 121500db7afdSDavid E. O'Brien return __result; 121600db7afdSDavid E. O'Brien } 121700db7afdSDavid E. O'Brien //@} 121800db7afdSDavid E. O'Brien 121900db7afdSDavid E. O'Brien //@{ 122000db7afdSDavid E. O'Brien /** 122100db7afdSDavid E. O'Brien * @brief Global I/O operators for bitsets. 122200db7afdSDavid E. O'Brien * 122300db7afdSDavid E. O'Brien * Direct I/O between streams and bitsets is supported. Output is 122400db7afdSDavid E. O'Brien * straightforward. Input will skip whitespace, only accept '0' and '1' 122500db7afdSDavid E. O'Brien * characters, and will only extract as many digits as the %bitset will 122600db7afdSDavid E. O'Brien * hold. 122700db7afdSDavid E. O'Brien */ 122800db7afdSDavid E. O'Brien template<class _CharT, class _Traits, size_t _Nb> 1229*f8a1b7d9SAlexander Kabaev std::basic_istream<_CharT, _Traits>& 1230*f8a1b7d9SAlexander Kabaev operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x) 123100db7afdSDavid E. O'Brien { 123200db7afdSDavid E. O'Brien typedef typename _Traits::char_type char_type; 1233*f8a1b7d9SAlexander Kabaev std::basic_string<_CharT, _Traits> __tmp; 123400db7afdSDavid E. O'Brien __tmp.reserve(_Nb); 123500db7afdSDavid E. O'Brien 1236*f8a1b7d9SAlexander Kabaev std::ios_base::iostate __state = std::ios_base::goodbit; 1237*f8a1b7d9SAlexander Kabaev typename std::basic_istream<_CharT, _Traits>::sentry __sentry(__is); 123800db7afdSDavid E. O'Brien if (__sentry) 123900db7afdSDavid E. O'Brien { 1240ffeaf689SAlexander Kabaev try 1241ffeaf689SAlexander Kabaev { 124200db7afdSDavid E. O'Brien basic_streambuf<_CharT, _Traits>* __buf = __is.rdbuf(); 1243ffeaf689SAlexander Kabaev // _GLIBCXX_RESOLVE_LIB_DEFECTS 1244ffeaf689SAlexander Kabaev // 303. Bitset input operator underspecified 1245ffeaf689SAlexander Kabaev const char_type __zero = __is.widen('0'); 1246ffeaf689SAlexander Kabaev const char_type __one = __is.widen('1'); 1247*f8a1b7d9SAlexander Kabaev for (size_t __i = _Nb; __i > 0; --__i) 124800db7afdSDavid E. O'Brien { 124900db7afdSDavid E. O'Brien static typename _Traits::int_type __eof = _Traits::eof(); 125000db7afdSDavid E. O'Brien 125100db7afdSDavid E. O'Brien typename _Traits::int_type __c1 = __buf->sbumpc(); 125200db7afdSDavid E. O'Brien if (_Traits::eq_int_type(__c1, __eof)) 125300db7afdSDavid E. O'Brien { 1254*f8a1b7d9SAlexander Kabaev __state |= std::ios_base::eofbit; 125500db7afdSDavid E. O'Brien break; 125600db7afdSDavid E. O'Brien } 125700db7afdSDavid E. O'Brien else 125800db7afdSDavid E. O'Brien { 1259*f8a1b7d9SAlexander Kabaev const char_type __c2 = _Traits::to_char_type(__c1); 1260ffeaf689SAlexander Kabaev if (__c2 == __zero) 1261ffeaf689SAlexander Kabaev __tmp.push_back('0'); 1262ffeaf689SAlexander Kabaev else if (__c2 == __one) 1263ffeaf689SAlexander Kabaev __tmp.push_back('1'); 1264ffeaf689SAlexander Kabaev else if (_Traits::eq_int_type(__buf->sputbackc(__c2), 1265ffeaf689SAlexander Kabaev __eof)) 126600db7afdSDavid E. O'Brien { 1267*f8a1b7d9SAlexander Kabaev __state |= std::ios_base::failbit; 126800db7afdSDavid E. O'Brien break; 126900db7afdSDavid E. O'Brien } 127000db7afdSDavid E. O'Brien } 127100db7afdSDavid E. O'Brien } 1272ffeaf689SAlexander Kabaev } 1273ffeaf689SAlexander Kabaev catch(...) 1274*f8a1b7d9SAlexander Kabaev { __is._M_setstate(std::ios_base::badbit); } 1275ffeaf689SAlexander Kabaev } 127600db7afdSDavid E. O'Brien 1277ffeaf689SAlexander Kabaev if (__tmp.empty() && _Nb) 1278*f8a1b7d9SAlexander Kabaev __state |= std::ios_base::failbit; 127900db7afdSDavid E. O'Brien else 128000db7afdSDavid E. O'Brien __x._M_copy_from_string(__tmp, static_cast<size_t>(0), _Nb); 1281ffeaf689SAlexander Kabaev if (__state) 1282ffeaf689SAlexander Kabaev __is.setstate(__state); 128300db7afdSDavid E. O'Brien return __is; 128400db7afdSDavid E. O'Brien } 128500db7afdSDavid E. O'Brien 128600db7afdSDavid E. O'Brien template <class _CharT, class _Traits, size_t _Nb> 1287*f8a1b7d9SAlexander Kabaev std::basic_ostream<_CharT, _Traits>& 1288*f8a1b7d9SAlexander Kabaev operator<<(std::basic_ostream<_CharT, _Traits>& __os, 1289*f8a1b7d9SAlexander Kabaev const bitset<_Nb>& __x) 129000db7afdSDavid E. O'Brien { 1291*f8a1b7d9SAlexander Kabaev std::basic_string<_CharT, _Traits> __tmp; 129200db7afdSDavid E. O'Brien __x._M_copy_to_string(__tmp); 129300db7afdSDavid E. O'Brien return __os << __tmp; 129400db7afdSDavid E. O'Brien } 1295*f8a1b7d9SAlexander Kabaev 1296*f8a1b7d9SAlexander Kabaev // Specializations for zero-sized bitsets, to avoid "unsigned comparison 1297*f8a1b7d9SAlexander Kabaev // with zero" warnings. 1298*f8a1b7d9SAlexander Kabaev template<> 1299*f8a1b7d9SAlexander Kabaev inline bitset<0>& 1300*f8a1b7d9SAlexander Kabaev bitset<0>:: 1301*f8a1b7d9SAlexander Kabaev set(size_t, bool) 1302*f8a1b7d9SAlexander Kabaev { 1303*f8a1b7d9SAlexander Kabaev __throw_out_of_range(__N("bitset::set")); 1304*f8a1b7d9SAlexander Kabaev return *this; 1305*f8a1b7d9SAlexander Kabaev } 1306*f8a1b7d9SAlexander Kabaev 1307*f8a1b7d9SAlexander Kabaev template<> 1308*f8a1b7d9SAlexander Kabaev inline bitset<0>& 1309*f8a1b7d9SAlexander Kabaev bitset<0>:: 1310*f8a1b7d9SAlexander Kabaev reset(size_t) 1311*f8a1b7d9SAlexander Kabaev { 1312*f8a1b7d9SAlexander Kabaev __throw_out_of_range(__N("bitset::reset")); 1313*f8a1b7d9SAlexander Kabaev return *this; 1314*f8a1b7d9SAlexander Kabaev } 1315*f8a1b7d9SAlexander Kabaev 1316*f8a1b7d9SAlexander Kabaev template<> 1317*f8a1b7d9SAlexander Kabaev inline bitset<0>& 1318*f8a1b7d9SAlexander Kabaev bitset<0>:: 1319*f8a1b7d9SAlexander Kabaev flip(size_t) 1320*f8a1b7d9SAlexander Kabaev { 1321*f8a1b7d9SAlexander Kabaev __throw_out_of_range(__N("bitset::flip")); 1322*f8a1b7d9SAlexander Kabaev return *this; 1323*f8a1b7d9SAlexander Kabaev } 1324*f8a1b7d9SAlexander Kabaev 1325*f8a1b7d9SAlexander Kabaev template<> 1326*f8a1b7d9SAlexander Kabaev inline bool 1327*f8a1b7d9SAlexander Kabaev bitset<0>:: 1328*f8a1b7d9SAlexander Kabaev test(size_t) const 1329*f8a1b7d9SAlexander Kabaev { 1330*f8a1b7d9SAlexander Kabaev __throw_out_of_range(__N("bitset::test")); 1331*f8a1b7d9SAlexander Kabaev return false; 1332*f8a1b7d9SAlexander Kabaev } 133300db7afdSDavid E. O'Brien //@} 1334*f8a1b7d9SAlexander Kabaev 1335*f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NESTED_NAMESPACE 133600db7afdSDavid E. O'Brien 1337ffeaf689SAlexander Kabaev #undef _GLIBCXX_BITSET_WORDS 1338ffeaf689SAlexander Kabaev #undef _GLIBCXX_BITSET_BITS_PER_WORD 133900db7afdSDavid E. O'Brien 1340ffeaf689SAlexander Kabaev #ifdef _GLIBCXX_DEBUG 1341ffeaf689SAlexander Kabaev # include <debug/bitset> 1342ffeaf689SAlexander Kabaev #endif 1343ffeaf689SAlexander Kabaev 1344ffeaf689SAlexander Kabaev #endif /* _GLIBCXX_BITSET */ 1345