iLand
bitset.h
Go to the documentation of this file.
1// bitset standard header
2#pragma once
3#ifndef _BITSET_
4#define _BITSET_
5#ifndef RC_INVOKED
6#include <string>
7#include <iosfwd>
8
9 #pragma pack(push,_CRT_PACKING)
10 #pragma warning(push,3)
11 #pragma push_macro("new")
12 #undef new
13
14 #pragma warning(disable: 4127)
15
16 #pragma warning(disable: 6294)
17
18_STD_BEGIN
19 // TEMPLATE CLASS bitset
20template<size_t _Bits>
21 class bitset
22 { // store fixed-length sequence of Boolean elements
23public:
24 typedef typename _If<_Bits <= 32, _Uint32t, _ULonglong>::type _Ty;
25
26
27 // CLASS reference
28 class reference
29 { // proxy for an element
30 friend class bitset<_Bits>;
31
32 public:
33 ~reference() _NOEXCEPT
34 { // destroy the object
35 }
36
37 reference& operator=(bool _Val) _NOEXCEPT
38 { // assign Boolean to element
39 _Pbitset->set(_Mypos, _Val);
40 return (*this);
41 }
42
43 reference& operator=(const reference& _Bitref) _NOEXCEPT
44 { // assign reference to element
45 _Pbitset->set(_Mypos, bool(_Bitref));
46 return (*this);
47 }
48
49 reference& flip() _NOEXCEPT
50 { // complement stored element
51 _Pbitset->flip(_Mypos);
52 return (*this);
53 }
54
55 bool operator~() const _NOEXCEPT
56 { // return complemented element
57 return (!_Pbitset->test(_Mypos));
58 }
59
60 operator bool() const _NOEXCEPT
61 { // return element
62 return (_Pbitset->test(_Mypos));
63 }
64
65 private:
66 reference() _NOEXCEPT
67 : _Pbitset(0), _Mypos(0)
68 { // default construct
69 }
70
71 reference(bitset<_Bits>& _Bitset, size_t _Pos)
72 : _Pbitset(&_Bitset), _Mypos(_Pos)
73 { // construct from bitset reference and position
74 }
75
76 bitset<_Bits> *_Pbitset; // pointer to the bitset
77 size_t _Mypos; // position of element in bitset
78 };
79
80 #if _ITERATOR_DEBUG_LEVEL == 2
81 static void _Validate(size_t _Pos)
82 { // verify that _Pos is within bounds
83 if (_Bits <= _Pos)
84 _DEBUG_ERROR("bitset index outside range");
85 }
86
87 #elif _ITERATOR_DEBUG_LEVEL == 1
88 static void _Validate(size_t _Pos)
89 { // verify that _Pos is within bounds
90 _SCL_SECURE_VALIDATE_RANGE(_Pos < _Bits);
91 }
92
93 #else /* _ITERATOR_DEBUG_LEVEL == 2 */
94 static void _Validate(size_t)
95 { // (don't) verify that _Pos is within bounds
96 }
97 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
98
99 constexpr bool _Subscript(size_t _Pos) const
100 { // subscript nonmutable sequence
101 return ((_Array[_Pos / size_t(_Bitsperword)]
102 & ((_Ty)1 << _Pos % _Bitsperword)) != 0);
103 }
104
105 constexpr bool operator[](size_t _Pos) const
106 { // subscript nonmutable sequence
107 #if _ITERATOR_DEBUG_LEVEL == 0
108 return (_Subscript(_Pos));
109
110 #else /* _ITERATOR_DEBUG_LEVEL == 0 */
111 return (_Bits <= _Pos
112 ? (_Validate(_Pos), false)
113 : _Subscript(_Pos));
114 #endif /* _ITERATOR_DEBUG_LEVEL == 0 */
115 }
116
117 reference operator[](size_t _Pos)
118 { // subscript mutable sequence
119 _Validate(_Pos);
120 return (reference(*this, _Pos));
121 }
122
123 constexpr bitset() _NOEXCEPT
124 : _Array()
125 { // construct with all false values
126 }
127
128 static constexpr bool _Need_mask
129 = _Bits < CHAR_BIT * sizeof (_ULonglong);
130
131 static constexpr _ULonglong _Mask
132 = (1ULL << (_Need_mask ? _Bits : 0)) - 1ULL;
133
134 constexpr bitset(_ULonglong _Val) _NOEXCEPT
135 : _Array{static_cast<_Ty>(_Need_mask ? _Val & _Mask : _Val)}
136 { // construct from bits in unsigned long long
137 }
138
139 #define _BITSET_SIZE_TYPE \
140 typename basic_string<_Elem, _Tr, _Alloc>::size_type
141
142 template<class _Elem,
143 class _Tr,
144 class _Alloc>
145 explicit bitset(const basic_string<_Elem, _Tr, _Alloc>& _Str,
146 _BITSET_SIZE_TYPE _Pos = 0,
147 _BITSET_SIZE_TYPE _Count = basic_string<_Elem, _Tr, _Alloc>::npos,
148 _Elem _E0 = (_Elem)'0',
149 _Elem _E1 = (_Elem)'1')
150 { // construct from [_Pos, _Pos + _Count) elements in string
151 _Construct(_Str, _Pos, _Count, _E0, _E1);
152 }
153
154 template<class _Elem>
155 explicit bitset(const _Elem *_Ptr,
156 typename basic_string<_Elem>::size_type _Count =
157 basic_string<_Elem>::npos,
158 _Elem _E0 = (_Elem)'0',
159 _Elem _E1 = (_Elem)'1')
160 { // initialize from NTBS
161 _Construct(
162 _Count == basic_string<_Elem>::npos
163 ? basic_string<_Elem>(_Ptr)
164 : basic_string<_Elem>(_Ptr, _Count),
165 0, _Count, _E0, _E1);
166 }
167
168 template<class _Elem,
169 class _Tr,
170 class _Alloc>
171 void _Construct(
172 const basic_string<_Elem, _Tr, _Alloc>& _Str,
174 _BITSET_SIZE_TYPE _Count,
175 _Elem _E0,
176 _Elem _E1)
177 { // initialize from [_Pos, _Pos + _Count) elements in string
178 if (_Str.size() < _Pos)
179 _Xran(); // _Pos off end
180 if (_Str.size() - _Pos < _Count)
181 _Count = _Str.size() - _Pos; // trim _Count to size
182
183 typename basic_string<_Elem, _Tr, _Alloc>::size_type _Num;
184 for (_Num = 0; _Num < _Count; ++_Num)
185 if (!_Tr::eq(_Str[_Pos + _Num], _E0)
186 && !_Tr::eq(_Str[_Pos + _Num], _E1))
187 _Xinv();
188
189 if (_Bits < _Count)
190 _Count = _Bits; // trim _Count to length of bitset
191 _Tidy();
192
193 for (_Pos += _Count, _Num = 0; _Num < _Count; ++_Num)
194 if (_Tr::eq(_Str[--_Pos], _E1))
195 set(_Num);
196 }
197
198 bitset& operator&=(const bitset& _Right) _NOEXCEPT
199 { // AND in _Right
200 for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos)
201 _Array[_Wpos] &= _Right._Getword(_Wpos);
202 return (*this);
203 }
204
205 bitset& operator|=(const bitset& _Right) _NOEXCEPT
206 { // OR in _Right
207 for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos)
208 _Array[_Wpos] |= _Right._Getword(_Wpos);
209 return (*this);
210 }
211
212 bitset& operator^=(const bitset& _Right) _NOEXCEPT
213 { // XOR in _Right
214 for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos)
215 _Array[_Wpos] ^= _Right._Getword(_Wpos);
216 return (*this);
217 }
218
219 bitset& operator<<=(size_t _Pos) _NOEXCEPT
220 { // shift left by _Pos
221 const ptrdiff_t _Wordshift = (ptrdiff_t)(_Pos / _Bitsperword);
222 if (_Wordshift != 0)
223 for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos)
224 _Array[_Wpos] = _Wordshift <= _Wpos // shift by words
225 ? _Array[_Wpos - _Wordshift] : (_Ty)0;
226
227 if ((_Pos %= _Bitsperword) != 0)
228 { // 0 < _Pos < _Bitsperword, shift by bits
229 for (ptrdiff_t _Wpos = _Words; 0 < _Wpos; --_Wpos)
230 _Array[_Wpos] = (_Ty)((_Array[_Wpos] << _Pos)
231 | (_Array[_Wpos - 1] >> (_Bitsperword - _Pos)));
232 _Array[0] <<= _Pos;
233 }
234 _Trim();
235 return (*this);
236 }
237
238 bitset& operator>>=(size_t _Pos) _NOEXCEPT
239 { // shift right by _Pos, first by words then by bits
240 const ptrdiff_t _Wordshift = (ptrdiff_t)(_Pos / _Bitsperword);
241 if (_Wordshift != 0)
242 for (ptrdiff_t _Wpos = 0; _Wpos <= _Words; ++_Wpos)
243 _Array[_Wpos] = _Wordshift <= _Words - _Wpos
244 ? _Array[_Wpos + _Wordshift] : (_Ty)0;
245
246 if ((_Pos %= _Bitsperword) != 0)
247 { // 0 < _Pos < _Bitsperword, shift by bits
248 for (ptrdiff_t _Wpos = 0; _Wpos < _Words; ++_Wpos)
249 _Array[_Wpos] = (_Ty)((_Array[_Wpos] >> _Pos)
250 | (_Array[_Wpos + 1] << (_Bitsperword - _Pos)));
251 _Array[_Words] >>= _Pos;
252 }
253 return (*this);
254 }
255
256 bitset& set() _NOEXCEPT
257 { // set all bits true
258 _Tidy((_Ty)~0);
259 return (*this);
260 }
261
262 bitset& set(size_t _Pos,
263 bool _Val = true)
264 { // set bit at _Pos to _Val
265 if (_Bits <= _Pos)
266 _Xran(); // _Pos off end
267 if (_Val)
268 _Array[_Pos / size_t(_Bitsperword)] |= (_Ty)1 << _Pos % _Bitsperword;
269 else
270 _Array[_Pos / size_t(_Bitsperword)] &= ~((_Ty)1 << _Pos % _Bitsperword);
271 return (*this);
272 }
273
274 bitset& reset() _NOEXCEPT
275 { // set all bits false
276 _Tidy();
277 return (*this);
278 }
279
280 bitset& reset(size_t _Pos)
281 { // set bit at _Pos to false
282 return (set(_Pos, false));
283 }
284
285 bitset operator~() const _NOEXCEPT
286 { // flip all bits
287 return (bitset(*this).flip());
288 }
289
290 bitset& flip() _NOEXCEPT
291 { // flip all bits
292 for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos)
293 _Array[_Wpos] = (_Ty)~_Array[_Wpos];
294
295 _Trim();
296 return (*this);
297 }
298
299 bitset& flip(size_t _Pos)
300 { // flip bit at _Pos
301 if (_Bits <= _Pos)
302 _Xran(); // _Pos off end
303 _Array[_Pos / _Bitsperword] ^= (_Ty)1 << _Pos % _Bitsperword;
304 return (*this);
305 }
306
307 unsigned long to_ulong() const
308 { // convert bitset to unsigned long
309 _ULonglong _Val = to_ullong();
310 unsigned long _Ans = (unsigned long)_Val;
311 if (_Ans != _Val)
312 _Xoflo();
313 return (_Ans);
314 }
315
316 _ULonglong to_ullong() const
317 { // convert bitset to unsigned long long
318 static_assert(sizeof (_ULonglong) % sizeof (_Ty) == 0,
319 "unsigned long long not multiple of _Ty");
320
321 ptrdiff_t _Wpos = _Words;
322 for (; (ptrdiff_t)(sizeof (_ULonglong) / sizeof (_Ty)) <= _Wpos;
323 --_Wpos)
324 if (_Array[_Wpos] != 0)
325 _Xoflo(); // fail if any high-order words are nonzero
326
327 _ULonglong _Val = _Array[_Wpos];
328 for (; 0 <= --_Wpos; )
329 _Val = ((_Val << (_Bitsperword - 1)) << 1) | _Array[_Wpos];
330 return (_Val);
331 }
332
333 template<class _Elem = char,
334 class _Tr = char_traits<_Elem>,
335 class _Alloc = allocator<_Elem> >
336 basic_string<_Elem, _Tr, _Alloc>
337 to_string(_Elem _E0 = (_Elem)'0',
338 _Elem _E1 = (_Elem)'1') const
339 { // convert bitset to string
340 basic_string<_Elem, _Tr, _Alloc> _Str;
341 typename basic_string<_Elem, _Tr, _Alloc>::size_type _Pos;
342 _Str.reserve(_Bits);
343
344 for (_Pos = _Bits; 0 < _Pos; )
345 if (test(--_Pos))
346 _Str += _E1;
347 else
348 _Str += _E0;
349 return (_Str);
350 }
351
352 size_t count() const _NOEXCEPT
353 { // count number of set bits
354 const char *const _Bitsperbyte =
355 "\0\1\1\2\1\2\2\3\1\2\2\3\2\3\3\4"
356 "\1\2\2\3\2\3\3\4\2\3\3\4\3\4\4\5"
357 "\1\2\2\3\2\3\3\4\2\3\3\4\3\4\4\5"
358 "\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
359 "\1\2\2\3\2\3\3\4\2\3\3\4\3\4\4\5"
360 "\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
361 "\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
362 "\3\4\4\5\4\5\5\6\4\5\5\6\5\6\6\7"
363 "\1\2\2\3\2\3\3\4\2\3\3\4\3\4\4\5"
364 "\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
365 "\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
366 "\3\4\4\5\4\5\5\6\4\5\5\6\5\6\6\7"
367 "\2\3\3\4\3\4\4\5\3\4\4\5\4\5\5\6"
368 "\3\4\4\5\4\5\5\6\4\5\5\6\5\6\6\7"
369 "\3\4\4\5\4\5\5\6\4\5\5\6\5\6\6\7"
370 "\4\5\5\6\5\6\6\7\5\6\6\7\6\7\7\x8";
371 const unsigned char *_Ptr =
372 (const unsigned char *)(const void *)_Array;
373 const unsigned char *const _End = _Ptr + sizeof (_Array);
374 size_t _Val = 0;
375 for ( ; _Ptr != _End; ++_Ptr)
376 _Val += _Bitsperbyte[*_Ptr];
377 return (_Val);
378 }
379
380 constexpr size_t size() const _NOEXCEPT
381 { // return size of bitset
382 return (_Bits);
383 }
384
385 size_t hash() const
386 { // hash bits to size_t value by pseudorandomizing transform
387 return (_Hash_seq((const unsigned char *)_Array,
388 sizeof (_Array)));
389 }
390
391 bool operator==(const bitset& _Right) const _NOEXCEPT
392 { // test for bitset equality
393 for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos)
394 if (_Array[_Wpos] != _Right._Getword(_Wpos))
395 return (false);
396 return (true);
397 }
398
399 bool operator!=(const bitset& _Right) const _NOEXCEPT
400 { // test for bitset inequality
401 return (!(*this == _Right));
402 }
403
404 bool test(size_t _Pos) const
405 { // test if bit at _Pos is set
406 if (_Bits <= _Pos)
407 _Xran(); // _Pos off end
408 return (_Subscript(_Pos));
409 }
410
411 bool any() const _NOEXCEPT
412 { // test if any bits are set
413 for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos)
414 if (_Array[_Wpos] != 0)
415 return (true);
416 return (false);
417 }
418
419 bool none() const _NOEXCEPT
420 { // test if no bits are set
421 return (!any());
422 }
423
424 bool all() const _NOEXCEPT
425 { // test if all bits set
426 return (count() == size());
427 }
428
429 bitset operator<<(size_t _Pos) const _NOEXCEPT
430 { // return bitset shifted left by _Pos
431 return (bitset(*this) <<= _Pos);
432 }
433
434 bitset operator>>(size_t _Pos) const _NOEXCEPT
435 { // return bitset shifted right by _Pos
436 return (bitset(*this) >>= _Pos);
437 }
438
439 _Ty _Getword(size_t _Wpos) const
440 { // get word at _Wpos
441 return (_Array[_Wpos]);
442 }
443
444private:
445 enum : ptrdiff_t
446
447 { // parameters for packing bits into words
448 _Bitsperword = (ptrdiff_t)(CHAR_BIT * sizeof (_Ty)),
449 _Words = (ptrdiff_t)(_Bits == 0
450 ? 0 : (_Bits - 1) / _Bitsperword)}; // NB: number of words - 1
451
452 void _Tidy(_Ty _Wordval = 0)
453 { // set all words to _Wordval
454 for (ptrdiff_t _Wpos = _Words; 0 <= _Wpos; --_Wpos)
455 _Array[_Wpos] = _Wordval;
456 if (_Wordval != 0)
457 _Trim();
458 }
459
460 void _Trim()
461 { // clear any trailing bits in last word
462 _Trim_if(bool_constant<_Bits == 0 || _Bits % _Bitsperword != 0>());
463 }
464
465 void _Trim_if(true_type)
466 { // bits to trim, remove them
467 _Array[_Words] &= ((_Ty)1 << _Bits % _Bitsperword) - 1;
468 }
469
470 void _Trim_if(false_type)
471 { // no bits to trim, do nothing
472 }
473
474 [[noreturn]] void _Xinv() const
475 { // report invalid string element in bitset conversion
476 _Xinvalid_argument("invalid bitset<N> char");
477 }
478
479 [[noreturn]] void _Xoflo() const
480 { // report converted value too big to represent
481 _Xoverflow_error("bitset<N> overflow");
482 }
483
484 [[noreturn]] void _Xran() const
485 { // report bit index out of range
486 _Xout_of_range("invalid bitset<N> position");
487 }
488
489 _Ty _Array[_Words + 1]; // the set of bits
490 };
491
492 // bitset TEMPLATE FUNCTIONS
493template<size_t _Bits> inline
495 const bitset<_Bits>& _Right) _NOEXCEPT
496 { // return bitset _Left AND _Right
497 bitset<_Bits> _Ans = _Left;
498 return (_Ans &= _Right);
499 }
500
501template<size_t _Bits> inline
503 const bitset<_Bits>& _Right) _NOEXCEPT
504 { // return bitset _Left OR _Right
505 bitset<_Bits> _Ans = _Left;
506 return (_Ans |= _Right);
507 }
508
509template<size_t _Bits> inline
511 const bitset<_Bits>& _Right) _NOEXCEPT
512 { // return bitset _Left XOR _Right
513 bitset<_Bits> _Ans = _Left;
514 return (_Ans ^= _Right);
515 }
516
517template<class _Elem,
518 class _Tr,
519 size_t _Bits> inline
520 basic_ostream<_Elem, _Tr>& operator<<(
521 basic_ostream<_Elem, _Tr>& _Ostr, const bitset<_Bits>& _Right)
522 { // insert bitset as a string
523 const ctype<_Elem>& _Ctype_fac = _USE(_Ostr.getloc(), ctype<_Elem>);
524 const _Elem _E0 = _Ctype_fac.widen('0');
525 const _Elem _E1 = _Ctype_fac.widen('1');
526
527 return (_Ostr
528 << _Right.template to_string<_Elem, _Tr, allocator<_Elem> >(
529 _E0, _E1));
530 }
531
532 // TEMPLATE operator>>
533template<class _Elem,
534 class _Tr,
535 size_t _Bits> inline
536 basic_istream<_Elem, _Tr>& operator>>(
537 basic_istream<_Elem, _Tr>& _Istr, bitset<_Bits>& _Right)
538 { // extract bitset as a string
539 const ctype<_Elem>& _Ctype_fac = _USE(_Istr.getloc(), ctype<_Elem>);
540 const _Elem _E0 = _Ctype_fac.widen('0');
541 const _Elem _E1 = _Ctype_fac.widen('1');
542 ios_base::iostate _State = ios_base::goodbit;
543 bool _Changed = false;
544 string _Str;
545 const typename basic_istream<_Elem, _Tr>::sentry _Ok(_Istr);
546
547 if (_Ok)
548 { // valid stream, extract elements
549 _TRY_IO_BEGIN
550 typename _Tr::int_type _Meta = _Istr.rdbuf()->sgetc();
551 for (size_t _Count = _Right.size(); 0 < _Count;
552 _Meta = _Istr.rdbuf()->snextc(), --_Count)
553 { // test _Meta
554 _Elem _Char;
555 if (_Tr::eq_int_type(_Tr::eof(), _Meta))
556 { // end of file, quit
557 _State |= ios_base::eofbit;
558 break;
559 }
560 else if ((_Char = _Tr::to_char_type(_Meta)) != _E0
561 && _Char != _E1)
562 break; // invalid element
563 else if (_Str.max_size() <= _Str.size())
564 { // no room in string, give up (unlikely)
565 _State |= ios_base::failbit;
566 break;
567 }
568 else
569 { // valid, append '0' or '1'
570 if (_Char == _E1)
571 _Str.append(1, '1');
572 else
573 _Str.append(1, '0');
574 _Changed = true;
575 }
576 }
577 _CATCH_IO_(_Istr)
578 }
579
580 if (!_Changed)
581 _State |= ios_base::failbit;
582 _Istr.setstate(_State);
583 _Right = bitset<_Bits>(_Str); // convert string and store
584 return (_Istr);
585 }
586
587 // TEMPLATE STRUCT SPECIALIZATION hash
588template<size_t _Bits>
589 struct hash<bitset<_Bits> >
590 { // hash functor for bitset<_Bits>
592 typedef size_t result_type;
593
594 size_t operator()(const argument_type& _Keyval) const
595 { // hash _Keyval to size_t value by pseudorandomizing transform
596 return (_Keyval.hash());
597 }
598 };
599_STD_END
600
601 #pragma pop_macro("new")
602 #pragma warning(pop)
603 #pragma pack(pop)
604#endif /* RC_INVOKED */
605#endif /* _BITSET_ */
606
607/*
608 * Copyright (c) by P.J. Plauger. All rights reserved.
609 * Consult your license regarding permissions and restrictions.
610V6.50:0009 */
#define _BITSET_SIZE_TYPE
Definition: bitset.h:139
bitset< _Bits > operator|(const bitset< _Bits > &_Left, const bitset< _Bits > &_Right) _NOEXCEPT
Definition: bitset.h:502
basic_istream< _Elem, _Tr > & operator>>(basic_istream< _Elem, _Tr > &_Istr, bitset< _Bits > &_Right)
Definition: bitset.h:536
basic_ostream< _Elem, _Tr > & operator<<(basic_ostream< _Elem, _Tr > &_Ostr, const bitset< _Bits > &_Right)
Definition: bitset.h:520
bitset< _Bits > operator&(const bitset< _Bits > &_Left, const bitset< _Bits > &_Right) _NOEXCEPT
Definition: bitset.h:494
bitset< _Bits > operator^(const bitset< _Bits > &_Left, const bitset< _Bits > &_Right) _NOEXCEPT
Definition: bitset.h:510
Definition: bitset.h:22
bool operator~() const _NOEXCEPT
Definition: bitset.h:55
reference & operator=(const reference &_Bitref) _NOEXCEPT
Definition: bitset.h:43
reference & flip() _NOEXCEPT
Definition: bitset.h:49
_If< _Bits<=32, _Uint32t, _ULonglong >::type _Ty;class reference { friend class bitset< _Bits >;public:~reference() _NOEXCEPT { } reference &operator=(bool _Val) _NOEXCEPT { _Pbitset-> set(_Mypos, _Val)
Definition: bitset.h:39
size_t result_type
Definition: bitset.h:592
bitset< _Bits > argument_type
Definition: bitset.h:591
size_t operator()(const argument_type &_Keyval) const
Definition: bitset.h:594