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