Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_34_1/libs/dynamic_bitset/bitset_test.hpp @ 29

Last change on this file since 29 was 29, checked in by landauf, 16 years ago

updated boost from 1_33_1 to 1_34_1

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