os/ossrv/ossrv_pub/boost_apis/boost/graph/detail/bitset.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 //=======================================================================
     2 // Copyright 2001 Jeremy G. Siek
     3 // Authors: Jeremy G. Siek
     4 //
     5 // Distributed under the Boost Software License, Version 1.0. (See
     6 // accompanying file LICENSE_1_0.txt or copy at
     7 // http://www.boost.org/LICENSE_1_0.txt)
     8 //=======================================================================
     9 
    10 /*
    11  * Copyright (c) 1998
    12  * Silicon Graphics Computer Systems, Inc.
    13  *
    14  * Permission to use, copy, modify, distribute and sell this software
    15  * and its documentation for any purpose is hereby granted without fee,
    16  * provided that the above copyright notice appear in all copies and
    17  * that both that copyright notice and this permission notice appear
    18  * in supporting documentation.  Silicon Graphics makes no
    19  * representations about the suitability of this software for any
    20  * purpose.  It is provided "as is" without express or implied warranty.
    21  */
    22 
    23 #include <boost/config.hpp>
    24 #include <memory>
    25 #include <stdexcept>
    26 #include <algorithm>
    27 #include <string>
    28 #include <boost/config.hpp>
    29 #include <boost/pending/ct_if.hpp>
    30 #include <boost/graph/detail/bitset_adaptor.hpp>
    31 
    32 // This provides versions of std::bitset with both static and dynamic size.
    33 
    34 // UNDER CONSTRUCTION
    35 
    36 
    37 // replace this later
    38 #include <cassert>
    39 #define BOOST_ASSERT_THROW(expr, except) assert(expr)
    40 
    41 namespace boost {
    42 
    43   namespace detail {
    44     // structure to aid in counting bits
    45     template<bool dummy = true>
    46     struct bit_count {
    47       static unsigned char value[256];
    48     };
    49 
    50     // Mapping from 8 bit unsigned integers to the index of the first bit
    51     template<bool dummy = true>
    52     struct first_bit_location {
    53       static unsigned char value[256];
    54     };
    55 
    56     template <typename WordType>  // this size is in bits
    57     struct word_traits {
    58       typedef WordType word_type;
    59       static const std::size_t word_size = CHAR_BIT * sizeof(word_type);
    60     };
    61     
    62     //=========================================================================
    63     template <class WordTraits, class SizeType, class Derived>
    64     class bitset_base
    65       : public bitset_adaptor< SizeType, 
    66                                bitset_base<WordTraits, SizeType, Derived> >
    67     {
    68       //    private:
    69     public:
    70       typedef SizeType size_type;
    71       typedef typename WordTraits::word_type word_type;
    72 
    73       static size_type s_which_word(size_type pos) {
    74         return pos / WordTraits::word_size;
    75       }
    76       static size_type s_which_byte(size_type pos) {
    77         return (pos % WordTraits::word_size) / CHAR_BIT;
    78       }
    79       static size_type s_which_bit(size_type pos) {
    80         return pos % WordTraits::word_size;
    81       }
    82       static word_type s_mask_bit(size_type pos) {
    83         return (static_cast<word_type>(1)) << s_which_bit(pos); 
    84       }
    85       word_type& m_get_word(size_type pos) {
    86         return data()[s_which_word(pos)]; 
    87       }
    88       word_type m_get_word(size_type pos) const {
    89         return data()[s_which_word(pos)]; 
    90       }
    91       word_type& m_hi_word() { return data()[num_words() - 1]; }
    92       word_type  m_hi_word() const { return data()[num_words() - 1]; }
    93 
    94       void m_sanitize_highest() {
    95         size_type extra_bits = size() % WordTraits::word_size;
    96         if (extra_bits)
    97           m_hi_word() &= ~((~static_cast<word_type>(0)) << extra_bits);
    98       }
    99     public:
   100 
   101       class reference {
   102         friend class bitset_base;
   103 
   104         word_type *m_word_ptr;
   105         size_type m_bit_pos;
   106 
   107         // left undefined
   108         reference();
   109 
   110         reference(bitset_base& b, size_type pos ) {
   111           m_word_ptr = &b.m_get_word(pos);
   112           m_bit_pos = s_which_bit(pos);
   113         }
   114 
   115       public:
   116         ~reference() {}
   117 
   118         // for b[i] = x;
   119         reference& operator=(bool x) {
   120           if ( x )
   121             *m_word_ptr |= s_mask_bit(m_bit_pos);
   122           else
   123             *m_word_ptr &= ~s_mask_bit(m_bit_pos);
   124 
   125           return *this;
   126         }
   127         // for b[i] = b[j];
   128         reference& operator=(const reference& j) {
   129           if ( (*(j.m_word_ptr) & s_mask_bit(j.m_bit_pos)) )
   130             *m_word_ptr |= s_mask_bit(m_bit_pos);
   131           else
   132             *m_word_ptr &= ~s_mask_bit(m_bit_pos);
   133 
   134           return *this;
   135         }
   136         // flips the bit
   137         bool operator~() const { 
   138           return (*(m_word_ptr) & s_mask_bit(m_bit_pos)) == 0; 
   139         }
   140         // for x = b[i];
   141         operator bool() const { 
   142           return (*(m_word_ptr) & s_mask_bit(m_bit_pos)) != 0; 
   143         }
   144         // for b[i].flip();
   145         reference& flip() {
   146           *m_word_ptr ^= s_mask_bit(m_bit_pos);
   147           return *this;
   148         }
   149       };
   150 
   151       void init_from_ulong(unsigned long val) {
   152         reset();
   153         const size_type n = (std::min)(sizeof(unsigned long) * CHAR_BIT,
   154                                      WordTraits::word_size * num_words());
   155         for(size_type i = 0; i < n; ++i, val >>= 1)
   156           if ( val & 0x1 )
   157             m_get_word(i) |= s_mask_bit(i);
   158       }
   159       
   160       // intersection: this = this & x
   161       Derived& operator&=(const Derived& x) {
   162         for (size_type i = 0; i < num_words(); ++i)
   163           data()[i] &= x.data()[i];
   164         return static_cast<Derived&>(*this);
   165       }
   166       // union: this = this | x
   167       Derived& operator|=(const Derived& x) {
   168         for (size_type i = 0; i < num_words(); ++i)
   169           data()[i] |= x.data()[i];
   170         return static_cast<Derived&>(*this);
   171       }
   172       // exclusive or: this = this ^ x
   173       Derived& operator^=(const Derived& x) {
   174         for (size_type i = 0; i < num_words(); ++i)
   175           data()[i] ^= x.data()[i];
   176         return static_cast<Derived&>(*this);
   177       }
   178       // left shift
   179       Derived& operator<<=(size_type pos);
   180 
   181       // right shift
   182       Derived& operator>>=(size_type pos);
   183 
   184       Derived& set() {
   185         for (size_type i = 0; i < num_words(); ++i)
   186           data()[i] = ~static_cast<word_type>(0);
   187         m_sanitize_highest();
   188         return static_cast<Derived&>(*this);
   189       }
   190 
   191       Derived& set(size_type pos, int val = true)
   192       {
   193         BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::set(pos,value)"));
   194         if (val)
   195           m_get_word(pos) |= s_mask_bit(pos);
   196         else
   197           m_get_word(pos) &= ~s_mask_bit(pos);
   198         return static_cast<Derived&>(*this);
   199       }
   200       
   201       Derived& reset() {
   202         for (size_type i = 0; i < num_words(); ++i)
   203           data()[i] = 0;
   204         return static_cast<Derived&>(*this);
   205       }
   206 
   207       Derived& reset(size_type pos) {
   208         BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::reset(pos)"));
   209         m_get_word(pos) &= ~s_mask_bit(pos);
   210         return static_cast<Derived&>(*this);
   211       }
   212 
   213       // compliment
   214       Derived operator~() const {
   215         return Derived(static_cast<const Derived&>(*this)).flip();
   216       }
   217       
   218       Derived& flip() {
   219         for (size_type i = 0; i < num_words(); ++i)
   220           data()[i] = ~data()[i];
   221         m_sanitize_highest();
   222         return static_cast<Derived&>(*this);
   223       }
   224       Derived& flip(size_type pos) {
   225         BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::flip(pos)"));
   226         m_get_word(pos) ^= s_mask_bit(pos);
   227         return static_cast<Derived&>(*this);
   228       }
   229 
   230       // element access
   231       reference operator[](size_type pos) { return reference(*this, pos); }
   232       bool operator[](size_type pos) const { return test(pos); }
   233 
   234       unsigned long to_ulong() const;
   235 
   236       // to_string
   237 
   238       
   239       size_type count() const {
   240         size_type result = 0;
   241         const unsigned char* byte_ptr = (const unsigned char*)data();
   242         const unsigned char* end_ptr = 
   243           (const unsigned char*)(data() + num_words());
   244         while ( byte_ptr < end_ptr ) {
   245           result += bit_count<>::value[*byte_ptr];
   246           byte_ptr++;
   247         }
   248         return result;
   249       }   
   250       
   251       // size() must be provided by Derived class
   252 
   253       bool operator==(const Derived& x) const {
   254         return std::equal(data(), data() + num_words(), x.data());
   255       }
   256 
   257       bool operator!=(const Derived& x) const {
   258         return ! this->operator==(x);
   259       }
   260 
   261       bool test(size_type pos) const {
   262         BOOST_ASSERT_THROW(pos < size(), std::out_of_range("boost::bitset::test(pos)"));
   263         return (m_get_word(pos) & s_mask_bit(pos))
   264           != static_cast<word_type>(0);
   265       }
   266 
   267       bool any() const {
   268         for (size_type i = 0; i < num_words(); ++i) {
   269           if ( data()[i] != static_cast<word_type>(0) )
   270             return true;
   271         }
   272         return false;
   273       }
   274       bool none() const {
   275         return !any();
   276       }
   277 
   278       Derived operator<<(size_type pos) const
   279         { return Derived(static_cast<const Derived&>(*this)) <<= pos; }
   280 
   281       Derived operator>>(size_type pos) const
   282         { return Derived(static_cast<const Derived&>(*this)) >>= pos; }
   283 
   284       template <class CharT, class Traits, class Alloc>
   285       void m_copy_from_string(const basic_string<CharT,Traits,Alloc>& s,
   286                               size_type pos, size_type n)
   287       {
   288         reset();
   289         const size_type nbits = (std::min)(size(), (std::min)(n, s.size() - pos));
   290         for (size_type i = 0; i < nbits; ++i) {
   291           switch(s[pos + nbits - i - 1]) {
   292           case '0':
   293             break;
   294           case '1':
   295             this->set(i);
   296             break;
   297           default:
   298             throw std::invalid_argument
   299               ("boost::bitset_base::m_copy_from_string(s, pos, n)");
   300           }
   301         }
   302       }
   303 
   304       template <class CharT, class Traits, class Alloc>
   305       void m_copy_to_string(basic_string<CharT, Traits, Alloc>& s) const
   306       {
   307         s.assign(size(), '0');
   308         
   309         for (size_type i = 0; i < size(); ++i)
   310           if (test(i))
   311             s[size() - 1 - i] = '1';
   312       }
   313 
   314       //-----------------------------------------------------------------------
   315       // Stuff not in std::bitset
   316 
   317       // difference:  this = this - x
   318       Derived& operator-=(const Derived& x) {
   319         for (size_type i = 0; i < num_words(); ++i)
   320           data()[i] &= ~x.data()[i];
   321         return static_cast<Derived&>(*this);
   322       }
   323 
   324       // this wasn't working, why?
   325       int compare_3way(const Derived& x) const {
   326         return std::lexicographical_compare_3way
   327           (data(), data() + num_words(), x.data(), x.data() + x.num_words());
   328       }
   329 
   330       // less-than compare
   331       bool operator<(const Derived& x) const {
   332         return std::lexicographical_compare
   333           (data(), data() + num_words(), x.data(), x.data() + x.num_words());
   334       }
   335 
   336       // find the index of the first "on" bit
   337       size_type find_first() const;
   338 
   339       // find the index of the next "on" bit after prev
   340       size_type find_next(size_type prev) const;
   341 
   342       
   343       size_type _Find_first() const { return find_first(); }
   344 
   345       // find the index of the next "on" bit after prev
   346       size_type _Find_next(size_type prev) const { return find_next(prev); }
   347 
   348       //    private:
   349       word_type* data()
   350         { return static_cast<Derived*>(this)->data(); }
   351 
   352       const word_type* data() const 
   353         { return static_cast<const Derived*>(this)->data(); }
   354 
   355       size_type num_words() const 
   356         { return static_cast<const Derived*>(this)->num_words(); }
   357 
   358       size_type size() const 
   359         { return static_cast<const Derived*>(this)->size(); }
   360     };
   361 
   362     // 23.3.5.3 bitset operations:
   363     template <class W, class S, class D>
   364     inline D operator&(const bitset_base<W,S,D>& x,
   365                        const bitset_base<W,S,D>& y) {
   366       D result(static_cast<const D&>(x));
   367       result &= static_cast<const D&>(y);
   368       return result;
   369     }
   370 
   371     template <class W, class S, class D>
   372     inline D operator|(const bitset_base<W,S,D>& x,
   373                        const bitset_base<W,S,D>& y) {
   374       D result(static_cast<const D&>(x));
   375       result |= static_cast<const D&>(y);
   376       return result;
   377     }
   378 
   379     template <class W, class S, class D>
   380     inline D operator^(const bitset_base<W,S,D>& x,
   381                        const bitset_base<W,S,D>& y) {
   382       D result(static_cast<const D&>(x));
   383       result ^= static_cast<const D&>(y);
   384       return result;
   385     }
   386 
   387     // this one is an extension
   388     template <class W, class S, class D>
   389     inline D operator-(const bitset_base<W,S,D>& x,
   390                        const bitset_base<W,S,D>& y) {
   391       D result(static_cast<const D&>(x));
   392       result -= static_cast<const D&>(y);
   393       return result;
   394     }
   395 
   396     template <class W, class S, class D>
   397     inline int compare_3way(const bitset_base<W,S,D>& x,
   398                             const bitset_base<W,S,D>& y) {
   399       return std::lexicographical_compare_3way
   400         (x.data(), x.data() + x.num_words(), 
   401          y.data(), y.data() + y.num_words());
   402     }
   403 
   404 
   405     template <class W, class S, class D>
   406     std::istream&
   407     operator>>(std::istream& is, bitset_base<W,S,D>& x) {
   408       std::string tmp;
   409       tmp.reserve(x.size());
   410 
   411       // In new templatized iostreams, use istream::sentry
   412       if (is.flags() & ios::skipws) {
   413         char c;
   414         do
   415           is.get(c);
   416         while (is && isspace(c));
   417         if (is)
   418           is.putback(c);
   419       }
   420 
   421       for (S i = 0; i < x.size(); ++i) {
   422         char c;
   423         is.get(c);
   424 
   425         if (!is)
   426           break;
   427         else if (c != '0' && c != '1') {
   428           is.putback(c);
   429           break;
   430         }
   431         else
   432           //      tmp.push_back(c);
   433           tmp += c;
   434       }
   435 
   436       if (tmp.empty())
   437         is.clear(is.rdstate() | ios::failbit);
   438       else
   439         x.m_copy_from_string(tmp, static_cast<S>(0), x.size());
   440 
   441       return is;
   442     }
   443 
   444     template <class W, class S, class D>
   445     std::ostream& operator<<(std::ostream& os, 
   446                              const bitset_base<W,S,D>& x) {
   447       std::string tmp;
   448       x.m_copy_to_string(tmp);
   449       return os << tmp;
   450     }
   451 
   452     //=========================================================================
   453     template <typename WordType = unsigned long,
   454               typename SizeType = std::size_t,
   455               typename Allocator = std::allocator<WordType>
   456              >
   457     class dyn_size_bitset
   458       : public bitset_base<word_traits<WordType>, SizeType,
   459           dyn_size_bitset<WordType,SizeType,Allocator> >
   460     {
   461       typedef dyn_size_bitset self;
   462     public:
   463       typedef SizeType size_type;
   464     private:
   465       typedef word_traits<WordType> WordTraits;
   466       static const size_type word_size = WordTraits::word_size;
   467 
   468     public:
   469       dyn_size_bitset(unsigned long val, 
   470                       size_type n,
   471                       const Allocator& alloc = Allocator()) 
   472         : m_data(alloc.allocate((n + word_size - 1) / word_size)),
   473           m_size(n),
   474           m_num_words((n + word_size - 1) / word_size),
   475           m_alloc(alloc)
   476       {
   477         init_from_ulong(val);
   478       }
   479 
   480       dyn_size_bitset(size_type n,  // size of the set's "universe"
   481                       const Allocator& alloc = Allocator())
   482         : m_data(alloc.allocate((n + word_size - 1) / word_size)), 
   483           m_size(n), m_num_words((n + word_size - 1) / word_size),
   484           m_alloc(alloc)
   485       { }
   486 
   487       template<class CharT, class Traits, class Alloc>
   488       explicit dyn_size_bitset
   489         (const basic_string<CharT,Traits,Alloc>& s,
   490          std::size_t pos = 0,
   491          std::size_t n = std::size_t(basic_string<CharT,Traits,Alloc>::npos),
   492          const Allocator& alloc = Allocator())
   493         : m_data(alloc.allocate((n + word_size - 1) / word_size)), 
   494           m_size(n), m_num_words((n + word_size - 1) / word_size),
   495           m_alloc(alloc)
   496       {
   497         BOOST_ASSERT_THROW(pos < s.size(), std::out_of_range("dyn_size_bitset::dyn_size_bitset(s,pos,n,alloc)"));
   498         m_copy_from_string(s, pos, n);
   499       }
   500 
   501       template <typename InputIterator>
   502       explicit dyn_size_bitset
   503         (InputIterator first, InputIterator last,
   504          size_type n,  // size of the set's "universe"
   505          const Allocator& alloc = Allocator())
   506         : m_data(alloc.allocate((n + word_size - 1) / word_size)), 
   507           m_size(N), m_num_words((n + word_size - 1) / word_size),
   508           m_alloc(alloc)
   509       {
   510         while (first != last)
   511           this->set(*first++);
   512       }
   513 
   514       ~dyn_size_bitset() { 
   515         m_alloc.deallocate(m_data, m_num_words); 
   516       }
   517       
   518       size_type size() const { return m_size; }
   519 
   520       // protected:
   521       size_type num_words() const { return m_num_words; }
   522 
   523       word_type* data() { return m_data; }
   524       const word_type* data() const { return m_data; }
   525 
   526     protected:
   527       word_type* m_data;
   528       SizeType m_size;
   529       SizeType m_num_words;
   530       Allocator m_alloc;
   531     };
   532 
   533     //=========================================================================
   534     template <std::size_t N, typename WordType = unsigned long,
   535       typename SizeType = std::size_t>
   536     class bitset
   537       : public bitset_base<word_traits<WordType>, SizeType,
   538           bitset<N, WordType, SizeType> >
   539     {
   540       typedef bitset self;
   541       static const std::size_t word_size = word_traits<WordType>::word_size;
   542     public:
   543         // 23.3.5.1 constructors:
   544       bitset() {
   545 #if defined(__GNUC__)
   546         for (size_type i = 0; i < num_words(); ++i)
   547           m_data[i] = static_cast<WordType>(0);
   548 #endif
   549       }
   550 
   551       bitset(unsigned long val) {
   552         init_from_ulong(val);
   553       }
   554 
   555       template<class CharT, class Traits, class Alloc>
   556       explicit bitset
   557         (const basic_string<CharT,Traits,Alloc>& s,
   558          std::size_t pos = 0,
   559          std::size_t n = std::size_t(basic_string<CharT,Traits,Alloc>::npos))
   560       {
   561         BOOST_ASSERT_THROW
   562           (pos < s.size(), std::out_of_range("bitset::bitset(s,pos,n)"));
   563         m_copy_from_string(s, pos, n);
   564       }
   565 
   566       size_type size() const { return N; }
   567 
   568       // protected:
   569       size_type num_words() const { return (N + word_size - 1) / word_size; }
   570 
   571       word_type* data() { return m_data; }
   572       const word_type* data() const { return m_data; }
   573     protected:
   574       word_type m_data[(N + word_size - 1) / word_size];
   575     };
   576 
   577     //=========================================================================
   578     struct select_static_bitset {
   579       template <std::size_t N, typename WordT, typename SizeT, typename Alloc>
   580       struct bind_ {
   581         typedef bitset<N, WordT, SizeT> type;
   582       };
   583     };
   584     struct select_dyn_size_bitset {
   585       template <std::size_t N, typename WordT, typename SizeT, typename Alloc>
   586       struct bind_ {
   587         typedef dyn_size_bitset<WordT, SizeT, Alloc> type;
   588       };
   589     };
   590 
   591     template <std::size_t N = 0, // 0 means use dynamic
   592       typename WordType = unsigned long,
   593       typename Size_type = std::size_t, 
   594       typename Allocator = std::allocator<WordType>
   595              >
   596     class bitset_generator {
   597       typedef typename ct_if<N, select_dyn_size_bitset,
   598         select_static_bitset>::type selector;
   599     public:
   600       typedef typename selector
   601         ::template bind_<N, WordType, SizeType, Allocator>::type type;
   602     };
   603 
   604 
   605     //=========================================================================
   606     // bitset_base non-inline member function implementations
   607 
   608     template <class WordTraits, class SizeType, class Derived>
   609     Derived&
   610     bitset_base<WordTraits, SizeType, Derived>::
   611     operator<<=(size_type shift)
   612     {
   613       typedef typename WordTraits::word_type word_type;
   614       typedef SizeType size_type;
   615       if (shift != 0) {
   616         const size_type wshift = shift / WordTraits::word_size;
   617         const size_type offset = shift % WordTraits::word_size;
   618         const size_type sub_offset = WordTraits::word_size - offset;
   619         size_type n = num_words() - 1;
   620         for ( ; n > wshift; --n)
   621           data()[n] = (data()[n - wshift] << offset) |
   622             (data()[n - wshift - 1] >> sub_offset);
   623         if (n == wshift)
   624           data()[n] = data()[0] << offset;
   625         for (size_type n1 = 0; n1 < n; ++n1)
   626           data()[n1] = static_cast<word_type>(0);
   627       }
   628       m_sanitize_highest();
   629       return static_cast<Derived&>(*this);
   630     } // end operator<<=
   631 
   632 
   633     template <class WordTraits, class SizeType, class Derived>
   634     Derived&
   635     bitset_base<WordTraits, SizeType, Derived>::
   636     operator>>=(size_type shift)
   637     {
   638       typedef typename WordTraits::word_type word_type;
   639       typedef SizeType size_type;
   640       if (shift != 0) {
   641         const size_type wshift = shift / WordTraits::word_size;
   642         const size_type offset = shift % WordTraits::word_size;
   643         const size_type sub_offset = WordTraits::word_size - offset;
   644         const size_type limit = num_words() - wshift - 1;
   645         size_type n = 0;
   646         for ( ; n < limit; ++n)
   647           data()[n] = (data()[n + wshift] >> offset) |
   648             (data()[n + wshift + 1] << sub_offset);
   649         data()[limit] = data()[num_words()-1] >> offset;
   650         for (size_type n1 = limit + 1; n1 < num_words(); ++n1)
   651           data()[n1] = static_cast<word_type>(0);
   652       }
   653       m_sanitize_highest();
   654       return static_cast<Derived&>(*this);
   655     } // end operator>>=
   656 
   657 
   658     template <class WordTraits, class SizeType, class Derived>
   659     unsigned long bitset_base<WordTraits, SizeType, Derived>::
   660     to_ulong() const 
   661     {
   662       typedef typename WordTraits::word_type word_type;
   663       typedef SizeType size_type;
   664       const std::overflow_error
   665         overflow("boost::bit_set::operator unsigned long()");
   666 
   667       if (sizeof(word_type) >= sizeof(unsigned long)) {
   668         for (size_type i = 1; i < num_words(); ++i)
   669           BOOST_ASSERT_THROW(! data()[i], overflow);
   670         
   671         const word_type mask 
   672           = static_cast<word_type>(static_cast<unsigned long>(-1));
   673         BOOST_ASSERT_THROW(! (data()[0] & ~mask), overflow);
   674         
   675         return static_cast<unsigned long>(data()[0] & mask);
   676       }
   677       else { // sizeof(word_type) < sizeof(unsigned long).
   678         const size_type nwords =
   679           (sizeof(unsigned long) + sizeof(word_type) - 1) / sizeof(word_type);
   680 
   681         size_type min_nwords = nwords;
   682         if (num_words() > nwords) {
   683           for (size_type i = nwords; i < num_words(); ++i)
   684             BOOST_ASSERT_THROW(!data()[i], overflow);
   685         }
   686         else
   687           min_nwords = num_words();
   688 
   689         // If unsigned long is 8 bytes and word_type is 6 bytes, then
   690         // an unsigned long consists of all of one word plus 2 bytes
   691         // from another word.
   692         const size_type part = sizeof(unsigned long) % sizeof(word_type);
   693 
   694 #if 0
   695         // bug in here?
   696         // >> to far?
   697         BOOST_ASSERT_THROW((part != 0 
   698                             && nwords <= num_words() 
   699                             && (data()[min_nwords - 1] >>
   700                                 ((sizeof(word_type) - part) * CHAR_BIT)) != 0),
   701                            overflow);
   702 #endif
   703 
   704         unsigned long result = 0;
   705         for (size_type i = 0; i < min_nwords; ++i) {
   706           result |= static_cast<unsigned long>(
   707              data()[i]) << (i * sizeof(word_type) * CHAR_BIT);
   708         }
   709         return result;
   710       }
   711     }// end operator unsigned long()
   712 
   713 
   714     template <class WordTraits, class SizeType, class Derived>
   715     SizeType bitset_base<WordTraits,SizeType,Derived>::
   716     find_first() const
   717     {
   718       SizeType not_found = size();
   719       for (size_type i = 0; i < num_words(); i++ ) {
   720         word_type thisword = data()[i];
   721         if ( thisword != static_cast<word_type>(0) ) {
   722           // find byte within word
   723           for ( std::size_t j = 0; j < sizeof(word_type); j++ ) {
   724             unsigned char this_byte
   725               = static_cast<unsigned char>(thisword & (~(unsigned char)0));
   726             if ( this_byte )
   727               return i * WordTraits::word_size + j * CHAR_BIT +
   728                 first_bit_location<>::value[this_byte];
   729 
   730             thisword >>= CHAR_BIT;
   731           }
   732         }
   733       }
   734       // not found, so return an indication of failure.
   735       return not_found;
   736     }
   737 
   738     template <class WordTraits, class SizeType, class Derived>
   739     SizeType bitset_base<WordTraits, SizeType, Derived>::
   740     bitset_base<WordTraits,SizeType,Derived>::
   741     find_next(size_type prev) const
   742     {
   743       SizeType not_found = size();
   744       // make bound inclusive
   745       ++prev;
   746 
   747       // check out of bounds
   748       if ( prev >= num_words() * WordTraits::word_size )
   749         return not_found;
   750 
   751         // search first word
   752       size_type i = s_which_word(prev);
   753       word_type thisword = data()[i];
   754 
   755         // mask off bits below bound
   756       thisword &= (~static_cast<word_type>(0)) << s_which_bit(prev);
   757 
   758       if ( thisword != static_cast<word_type>(0) ) {
   759         // find byte within word
   760         // get first byte into place
   761         thisword >>= s_which_byte(prev) * CHAR_BIT;
   762         for ( size_type j = s_which_byte(prev); j < sizeof(word_type); j++ ) {
   763           unsigned char this_byte
   764             = static_cast<unsigned char>(thisword & (~(unsigned char)0));
   765           if ( this_byte )
   766             return i * WordTraits::word_size + j * CHAR_BIT +
   767               first_bit_location<>::value[this_byte];
   768 
   769           thisword >>= CHAR_BIT;
   770         }
   771       }
   772 
   773       // check subsequent words
   774       i++;
   775       for ( ; i < num_words(); i++ ) {
   776         word_type thisword = data()[i];
   777         if ( thisword != static_cast<word_type>(0) ) {
   778           // find byte within word
   779           for ( size_type j = 0; j < sizeof(word_type); j++ ) {
   780             unsigned char this_byte
   781               = static_cast<unsigned char>(thisword & (~(unsigned char)0));
   782             if ( this_byte )
   783               return i * WordTraits::word_size + j * CHAR_BIT +
   784                 first_bit_location<>::value[this_byte];
   785 
   786             thisword >>= CHAR_BIT;
   787           }
   788         }
   789       }
   790 
   791       // not found, so return an indication of failure.
   792       return not_found;
   793     } // end find_next
   794 
   795 
   796     template <bool dummy>
   797     unsigned char bit_count<dummy>::value[] = {
   798       0, /*   0 */ 1, /*   1 */ 1, /*   2 */ 2, /*   3 */ 1, /*   4 */
   799       2, /*   5 */ 2, /*   6 */ 3, /*   7 */ 1, /*   8 */ 2, /*   9 */
   800       2, /*  10 */ 3, /*  11 */ 2, /*  12 */ 3, /*  13 */ 3, /*  14 */
   801       4, /*  15 */ 1, /*  16 */ 2, /*  17 */ 2, /*  18 */ 3, /*  19 */
   802       2, /*  20 */ 3, /*  21 */ 3, /*  22 */ 4, /*  23 */ 2, /*  24 */
   803       3, /*  25 */ 3, /*  26 */ 4, /*  27 */ 3, /*  28 */ 4, /*  29 */
   804       4, /*  30 */ 5, /*  31 */ 1, /*  32 */ 2, /*  33 */ 2, /*  34 */
   805       3, /*  35 */ 2, /*  36 */ 3, /*  37 */ 3, /*  38 */ 4, /*  39 */
   806       2, /*  40 */ 3, /*  41 */ 3, /*  42 */ 4, /*  43 */ 3, /*  44 */
   807       4, /*  45 */ 4, /*  46 */ 5, /*  47 */ 2, /*  48 */ 3, /*  49 */
   808       3, /*  50 */ 4, /*  51 */ 3, /*  52 */ 4, /*  53 */ 4, /*  54 */
   809       5, /*  55 */ 3, /*  56 */ 4, /*  57 */ 4, /*  58 */ 5, /*  59 */
   810       4, /*  60 */ 5, /*  61 */ 5, /*  62 */ 6, /*  63 */ 1, /*  64 */
   811       2, /*  65 */ 2, /*  66 */ 3, /*  67 */ 2, /*  68 */ 3, /*  69 */
   812       3, /*  70 */ 4, /*  71 */ 2, /*  72 */ 3, /*  73 */ 3, /*  74 */
   813       4, /*  75 */ 3, /*  76 */ 4, /*  77 */ 4, /*  78 */ 5, /*  79 */
   814       2, /*  80 */ 3, /*  81 */ 3, /*  82 */ 4, /*  83 */ 3, /*  84 */
   815       4, /*  85 */ 4, /*  86 */ 5, /*  87 */ 3, /*  88 */ 4, /*  89 */
   816       4, /*  90 */ 5, /*  91 */ 4, /*  92 */ 5, /*  93 */ 5, /*  94 */
   817       6, /*  95 */ 2, /*  96 */ 3, /*  97 */ 3, /*  98 */ 4, /*  99 */
   818       3, /* 100 */ 4, /* 101 */ 4, /* 102 */ 5, /* 103 */ 3, /* 104 */
   819       4, /* 105 */ 4, /* 106 */ 5, /* 107 */ 4, /* 108 */ 5, /* 109 */
   820       5, /* 110 */ 6, /* 111 */ 3, /* 112 */ 4, /* 113 */ 4, /* 114 */
   821       5, /* 115 */ 4, /* 116 */ 5, /* 117 */ 5, /* 118 */ 6, /* 119 */
   822       4, /* 120 */ 5, /* 121 */ 5, /* 122 */ 6, /* 123 */ 5, /* 124 */
   823       6, /* 125 */ 6, /* 126 */ 7, /* 127 */ 1, /* 128 */ 2, /* 129 */
   824       2, /* 130 */ 3, /* 131 */ 2, /* 132 */ 3, /* 133 */ 3, /* 134 */
   825       4, /* 135 */ 2, /* 136 */ 3, /* 137 */ 3, /* 138 */ 4, /* 139 */
   826       3, /* 140 */ 4, /* 141 */ 4, /* 142 */ 5, /* 143 */ 2, /* 144 */
   827       3, /* 145 */ 3, /* 146 */ 4, /* 147 */ 3, /* 148 */ 4, /* 149 */
   828       4, /* 150 */ 5, /* 151 */ 3, /* 152 */ 4, /* 153 */ 4, /* 154 */
   829       5, /* 155 */ 4, /* 156 */ 5, /* 157 */ 5, /* 158 */ 6, /* 159 */
   830       2, /* 160 */ 3, /* 161 */ 3, /* 162 */ 4, /* 163 */ 3, /* 164 */
   831       4, /* 165 */ 4, /* 166 */ 5, /* 167 */ 3, /* 168 */ 4, /* 169 */
   832       4, /* 170 */ 5, /* 171 */ 4, /* 172 */ 5, /* 173 */ 5, /* 174 */
   833       6, /* 175 */ 3, /* 176 */ 4, /* 177 */ 4, /* 178 */ 5, /* 179 */
   834       4, /* 180 */ 5, /* 181 */ 5, /* 182 */ 6, /* 183 */ 4, /* 184 */
   835       5, /* 185 */ 5, /* 186 */ 6, /* 187 */ 5, /* 188 */ 6, /* 189 */
   836       6, /* 190 */ 7, /* 191 */ 2, /* 192 */ 3, /* 193 */ 3, /* 194 */
   837       4, /* 195 */ 3, /* 196 */ 4, /* 197 */ 4, /* 198 */ 5, /* 199 */
   838       3, /* 200 */ 4, /* 201 */ 4, /* 202 */ 5, /* 203 */ 4, /* 204 */
   839       5, /* 205 */ 5, /* 206 */ 6, /* 207 */ 3, /* 208 */ 4, /* 209 */
   840       4, /* 210 */ 5, /* 211 */ 4, /* 212 */ 5, /* 213 */ 5, /* 214 */
   841       6, /* 215 */ 4, /* 216 */ 5, /* 217 */ 5, /* 218 */ 6, /* 219 */
   842       5, /* 220 */ 6, /* 221 */ 6, /* 222 */ 7, /* 223 */ 3, /* 224 */
   843       4, /* 225 */ 4, /* 226 */ 5, /* 227 */ 4, /* 228 */ 5, /* 229 */
   844       5, /* 230 */ 6, /* 231 */ 4, /* 232 */ 5, /* 233 */ 5, /* 234 */
   845       6, /* 235 */ 5, /* 236 */ 6, /* 237 */ 6, /* 238 */ 7, /* 239 */
   846       4, /* 240 */ 5, /* 241 */ 5, /* 242 */ 6, /* 243 */ 5, /* 244 */
   847       6, /* 245 */ 6, /* 246 */ 7, /* 247 */ 5, /* 248 */ 6, /* 249 */
   848       6, /* 250 */ 7, /* 251 */ 6, /* 252 */ 7, /* 253 */ 7, /* 254 */
   849       8  /* 255 */
   850     }; // end _Bit_count
   851 
   852     template <bool dummy>
   853     unsigned char first_bit_location<dummy>::value[] = {
   854       0, /*   0 */ 0, /*   1 */ 1, /*   2 */ 0, /*   3 */ 2, /*   4 */
   855       0, /*   5 */ 1, /*   6 */ 0, /*   7 */ 3, /*   8 */ 0, /*   9 */
   856       1, /*  10 */ 0, /*  11 */ 2, /*  12 */ 0, /*  13 */ 1, /*  14 */
   857       0, /*  15 */ 4, /*  16 */ 0, /*  17 */ 1, /*  18 */ 0, /*  19 */
   858       2, /*  20 */ 0, /*  21 */ 1, /*  22 */ 0, /*  23 */ 3, /*  24 */
   859       0, /*  25 */ 1, /*  26 */ 0, /*  27 */ 2, /*  28 */ 0, /*  29 */
   860       1, /*  30 */ 0, /*  31 */ 5, /*  32 */ 0, /*  33 */ 1, /*  34 */
   861       0, /*  35 */ 2, /*  36 */ 0, /*  37 */ 1, /*  38 */ 0, /*  39 */
   862       3, /*  40 */ 0, /*  41 */ 1, /*  42 */ 0, /*  43 */ 2, /*  44 */
   863       0, /*  45 */ 1, /*  46 */ 0, /*  47 */ 4, /*  48 */ 0, /*  49 */
   864       1, /*  50 */ 0, /*  51 */ 2, /*  52 */ 0, /*  53 */ 1, /*  54 */
   865       0, /*  55 */ 3, /*  56 */ 0, /*  57 */ 1, /*  58 */ 0, /*  59 */
   866       2, /*  60 */ 0, /*  61 */ 1, /*  62 */ 0, /*  63 */ 6, /*  64 */
   867       0, /*  65 */ 1, /*  66 */ 0, /*  67 */ 2, /*  68 */ 0, /*  69 */
   868       1, /*  70 */ 0, /*  71 */ 3, /*  72 */ 0, /*  73 */ 1, /*  74 */
   869       0, /*  75 */ 2, /*  76 */ 0, /*  77 */ 1, /*  78 */ 0, /*  79 */
   870       4, /*  80 */ 0, /*  81 */ 1, /*  82 */ 0, /*  83 */ 2, /*  84 */
   871       0, /*  85 */ 1, /*  86 */ 0, /*  87 */ 3, /*  88 */ 0, /*  89 */
   872       1, /*  90 */ 0, /*  91 */ 2, /*  92 */ 0, /*  93 */ 1, /*  94 */
   873       0, /*  95 */ 5, /*  96 */ 0, /*  97 */ 1, /*  98 */ 0, /*  99 */
   874       2, /* 100 */ 0, /* 101 */ 1, /* 102 */ 0, /* 103 */ 3, /* 104 */
   875       0, /* 105 */ 1, /* 106 */ 0, /* 107 */ 2, /* 108 */ 0, /* 109 */
   876       1, /* 110 */ 0, /* 111 */ 4, /* 112 */ 0, /* 113 */ 1, /* 114 */
   877       0, /* 115 */ 2, /* 116 */ 0, /* 117 */ 1, /* 118 */ 0, /* 119 */
   878       3, /* 120 */ 0, /* 121 */ 1, /* 122 */ 0, /* 123 */ 2, /* 124 */
   879       0, /* 125 */ 1, /* 126 */ 0, /* 127 */ 7, /* 128 */ 0, /* 129 */
   880       1, /* 130 */ 0, /* 131 */ 2, /* 132 */ 0, /* 133 */ 1, /* 134 */
   881       0, /* 135 */ 3, /* 136 */ 0, /* 137 */ 1, /* 138 */ 0, /* 139 */
   882       2, /* 140 */ 0, /* 141 */ 1, /* 142 */ 0, /* 143 */ 4, /* 144 */
   883       0, /* 145 */ 1, /* 146 */ 0, /* 147 */ 2, /* 148 */ 0, /* 149 */
   884       1, /* 150 */ 0, /* 151 */ 3, /* 152 */ 0, /* 153 */ 1, /* 154 */
   885       0, /* 155 */ 2, /* 156 */ 0, /* 157 */ 1, /* 158 */ 0, /* 159 */
   886       5, /* 160 */ 0, /* 161 */ 1, /* 162 */ 0, /* 163 */ 2, /* 164 */
   887       0, /* 165 */ 1, /* 166 */ 0, /* 167 */ 3, /* 168 */ 0, /* 169 */
   888       1, /* 170 */ 0, /* 171 */ 2, /* 172 */ 0, /* 173 */ 1, /* 174 */
   889       0, /* 175 */ 4, /* 176 */ 0, /* 177 */ 1, /* 178 */ 0, /* 179 */
   890       2, /* 180 */ 0, /* 181 */ 1, /* 182 */ 0, /* 183 */ 3, /* 184 */
   891       0, /* 185 */ 1, /* 186 */ 0, /* 187 */ 2, /* 188 */ 0, /* 189 */
   892       1, /* 190 */ 0, /* 191 */ 6, /* 192 */ 0, /* 193 */ 1, /* 194 */
   893       0, /* 195 */ 2, /* 196 */ 0, /* 197 */ 1, /* 198 */ 0, /* 199 */
   894       3, /* 200 */ 0, /* 201 */ 1, /* 202 */ 0, /* 203 */ 2, /* 204 */
   895       0, /* 205 */ 1, /* 206 */ 0, /* 207 */ 4, /* 208 */ 0, /* 209 */
   896       1, /* 210 */ 0, /* 211 */ 2, /* 212 */ 0, /* 213 */ 1, /* 214 */
   897       0, /* 215 */ 3, /* 216 */ 0, /* 217 */ 1, /* 218 */ 0, /* 219 */
   898       2, /* 220 */ 0, /* 221 */ 1, /* 222 */ 0, /* 223 */ 5, /* 224 */
   899       0, /* 225 */ 1, /* 226 */ 0, /* 227 */ 2, /* 228 */ 0, /* 229 */
   900       1, /* 230 */ 0, /* 231 */ 3, /* 232 */ 0, /* 233 */ 1, /* 234 */
   901       0, /* 235 */ 2, /* 236 */ 0, /* 237 */ 1, /* 238 */ 0, /* 239 */
   902       4, /* 240 */ 0, /* 241 */ 1, /* 242 */ 0, /* 243 */ 2, /* 244 */
   903       0, /* 245 */ 1, /* 246 */ 0, /* 247 */ 3, /* 248 */ 0, /* 249 */
   904       1, /* 250 */ 0, /* 251 */ 2, /* 252 */ 0, /* 253 */ 1, /* 254 */
   905       0, /* 255 */
   906     }; // end _First_one
   907 
   908   } // namespace detail
   909 
   910 } // namespace boost