]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/dynamic_bitset/test/bitset_test.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / dynamic_bitset / test / bitset_test.hpp
CommitLineData
7c673cae
FG
1// -----------------------------------------------------------
2// Copyright (c) 2001 Jeremy Siek
3// Copyright (c) 2003-2006, 2008 Gennaro Prota
4// Copyright (c) 2014 Ahmed Charles
5// Copyright (c) 2014 Riccardo Marcangelo
6//
7// Distributed under the Boost Software License, Version 1.0.
8// (See accompanying file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10//
11// -----------------------------------------------------------
12
13#ifndef BOOST_BITSET_TEST_HPP_GP_20040319
14#define BOOST_BITSET_TEST_HPP_GP_20040319
15
16#include "boost/config.hpp"
17#if !defined (BOOST_NO_STD_LOCALE)
18# include <locale>
19#endif
20
21#include <vector>
22#include <fstream> // used for operator<<
23#include <string> // for (basic_string and) getline()
24#include <algorithm> // for std::min
25#include <assert.h> // <cassert> is sometimes macro-guarded :-(
26
27#include "boost/limits.hpp"
28#include "boost/dynamic_bitset/dynamic_bitset.hpp"
29#include "boost/test/minimal.hpp"
30
31
32template <typename Block>
33inline bool nth_bit(Block num, std::size_t n)
34{
35#ifdef __BORLANDC__
36 // Borland deduces Block as a const qualified type,
37 // and thus finds numeric_limits<Block> to be zero :(
38 // (though not directly relevant here, see also
39 // lib issue 559)
40 int block_width = sizeof(Block) * CHAR_BIT;
41#else
42 int block_width = std::numeric_limits<Block>::digits;
43#endif
44
45 assert(n < (std::size_t) block_width);
46 return (num >> n) & 1;
47}
48
49// A long, 'irregular', string useful for various tests
50std::string get_long_string()
51{
52 const char * const p =
53 // 6 5 4 3 2 1
54 // 3210987654321098765432109876543210987654321098765432109876543210
55 "1110011100011110000011110000011111110000000000000110101110000000"
56 "1010101000011100011101010111110000101011111000001111100011100011"
57 "0000000110000001000000111100000111100010101111111000000011100011"
58 "1111111111111111111111111111111111111111111111111111111111111100"
59 "1000001100000001111111111111110000000011111000111100001010100000"
60 "101000111100011010101110011011000000010";
61
62 return std::string(p);
63}
64
65const char * test_file_name()
66{
67 return "boost_dynamic_bitset_tests";
68}
69
70#if defined BOOST_OLD_IOSTREAMS || defined BOOST_NO_STD_LOCALE
71template <typename Stream>
72bool is_one_or_zero(const Stream & /*s*/, char c)
73{
74 return c == '1' || c == '0';
75}
76template <typename Stream>
77bool is_white_space(const Stream & /*s*/, char c)
78{
79 return std::isspace(c);
80}
81#else
82template <typename Stream, typename Ch>
83bool is_one_or_zero(const Stream& s, Ch c)
84{
85 typedef typename Stream::traits_type Tr;
86 const Ch zero = s.widen('0');
87 const Ch one = s.widen('1');
88
89 return Tr::eq(c, one) || Tr::eq(c, zero);
90}
91template <typename Stream, typename Ch>
92bool is_white_space(const Stream & s, Ch c)
93{
94 // NOTE: the using directive is to satisfy Borland 5.6.4
95 // with its own library (STLport), which doesn't
96 // like std::isspace(c, loc)
97 using namespace std;
98 return isspace(c, s.getloc());
99}
100#endif // defined BOOST_OLD_IOSTREAMS
101
102
103template <typename Stream>
104bool has_flags(const Stream& s, std::ios::iostate flags)
105{
106 return (s.rdstate() & flags) != std::ios::goodbit;
107}
108
109
110// constructors
111// default (can't do this generically)
112
113template <typename Bitset>
114struct bitset_test {
115
116 typedef typename Bitset::block_type Block;
117 BOOST_STATIC_CONSTANT(int, bits_per_block = Bitset::bits_per_block);
118
119 // from unsigned long
120 //
121 // Note: this is templatized so that we check that the do-the-right-thing
122 // constructor dispatch is working correctly.
123 //
124 template <typename NumBits, typename Value>
125 static void from_unsigned_long(NumBits num_bits, Value num)
126 {
127 // An object of size sz = num_bits is constructed:
128 // - the first m bit positions are initialized to the corresponding
129 // bit values in num (m being the smaller of sz and ulong_width)
130 //
131 // - any remaining bit positions are initialized to zero
132 //
133
134 Bitset b(static_cast<typename Bitset::size_type>(num_bits), static_cast<unsigned long>(num));
135
136 // OK, we can now cast to size_type
137 typedef typename Bitset::size_type size_type;
138 const size_type sz = static_cast<size_type>(num_bits);
139
140 BOOST_CHECK(b.size() == sz);
141
142 const std::size_t ulong_width = std::numeric_limits<unsigned long>::digits;
143 size_type m = sz;
144 if (ulong_width < sz)
145 m = ulong_width;
146
147 size_type i = 0;
148 for ( ; i < m; ++i)
149 BOOST_CHECK(b.test(i) == nth_bit(static_cast<unsigned long>(num), i));
150 for ( ; i < sz; ++i)
151 BOOST_CHECK(b.test(i) == 0);
152 }
153
154 // from string
155 //
156 // Note: The corresponding function in dynamic_bitset (constructor
157 // from a string) has several default arguments. Actually we don't
158 // test the correct working of those defaults here (except for the
159 // default of num_bits). I'm not sure what to do in this regard.
160 //
161 // Note2: the default argument expression for num_bits doesn't use
162 // static_cast, to avoid a gcc 2.95.3 'sorry, not implemented'
163 //
164 template <typename Ch, typename Tr, typename Al>
165 static void from_string(const std::basic_string<Ch, Tr, Al>& str,
166 std::size_t pos,
167 std::size_t max_char,
168 std::size_t num_bits = (std::size_t)(-1))
169 {
170
171 std::size_t rlen = (std::min)(max_char, str.size() - pos);
172
173 // The resulting size N of the bitset is num_bits, if
174 // that is different from the default arg, rlen otherwise.
175 // Put M = the smaller of N and rlen, then character
176 // position pos + M - 1 corresponds to bit position zero.
177 // Subsequent decreasing character positions correspond to
178 // increasing bit positions.
179
180 const bool size_upon_string = num_bits == (std::size_t)(-1);
181 Bitset b = size_upon_string ?
182 Bitset(str, pos, max_char)
183 : Bitset(str, pos, max_char, num_bits);
184
185 const std::size_t actual_size = size_upon_string? rlen : num_bits;
186 BOOST_CHECK(b.size() == actual_size);
187 std::size_t m = (std::min)(num_bits, rlen);
188 std::size_t j;
189 for (j = 0; j < m; ++j)
190 BOOST_CHECK(b[j] == (str[pos + m - 1 - j] == '1'));
191 // If M < N, remaining bit positions are zero
192 for (; j < actual_size; ++j)
193 BOOST_CHECK(b[j] == 0);
194
195
196 }
197
198 static void to_block_range(const Bitset & b /*, BlockOutputIterator result*/)
199 {
200 typedef typename Bitset::size_type size_type;
201
202 Block sentinel = 0xF0;
203 int s = 8; // number of sentinels (must be *even*)
204 int offset = s/2;
205 std::vector<Block> v(b.num_blocks() + s, sentinel);
206
207 boost::to_block_range(b, v.begin() + offset);
208
209 assert(v.size() >= (size_type)s && (s >= 2) && (s % 2 == 0));
210 // check sentinels at both ends
211 for(int i = 0; i < s/2; ++i) {
212 BOOST_CHECK(v[i] == sentinel);
213 BOOST_CHECK(v[v.size()-1-i] == sentinel);
214 }
215
216 typename std::vector<Block>::const_iterator p = v.begin() + offset;
217 for(size_type n = 0; n < b.num_blocks(); ++n, ++p) {
218 typename Bitset::block_width_type i = 0;
219 for(; i < bits_per_block; ++i) {
220 size_type bit = n * bits_per_block + i;
221 BOOST_CHECK(nth_bit(*p, i) == (bit < b.size()? b[bit] : 0));
222 }
223 }
224 }
225
226 // TODO from_block_range (below) should be splitted
227
228 // PRE: std::equal(first1, last1, first2) == true
229 static void from_block_range(const std::vector<Block>& blocks)
230 {
231 { // test constructor from block range
232 Bitset bset(blocks.begin(), blocks.end());
233 std::size_t n = blocks.size();
234 for (std::size_t b = 0; b < n; ++b) {
235 typename Bitset::block_width_type i = 0;
236 for (; i < bits_per_block; ++i) {
237 std::size_t bit = b * bits_per_block + i;
238 BOOST_CHECK(bset[bit] == nth_bit(blocks[b], i));
239 }
240 }
241 BOOST_CHECK(bset.size() == n * bits_per_block);
242 }
243 { // test boost::from_block_range
244 const typename Bitset::size_type n = blocks.size();
245 Bitset bset(n * bits_per_block);
246 boost::from_block_range(blocks.begin(), blocks.end(), bset);
247 for (std::size_t b = 0; b < n; ++b) {
248 typename Bitset::block_width_type i = 0;
249 for (; i < bits_per_block; ++i) {
250 std::size_t bit = b * bits_per_block + i;
251 BOOST_CHECK(bset[bit] == nth_bit(blocks[b], i));
252 }
253 }
254 BOOST_CHECK(n <= bset.num_blocks());
255 }
256 }
257
258 // copy constructor (absent from std::bitset)
259 static void copy_constructor(const Bitset& b)
260 {
261 Bitset copy(b);
262 BOOST_CHECK(b == copy);
263
264 // Changes to the copy do not affect the original
265 if (b.size() > 0) {
266 std::size_t pos = copy.size() / 2;
267 copy.flip(pos);
268 BOOST_CHECK(copy[pos] != b[pos]);
269 }
270 }
271
272 // copy assignment operator (absent from std::bitset)
273 static void copy_assignment_operator(const Bitset& lhs, const Bitset& rhs)
274 {
275 Bitset b(lhs);
276 b = rhs;
277 b = b; // self assignment check
278 BOOST_CHECK(b == rhs);
279
280 // Changes to the copy do not affect the original
281 if (b.size() > 0) {
282 std::size_t pos = b.size() / 2;
283 b.flip(pos);
284 BOOST_CHECK(b[pos] != rhs[pos]);
285 }
286 }
287
288 static void max_size(const Bitset& b)
289 {
290 BOOST_CHECK(b.max_size() > 0);
291 }
292
293#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
294
295 // move constructor (absent from std::bitset)
296 static void move_constructor(const Bitset& b)
297 {
298 Bitset copy(boost::move(b));
299 BOOST_CHECK(b == copy);
300 }
301
302 // move assignment operator (absent from std::bitset)
303 static void move_assignment_operator(const Bitset& lhs, const Bitset& rhs)
304 {
305 Bitset b(lhs);
306 Bitset c(rhs);
307 b = boost::move(c);
308 b = boost::move(b); // self assignment check
309 BOOST_CHECK(b == rhs);
310 }
311
312#endif // BOOST_NO_CXX11_RVALUE_REFERENCES
313
314 static void swap(const Bitset& lhs, const Bitset& rhs)
315 {
316 // bitsets must be swapped
317 Bitset copy1(lhs);
318 Bitset copy2(rhs);
319 copy1.swap(copy2);
320
321 BOOST_CHECK(copy1 == rhs);
322 BOOST_CHECK(copy2 == lhs);
323
324 // references must be stable under a swap
325 for(typename Bitset::size_type i = 0; i < lhs.size(); ++i) {
326 Bitset b1(lhs);
327 Bitset b2(rhs);
328 typename Bitset::reference ref = b1[i];
329 bool x = ref;
330 if (i < b2.size())
331 b2[i] = !x; // make sure b2[i] is different
332 b1.swap(b2);
333 BOOST_CHECK(b2[i] == x); // now it must be equal..
334 b2.flip(i);
335 BOOST_CHECK(ref == b2[i]); // .. and ref must be into b2
336 BOOST_CHECK(ref == !x);
337 }
338
339 }
340
341 static void resize(const Bitset& lhs)
342 {
343 Bitset b(lhs);
344
345 // Test no change in size
346 b.resize(lhs.size());
347 BOOST_CHECK(b == lhs);
348
349 // Test increase in size
350 b.resize(lhs.size() * 2, true);
351
352 std::size_t i;
353 for (i = 0; i < lhs.size(); ++i)
354 BOOST_CHECK(b[i] == lhs[i]);
355 for (; i < b.size(); ++i)
356 BOOST_CHECK(b[i] == true);
357
358 // Test decrease in size
359 b.resize(lhs.size());
360 for (i = 0; i < lhs.size(); ++i)
361 BOOST_CHECK(b[i] == lhs[i]);
362 }
363
364 static void clear(const Bitset& lhs)
365 {
366 Bitset b(lhs);
367 b.clear();
368 BOOST_CHECK(b.size() == 0);
369 }
370
371 static void pop_back(const Bitset& lhs)
372 {
373 Bitset b(lhs);
374 b.pop_back();
375 BOOST_CHECK(b.size() == lhs.size() - 1);
376 for (std::size_t i = 0; i < b.size(); ++i)
377 BOOST_CHECK(b[i] == lhs[i]);
378
379 b.pop_back();
380 BOOST_CHECK(b.size() == lhs.size() - 2);
381 for (std::size_t j = 0; j < b.size(); ++j)
382 BOOST_CHECK(b[j] == lhs[j]);
383 }
384
385 static void append_bit(const Bitset& lhs)
386 {
387 Bitset b(lhs);
388 b.push_back(true);
389 BOOST_CHECK(b.size() == lhs.size() + 1);
390 BOOST_CHECK(b[b.size() - 1] == true);
391 for (std::size_t i = 0; i < lhs.size(); ++i)
392 BOOST_CHECK(b[i] == lhs[i]);
393
394 b.push_back(false);
395 BOOST_CHECK(b.size() == lhs.size() + 2);
396 BOOST_CHECK(b[b.size() - 1] == false);
397 BOOST_CHECK(b[b.size() - 2] == true);
398 for (std::size_t j = 0; j < lhs.size(); ++j)
399 BOOST_CHECK(b[j] == lhs[j]);
400 }
401
402 static void append_block(const Bitset& lhs)
403 {
404 Bitset b(lhs);
405 Block value(128);
406 b.append(value);
407 BOOST_CHECK(b.size() == lhs.size() + bits_per_block);
408 for (typename Bitset::block_width_type i = 0; i < bits_per_block; ++i)
409 BOOST_CHECK(b[lhs.size() + i] == bool((value >> i) & 1));
410 }
411
412 static void append_block_range(const Bitset& lhs, const std::vector<Block>& blocks)
413 {
414 Bitset b(lhs), c(lhs);
415 b.append(blocks.begin(), blocks.end());
416 for (typename std::vector<Block>::const_iterator i = blocks.begin();
417 i != blocks.end(); ++i)
418 c.append(*i);
419 BOOST_CHECK(b == c);
420 }
421
422 // operator[] and reference members
423 // PRE: b[i] == bit_vec[i]
424 static void operator_bracket(const Bitset& lhs, const std::vector<bool>& bit_vec)
425 {
426 Bitset b(lhs);
427 std::size_t i, j, k;
428
429 // x = b[i]
430 // x = ~b[i]
431 for (i = 0; i < b.size(); ++i) {
432 bool x = b[i];
433 BOOST_CHECK(x == bit_vec[i]);
434 x = ~b[i];
435 BOOST_CHECK(x == !bit_vec[i]);
436 }
437 Bitset prev(b);
438
439 // b[i] = x
440 for (j = 0; j < b.size(); ++j) {
441 bool x = !prev[j];
442 b[j] = x;
443 for (k = 0; k < b.size(); ++k)
444 if (j == k)
445 BOOST_CHECK(b[k] == x);
446 else
447 BOOST_CHECK(b[k] == prev[k]);
448 b[j] = prev[j];
449 }
450 b.flip();
451
452 // b[i] = b[j]
453 for (i = 0; i < b.size(); ++i) {
454 b[i] = prev[i];
455 for (j = 0; j < b.size(); ++j) {
456 if (i == j)
457 BOOST_CHECK(b[j] == prev[j]);
458 else
459 BOOST_CHECK(b[j] == !prev[j]);
460 }
461 b[i] = !prev[i];
462 }
463
464 // b[i].flip()
465 for (i = 0; i < b.size(); ++i) {
466 b[i].flip();
467 for (j = 0; j < b.size(); ++j) {
468 if (i == j)
469 BOOST_CHECK(b[j] == prev[j]);
470 else
471 BOOST_CHECK(b[j] == !prev[j]);
472 }
473 b[i].flip();
474 }
475 }
476
477 //===========================================================================
478 // bitwise operators
479
480 // bitwise and assignment
481
482 // PRE: b.size() == rhs.size()
483 static void and_assignment(const Bitset& b, const Bitset& rhs)
484 {
485 Bitset lhs(b);
486 Bitset prev(lhs);
487 lhs &= rhs;
488 // Clears each bit in lhs for which the corresponding bit in rhs is
489 // clear, and leaves all other bits unchanged.
490 for (std::size_t I = 0; I < lhs.size(); ++I)
491 if (rhs[I] == 0)
492 BOOST_CHECK(lhs[I] == 0);
493 else
494 BOOST_CHECK(lhs[I] == prev[I]);
495 }
496
497 // PRE: b.size() == rhs.size()
498 static void or_assignment(const Bitset& b, const Bitset& rhs)
499 {
500 Bitset lhs(b);
501 Bitset prev(lhs);
502 lhs |= rhs;
503 // Sets each bit in lhs for which the corresponding bit in rhs is set, and
504 // leaves all other bits unchanged.
505 for (std::size_t I = 0; I < lhs.size(); ++I)
506 if (rhs[I] == 1)
507 BOOST_CHECK(lhs[I] == 1);
508 else
509 BOOST_CHECK(lhs[I] == prev[I]);
510 }
511
512 // PRE: b.size() == rhs.size()
513 static void xor_assignment(const Bitset& b, const Bitset& rhs)
514 {
515 Bitset lhs(b);
516 Bitset prev(lhs);
517 lhs ^= rhs;
518 // Flips each bit in lhs for which the corresponding bit in rhs is set,
519 // and leaves all other bits unchanged.
520 for (std::size_t I = 0; I < lhs.size(); ++I)
521 if (rhs[I] == 1)
522 BOOST_CHECK(lhs[I] == !prev[I]);
523 else
524 BOOST_CHECK(lhs[I] == prev[I]);
525 }
526
527 // PRE: b.size() == rhs.size()
528 static void sub_assignment(const Bitset& b, const Bitset& rhs)
529 {
530 Bitset lhs(b);
531 Bitset prev(lhs);
532 lhs -= rhs;
533 // Resets each bit in lhs for which the corresponding bit in rhs is set,
534 // and leaves all other bits unchanged.
535 for (std::size_t I = 0; I < lhs.size(); ++I)
536 if (rhs[I] == 1)
537 BOOST_CHECK(lhs[I] == 0);
538 else
539 BOOST_CHECK(lhs[I] == prev[I]);
540 }
541
542 static void shift_left_assignment(const Bitset& b, std::size_t pos)
543 {
544 Bitset lhs(b);
545 Bitset prev(lhs);
546 lhs <<= pos;
547 // Replaces each bit at position I in lhs with the following value:
548 // - If I < pos, the new value is zero
549 // - If I >= pos, the new value is the previous value of the bit at
550 // position I - pos
551 for (std::size_t I = 0; I < lhs.size(); ++I)
552 if (I < pos)
553 BOOST_CHECK(lhs[I] == 0);
554 else
555 BOOST_CHECK(lhs[I] == prev[I - pos]);
556 }
557
558 static void shift_right_assignment(const Bitset& b, std::size_t pos)
559 {
560 Bitset lhs(b);
561 Bitset prev(lhs);
562 lhs >>= pos;
563 // Replaces each bit at position I in lhs with the following value:
564 // - If pos >= N - I, the new value is zero
565 // - If pos < N - I, the new value is the previous value of the bit at
566 // position I + pos
567 std::size_t N = lhs.size();
568 for (std::size_t I = 0; I < N; ++I)
569 if (pos >= N - I)
570 BOOST_CHECK(lhs[I] == 0);
571 else
572 BOOST_CHECK(lhs[I] == prev[I + pos]);
573 }
574
575
576 static void set_all(const Bitset& b)
577 {
578 Bitset lhs(b);
579 lhs.set();
580 for (std::size_t I = 0; I < lhs.size(); ++I)
581 BOOST_CHECK(lhs[I] == 1);
582 }
583
584 static void set_one(const Bitset& b, std::size_t pos, bool value)
585 {
586 Bitset lhs(b);
587 std::size_t N = lhs.size();
588 if (pos < N) {
589 Bitset prev(lhs);
590 // Stores a new value in the bit at position pos in lhs.
591 lhs.set(pos, value);
592 BOOST_CHECK(lhs[pos] == value);
593
594 // All other values of lhs remain unchanged
595 for (std::size_t I = 0; I < N; ++I)
596 if (I != pos)
597 BOOST_CHECK(lhs[I] == prev[I]);
598 } else {
599 // Not in range, doesn't satisfy precondition.
600 }
601 }
602
603 static void reset_all(const Bitset& b)
604 {
605 Bitset lhs(b);
606 // Resets all bits in lhs
607 lhs.reset();
608 for (std::size_t I = 0; I < lhs.size(); ++I)
609 BOOST_CHECK(lhs[I] == 0);
610 }
611
612 static void reset_one(const Bitset& b, std::size_t pos)
613 {
614 Bitset lhs(b);
615 std::size_t N = lhs.size();
616 if (pos < N) {
617 Bitset prev(lhs);
618 lhs.reset(pos);
619 // Resets the bit at position pos in lhs
620 BOOST_CHECK(lhs[pos] == 0);
621
622 // All other values of lhs remain unchanged
623 for (std::size_t I = 0; I < N; ++I)
624 if (I != pos)
625 BOOST_CHECK(lhs[I] == prev[I]);
626 } else {
627 // Not in range, doesn't satisfy precondition.
628 }
629 }
630
631 static void operator_flip(const Bitset& b)
632 {
633 Bitset lhs(b);
634 Bitset x(lhs);
635 BOOST_CHECK(~lhs == x.flip());
636 }
637
638 static void flip_all(const Bitset& b)
639 {
640 Bitset lhs(b);
641 std::size_t N = lhs.size();
642 Bitset prev(lhs);
643 lhs.flip();
644 // Toggles all the bits in lhs
645 for (std::size_t I = 0; I < N; ++I)
646 BOOST_CHECK(lhs[I] == !prev[I]);
647 }
648
649 static void flip_one(const Bitset& b, std::size_t pos)
650 {
651 Bitset lhs(b);
652 std::size_t N = lhs.size();
653 if (pos < N) {
654 Bitset prev(lhs);
655 lhs.flip(pos);
656 // Toggles the bit at position pos in lhs
657 BOOST_CHECK(lhs[pos] == !prev[pos]);
658
659 // All other values of lhs remain unchanged
660 for (std::size_t I = 0; I < N; ++I)
661 if (I != pos)
662 BOOST_CHECK(lhs[I] == prev[I]);
663 } else {
664 // Not in range, doesn't satisfy precondition.
665 }
666 }
667
668 // empty
669 static void empty(const Bitset& b)
670 {
671 BOOST_CHECK(b.empty() == (b.size() == 0));
672 }
673
674 // to_ulong()
675 static void to_ulong(const Bitset& lhs)
676 {
677 typedef unsigned long result_type;
678 std::size_t n = std::numeric_limits<result_type>::digits;
679 std::size_t sz = lhs.size();
680
681 bool will_overflow = false;
682 for (std::size_t i = n; i < sz; ++i) {
683 if (lhs.test(i) != 0) {
684 will_overflow = true;
685 break;
686 }
687 }
688 if (will_overflow) {
689 try {
690 (void)lhs.to_ulong();
691 BOOST_CHECK(false); // It should have thrown an exception
692 } catch (std::overflow_error & ex) {
693 // Good!
694 BOOST_CHECK(!!ex.what());
695 } catch (...) {
696 BOOST_CHECK(false); // threw the wrong exception
697 }
698 } else {
699 result_type num = lhs.to_ulong();
700 // Be sure the number is right
701 if (sz == 0)
702 BOOST_CHECK(num == 0);
703 else {
704 for (std::size_t i = 0; i < sz; ++i)
705 BOOST_CHECK(lhs[i] == (i < n ? nth_bit(num, i) : 0));
706 }
707 }
708 }
709
710 // to_string()
711 static void to_string(const Bitset& b)
712 {
713 std::string str;
714 boost::to_string(b, str);
715 BOOST_CHECK(str.size() == b.size());
716 for (std::size_t i = 0; i < b.size(); ++i)
717 BOOST_CHECK(str[b.size() - 1 - i] ==(b.test(i)? '1':'0'));
718 }
719
720 static void count(const Bitset& b)
721 {
722 std::size_t c = b.count();
723 std::size_t actual = 0;
724 for (std::size_t i = 0; i < b.size(); ++i)
725 if (b[i])
726 ++actual;
727 BOOST_CHECK(c == actual);
728 }
729
730 static void size(const Bitset& b)
731 {
732 BOOST_CHECK(Bitset(b).set().count() == b.size());
733 }
734
735 static void capacity_test_one(const Bitset& lhs)
736 {
737 //empty bitset
738 Bitset b(lhs);
739 BOOST_CHECK(b.capacity() == 0);
740 }
741
742 static void capacity_test_two(const Bitset& lhs)
743 {
744 //bitset constructed with size "100"
745 Bitset b(lhs);
746 BOOST_CHECK(b.capacity() >= 100);
747 b.resize(200);
748 BOOST_CHECK(b.capacity() >= 200);
749 }
750
751 static void reserve_test_one(const Bitset& lhs)
752 {
753 //empty bitset
754 Bitset b(lhs);
755 b.reserve(16);
756 BOOST_CHECK(b.capacity() >= 16);
757 }
758
759 static void reserve_test_two(const Bitset& lhs)
760 {
761 //bitset constructed with size "100"
762 Bitset b(lhs);
763 BOOST_CHECK(b.capacity() >= 100);
764 b.reserve(60);
765 BOOST_CHECK(b.size() == 100);
766 BOOST_CHECK(b.capacity() >= 100);
767 b.reserve(160);
768 BOOST_CHECK(b.size() == 100);
769 BOOST_CHECK(b.capacity() >= 160);
770 }
771
772 static void shrink_to_fit_test_one(const Bitset& lhs)
773 {
774 //empty bitset
775 Bitset b(lhs);
776 b.shrink_to_fit();
777 BOOST_CHECK(b.size() == 0);
778 BOOST_CHECK(b.capacity() == 0);
779 }
780
781 static void shrink_to_fit_test_two(const Bitset& lhs)
782 {
783 //bitset constructed with size "100"
784 Bitset b(lhs);
785 b.shrink_to_fit();
786 BOOST_CHECK(b.capacity() >= 100);
787 BOOST_CHECK(b.size() == 100);
788 b.reserve(200);
789 BOOST_CHECK(b.capacity() >= 200);
790 BOOST_CHECK(b.size() == 100);
791 b.shrink_to_fit();
792 BOOST_CHECK(b.capacity() < 200);
793 BOOST_CHECK(b.size() == 100);
794 }
795
796 static void all(const Bitset& b)
797 {
798 BOOST_CHECK(b.all() == (b.count() == b.size()));
799 bool result = true;
800 for(std::size_t i = 0; i < b.size(); ++i)
801 if(!b[i]) {
802 result = false;
803 break;
804 }
805 BOOST_CHECK(b.all() == result);
806 }
807
808 static void any(const Bitset& b)
809 {
810 BOOST_CHECK(b.any() == (b.count() != 0));
811 bool result = false;
812 for(std::size_t i = 0; i < b.size(); ++i)
813 if(b[i]) {
814 result = true;
815 break;
816 }
817 BOOST_CHECK(b.any() == result);
818 }
819
820 static void none(const Bitset& b)
821 {
822 bool result = true;
823 for(std::size_t i = 0; i < b.size(); ++i) {
824 if(b[i]) {
825 result = false;
826 break;
827 }
828 }
829 BOOST_CHECK(b.none() == result);
830
831 // sanity
832 BOOST_CHECK(b.none() == !b.any());
833 BOOST_CHECK(b.none() == (b.count() == 0));
834 }
835
836 static void subset(const Bitset& a, const Bitset& b)
837 {
838 BOOST_CHECK(a.size() == b.size()); // PRE
839
840 bool is_subset = true;
841 if (b.size()) { // could use b.any() but let's be safe
842 for(std::size_t i = 0; i < a.size(); ++i) {
843 if(a.test(i) && !b.test(i)) {
844 is_subset = false;
845 break;
846 }
847 }
848 }
849 else {
850 // sanity
851 BOOST_CHECK(a.count() == 0);
852 BOOST_CHECK(a.any() == false);
853
854 //is_subset = (a.any() == false);
855 }
856
857 BOOST_CHECK(a.is_subset_of(b) == is_subset);
858 }
859
860 static void proper_subset(const Bitset& a, const Bitset& b)
861 {
862 // PRE: a.size() == b.size()
863 BOOST_CHECK(a.size() == b.size());
864
865 bool is_proper = false;
866
867 if (b.size() != 0) {
868
869 // check it's a subset
870 subset(a, b);
871
872 // is it proper?
873 for (std::size_t i = 0; i < a.size(); ++i) {
874 if (!a.test(i) && b.test(i)) {
875 is_proper = true;
876 // sanity
877 BOOST_CHECK(a.count() < b.count());
878 BOOST_CHECK(b.any());
879 }
880 }
881 }
882
883 BOOST_CHECK(a.is_proper_subset_of(b) == is_proper);
884 if (is_proper)
885 BOOST_CHECK(b.is_proper_subset_of(a) != is_proper);// antisymmetry
886 }
887
888 static void intersects(const Bitset& a, const Bitset& b)
889 {
890 bool have_intersection = false;
891
892 typename Bitset::size_type m = a.size() < b.size() ? a.size() : b.size();
893 for(typename Bitset::size_type i = 0; i < m && !have_intersection; ++i)
894 if(a[i] == true && b[i] == true)
895 have_intersection = true;
896
897 BOOST_CHECK(a.intersects(b) == have_intersection);
898 // also check commutativity
899 BOOST_CHECK(b.intersects(a) == have_intersection);
900 }
901
902 static void find_first(const Bitset& b)
903 {
904 // find first non-null bit, if any
905 typename Bitset::size_type i = 0;
906 while (i < b.size() && b[i] == 0)
907 ++i;
908
909 if (i == b.size())
910 BOOST_CHECK(b.find_first() == Bitset::npos); // not found;
911 else {
912 BOOST_CHECK(b.find_first() == i);
913 BOOST_CHECK(b.test(i) == true);
914 }
915
916 }
917
918 static void find_next(const Bitset& b, typename Bitset::size_type prev)
919 {
920 BOOST_CHECK(next_bit_on(b, prev) == b.find_next(prev));
921 }
922
923 static void operator_equal(const Bitset& a, const Bitset& b)
924 {
925 if (a == b) {
926 for (std::size_t I = 0; I < a.size(); ++I)
927 BOOST_CHECK(a[I] == b[I]);
928 } else {
929 if (a.size() == b.size()) {
930 bool diff = false;
931 for (std::size_t I = 0; I < a.size(); ++I)
932 if (a[I] != b[I]) {
933 diff = true;
934 break;
935 }
936 BOOST_CHECK(diff);
937 }
938 }
939 }
940
941 static void operator_not_equal(const Bitset& a, const Bitset& b)
942 {
943 if (a != b) {
944 if (a.size() == b.size()) {
945 bool diff = false;
946 for (std::size_t I = 0; I < a.size(); ++I)
947 if (a[I] != b[I]) {
948 diff = true;
949 break;
950 }
951 BOOST_CHECK(diff);
952 }
953 } else {
954 for (std::size_t I = 0; I < a.size(); ++I)
955 BOOST_CHECK(a[I] == b[I]);
956 }
957 }
958
959 static bool less_than(const Bitset& a, const Bitset& b)
960 {
961 // Compare from most significant to least.
962 // Careful, don't send unsigned int into negative territory!
963 if (a.size() == 0)
964 return false;
965
966 std::size_t I;
967 for (I = a.size() - 1; I > 0; --I)
968 if (a[I] < b[I])
969 return true;
970 else if (a[I] > b[I])
971 return false;
972 // if (a[I] = b[I]) skip to next
973
974 if (a[0] < b[0])
975 return true;
976 else
977 return false;
978 }
979
980 static typename Bitset::size_type next_bit_on(const Bitset& b, typename Bitset::size_type prev)
981 {
982 // helper function for find_next()
983 //
984
985 if (b.none() == true || prev == Bitset::npos)
986 return Bitset::npos;
987
988 ++prev;
989
990 if (prev >= b.size())
991 return Bitset::npos;
992
993 typename Bitset::size_type i = prev;
994 while (i < b.size() && b[i] == 0)
995 ++i;
996
997 return i==b.size() ? Bitset::npos : i;
998
999 }
1000
1001 static void operator_less_than(const Bitset& a, const Bitset& b)
1002 {
1003 if (less_than(a, b))
1004 BOOST_CHECK(a < b);
1005 else
1006 BOOST_CHECK(!(a < b));
1007 }
1008
1009 static void operator_greater_than(const Bitset& a, const Bitset& b)
1010 {
1011 if (less_than(a, b) || a == b)
1012 BOOST_CHECK(!(a > b));
1013 else
1014 BOOST_CHECK(a > b);
1015 }
1016
1017 static void operator_less_than_eq(const Bitset& a, const Bitset& b)
1018 {
1019 if (less_than(a, b) || a == b)
1020 BOOST_CHECK(a <= b);
1021 else
1022 BOOST_CHECK(!(a <= b));
1023 }
1024
1025 static void operator_greater_than_eq(const Bitset& a, const Bitset& b)
1026 {
1027 if (less_than(a, b))
1028 BOOST_CHECK(!(a >= b));
1029 else
1030 BOOST_CHECK(a >= b);
1031 }
1032
1033 static void test_bit(const Bitset& b, std::size_t pos)
1034 {
1035 Bitset lhs(b);
1036 std::size_t N = lhs.size();
1037 if (pos < N) {
1038 BOOST_CHECK(lhs.test(pos) == lhs[pos]);
1039 } else {
1040 // Not in range, doesn't satisfy precondition.
1041 }
1042 }
1043
1044 static void test_set_bit(const Bitset& b, std::size_t pos, bool value)
1045 {
1046 Bitset lhs(b);
1047 std::size_t N = lhs.size();
1048 if (pos < N) {
1049 Bitset prev(lhs);
1050 // Stores a new value in the bit at position pos in lhs.
1051 BOOST_CHECK(lhs.test_set(pos, value) == prev[pos]);
1052 BOOST_CHECK(lhs[pos] == value);
1053
1054 // All other values of lhs remain unchanged
1055 for (std::size_t I = 0; I < N; ++I)
1056 if (I != pos)
1057 BOOST_CHECK(lhs[I] == prev[I]);
1058 } else {
1059 // Not in range, doesn't satisfy precondition.
1060 }
1061 }
1062
1063 static void operator_shift_left(const Bitset& lhs, std::size_t pos)
1064 {
1065 Bitset x(lhs);
1066 BOOST_CHECK((lhs << pos) == (x <<= pos));
1067 }
1068
1069 static void operator_shift_right(const Bitset& lhs, std::size_t pos)
1070 {
1071 Bitset x(lhs);
1072 BOOST_CHECK((lhs >> pos) == (x >>= pos));
1073 }
1074
1075 // operator|
1076 static
1077 void operator_or(const Bitset& lhs, const Bitset& rhs)
1078 {
1079 Bitset x(lhs);
1080 BOOST_CHECK((lhs | rhs) == (x |= rhs));
1081 }
1082
1083 // operator&
1084 static
1085 void operator_and(const Bitset& lhs, const Bitset& rhs)
1086 {
1087 Bitset x(lhs);
1088 BOOST_CHECK((lhs & rhs) == (x &= rhs));
1089 }
1090
1091 // operator^
1092 static
1093 void operator_xor(const Bitset& lhs, const Bitset& rhs)
1094 {
1095 Bitset x(lhs);
1096 BOOST_CHECK((lhs ^ rhs) == (x ^= rhs));
1097 }
1098
1099 // operator-
1100 static
1101 void operator_sub(const Bitset& lhs, const Bitset& rhs)
1102 {
1103 Bitset x(lhs);
1104 BOOST_CHECK((lhs - rhs) == (x -= rhs));
1105 }
1106
1107//------------------------------------------------------------------------------
1108// I/O TESTS
1109 // The following tests assume the results of extraction (i.e.: contents,
1110 // state and width of is, contents of b) only depend on input (the string
1111 // str). In other words, they don't consider "unexpected" errors such as
1112 // stream corruption or out of memory. The reason is simple: if e.g. the
1113 // stream buffer throws, the stream layer may eat the exception and
1114 // transform it into a badbit. But we can't trust the stream state here,
1115 // because one of the things that we want to test is exactly whether it
1116 // is set correctly. Similarly for insertion.
1117 //
1118 // To provide for these cases would require that the test functions know
1119 // in advance whether the stream buffer and/or allocations will fail, and
1120 // when; that is, we should write both a special allocator and a special
1121 // stream buffer capable of throwing "on demand" and pass them here.
1122
1123 // Seems overkill for these kinds of unit tests.
1124 //-------------------------------------------------------------------------
1125
1126 // operator<<( [basic_]ostream,
1127 template <typename Stream>
1128 static void stream_inserter(const Bitset & b,
1129 Stream & s,
1130 const char * file_name
1131 )
1132 {
1133#if defined BOOST_OLD_IOSTREAMS
1134 typedef char char_type;
1135 typedef std::string string_type;
1136 typedef ifstream corresponding_input_stream_type;
1137#else
1138 typedef typename Stream::char_type char_type;
1139 typedef std::basic_string<char_type> string_type;
1140 typedef std::basic_ifstream<char_type> corresponding_input_stream_type;
1141
1142 std::ios::iostate except = s.exceptions();
1143#endif
1144
1145 typedef typename Bitset::size_type size_type;
1146 std::streamsize w = s.width();
1147 char_type fill_char = s.fill();
1148 std::ios::iostate oldstate = s.rdstate();
1149 bool stream_was_good = s.good();
1150
1151 bool did_throw = false;
1152 try {
1153 s << b;
1154 }
1155#if defined BOOST_OLD_IOSTREAMS
1156 catch(...) {
1157 BOOST_CHECK(false);
1158 }
1159#else
1160 catch (const std::ios_base::failure &) {
1161 BOOST_CHECK((except & s.rdstate()) != 0);
1162 did_throw = true;
1163 } catch (...) {
1164 did_throw = true;
1165 }
1166#endif
1167
1168 BOOST_CHECK(did_throw || !stream_was_good || (s.width() == 0));
1169
1170 if (!stream_was_good) {
1171 BOOST_CHECK(s.good() == false);
1172
1173 // this should actually be oldstate == s.rdstate()
1174 // but some implementations add badbit in the
1175 // sentry constructor
1176 //
1177 BOOST_CHECK((oldstate & s.rdstate()) == oldstate);
1178 BOOST_CHECK(s.width() == w);
1179 }
1180 else {
1181 if(!did_throw)
1182 BOOST_CHECK(s.width() == 0);
1183 // This test require that os be an output _and_ input stream.
1184 // Of course dynamic_bitset's operator << doesn't require that.
1185
1186 size_type total_len = w <= 0 || static_cast<size_type>(w) < b.size()? b.size() : static_cast<size_type>(w);
1187 const string_type padding (total_len - b.size(), fill_char);
1188 string_type expected;
1189 boost::to_string(b, expected);
1190 if ((s.flags() & std::ios::adjustfield) != std::ios::left)
1191 expected = padding + expected;
1192 else
1193 expected = expected + padding;
1194
1195 assert(expected.length() == total_len);
1196
1197 // close, and reopen the file stream to verify contents
1198 s.close();
1199 corresponding_input_stream_type is(file_name);
1200 string_type contents;
1201 std::getline(is, contents, char_type());
1202 BOOST_CHECK(contents == expected);
1203 }
1204 }
1205
1206 // operator>>( [basic_]istream
1207 template <typename Stream, typename String>
1208 static void stream_extractor(Bitset& b,
1209 Stream& is,
1210 String& str
1211 )
1212 {
1213 // save necessary info then do extraction
1214 //
1215 const std::streamsize w = is.width();
1216 Bitset a_copy(b);
1217 bool stream_was_good = is.good();
1218
1219 bool did_throw = false;
1220
1221#if defined BOOST_OLD_IOSTREAMS
1222 bool has_stream_exceptions = false;
1223 is >> b;
1224#else
1225 const std::ios::iostate except = is.exceptions();
1226 bool has_stream_exceptions = true;
1227 try {
1228 is >> b;
1229 }
1230 catch(const std::ios::failure &) {
1231 did_throw = true;
1232 }
1233
1234 // postconditions
1235 BOOST_CHECK(except == is.exceptions()); // paranoid
1236#endif
1237 //------------------------------------------------------------------
1238
1239 // postconditions
1240 BOOST_CHECK(b.size() <= b.max_size());
1241 if(w > 0)
1242 BOOST_CHECK(b.size() <= static_cast<typename Bitset::size_type>(w));
1243
1244 // throw if and only if required
1245 if(has_stream_exceptions) {
1246 const bool exceptional_state = has_flags(is, is.exceptions());
1247 BOOST_CHECK(exceptional_state == did_throw);
1248 }
1249
1250 typedef typename String::size_type size_type;
1251 typedef typename String::value_type Ch;
1252 size_type after_digits = 0;
1253
1254 if(!stream_was_good) {
1255 BOOST_CHECK(has_flags(is, std::ios::failbit));
1256 BOOST_CHECK(b == a_copy);
1257 BOOST_CHECK(is.width() == (did_throw ? w : 0));
1258 }
1259 else {
1260 // stream was good(), parse the string;
1261 // it may contain three parts, all of which are optional
1262 // {spaces} {digits} {non-digits}
1263 // opt opt opt
1264 //
1265 // The values of b.max_size() and is.width() may lead to
1266 // ignore part of the digits, if any.
1267
1268 size_type pos = 0;
1269 size_type len = str.length();
1270 // {spaces}
1271 for( ; pos < len && is_white_space(is, str[pos]); ++pos)
1272 {}
1273 size_type after_spaces = pos;
1274 // {digits} or part of them
1275 const typename Bitset::size_type max_digits =
1276 w > 0 && static_cast<typename Bitset::size_type>(w) < b.max_size()
1277 ? static_cast<typename Bitset::size_type>(w) : b.max_size();
1278
1279 for( ; pos < len && (pos - after_spaces) < max_digits; ++pos) {
1280 if(!is_one_or_zero(is, str[pos]))
1281 break;
1282 }
1283 after_digits = pos;
1284 size_type num_digits = after_digits - after_spaces;
1285
1286 // eofbit
1287 if((after_digits == len && max_digits > num_digits ))
1288 BOOST_CHECK(has_flags(is, std::ios::eofbit));
1289 else
1290 BOOST_CHECK(!has_flags(is, std::ios::eofbit));
1291
1292 // failbit <=> there are no digits, except for the library
1293 // issue explained below.
1294 //
1295 if(num_digits == 0) {
1296 if(after_digits == len && has_stream_exceptions &&
1297 (is.exceptions() & std::ios::eofbit) != std::ios::goodbit) {
1298 // This is a special case related to library issue 195:
1299 // reaching eof when skipping whitespaces in the sentry ctor.
1300 // The resolution says the sentry constructor should set *both*
1301 // eofbit and failbit; but many implementations deliberately
1302 // set eofbit only. See for instance:
1303 // http://gcc.gnu.org/ml/libstdc++/2000-q1/msg00086.html
1304 //
1305 BOOST_CHECK(did_throw);
1306
1307 }
1308 else {
1309 BOOST_CHECK(has_flags(is, std::ios::failbit));
1310 }
1311 }
1312 else
1313 BOOST_CHECK(!has_flags(is, std::ios::failbit));
1314
1315
1316 if(num_digits == 0 && after_digits == len) {
1317 // The VC6 library has a bug/non-conformity in the sentry
1318 // constructor. It uses code like
1319 // // skip whitespaces...
1320 // int_type _C = rdbuf()->sgetc();
1321 // while (!_Tr::eq_int_type(_Tr::eof(), _C) ...
1322 //
1323 // For an empty file the while statement is never "entered"
1324 // and the stream remains in good() state; thus the sentry
1325 // object gives "true" when converted to bool. This is worse
1326 // than the case above, because not only failbit is not set,
1327 // but no bit is set at all, end we end up clearing the
1328 // bitset though there's nothing in the file to be extracted.
1329 // Note that the dynamic_bitset docs say a sentry object is
1330 // constructed and then converted to bool, thus we rely on
1331 // what the underlying library does.
1332 //
1333#if !defined(BOOST_DINKUMWARE_STDLIB) || (BOOST_DINKUMWARE_STDLIB >= 306)
1334 BOOST_CHECK(b == a_copy);
1335#else
1336 BOOST_CHECK(b.empty() == true);
1337#endif
1338 }
1339 else {
1340 String sub = str.substr(after_spaces, num_digits);
1341 BOOST_CHECK(b == Bitset(sub));
1342 }
1343
1344 // check width
1345 BOOST_CHECK(is.width() == 0
1346 || (after_digits == len && num_digits == 0 && did_throw));
1347 }
1348
1349
1350 // clear the stream to allow further reading then
1351 // retrieve any remaining chars with a single getline()
1352 is.exceptions(std::ios::goodbit);
1353 is.clear();
1354 String remainder;
1355 std::getline(is, remainder, Ch());
1356 if(stream_was_good)
1357 BOOST_CHECK(remainder == str.substr(after_digits));
1358 else
1359 BOOST_CHECK(remainder == str);
1360
1361 }
1362
1363
1364};
1365
1366
1367
1368#endif // include guard