Main Page   Reference Manual   Compound List   File List  

libecc/bitset.h

Go to the documentation of this file.
00001 //
00006 //
00007 // This file is part of the libecc package.
00008 // Copyright (C) 2002, by
00009 //
00010 // Carlo Wood, Run on IRC <carlo@alinoe.com>
00011 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
00012 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
00013 //
00014 // This program is free software; you can redistribute it and/or
00015 // modify it under the terms of the GNU General Public License
00016 // as published by the Free Software Foundation; either version 2
00017 // of the License, or (at your option) any later version.
00018 //
00019 // This program is distributed in the hope that it will be useful,
00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 // GNU General Public License for more details.
00023 //
00024 // You should have received a copy of the GNU General Public License
00025 // along with this program; if not, write to the Free Software
00026 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00027 
00028 #ifndef LIBECC_BITS_H
00029 #define LIBECC_BITS_H
00030 
00031 #ifndef LIBECC_DEBUG_H
00032 #error "You need to include the appropriate debug.h in the source file, before including this header file."
00033 #endif
00034 
00035 #include <libecc/config.h>
00036 #include <iosfwd>
00037 #include <cstddef>
00038 #include <cstring>
00039 #include <string>
00040 #include <inttypes.h>
00041 #include <cassert>
00042 #include <endian.h>
00043 #ifdef CWDEBUG
00044 #include "debug.h"
00045 #include <libcwd/cwprint.h>
00046 #endif
00047 #define LIBECC_TRACK_EXPR_TEMPORARIES (ECC_DEBUG && 1)
00048 #if LIBECC_TRACK_EXPR_TEMPORARIES
00049 #include <set>
00050 #endif
00051 
00052 #if defined(__i386__) && defined(HAVE_NASM)
00053 // Assembly code, defined in window.s.
00054 extern "C" int libecc_shift_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00055 extern "C" int libecc_shiftwindow_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00056 #endif
00057 
00058 namespacelibecc {
00059 
00069 typedef unsigned long bitset_digit_t;
00070 
00072 static unsigned int const bitset_digit_bits = sizeof(bitset_digit_t) * 8;
00073 
00075 #if ECC_BITS == 32
00076 static unsigned int const bitset_digit_bits_log2 = 5;
00077 #elif ECC_BITS == 64
00078 static unsigned int const bitset_digit_bits_log2 = 6;
00079 #elif ECC_BITS == 128
00080 #warning 128 bit code has not been tested.  This warning will remain here until you mail me.
00081 static unsigned int const bitset_digit_bits_log2 = 7;
00082 #endif
00083 
00084 //------------------------------------------------------------------------------------------------------------------
00085 // Iterators
00086 //
00087 
00097 classbitset_index {
00098 #if defined(__i386__) || defined(LIBECC_DOXYGEN)
00099   protected:
00100     int M_index;                        
00101 
00102   public:
00103     // Accessors.
00104     int get_index(void) const;
00105 
00106 #else
00107   protected:
00108     int M_digit;                        
00109     bitset_digit_t M_mask;              
00110 
00111   public:
00112     // Accessors.
00113     int get_digit(void) const;
00114     bitset_digit_t get_mask(void) const;
00115 
00116     // Used in polynomial.h
00117     int get_index(void) const;
00118 #endif
00119 
00120   public:
00121     // Equality Comparable.
00122     friend bool operator==(bitset_index const& i1, bitset_index const& i2);
00123     friend bool operator!=(bitset_index const& i1, bitset_index const& i2);
00124 
00125   protected:
00126     // Bidirectional.
00127     void left(void);
00128     void right(void);
00129 
00130     // Random access.
00131     void left(int n);
00132     void right(int n);
00133     friend int subtract(bitset_index const& i1, bitset_index const& i2);
00134 
00135   protected:
00136     // Constructors.
00137     bitset_index(void);
00138     bitset_index(bitset_index const& index);
00139     bitset_index(int bit);
00140 
00141   public:
00142     friend std::ostream& operator<<(std::ostream& os, bitset_index const& i);
00143 };
00144 
00145 #if defined(__i386__) || defined(LIBECC_DOXYGEN)
00146 
00150 inline int
00151 bitset_index::get_index(void) const
00152 {
00153   return M_index;
00154 }
00155 
00156 #else // !defined(__i386__)
00157 
00158 // Accessor for the current digit index.
00159 inline int
00160 bitset_index::get_digit(void) const
00161 {
00162   return M_digit;
00163 }
00164 
00165 // Accessor for the current digit mask.
00166 inline bitset_digit_t
00167 bitset_index::get_mask(void) const
00168 { 
00169   return M_mask;
00170 }
00171 
00172 #include <strings.h>   // Needed for ffsl.
00173 inline int
00174 bitset_index::get_index(void) const
00175 {
00176   return M_digit * bitset_digit_bits + ::ffsl(M_mask) - 1;
00177 }
00178 
00179 #endif // !defined(__i386__)
00180 
00184 inline bool
00185 operator==(bitset_index const& i1, bitset_index const& i2)
00186 {
00187 #ifdef __i386__
00188   return (i1.M_index == i2.M_index);
00189 #else
00190   return (i1.M_digit == i2.M_digit && i1.M_mask == i2.M_mask);
00191 #endif
00192 }
00193 
00197 inline bool
00198 operator!=(bitset_index const& i1, bitset_index const& i2)
00199 {
00200 #ifdef __i386__
00201   return (i1.M_index != i2.M_index);
00202 #else
00203   return (i1.M_digit != i2.M_digit || i1.M_mask != i2.M_mask);
00204 #endif
00205 }
00206 
00210 inline
00211 bitset_index::bitset_index(void)
00212 {
00213 }
00214 
00218 inline
00219 bitset_index::bitset_index(bitset_index const& index) :
00220 #ifdef __i386__
00221     M_index(index.M_index)
00222 #else
00223     M_digit(index.M_digit), M_mask(index.M_mask)
00224 #endif
00225 { 
00226 }
00227 
00234 inline
00235 bitset_index::bitset_index(int bit) :
00236 #ifdef __i386__
00237     M_index(bit)
00238 #else
00239     // If bit == -1 then M_digit should become -1 and M_mask 0x80000000.
00240     M_digit(bit >> bitset_digit_bits_log2),
00241     M_mask(static_cast<bitset_digit_t>(1) << ((unsigned int)bit & (bitset_digit_bits - 1)))
00242 #endif
00243 {
00244 }
00245 
00249 inline void
00250 bitset_index::left(void)
00251 {
00252 #ifdef __i386__
00253   ++M_index;
00254 #else
00255   if ((M_mask <<= 1) == 0)
00256   {
00257     ++M_digit;
00258     M_mask = 1;
00259   }
00260 #endif
00261 }
00262 
00266 inline void
00267 bitset_index::right(void)
00268 {
00269 #ifdef __i386__
00270   --M_index;
00271 #else
00272   if ((M_mask >>= 1) == 0)
00273   {
00274     --M_digit;
00275     M_mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
00276   }
00277 #endif
00278 }
00279 
00283 inline void
00284 bitset_index::left(int n)
00285 {
00286 #ifdef __i386__
00287   M_index += n;
00288 #else
00289   int const digit_shift = n >> bitset_digit_bits_log2;
00290   int const mask_shift = n & (bitset_digit_bits - 1);
00291   M_digit += digit_shift;
00292   if (mask_shift)
00293   {
00294     bitset_digit_t new_mask = M_mask << mask_shift;
00295     if (new_mask == 0)
00296     {
00297       ++M_digit;
00298       new_mask = M_mask >> (bitset_digit_bits - mask_shift);
00299     }
00300     M_mask = new_mask;
00301   }
00302 #endif
00303 }
00304 
00308 inline void
00309 bitset_index::right(int n)
00310 {
00311 #ifdef __i386__
00312   M_index -= n;
00313 #else
00314   int const digit_shift = n >> bitset_digit_bits_log2;
00315   int const mask_shift = n & (bitset_digit_bits - 1);
00316   M_digit -= digit_shift;
00317   if (mask_shift)
00318   {
00319     bitset_digit_t new_mask = M_mask >> mask_shift;
00320     if (new_mask == 0)
00321     {
00322       --M_digit;
00323       new_mask = M_mask << (bitset_digit_bits - mask_shift);
00324     }
00325     M_mask = new_mask;
00326   }
00327 #endif
00328 }
00329 
00330 enum {
00331   forwards_iterating,
00332   backwards_iterating
00333 };
00334 
00335 // Forward declarations.
00336 template<int DIRECTION> classbitset_index_iterator;
00337 template<int DIRECTION> bool operator<(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
00338 template<int DIRECTION> bool operator>(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
00339 template<int DIRECTION> bool operator<=(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
00340 template<int DIRECTION> bool operator>=(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
00341 
00350 template<int DIRECTION>
00351   classbitset_index_iterator : public bitset_index {
00352     public:
00353       // LessThan Comparable.
00354       friend bool operator< <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
00355       friend bool operator> <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
00356       friend bool operator<= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
00357       friend bool operator>= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
00358 
00359     public:
00360       // Bidirectional.
00361       void increment(void);
00362       void decrement(void);
00363 
00364       // Random access.
00365       void increment(int n);
00366       void decrement(int n);
00367 
00368       friend int operator-(bitset_index const& i1, bitset_index const& i2);
00369 
00370     public:
00371       // Constructors.
00372       bitset_index_iterator(void);
00373       bitset_index_iterator(bitset_index_iterator const& index);
00374       bitset_index_iterator(int bit);
00375   };
00376 
00380 template<int DIRECTION>
00381   inline
00382   bitset_index_iterator<DIRECTION>::bitset_index_iterator(void)
00383   {
00384   }
00385 
00389 template<int DIRECTION>
00390   inline
00391   bitset_index_iterator<DIRECTION>::bitset_index_iterator(bitset_index_iterator<DIRECTION> const& index) :
00392       bitset_index(index)
00393   { 
00394   }
00395 
00402 template<int DIRECTION>
00403   inline
00404   bitset_index_iterator<DIRECTION>::bitset_index_iterator(int bit) : bitset_index(bit)
00405   {
00406   }
00407 
00411 template<int DIRECTION>
00412   inline bool
00413   operator<(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00414   {
00415 #ifdef __i386__
00416     if (DIRECTION == forwards_iterating)
00417       return (i1.M_index < i2.M_index);
00418     else
00419       return (i1.M_index > i2.M_index);
00420 #else
00421     if (DIRECTION == forwards_iterating)
00422       return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
00423     else
00424       return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
00425 #endif
00426   }
00427 
00431 template<int DIRECTION>
00432   inline bool
00433   operator>(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00434   {
00435 #ifdef __i386__
00436     if (DIRECTION == forwards_iterating)
00437       return (i1.M_index > i2.M_index);
00438     else
00439       return (i1.M_index < i2.M_index);
00440 #else
00441     if (DIRECTION == forwards_iterating)
00442       return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
00443     else
00444       return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
00445 #endif
00446   }
00447 
00451 template<int DIRECTION>
00452   inline bool
00453   operator<=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00454   {
00455 #ifdef __i386__
00456     if (DIRECTION == forwards_iterating)
00457       return (i1.M_index <= i2.M_index);
00458     else
00459       return (i1.M_index >= i2.M_index);
00460 #else
00461     if (DIRECTION == forwards_iterating)
00462       return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
00463     else
00464       return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
00465 #endif
00466   }
00467 
00471 template<int DIRECTION>
00472   inline bool
00473   operator>=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00474   {
00475 #ifdef __i386__
00476     if (DIRECTION == forwards_iterating)
00477       return (i1.M_index >= i2.M_index);
00478     else
00479       return (i1.M_index <= i2.M_index);
00480 #else
00481     if (DIRECTION == forwards_iterating)
00482       return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
00483     else
00484       return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
00485 #endif
00486   }
00487 
00491 template<int DIRECTION>
00492   inline void
00493   bitset_index_iterator<DIRECTION>::increment(void)
00494   {
00495     if (DIRECTION == forwards_iterating)
00496       left();
00497     else
00498       right();
00499   }
00500 
00504 template<int DIRECTION>
00505   inline void
00506   bitset_index_iterator<DIRECTION>::decrement(void)
00507   {
00508     if (DIRECTION == forwards_iterating)
00509       right();
00510     else
00511       left();
00512   }
00513 
00517 template<int DIRECTION>
00518   inline void
00519   bitset_index_iterator<DIRECTION>::increment(int n)
00520   {
00521     if (DIRECTION == forwards_iterating)
00522       left(n);
00523     else
00524       right(n);
00525   }
00526 
00530 template<int DIRECTION>
00531   inline void
00532   bitset_index_iterator<DIRECTION>::decrement(int n)
00533   {
00534     if (DIRECTION == forwards_iterating)
00535       right(n);
00536     else
00537       left(n);
00538   }
00539 
00540 template<int DIRECTION>
00541   inline int
00542   operator-(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00543   {
00544     return (DIRECTION == forwards_iterating) ? subtract(i1, i2) : subtract(i2, i1);
00545   }
00546 
00547 // Forward declarations.
00548 template<unsigned int N, int DIRECTION> classbitset_iterator;
00549 template<unsigned int N, int DIRECTION> bitset_iterator<N, DIRECTION> operator+(bitset_iterator<N, DIRECTION> const&, int);
00550 template<unsigned int N, int DIRECTION> bitset_iterator<N, DIRECTION> operator+(int, bitset_iterator<N, DIRECTION> const&);
00551 template<unsigned int N, int DIRECTION> bitset_iterator<N, DIRECTION> operator-(bitset_iterator<N, DIRECTION> const&, int);
00552 template<unsigned int N, int DIRECTION> bitset_iterator<N, DIRECTION> operator-(int, bitset_iterator<N, DIRECTION> const&);
00553 template<unsigned int N> structbitset_base;
00554 template<unsigned int N, bool inverted> classbitset_invertible;
00555 
00565 template<unsigned int N, int DIRECTION>
00566   classbitset_iterator : public bitset_index_iterator<DIRECTION>,
00567                           public std::iterator<std::random_access_iterator_tag, bitset_digit_t,
00568                                                int, bitset_digit_t*, bitset_digit_t&> {
00569     protected:
00570       bitset_base<N> const* M_bitset_ptr;
00571 
00572     public:
00573       // Default Constructible
00574       bitset_iterator(void);
00575 
00576       // Assignable
00577       bitset_iterator(bitset_iterator const& iter);
00578       bitset_iterator& operator=(bitset_iterator const& iter);
00579       bitset_iterator& operator=(bitset_index_iterator<DIRECTION> const& index);
00580 
00581       // Dereferencable
00582       bitset_digit_t operator*() const;
00583 
00584       // Bi-directional iterator
00585       //
00586       bitset_iterator& operator++();
00587       bitset_iterator operator++(int);
00588       bitset_iterator& operator--();
00589       bitset_iterator operator--(int);
00590 
00591       // Random Access Iterator
00592       //
00593       bitset_iterator& operator+=(int n);
00594       friend bitset_iterator operator+ <>(bitset_iterator const& i, int n);
00595       friend bitset_iterator operator+ <>(int n, bitset_iterator const& i);
00596       bitset_iterator& operator-=(int n);
00597       friend bitset_iterator operator- <>(bitset_iterator const& i, int n);
00598       friend bitset_iterator operator- <>(int n, bitset_iterator const& i);
00599       bitset_digit_t operator[](int n) const;
00600 
00601       // Special
00602       //
00603       bitset_iterator(bitset_base<N> const* bitset_ptr, int bit);
00604       void find1(void);
00605 
00606 #ifndef __i386__
00607     private:
00608       void find1_forward(void);
00609       void find1_backward(void);
00610 #endif
00611   };
00612 
00622 template<unsigned int N>
00623   structbitset_base {
00624     public:
00625       // Fix this if you add members in front of vector.
00626       static size_t const offsetof_vector = 0; //sizeof(bitset_digit_t);
00627 
00628     public:
00632       static unsigned int const number_of_bits = N;
00633 
00635       static unsigned int const digits = (N == 0) ? 0 : ((N - 1) / bitset_digit_bits + 1);
00636 
00637       // ! The number of valid bits in the most significant digit.
00638       static unsigned int const number_of_valid_bits = bitset_digit_bits - (digits * bitset_digit_bits - N);
00639 
00641       static bitset_digit_t const valid_bits = ((static_cast<bitset_digit_t>(1) << (number_of_valid_bits - 1)) << 1) - 1;
00642 
00644       static bool const has_excess_bits = ((digits * bitset_digit_bits) != N);
00645 
00646     protected:
00653       //bitset_digit_t empty_space1;
00654       bitset_digit_t vector[digits];
00655       //bitset_digit_t empty_space2;
00656 
00657       template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00658         friend bool operator==(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00659 
00660       template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00661         friend bool operator!=(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00662 
00663     public:
00664       // Digit representation
00665       bitset_digit_t& rawdigit(unsigned int d) { return this->vector[d]; }
00666       bitset_digit_t rawdigit(unsigned int d) const{ return this->vector[d]; }
00667       bitset_digit_t* digits_ptr(void) { return this->vector; }
00668       bitset_digit_t const* digits_ptr(void) const{ return this->vector; }
00669       uint32_t digit32(unsigned int d32) const
00670      {
00671         if (sizeof(bitset_digit_t) == 4)
00672           return this->vector[d32];
00673         else
00674         {
00675           unsigned int d = d32 / (sizeof(bitset_digit_t) / 4);
00676           unsigned int r = d32 % (sizeof(bitset_digit_t) / 4);
00677 #if __BYTE_ORDER == __LITTLE_ENDIAN
00678           return (this->vector[d] >> (r * 32));
00679 #elif __BYTE_ORDER == __BIG_ENDIAN
00680           return (this->vector[d] >> (bitset_digit_bits - 32 - (r * 32)));
00681 #endif
00682         }
00683       }
00684 
00685     public:
00686       // Iterator stuff.
00688       typedef bitset_iterator<N, forwards_iterating> const_iterator;
00690       typedef bitset_iterator<N, backwards_iterating> const_reverse_iterator;
00692       const_iterator begin(void) const{ return const_iterator(this, 0); }
00694       const_iterator end(void) const{ return const_iterator(this, N); }
00696       const_reverse_iterator rbegin(void) const{ return const_reverse_iterator(this, N - 1); }
00698       const_reverse_iterator rend(void) const{ return const_reverse_iterator(this, -1); }
00699 
00700       template<unsigned int m>
00701         void xor_with_zero_padded(bitset_base<m> const& bitset, int lsb, int msb, int shift);
00702 
00703       // Slower functions for shifting an arbitrary distance.
00704       void operator<<=(unsigned int shift);
00705       void operator>>=(unsigned int shift);
00706 
00707       // Single bit operations
00708       bool test(size_t n) const;                                        // Return true if bit `n' is set.
00709       bool odd(void) const;                                             // Return true if the vector has an odd number of bits set.
00710       void set(size_t n);                                               // Set bit `n'.
00711       void clear(size_t n);                                             // Clear bit `n'.
00712       void flip(size_t n);                                              // Toggle bit `n'.
00713 
00714       // Single bit operations using iterators.
00715       bool test(bitset_index const& index) const;                       // Return true if bit refered to by `index' is set.
00716       void set(bitset_index const& index);                              // Set bit refered to by `index'.
00717       void clear(bitset_index const& index);                            // Clear bit refered to by `index'.
00718       void flip(bitset_index const& index);                             // Toggle bit refered to by `index'.
00719 
00720       // Single bit operations at a constant position
00721       template<unsigned int pos>
00722         bool test(void) const;                                          // Return true if bit `pos' is set.
00723       template<unsigned int pos>
00724         void set(void);                                                 // Set bit `pos'.
00725       template<unsigned int pos>
00726         void clear(void);                                               // Clear bit `pos'.
00727       template<unsigned int pos>
00728         void flip(void);                                                // Toggle bit `pos'.
00729 
00730       // Other functions
00731       void reset(void);
00732       void setall(void);
00733       bool any(void) const;
00734   };
00735 
00752 template<unsigned int N>
00753   template<unsigned int m>
00754 #if defined(__i386__) && defined(HAVE_NASM)
00755   inline
00756 #endif
00757   void
00758   bitset_base<N>::xor_with_zero_padded(bitset_base<m> const& bitset, int lsb, int msb, int shift)
00759   {
00760 #if defined(__i386__) && defined(HAVE_NASM)
00761     libecc_shift_xorassign(this->vector, bitset.digits_ptr(), lsb, msb, shift);
00762 #else
00763     int digit1 = lsb >> bitset_digit_bits_log2;
00764     int digit2 = msb >> bitset_digit_bits_log2;
00765     bitset_digit_t d1 = 0;
00766     // We can't use bitset.digit() because we need access to negative indexes.
00767     bitset_digit_t const* const digits_ptr = bitset.digits_ptr();
00768     if (shift < 0)
00769     {
00770       int bitshift = (-shift) & (bitset_digit_bits - 1);
00771       int digitshift = (-shift) >> bitset_digit_bits_log2;
00772       if (bitshift == 0)
00773       {
00774         for (int digit = digit2; digit >= digit1; --digit)
00775         {
00776           bitset_digit_t d2 = digits_ptr[digit];
00777           this->vector[digit - digitshift] ^= d2;
00778         }
00779       }
00780       else
00781       {
00782         for (int digit = digit2; digit >= digit1; --digit)
00783         {
00784           bitset_digit_t d2 = digits_ptr[digit];
00785           this->vector[digit - digitshift] ^= (d2 >> bitshift) | (d1 << (bitset_digit_bits - bitshift));
00786           d1 = d2;
00787         }
00788         this->vector[digit1 - 1 - digitshift] ^= (d1 << (bitset_digit_bits - bitshift));
00789       }
00790     }
00791     else if (shift > 0)
00792     {
00793       int bitshift = shift & (bitset_digit_bits - 1);
00794       int digitshift = shift >> bitset_digit_bits_log2;
00795       if (bitshift == 0)
00796       {
00797         for (int digit = digit1; digit <= digit2; ++digit)
00798         {
00799           bitset_digit_t d2 = digits_ptr[digit];
00800           this->vector[digit + digitshift] ^= d2;
00801           d1 = d2;
00802         }
00803       }
00804       else
00805       {
00806         for (int digit = digit1; digit <= digit2; ++digit)
00807         {
00808           bitset_digit_t d2 = digits_ptr[digit];
00809           this->vector[digit + digitshift] ^= (d2 << bitshift) | (d1 >> (bitset_digit_bits - bitshift));
00810           d1 = d2;
00811         }
00812         this->vector[digit2 + 1 + digitshift] ^= (d1 >> (bitset_digit_bits - bitshift));
00813       }
00814     }
00815     else
00816     {
00817       for (int digit = digit1; digit <= digit2; ++digit)
00818         this->vector[digit] ^= digits_ptr[digit];
00819     }
00820 #endif
00821   }
00822 
00823 #ifndef HIDE_FROM_DOXYGEN
00824 namespaceOperator {
00825 
00826 #ifdef __i386__
00827 
00828 //
00829 // Due to heavily broken inlining heuristics of gcc,
00830 // we are forced to use macros to do the assembly
00831 // inlining.  There is no alternative, I tried everything.
00832 //
00833 
00834 #define LIBECC_INVERT "xorl $-1,%%eax\n\t"
00835 #define LIBECC_NOTHING ""
00836 
00837 #define LIBECC_ASMLOOP(destination, source, count, OPCODE, OPTIONAL_INVERT)     \
00838   do {                                                  \
00839     int __d0, __d1, __d2;                               \
00840     __asm__ __volatile__ (                              \
00841       "\n1:\n\t"                                        \
00842         "movl (%5,%%ecx,4),%%eax\n\t"                   \
00843         OPTIONAL_INVERT                                 \
00844         OPCODE " %%eax,(%4,%%ecx,4)\n\t"                \
00845         "decl %%ecx\n\t"                                \
00846         "jnz 1b"                                        \
00847         : "=c" (__d0), "=&r" (__d1), "=&r" (__d2)       \
00848         : "0" (count),                                  \
00849           "1" ((destination) - 1),                      \
00850           "2" ((source) - 1)                            \
00851         : "%eax", "memory"                              \
00852     );                                                  \
00853   } while(0)
00854 
00855 #define LIBECC_ASMLOOP_BODY(OPCODE, destination, source, count, inverted) \
00856   do { \
00857     if (inverted) \
00858       LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_INVERT); \
00859     else \
00860       LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_NOTHING); \
00861   } while(0)
00862 
00863 #define LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, OPTIONAL_INVERT1, OPCODE2, OPTIONAL_INVERT3)              \
00864   do {                                                          \
00865     int __d0, __d1, __d2, __d3;                                 \
00866     __asm__ __volatile__ (                                      \
00867       "\n1:\n\t"                                                \
00868         "movl (%6,%%ecx,4),%%eax\n\t"                           \
00869         OPTIONAL_INVERT1                                        \
00870         OPCODE2 " (%7,%%ecx,4),%%eax\n\t"                       \
00871         OPTIONAL_INVERT3                                        \
00872         OPCODE " %%eax,(%5,%%ecx,4)\n\t"                        \
00873         "decl %%ecx\n\t"                                        \
00874         "jnz 1b"                                                \
00875         : "=c" (__d0), "=&r" (__d1), "=&r" (__d2), "=&r" (__d3) \
00876         : "0" (count),                                          \
00877           "1" ((destination) - 1),                              \
00878           "2" ((source1) - 1),                                  \
00879           "3" ((source2) - 1)                                   \
00880         : "%eax", "memory"                                      \
00881     );                                                          \
00882   } while(0)
00883 
00884 #define LIBECC_ASMLOOP2_BODY(OPCODE, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00885   do { \
00886     if (OPERATOR::id == libecc::Operator::bitsetAND::id) \
00887     { \
00888       if (inverted1 && inverted2) \
00889         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_INVERT); \
00890       else if (inverted1) \
00891         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00892       else if (inverted2) \
00893         LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00894       else \
00895         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_NOTHING); \
00896     } \
00897     else if (OPERATOR::id == libecc::Operator::bitsetOR::id) \
00898     { \
00899       if (inverted1 && inverted2) \
00900         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_INVERT); \
00901       else if (inverted1) \
00902         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00903       else if (inverted2) \
00904         LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00905       else \
00906         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_NOTHING); \
00907     } \
00908     else if (OPERATOR::id == libecc::Operator::bitsetXOR::id) \
00909     { \
00910       if (inverted1 == inverted2) \
00911         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_NOTHING); \
00912       else \
00913         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_INVERT); \
00914     } \
00915   } while(0)
00916 
00917 #define LIBECC_INLINE_ASMLOOP(ID, destination, source, count, inverted) \
00918     do { \
00919       if (ID == libecc::Operator::bitsetAssign::id) \
00920       { \
00921         LIBECC_ASMLOOP_BODY("movl", destination, source, count, inverted); \
00922       } \
00923       else if (ID == libecc::Operator::bitsetANDAssign::id) \
00924       { \
00925         LIBECC_ASMLOOP_BODY("andl", destination, source, count, inverted); \
00926       } \
00927       else if (ID == libecc::Operator::bitsetORAssign::id) \
00928       { \
00929         LIBECC_ASMLOOP_BODY("orl", destination, source, count, inverted); \
00930       } \
00931       else if (ID == libecc::Operator::bitsetXORAssign::id) \
00932       { \
00933         LIBECC_ASMLOOP_BODY("xorl", destination, source, count, inverted); \
00934       } \
00935     } while(0)
00936 
00937 #define LIBECC_INLINE_ASMLOOP2(ID, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00938     do { \
00939       if (ID == libecc::Operator::bitsetAssign::id) \
00940       { \
00941         LIBECC_ASMLOOP2_BODY("movl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00942       } \
00943       else if (ID == libecc::Operator::bitsetANDAssign::id) \
00944       { \
00945         LIBECC_ASMLOOP2_BODY("andl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00946       } \
00947       else if (ID == libecc::Operator::bitsetORAssign::id) \
00948       { \
00949         LIBECC_ASMLOOP2_BODY("orl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00950       } \
00951       else if (ID == libecc::Operator::bitsetXORAssign::id) \
00952       { \
00953         LIBECC_ASMLOOP2_BODY("xorl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00954       } \
00955     } while(0)
00956 
00957 #define LIBECC_ASMSHIFTRIGHT0(OP1)                      \
00958               __asm__ __volatile__ (                    \
00959                   "movl 4(%%esi),%%edx\n\t"             \
00960                   "shrl $1,%%edx\n\t"                   \
00961                   OP1                                   \
00962                   "movl %%edx,4(%%edi)"                 \
00963                 : "=&S" (ptr1),                         \
00964                   "=&D" (ptr2)                          \
00965                 : "0" (&this->vector[initial - count]), \
00966                   "1" (&result.vector[initial - count]) \
00967                 : "%eax", "%edx", "memory", "cc"        \
00968               )
00969 
00970 #if 0   // NOT faster.
00971 #define LIBECC_OP1_SOURCE "(%%esi)"
00972 #define LIBECC_OP2_SOURCE "(%%esi)"
00973 #define LIBECC_OP1_DESTINATION "(%%edi)"
00974 #define LIBECC_OP2_DESTINATION "(%%edi)"
00975 #define LIBECC_WORKREG "%%eax"
00976 #define LIBECC_CLOBBER "%eax"
00977 #define LIBECC_INIT "std\n\t"
00978 #define LIBECC_LOAD1 "lodsl\n\t"
00979 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00980 #define LIBECC_STORE1 "stosl\n\t"
00981 #define LIBECC_LOAD2 "lodsl\n\t"
00982 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
00983 #define LIBECC_STORE2 "stosl\n\t"
00984 #define LIBECC_DEINIT "cld\n\t"
00985 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "setc %%edx\n\t" OPERAND "\n\tbt $0,%%edx\n\t"
00986 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%edx"
00987 #define LIBECC_INITIAL_ESI &this->vector[initial]
00988 #define LIBECC_INITIAL_EDI &result.vector[initial]
00989 #else
00990 #define LIBECC_OP1_SOURCE "4(%%esi,%%ecx,4)"
00991 #define LIBECC_OP2_SOURCE "(%%esi,%%ecx,4)"
00992 #define LIBECC_OP1_DESTINATION "4(%%edi,%%ecx,4)"
00993 #define LIBECC_OP2_DESTINATION "(%%edi,%%ecx,4)"
00994 #define LIBECC_WORKREG "%%edx"
00995 #define LIBECC_CLOBBER "%edx"
00996 #define LIBECC_INIT
00997 #define LIBECC_LOAD1 "movl " LIBECC_OP1_SOURCE "," LIBECC_WORKREG "\n\t"
00998 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00999 #define LIBECC_STORE1 "movl " LIBECC_WORKREG "," LIBECC_OP1_DESTINATION "\n\t"
01000 #define LIBECC_LOAD2 "movl " LIBECC_OP2_SOURCE "," LIBECC_WORKREG "\n\t"
01001 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
01002 #define LIBECC_STORE2 "movl " LIBECC_WORKREG "," LIBECC_OP2_DESTINATION "\n\t"
01003 #define LIBECC_DEINIT
01004 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
01005 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%eax"
01006 #define LIBECC_INITIAL_ESI &this->vector[initial - count]
01007 #define LIBECC_INITIAL_EDI &result.vector[initial - count]
01008 #endif
01009 
01010 #define LIBECC_ASMSHIFTRIGHT1(OP1, OP2, CLOBBER)        \
01011               __asm__ __volatile__ (                    \
01012                   LIBECC_INIT                           \
01013                   LIBECC_LOAD1                          \
01014                   LIBECC_SHIFT                          \
01015                   OP1                                   \
01016                   LIBECC_STORE1                         \
01017                 "1:\n\t"                                \
01018                   LIBECC_LOAD2                          \
01019                   LIBECC_ROTATE                         \
01020                   OP2                                   \
01021                   LIBECC_STORE2                         \
01022                   "decl %%ecx\n\t"                      \
01023                   "jnz 1b\n\t"                          \
01024                   LIBECC_DEINIT                         \
01025                 : "=&S" (ptr1),                         \
01026                   "=&D" (ptr2),                         \
01027                   "=&c" (c)                             \
01028                 : "0" (LIBECC_INITIAL_ESI),             \
01029                   "1" (LIBECC_INITIAL_EDI),             \
01030                   "2" (count - 1)                       \
01031                 : "memory", "cc", CLOBBER               \
01032               )
01033 
01034 #define LIBECC_ASMSHIFTLEFT(OP1, OP2, FINISH)           \
01035               __asm__ __volatile__ (                    \
01036                   "movl -4(%%esi),%%edx\n\t"            \
01037                   "shll $1,%%edx\n\t"                   \
01038                   OP1                                   \
01039                   "movl %%edx,-4(%%edi)\n\t"            \
01040                   "jecxz 2f\n"                          \
01041                 "1:\n\t"                                \
01042                   "movl (%%esi),%%edx\n\t"              \
01043                   "rcll $1,%%edx\n\t"                   \
01044                   OP2                                   \
01045                   "movl %%edx,(%%edi)\n\t"              \
01046                   "leal 4(%%esi),%%esi\n\t"             \
01047                   "leal 4(%%edi),%%edi\n\t"             \
01048                   "decl %%ecx\n\t"                      \
01049                   "jnz 1b\n"                            \
01050                 "2:\n\t"                                \
01051                   FINISH                                \
01052                 : "=&S" (ptr1),                         \
01053                   "=&D" (ptr2),                         \
01054                   "=&c" (c)                             \
01055                 : "0" (&this->vector[initial + 1]),     \
01056                   "1" (&result.vector[initial + 1]),    \
01057                   "2" (count - 1),                      \
01058                   "n" (bitset_base<N>::valid_bits)      \
01059                 : "%eax", "%edx", "memory", "cc"        \
01060               )
01061 
01062 #define LIBECC_ASMSHIFTLEFT_FINISH(OP)                  \
01063                   "movl (%%esi),%%edx\n\t"              \
01064                   "rcll $1,%%edx\n\t"                   \
01065                   "andl %6,%%edx\n\t"                   \
01066                   OP                                    \
01067                   "movl %%edx,(%%edi)"
01068 
01069 #define LIBECC_LEFT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
01070 
01071 #endif // __i386__
01072 
01073 // Functors.
01074 
01075 // Functor for '&'.
01076 structbitsetAND {
01077   static int const id = 1;
01078   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 & digit2; }
01079   template<bool inverted1, bool inverted2>
01080    structexecbool {
01081      static bool const value = inverted1 && inverted2;
01082    };
01083 };
01084 
01085 // Functor for '|'.
01086 structbitsetOR {
01087   static int const id = 2;
01088   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 | digit2; }
01089   template<bool inverted1, bool inverted2>
01090    structexecbool {
01091      static bool const value = inverted1 || inverted2;
01092    };
01093 };
01094 
01095 // Functor for '^'.
01096 structbitsetXOR {
01097   static int const id = 3;
01098   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 ^ digit2; }
01099   template<bool inverted1, bool inverted2>
01100    structexecbool {
01101      static bool const value = (inverted1 != inverted2);
01102    };
01103 };
01104 
01105 // Functor for '='.
01106 structbitsetAssign {
01107   static int const id = 1;
01108   static bool const sets_excess_bits = true;
01109   static bool const with_zero_sets_zero = true;
01110   static bool const with_ones_sets_ones = true;
01111   static bool const with_ones_inverts = false;
01112   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out = in; }
01113 };
01114 
01115 // Functor for '&='.
01116 structbitsetANDAssign {
01117   static int const id = 2;
01118   static bool const sets_excess_bits = false;
01119   static bool const with_zero_sets_zero = true;
01120   static bool const with_ones_sets_ones = false;
01121   static bool const with_ones_inverts = false;
01122   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out &= in; }
01123 };
01124 
01125 // Functor for '|='.
01126 structbitsetORAssign {
01127   static int const id = 3;
01128   static bool const sets_excess_bits = true;
01129   static bool const with_zero_sets_zero = false;
01130   static bool const with_ones_sets_ones = true;
01131   static bool const with_ones_inverts = false;
01132   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out |= in; }
01133 };
01134 
01135 // Functor for '^='.
01136 structbitsetXORAssign {
01137   static int const id = 4;
01138   static bool const sets_excess_bits = true;
01139   static bool const with_zero_sets_zero = false;
01140   static bool const with_ones_sets_ones = false;
01141   static bool const with_ones_inverts = true;
01142   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out ^= in; }
01143 };
01144 
01145 #if LIBECC_TRACK_EXPR_TEMPORARIES
01146 extern std::multiset<void const*> bitsetExpression_bitset_invertible_pointers;
01147 #endif
01148 
01149 template<unsigned int N, bool inverted1, bool inverted2, typename OP>
01150   structbitsetExpression
01151   {
01152     bitset_invertible<N, inverted1> const& first;
01153     bitset_invertible<N, inverted2> const& second;
01154     OP op;
01155 
01156     bitsetExpression(bitset_invertible<N, inverted1> const& arg1, bitset_invertible<N, inverted2> const& arg2) :
01157         first(arg1), second(arg2)
01158     {
01159       // I found a problem with a destructed temporary that was still in use.
01160       // It seems that the pointer to this destructed temporary is stored in
01161       // this object.  The following code is added in order to debug this
01162       // problem.
01163 #if LIBECC_TRACK_EXPR_TEMPORARIES
01164       bitsetExpression_bitset_invertible_pointers.insert(&arg1);
01165       bitsetExpression_bitset_invertible_pointers.insert(&arg2);
01166       LibEccDout(dc::notice, "Constructed a bitsetExpression with arguments " <<
01167           (void const*)&first << " and " << (void const*)&second);
01168 #endif
01169     }
01170 #if LIBECC_TRACK_EXPR_TEMPORARIES
01171     ~bitsetExpression();
01172 #endif
01173   };
01174 
01175 #if LIBECC_TRACK_EXPR_TEMPORARIES
01176 template<unsigned int N, bool inverted1, bool inverted2, typename OP>
01177   bitsetExpression<N, inverted1, inverted2, OP>::~bitsetExpression()
01178   {
01179     bitsetExpression_bitset_invertible_pointers.erase(bitsetExpression_bitset_invertible_pointers.find(&first));
01180     bitsetExpression_bitset_invertible_pointers.erase(bitsetExpression_bitset_invertible_pointers.find(&second));
01181     LibEccDout(dc::notice, "Destructed bitsetExpression with arguments " <<
01182         (void const*)&first << " and " << (void const*)&second);
01183   }
01184 #endif
01185 
01186 } // namespace Operator
01187 #endif // HIDE_FROM_DOXYGEN
01188 
01206 template<unsigned int N, bool inverted>
01207   classbitset_invertible : public bitset_base<N> {
01208     public:
01209       // Constructors
01210       bitset_invertible(void);
01211       template<typename Expression>
01212         explicit bitset_invertible(Expression const&);
01213 
01214 #if LIBECC_TRACK_EXPR_TEMPORARIES
01215       ~bitset_invertible();
01216 #endif
01217 
01218     protected:
01219       template<typename OP, unsigned int x, bool invertedx>
01220         void assign(bitset_invertible<x, invertedx> const&, OP);
01221       template<typename OP1, unsigned int x, bool inverted1, bool inverted2, typename OP2>
01222         void assign(Operator::bitsetExpression<x, inverted1, inverted2, OP2> const&, OP1);
01223 
01224     private:
01225       template<unsigned int m, bool i>
01226         friend classbitset_invertible;
01227 
01228     public:
01230       void base2_print_on(std::ostream& os) const;
01231 
01233       bitset_digit_t digit(unsigned int d) const{ return inverted ? ~this->vector[d] : this->vector[d]; }
01234   };
01235 
01236 #if LIBECC_TRACK_EXPR_TEMPORARIES
01237 template<unsigned int N, bool inverted>
01238   bitset_invertible<N, inverted>::~bitset_invertible()
01239   {
01240     LibEccDout(dc::notice, "Destructing bitset_invertible at " << (void*)this);
01241     if (Operator::bitsetExpression_bitset_invertible_pointers.find(this) !=
01242         Operator::bitsetExpression_bitset_invertible_pointers.end())
01243       LibEccDoutFatal(dc::core, "This object is still in use by a bitsetExpression!");
01244   }
01245 #endif
01246 
01258 template<unsigned int N, bool inverted>
01259   void
01260   bitset_invertible<N, inverted>::base2_print_on(std::ostream& os) const
01261  {
01262     // Binary representation
01263     for (int d = bitset_base<N>::digits - 1; d >= 0; --d)
01264       for (bitset_digit_t mask = (~static_cast<bitset_digit_t>(0) >> 1) + 1; mask != 0; mask >>= 1)
01265         if (d != bitset_base<N>::digits - 1 || (mask & bitset_base<N>::valid_bits))
01266         {
01267           if ((this->digit(d) & mask) == inverted)
01268             os << '0';
01269           else
01270             os << '1';
01271         }
01272   }
01273 
01274 // Default constructor.
01275 template<unsigned int N, bool inverted>
01276   inline
01277   bitset_invertible<N, inverted>::bitset_invertible(void)
01278   {
01279     if (bitset_base<N>::has_excess_bits)
01280       this->vector[bitset_base<N>::digits - 1] = 0;                     // Reset the excess bits!
01281   }
01282 
01283 // Copy constructor.
01284 template<unsigned int N, bool inverted>
01285   template<typename Expression>
01286     inline
01287     bitset_invertible<N, inverted>::bitset_invertible(Expression const& expr)
01288     {
01289       this->assign(expr, Operator::bitsetAssign());
01290     }
01291 
01292 //
01293 // Assignment function.
01294 // This function handles:
01295 //
01296 // a = b;
01297 // a = ~b;
01298 // a &= b;
01299 // a &= ~b;
01300 // a |= b;
01301 // a |= ~b;
01302 // a ^= b;
01303 // a ^= ~b;
01304 //
01305 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
01306 //
01307 template<unsigned int N, bool inverted>
01308   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted_argument>
01309     inline void
01310     bitset_invertible<N, inverted>::assign(bitset_invertible<x, inverted_argument> const& bits, ASSIGNMENT_OPERATOR)
01311     {
01312       // Handle excess digits.
01313       if (bitset_base<N>::digits > bitset_base<x>::digits)
01314       {
01315         if (!inverted_argument)
01316         {
01317           // Fill excess digits with 0's when needed.
01318           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
01319             std::memset(&this->vector[bitset_base<x>::digits], 0, (bitset_base<N>::digits - bitset_base<x>::digits) * sizeof(bitset_digit_t));
01320         }
01321         else
01322         {
01323           // Fill excess digits with 1's when needed.
01324           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
01325           {
01326             unsigned int const count = bitset_base<N>::digits - bitset_base<x>::digits - 1;
01327             if (count)
01328               std::memset(&this->vector[bitset_base<x>::digits], 0xff, count * sizeof(bitset_digit_t));
01329             this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
01330           }
01331           // Or invert them.
01332           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
01333           {
01334 #ifdef __i386__
01335             int __d0, __d1;
01336             __asm__ __volatile__ (
01337                 "xorl %4,(%1)\n\t"
01338                 "jecxz 2f\n\t"
01339                 "subl %5,%1\n"
01340         "1:\n\t"
01341                 "xorl $-1,(%1,%%ecx,4)\n\t"
01342                 "decl %%ecx\n\t"
01343                 "jnz 1b\n"
01344         "2:"
01345                 : "=&c" (__d0), "=&r" (__d1)
01346                 : "0" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "1" (&this->vector[bitset_base<N>::digits - 1]),
01347                   "n" (bitset_base<N>::valid_bits), "n" ((bitset_base<N>::digits - bitset_base<x>::digits) * 4)
01348                 : "memory", "cc"
01349             );
01350 #else
01351             this->vector[bitset_base<N>::digits - 1] ^= bitset_base<N>::valid_bits;
01352             unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01353             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
01354 #endif
01355           }
01356         }
01357       }
01358 
01359       // Handle other digits.
01360 #ifdef __i386__
01361       LIBECC_INLINE_ASMLOOP(ASSIGNMENT_OPERATOR::id,
01362           this->vector, bits.digits_ptr(),
01363           ((bitset_base<N>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<N>::digits),
01364           inverted_argument);
01365 #else
01366       unsigned int d;
01367       if (bitset_base<N>::digits > bitset_base<x>::digits)
01368         d = bitset_base<x>::digits - 1;
01369       else
01370         d = bitset_base<N>::digits - 1;
01371       ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~bits.rawdigit(d) : bits.rawdigit(d));
01372       while(d) { --d; ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~bits.rawdigit(d) : bits.rawdigit(d)); }
01373 #endif
01374 
01375       // Reset excess bits if needed.
01376       if (((!inverted_argument && x > N) ||
01377             (inverted_argument && bitset_base<N>::digits <= bitset_base<x>::digits)) &&
01378           bitset_base<N>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
01379         this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
01380     }
01381 
01382 //
01383 // Assignment function for expressions.
01384 // This function handles:
01385 //
01386 // a = b & c;
01387 // a = b & ~c;
01388 // a = ~b & c;
01389 // a = ~b & ~b;
01390 // a = b | c;
01391 // a = b | ~c;
01392 // a = ~b | c;
01393 // a = ~b | ~b;
01394 // a = b ^ c;
01395 // a = b ^ ~c;
01396 // a = ~b ^ c;
01397 // a = ~b ^ ~b;
01398 // a &= b & c;
01399 // a &= b & ~c;
01400 // a &= ~b & c;
01401 // a &= ~b & ~b;
01402 // a &= b | c;
01403 // a &= b | ~c;
01404 // a &= ~b | c;
01405 // a &= ~b | ~b;
01406 // a &= b ^ c;
01407 // a &= b ^ ~c;
01408 // a &= ~b ^ c;
01409 // a &= ~b ^ ~b;
01410 // a |= b & c;
01411 // a |= b & ~c;
01412 // a |= ~b & c;
01413 // a |= ~b & ~b;
01414 // a |= b | c;
01415 // a |= b | ~c;
01416 // a |= ~b | c;
01417 // a |= ~b | ~b;
01418 // a |= b ^ c;
01419 // a |= b ^ ~c;
01420 // a |= ~b ^ c;
01421 // a |= ~b ^ ~b;
01422 // a ^= b & c;
01423 // a ^= b & ~c;
01424 // a ^= ~b & c;
01425 // a ^= ~b & ~b;
01426 // a ^= b | c;
01427 // a ^= b | ~c;
01428 // a ^= ~b | c;
01429 // a ^= ~b | ~b;
01430 // a ^= b ^ c;
01431 // a ^= b ^ ~c;
01432 // a ^= ~b ^ c;
01433 // a ^= ~b ^ ~b;
01434 //
01435 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
01436 // OPERATOR is one of bitsetAND, bitsetOR or bitsetXOR.
01437 //
01438 template<unsigned int N, bool inverted>
01439   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted1, bool inverted2, typename OPERATOR>
01440     inline void
01441     bitset_invertible<N, inverted>::assign(Operator::bitsetExpression<x, inverted1, inverted2, OPERATOR> const& expr, ASSIGNMENT_OPERATOR)
01442     {
01443       static bool const argument_has_leading_ones = OPERATOR::template execbool<inverted1, inverted2>::value;
01444 
01445       // Handle excess digits.
01446       if (bitset_base<N>::digits > bitset_base<x>::digits)
01447       {
01448         if (!argument_has_leading_ones)
01449         {
01450           // Fill excess digits with 0's when needed.
01451           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
01452             std::memset(&this->vector[bitset_base<x>::digits], 0, (bitset_base<N>::digits - bitset_base<x>::digits) * sizeof(bitset_digit_t));
01453         }
01454         else
01455         {
01456           // Fill excess digits with 1's when needed.
01457           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
01458           {
01459             unsigned int const count = bitset_base<N>::digits - bitset_base<x>::digits - 1;
01460             if (count)
01461               std::memset(&this->vector[bitset_base<x>::digits], 0xff, count * sizeof(bitset_digit_t));
01462             this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
01463           }
01464           // Or invert them.
01465           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
01466           {
01467 #ifdef __i386__
01468             int __d0, __d1;
01469             __asm__ __volatile__ (
01470                 "xorl %4,(%1)\n\t"
01471                 "jecxz 2f\n\t"
01472                 "subl %5,%1\n"
01473         "1:\n\t"
01474                 "xorl $-1,(%1,%%ecx,4)\n\t"
01475                 "decl %%ecx\n\t"
01476                 "jnz 1b\n"
01477         "2:"
01478                 : "=&c" (__d0), "=&r" (__d1)
01479                 : "0" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "1" (&this->vector[bitset_base<N>::digits - 1]),
01480                   "n" (bitset_base<N>::valid_bits), "n" ((bitset_base<N>::digits - bitset_base<x>::digits) * 4)
01481                 : "memory", "cc"
01482             );
01483 #else
01484             this->vector[bitset_base<N>::digits - 1] ^= bitset_base<N>::valid_bits;
01485             unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01486             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
01487 #endif
01488           }
01489         }
01490       }
01491 
01492       // Handle other digits.
01493 #ifdef __i386__
01494       LIBECC_INLINE_ASMLOOP2(ASSIGNMENT_OPERATOR::id, OPERATOR, inverted1, inverted2,
01495           this->vector, expr.first.digits_ptr(), expr.second.digits_ptr(),
01496           ((bitset_base<N>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<N>::digits));
01497 #else
01498       unsigned int d;
01499       if (bitset_base<N>::digits < bitset_base<x>::digits)
01500         d = bitset_base<N>::digits - 1;
01501       else
01502         d = bitset_base<x>::digits - 1;
01503       for(;;)
01504       {
01505         ASSIGNMENT_OPERATOR::exec(this->vector[d],
01506             OPERATOR::exec(inverted1 ? ~expr.first.rawdigit(d) : expr.first.rawdigit(d),
01507                            inverted2 ? ~expr.second.rawdigit(d) : expr.second.rawdigit(d)));
01508         if (!d)
01509           break;
01510         --d;
01511       }
01512 #endif
01513 
01514       // Reset excess bits if needed.
01515       if (((!argument_has_leading_ones && x > N) ||
01516             (argument_has_leading_ones && bitset_base<N>::digits <= bitset_base<x>::digits)) &&
01517           bitset_base<N>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
01518         this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
01519     }
01520 
01547 template<unsigned int N, bool inverted>
01548   inline bitset_invertible<N, !inverted> const&
01549   operator~(bitset_invertible<N, inverted> const& bits)
01550   {
01551     return *reinterpret_cast<bitset_invertible<N, !inverted> const*>(&bits);
01552   }
01553 
01554 #ifndef __i386__
01555 template<unsigned int N, int DIRECTION>
01556   void
01557   bitset_iterator<N, DIRECTION>::find1_forward(void)
01558   {
01559     if (this->M_digit < (int)bitset_base<N>::digits - 1 || (this->M_mask & bitset_base<N>::valid_bits))
01560     {
01561       register bitset_digit_t mask = this->M_mask;
01562       while(!(M_bitset_ptr->rawdigit(this->M_digit) & mask)) 
01563       {
01564         if ((mask <<= 1))
01565           continue;
01566         mask = 1;
01567         while(++(this->M_digit) < (int)bitset_base<N>::digits)
01568           if (M_bitset_ptr->rawdigit(this->M_digit))
01569             break;
01570         if (this->M_digit == (int)bitset_base<N>::digits)
01571         {
01572           this->M_digit = (N >> bitset_digit_bits_log2);
01573           mask = static_cast<bitset_digit_t>(1) << (N & (bitset_digit_bits - 1));
01574           break;
01575         }
01576       }
01577       this->M_mask = mask;
01578     }
01579   }
01580 
01581 template<unsigned int N, int DIRECTION>
01582   void
01583   bitset_iterator<N, DIRECTION>::find1_backward(void)
01584   {
01585     LibEccDout(dc::bitsetfind1, "Entering find1_backward with: " << 
01586         libcwd::cwprint_using(*static_cast<bitset_invertible<N, false> const*>(M_bitset_ptr), &bitset_invertible<N, false>::base2_print_on));
01587     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01588     if (this->M_digit >= 0)
01589     {
01590       register bitset_digit_t mask = this->M_mask;
01591       if (!(M_bitset_ptr->rawdigit(this->M_digit) & (mask | (mask - 1))))
01592       {
01593         mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
01594         do
01595         {
01596           if (--(this->M_digit) < 0)
01597           {
01598             this->M_mask = mask;
01599             return;
01600           }
01601         }
01602         while (!M_bitset_ptr->rawdigit(this->M_digit));
01603       }
01604       while(!(M_bitset_ptr->rawdigit(this->M_digit) & mask)) 
01605         mask >>= 1;
01606       this->M_mask = mask;
01607     }
01608     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01609   }
01610 #endif
01611 
01615 template<unsigned int N, int DIRECTION>
01616   inline void
01617   bitset_iterator<N, DIRECTION>::find1(void)
01618   {
01619     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01620     LibEccDout(dc::bitsetfind1, "Entering find1 with: " << 
01621         libcwd::cwprint_using(*static_cast<bitset_invertible<N, false> const*>(M_bitset_ptr), &bitset_invertible<N, false>::base2_print_on));
01622 #ifdef __i386__
01623     int bit_index, digit, ptr;
01624     if (DIRECTION == backwards_iterating)
01625     {
01626       __asm__ __volatile__ (
01627           // %eax: M_index (input) and work variable.
01628           // %ecx: bit_index (work variable).
01629           // %edi: &M_bitset_ptr->rawdigit(M_index/32 - 1) (input) and ptr (work variable).
01630           // %2  : digit (work variable).
01631 
01632           // Make a copy of M_index into %ecx, last time we used M_index.
01633           "movl %%eax,%%ecx\n\t"
01634           // Set %eax to its correct value by deviding it by 32.
01635           "sarl $5,%%eax\n\t"
01636           // Set bit_index to its correct value by taking the modulo 32 of it.
01637           "andl $31,%%ecx\n\t"
01638           // If M_index is -1, do nothing.
01639           "js 1f\n\t"
01640           // Copy the most significant digit, the digit with the
01641           // bit at which we will start the search, into %2.
01642           // digit = M_bitset_ptr->rawdigit(%eax)
01643           "movl 4(%%edi),%2\n\t"
01644           // Shift this digit left until the first bit comes at position 31.
01645           // bit_index = 31 - bit_index
01646           "xorl $31,%%ecx\n\t"
01647           // digit <<= bit_index
01648           "shll %%cl,%2\n\t"
01649           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01650           // This is not needed for the athlon for that reason, but we also need this orl
01651           // for the case that %cl equals zero in which case the ZF is cleared!
01652           "orl %2,%2\n\t"                       
01653           // If there is no bit set in the current digit, goto digit_search.
01654           "jz 5f\n\t"
01655           // Search for the (next) most significant bit set.
01656           // This is slow on i[345]86: 11 + 2*N cycles; only generates 2 uops on a pentium though.
01657           "bsrl %2,%2\n\t"
01658           // Correct M_index to point to this bit.
01659           // %eax <<= 5
01660           "sall $5,%%eax\n\t"
01661           // %2 -= bit_index
01662           "subl %%ecx,%2\n\t"
01663           // M_index = %eax + %2
01664           "addl %2,%%eax\n\t"
01665           // Done.
01666           // goto exit
01667           "jmp 1f\n\t"
01668           ".align 16\n"
01669        "7:\n\t"                         // Main loop.
01670           "movl (%%edi),%2\n\t"
01671           "subl $4,%%edi\n\t"
01672           "testl %2,%2\n\t"
01673           "jnz 6f\n\t"
01674        "5:\n\t"                         // digit_search:
01675           "decl %%eax\n\t"
01676           // Repeat main loop.
01677           "jns 7b\n"    
01678        "4:\n\t"                         // reached_end:
01679           // No set bit found at all.  Set M_index to -1.
01680           "movl $-1,%%eax\n\t"
01681           // Done.
01682           // goto exit
01683           "jmp 1f\n"
01684           // Search for the most significant bit set in this digit.
01685        "6:\n\t"
01686           "bsrl %2,%2\n\t"
01687           // Correct M_index to point to this bit.
01688           "sall $5,%%eax\n\t"
01689           "addl %2,%%eax\n"
01690        "1:"                             // exit:
01691 
01692           : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01693           : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() - 1 + (this->M_index >> 5))
01694           : "cc"
01695       );
01696     }
01697     else
01698     {
01699       __asm__ __volatile__ (
01700           // %eax: M_index (input) and work variable.
01701           // %ecx: bit_index (work variable).
01702           // %edi: &M_bitset_ptr->rawdigit(M_index/32 + 1) (input) and ptr (work variable).
01703           // %2  : digit (work variable).
01704 
01705           // if (M_index >= N) then goto exit
01706           "cmpl %6,%%eax\n\t"
01707           "jge 1f\n\t"
01708           // Make a copy of M_index into %ecx, last time we used M_index.
01709           "movl %%eax,%%ecx\n\t"
01710           // Set %eax to its correct value by deviding it by 32.
01711           "sarl $5,%%eax\n\t"
01712           // Set bit_index to its correct value by taking the modulo 32 of it.
01713           "andl $31,%%ecx\n\t"
01714           // Copy the least significant digit, the digit with the
01715           // bit at which we will start the search, into %2.
01716           // digit = M_bitset_ptr->rawdigit(%eax)
01717           "movl -4(%%edi),%2\n\t"
01718           // Shift this digit right until the first bit comes at position 0.
01719           // digit >>= bit_index
01720           "shrl %%cl,%2\n\t"
01721           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01722           // This is not needed for the athlon for that reason, but we also need this orl
01723           // for the case that %cl equals zero in which case the ZF is cleared!
01724           "orl %2,%2\n\t"                       
01725           // If there is no bit set in the current digit, goto digit_search.
01726           "jz 5f\n\t"
01727           // Search for the (next) most significant bit set.
01728           // This is slow on i[345]86: 11 + 2*N cycles; only generates 2 uops on a pentium though.
01729           "bsfl %2,%2\n\t"
01730           // Correct M_index to point to this bit.
01731           // %eax <<= 5
01732           "sall $5,%%eax\n\t"
01733           // %2 -= bit_index
01734           "addl %%ecx,%2\n\t"
01735           // M_index = %eax + %2
01736           "addl %2,%%eax\n\t"
01737           // Done.
01738           // goto exit
01739           "jmp 1f\n\t"
01740           ".align 16\n"
01741        "7:\n\t"                         // Main loop.
01742           "movl (%%edi),%2\n\t"
01743           "addl $4,%%edi\n\t"
01744           "testl %2,%2\n\t"
01745           "jnz 6f\n\t"
01746        "5:\n\t"                         // digit_search:
01747           "incl %%eax\n\t"
01748           "cmpl %7, %%eax\n\t"
01749           // Repeat main loop.
01750           "jnz 7b\n"            
01751        "4:\n\t"                         // reached_end:
01752           // No set bit found at all.  Set M_index to N.
01753           "movl %6,%%eax\n\t"
01754           // Done.
01755           // goto exit
01756           "jmp 1f\n"
01757           // Search for the least significant bit set in this digit.
01758        "6:\n\t"
01759           "bsfl %2,%2\n\t"
01760           // Correct M_index to point to this bit.
01761           "sall $5,%%eax\n\t"
01762           "addl %2,%%eax\n"
01763        "1:"                             // exit:
01764 
01765           : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01766           : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() + 1 + (this->M_index >> 5)),
01767             "n" (N), "n" (bitset_base<N>::digits)
01768           : "cc"
01769       );
01770     }
01771 #else
01772     if (DIRECTION == forwards_iterating)
01773       find1_forward();
01774     else
01775       find1_backward();
01776 #endif
01777     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01778     return;
01779   }
01780 
01781 
01785 template<unsigned int N, int DIRECTION>
01786   inline
01787   bitset_iterator<N, DIRECTION>::bitset_iterator(void)
01788   {
01789   }
01790 
01794 template<unsigned int N, int DIRECTION>
01795   inline
01796   bitset_iterator<N, DIRECTION>::bitset_iterator(bitset_base<N> const* bitset_ptr, int bit) :
01797       bitset_index_iterator<DIRECTION>(bit), M_bitset_ptr(bitset_ptr)
01798   {
01799   }
01800 
01804 template<unsigned int N, int DIRECTION>
01805   inline
01806   bitset_iterator<N, DIRECTION>::bitset_iterator(bitset_iterator const& iter) :
01807       bitset_index_iterator<DIRECTION>(iter), M_bitset_ptr(iter.M_bitset_ptr)
01808   {
01809   }
01810 
01814 template<unsigned int N, int DIRECTION>
01815   inline bitset_iterator<N, DIRECTION>&
01816   bitset_iterator<N, DIRECTION>::operator=(bitset_iterator<N, DIRECTION> const& iter)
01817   {
01818 #ifdef __i386__
01819     this->M_index = iter.M_index;
01820 #else
01821     this->M_digit = iter.M_digit;
01822     this->M_mask = iter.M_mask;
01823 #endif
01824     M_bitset_ptr = iter.M_bitset_ptr;
01825     return *this;
01826   }
01827 
01828 template<unsigned int N, int DIRECTION>
01829   inline bitset_iterator<N, DIRECTION>&
01830   bitset_iterator<N, DIRECTION>::operator=(bitset_index_iterator<DIRECTION> const& index)
01831   {
01832 #ifdef __i386__
01833     this->M_index = index.get_index();
01834 #else
01835     this->M_digit = index.get_digit();
01836     this->M_mask = index.get_mask();
01837 #endif
01838     return *this;
01839   }
01840 
01844 template<unsigned int N, int DIRECTION>
01845   inline bitset_iterator<N, DIRECTION>&
01846   bitset_iterator<N, DIRECTION>::operator++()
01847   {
01848     this->increment();
01849     return *this;
01850   }
01851 
01855 template<unsigned int N, int DIRECTION>
01856   inline bitset_iterator<N, DIRECTION>
01857   bitset_iterator<N, DIRECTION>::operator++(int)
01858   {
01859     bitset_iterator prev(*this);
01860     this->increment();
01861     return prev;
01862   }
01863 
01867 template<unsigned int N, int DIRECTION>
01868   inline bitset_iterator<N, DIRECTION>&
01869   bitset_iterator<N, DIRECTION>::operator--()
01870   {
01871     this->decrement();
01872     return *this;
01873   }
01874 
01878 template<unsigned int N, int DIRECTION>
01879   inline bitset_iterator<N, DIRECTION>
01880   bitset_iterator<N, DIRECTION>::operator--(int)
01881   {
01882     bitset_iterator prev(*this);
01883     this->decrement();
01884     return prev;
01885   }
01886 
01893 template<unsigned int N, int DIRECTION>
01894   inline bitset_digit_t
01895   bitset_iterator<N, DIRECTION>::operator*() const
01896  {
01897 #ifdef __i386__
01898     register unsigned int digit = this->M_index;
01899     register bitset_digit_t mask = 1;
01900     register unsigned short shift = this->M_index & (ECC_BITS - 1);
01901     digit >>= bitset_digit_bits_log2;
01902     mask <<= shift;
01903     return (M_bitset_ptr->rawdigit(digit) & mask);
01904 #else
01905     return (M_bitset_ptr->rawdigit(this->M_digit) & this->M_mask);
01906 #endif
01907   }
01908 
01912 template<unsigned int N, int DIRECTION>
01913   inline bitset_iterator<N, DIRECTION>&
01914   bitset_iterator<N, DIRECTION>::operator+=(int d)
01915   {
01916     this->increment(d);
01917     return *this;
01918   }
01919 
01923 template<unsigned int N, int DIRECTION>
01924   inline bitset_iterator<N, DIRECTION>&
01925   bitset_iterator<N, DIRECTION>::operator-=(int d)
01926   {
01927     this->decrement(d);
01928     return *this;
01929   }
01930 
01934 template<unsigned int N, int DIRECTION>
01935   inline bitset_iterator<N, DIRECTION>
01936   operator+(bitset_iterator<N, DIRECTION> const& i, int d)
01937   {
01938     bitset_iterator<N, DIRECTION> result(i);
01939     return result += d;
01940   }
01941 
01945 template<unsigned int N, int DIRECTION>
01946   inline bitset_iterator<N, DIRECTION>
01947   operator+(int d, bitset_iterator<N, DIRECTION> const& i)
01948   {
01949     bitset_iterator<N, DIRECTION> result(i);
01950     return result += d;
01951   }
01952 
01956 template<unsigned int N, int DIRECTION>
01957   inline bitset_iterator<N, DIRECTION>
01958   operator-(bitset_iterator<N, DIRECTION> const& i, int d)
01959   {
01960     bitset_iterator<N, DIRECTION> result(i);
01961     return result -= d;
01962   }
01963 
01967 template<unsigned int N, int DIRECTION>
01968   inline bitset_iterator<N, DIRECTION>
01969   operator-(int d, bitset_iterator<N, DIRECTION> const& i)
01970   {
01971     bitset_iterator<N, DIRECTION> result(i);
01972     return result -= d;
01973   }
01974 
01978 template<unsigned int N, int DIRECTION>
01979   inline bitset_digit_t
01980   bitset_iterator<N, DIRECTION>::operator[](int d) const
01981  {
01982     return *(*this + d);
01983   }
01984 
01985 //--------------------------------------------------------------------------------------------------------------------------
01992 template<unsigned int N>
01993   classbitset : public bitset_invertible<N, false> {
01994     public:
01995       // Constructors.
01996       bitset(void);
01997       bitset(std::string const&);
01998       explicit bitset(bitset_digit_t low_bits);
01999       // This definition must be here, inside the template class declaration because
02000       // otherwise the compiler (2.95 - 3.1) barfs.
02006       bitset(bitset_digit_t const (&v)[bitset_base<N>::digits])
02007       {
02008 #if ECC_DEBUG
02009         assert( (v[bitset_base<N>::digits - 1] & ~bitset_base<N>::valid_bits) == 0 );
02010 #endif
02011         std::memcpy(this->vector, v, sizeof(this->vector));
02012       }
02013 
02014       // Copy constructors.
02015       template<unsigned int m, bool inverted>
02016         bitset(bitset_invertible<m, inverted> const&);
02017       template<unsigned int m, bool i1, bool i2, typename OP>
02018         bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr);
02019 
02020       // Assignment operators.
02021       bitset& operator=(bitset const&);
02022       template<typename Expression>
02023         bitset& operator=(Expression const&);
02024 
02025       // Perform AND, OR, XOR operations
02026       template<typename Expression>
02027         bitset& operator&=(Expression const&);
02028       template<typename Expression>
02029         bitset& operator|=(Expression const&);
02030       template<typename Expression>
02031         bitset& operator^=(Expression const&);
02032 
02033     public:
02034       // Shift bitset left or right and perform operation with result.
02035       template<unsigned int shift, class DIRECTION, class OPERATION>
02036         void shift_op(bitset& result) const;
02037 
02039       bitset& operator<<=(unsigned int shift) { this->bitset_base<N>::operator<<=(shift); return *this; }
02041       bitset& operator>>=(unsigned int shift) { this->bitset_base<N>::operator>>=(shift); return *this; }
02042 
02043       // Rotate left or right
02044       template<unsigned int shift, class DIRECTION>                     // Return a copy rotated `shift' bits in `DIRECTION'.
02045         void rotate(bitset& result) const;
02046   };
02047 
02051 template<unsigned int N>
02052   inline
02053   bitset<N>::bitset(void)
02054   {
02055   }
02056 
02062 template<unsigned int N>
02063   inline
02064   bitset<N>::bitset(bitset_digit_t low_bits)
02065   {
02066 #if ECC_DEBUG
02067     assert( bitset_base<N>::digits > 1 || (low_bits & ~bitset_base<N>::valid_bits) == 0 );
02068 #endif
02069     std::memset(this->vector, 0, sizeof(this->vector));
02070     this->vector[0] = low_bits;
02071   }
02072 
02076 template<unsigned int N>
02077   void
02078   bitset_base<N>::setall(void)
02079   {
02080     this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
02081     if (bitset_base<N>::digits > 1)
02082     {
02083       int d = bitset_base<N>::digits - 2;
02084       do { this->vector[d] = ~static_cast<bitset_digit_t>(0); } while(--d >= 0);
02085     }
02086   }
02087 
02112 template<unsigned int N>
02113   template<typename Expression>
02114     inline
02115     bitset<N>& bitset<N>::operator=(Expression const& expr)
02116     {
02117       this->assign(expr, Operator::bitsetAssign());
02118       return *this;
02119     }
02120 
02121 // Special case, need to define this or else we'd get a default assignment operator.
02122 template<unsigned int N>
02123   inline bitset<N>&
02124   bitset<N>::operator=(bitset const& expr)
02125   {
02126     this->assign(expr, Operator::bitsetAssign());
02127     return *this;
02128   }
02129 
02146 template<unsigned int N>
02147   template<unsigned int m, bool inverted>
02148     inline bitset<N>::bitset(bitset_invertible<m, inverted> const& bits) : bitset_invertible<N, false>(bits)
02149     {
02150     }
02151 
02157 template<unsigned int N>
02158   template<unsigned int m, bool i1, bool i2, typename OP>
02159     inline bitset<N>::bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr) : bitset_invertible<N, false>(expr)
02160     {
02161     }
02162 
02174 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02175   bool operator==(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02176   {
02177     unsigned int d;
02178     if (bitset_invertible<n1, inverted1>::digits > bitset_invertible<n2, inverted2>::digits)
02179     {
02180       d = bitset_base<n1>::digits - 1;
02181       do
02182       {
02183         if (bits1.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02184           return false;
02185       }
02186       while (--d != bitset_base<n2>::digits - 1);
02187     }
02188     if (bitset_base<n2>::digits > bitset_base<n1>::digits)
02189     {
02190       d = bitset_base<n2>::digits - 1;
02191       do
02192       {
02193         if (bits2.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02194           return false;
02195       }
02196       while (--d != bitset_base<n1>::digits - 1);
02197     }
02198     if (bitset_base<n1>::digits > 1 && bitset_base<n2>::digits > 1)
02199     {
02200       if (bitset_base<n1>::digits == bitset_base<n2>::digits)
02201         d = bitset_base<n1>::digits - 1;
02202       do
02203       {
02204         if (inverted1 == inverted2)
02205         {
02206           if (bits1.vector[d] != bits2.vector[d])
02207             return false;
02208         }
02209         else
02210         {
02211           if (bits1.vector[d] != ~(bits2.vector[d]))
02212             return false;
02213         }
02214       }
02215       while(--d != 0);
02216     }
02217     if (inverted1 != inverted2)
02218       return (bits1.vector[0] == ~(bits2.vector[0]));
02219     return (bits1.vector[0] == bits2.vector[0]);
02220   }
02221 
02227 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02228   inline bool
02229   operator!=(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02230   {
02231     return !(bits1 == bits2);
02232   }
02233 
02238 template<unsigned int N>
02239   template<typename Expression>
02240     inline bitset<N>&
02241     bitset<N>::operator&=(Expression const& expr)
02242     {
02243       this->assign(expr, Operator::bitsetANDAssign());
02244       return *this;
02245     }
02246 
02251 template<unsigned int N>
02252   template<typename Expression>
02253     inline bitset<N>&
02254     bitset<N>::operator|=(Expression const& expr)
02255     {
02256       this->assign(expr, Operator::bitsetORAssign());
02257       return *this;
02258     }
02259 
02264 template<unsigned int N>
02265   template<typename Expression>
02266     inline bitset<N>&
02267     bitset<N>::operator^=(Expression const& expr)
02268     {
02269       this->assign(expr, Operator::bitsetXORAssign());
02270       return *this;
02271     }
02272 
02277 template<unsigned int m, bool inverted1, bool inverted2>
02278   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>
02279   operator&(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02280     {
02281       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>(arg1, arg2);
02282     }
02283 
02288 template<unsigned int m, bool inverted1, bool inverted2>
02289   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>
02290   operator|(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02291     {
02292       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>(arg1, arg2);
02293     }
02294 
02299 template<unsigned int m, bool inverted1, bool inverted2>
02300   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>
02301   operator^(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02302     {
02303       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>(arg1, arg2);
02304     }
02305 
02309 structassign {
02310   static int const id = 1;
02311   static bool const __clear = true;
02312   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02313   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02314 };
02315 
02319 structexor {
02320   static int const id = 2;
02321   static bool const __clear = false;
02322   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02323   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02324 };
02325 
02326 #ifndef HIDE_FROM_DOXYGEN
02327 structrotate_phase1 {
02328   static int const id = 3;
02329   static bool const __clear = false;
02330   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02331   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02332 };
02333 
02334 structrotate_phase2 {
02335 public:
02336   static int const id = 4;
02337   static bool const __clear = false;
02338   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02339   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 |= digit2; }
02340 };
02341 #endif
02342 
02353 template<unsigned int N>
02354   template<unsigned int shift, class DIRECTION, class OPERATION>
02355     void
02356     bitset<N>::shift_op(bitset& result) const
02357    {
02358       LibEccDout(dc::bitsetshift, "Entering shift_op<" << shift << ", " << libcwd::type_info_of<DIRECTION>().demangled_name() <<
02359           ", " << type_info_of<OPERATION>().demangled_name() << '>');
02360       LibEccDout(dc::bitsetshift|flush_cf, "Input : " << cwprint_using(*this, &bitset<N>::base2_print_on));
02361       if (shift == 1)
02362       {
02363         // Specialization for shift == 1.
02364         // digit_shift = 0
02365         // bit_shift = 1
02366         // zeroed_digits = 0 (likely and if not - then assumed).
02367         // Here we scan in the opposite direction of when shift > 1.
02368         static unsigned int const initial = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02369         static unsigned int const count = bitset_base<N>::digits - ((DIRECTION::__left && bitset_base<N>::has_excess_bits) ? 1 : 0);
02370 #ifdef __i386__
02371         if (count)
02372         {
02373           bitset_digit_t const volatile* ptr1;
02374           bitset_digit_t volatile* ptr2;
02375           int c;
02376           if (DIRECTION::__left)
02377           {
02378             if (OPERATION::id == libecc::exor::id)
02379             {
02380               if (bitset_base<N>::has_excess_bits)
02381                 LIBECC_ASMSHIFTLEFT(
02382                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02383                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"),
02384                     LIBECC_ASMSHIFTLEFT_FINISH("xorl (%%edi),%%edx\n\t"));
02385               else
02386                 LIBECC_ASMSHIFTLEFT(
02387                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02388                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"), "");
02389             }
02390             else if (OPERATION::id == libecc::rotate_phase2::id)
02391             {
02392               if (bitset_base<N>::has_excess_bits)
02393                 LIBECC_ASMSHIFTLEFT(
02394                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02395               else
02396                 LIBECC_ASMSHIFTLEFT(
02397                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", "");
02398             }
02399             else
02400             {
02401               if (bitset_base<N>::has_excess_bits)
02402                 LIBECC_ASMSHIFTLEFT("", "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02403               else
02404                 LIBECC_ASMSHIFTLEFT("", "", "");
02405             }
02406           }
02407           else if (count > 1)
02408           {
02409             if (OPERATION::id == libecc::exor::id)
02410               LIBECC_ASMSHIFTRIGHT1(
02411                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02412                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP2_DESTINATION "," LIBECC_WORKREG),
02413                   LIBECC_PRESERVE_CF_CLOBBER);
02414             else if (OPERATION::id == libecc::rotate_phase2::id)
02415               LIBECC_ASMSHIFTRIGHT1(
02416                   LIBECC_RIGHT_PRESERVE_CF("orl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02417                   "",
02418                   LIBECC_PRESERVE_CF_CLOBBER);
02419             else
02420               LIBECC_ASMSHIFTRIGHT1(
02421                   "",
02422                   "",
02423                   LIBECC_CLOBBER);
02424           }
02425           else
02426           {
02427             if (OPERATION::id == libecc::exor::id)
02428               LIBECC_ASMSHIFTRIGHT0("xorl 4(%%edi), %%edx\n\t");
02429             else if (OPERATION::id == libecc::rotate_phase2::id)
02430               LIBECC_ASMSHIFTRIGHT0("orl 4(%%edi), %%edx\n\t");
02431             else
02432               LIBECC_ASMSHIFTRIGHT0("");
02433           }
02434         }
02435         else if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02436           OPERATION::op(result.vector[0], ((this->vector[0] << 1) & bitset_base<N>::valid_bits));
02437 #else
02438         static unsigned int complement_shift = bitset_digit_bits - 1;
02439         static bitset_digit_t const mask1 = DIRECTION::__left ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02440         static bitset_digit_t const mask2 = DIRECTION::__right ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02441         bitset_digit_t const* ptr1 = &this->vector[initial];
02442         bitset_digit_t* ptr2 = &result.vector[initial];
02443         bool carry;
02444         if (count)
02445         {
02446           bitset_digit_t digit = *ptr1;
02447           carry = (digit & mask1);
02448           if (DIRECTION::__left)
02449             digit <<= 1;
02450           else
02451             digit >>= 1;
02452           OPERATION::mixed_op(*ptr2, digit);
02453           for (int c = count - 1; c; --c)
02454           {
02455             ptr1 -= DIRECTION::direction;
02456             ptr2 -= DIRECTION::direction;
02457             digit = *ptr1;
02458             if (carry)
02459             {
02460               carry = (digit & mask1);
02461               if (DIRECTION::__left)
02462                 digit <<= 1;
02463               else
02464                 digit >>= 1;
02465               digit |= mask2;
02466             }
02467             else
02468             {
02469               carry = (digit & mask1);
02470               if (DIRECTION::__left)
02471                 digit <<= 1;
02472               else
02473                 digit >>= 1;
02474             }
02475             OPERATION::op(*ptr2, digit);
02476           }
02477         }
02478         if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02479         {
02480           bitset_digit_t digit;
02481           if (count)
02482             digit = ptr1[-DIRECTION::direction];
02483           else
02484             digit = *ptr1;
02485           digit <<= 1;
02486           if (count && carry)
02487             digit |= mask2;
02488           if (count)
02489             OPERATION::op(ptr2[-DIRECTION::direction], (digit & bitset_base<N>::valid_bits));
02490           else
02491             OPERATION::op(*ptr2, (digit & bitset_base<N>::valid_bits));
02492         }
02493 #endif
02494       }
02495       else
02496       {
02497         static unsigned int const digit_shift = shift / bitset_digit_bits;
02498         static unsigned int const bit_shift = shift % bitset_digit_bits;
02499 
02500         static unsigned int const zeroed_digits =
02501           DIRECTION::__left ? ((shift < N) ? digit_shift : bitset_base<N>::digits)
02502                             : ((bitset_digit_bits - bitset_base<N>::number_of_valid_bits + shift) / bitset_digit_bits);
02503 
02504         if (zeroed_digits < bitset_base<N>::digits)
02505         {
02506           static unsigned int const complement_shift = (bit_shift == 0) ? 0 : bitset_digit_bits - bit_shift;
02507           static unsigned int const initial_to = DIRECTION::__right ? 0 : bitset_base<N>::digits - 1;
02508           static unsigned int const initial_from = initial_to + DIRECTION::direction * digit_shift;
02509           static unsigned int const final_from = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02510 
02511           register bitset_digit_t digit = this->vector[initial_from];
02512           if (initial_from != final_from)
02513           {
02514             register bitset_digit_t next_digit;
02515             unsigned int to = initial_to;
02516             unsigned int from = initial_from + DIRECTION::direction;
02517             if (from != final_from)
02518               do
02519               {
02520                 next_digit = this->vector[from];
02521                 if (bit_shift != 0)
02522                 {
02523                   if (DIRECTION::direction == -1)
02524                     digit <<= bit_shift;
02525                   else
02526                     digit >>= bit_shift;
02527                   digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02528                 }
02529                 OPERATION::op(result.vector[to], digit);
02530                 digit = next_digit;
02531                 to += DIRECTION::direction;
02532                 from += DIRECTION::direction;
02533               }
02534               while (from != final_from);
02535             if (DIRECTION::__left || bit_shift < bitset_base<N>::number_of_valid_bits || bit_shift != 0)
02536               next_digit = this->vector[final_from];
02537             if (bit_shift != 0)
02538             {
02539               if (DIRECTION::direction == -1)
02540                 digit <<= bit_shift;
02541               else
02542                 digit >>= bit_shift;
02543               digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02544             }
02545             if (DIRECTION::__left || bit_shift < bitset_base<N>::number_of_valid_bits)
02546             {
02547               OPERATION::op(result.vector[final_from - DIRECTION::direction * (digit_shift + 1)], digit);
02548               digit = DIRECTION::shift_copy(next_digit, bit_shift);
02549             }
02550           }
02551           else
02552           {
02553             if (DIRECTION::direction == -1)
02554               digit <<= bit_shift;
02555             else
02556               digit >>= bit_shift;
02557           }
02558           static bool const have_mixed_digit = shift != 0 && (DIRECTION::__left ? shift : (N - shift)) % bitset_digit_bits != 0;
02559           static unsigned int const last_digit = (DIRECTION::__left ? shift : (N - 1 - shift)) / bitset_digit_bits;
02560           if (have_mixed_digit)
02561             OPERATION::mixed_op(result.vector[last_digit], digit);
02562           else
02563             OPERATION::op(result.vector[last_digit], digit);
02564           if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02565             result.vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
02566         }
02567         if (OPERATION::__clear && zeroed_digits > 0)
02568         {
02569           static unsigned int const final_to = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02570           static unsigned int const initial_to = final_to - DIRECTION::direction * (zeroed_digits - 1);
02571           unsigned int to = initial_to;
02572           if (to != final_to)
02573             do
02574             {
02575               result.vector[to] = 0;
02576               to += DIRECTION::direction;
02577             }
02578             while(to != final_to);
02579           result.vector[to] = 0;
02580         }
02581       }
02582       LibEccDout(dc::bitsetshift|flush_cf, "Output: " << cwprint_using(result, &bitset<N>::base2_print_on));
02583     }
02584 
02585 template<unsigned int N>
02586   void
02587   bitset_base<N>::operator<<=(unsigned int shift)
02588   {
02589     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02590     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02591     int digit1 = bitset_base<N>::digits - digit_shift - 2;
02592     bitset_digit_t d0 = (digit1 >= -1) ? this->vector[digit1 + 1] : 0;
02593     for (int digit_to = bitset_base<N>::digits - 1; digit_to >= 0; --digit_to)
02594     {
02595       bitset_digit_t d1 = (digit1 >= 0) ? this->vector[digit1] : 0;
02596       if (bit_shift == 0)
02597         this->vector[digit_to] = d0;
02598       else
02599         this->vector[digit_to] = (d0 << bit_shift) | (d1 >> (bitset_digit_bits - bit_shift));
02600       d0 = d1;
02601       --digit1;
02602     }
02603     if (bitset_base<N>::has_excess_bits)
02604       this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;           // Reset possibly set excess bits.
02605   }
02606 
02607 template<unsigned int N>
02608   void
02609   bitset_base<N>::operator>>=(unsigned int shift)
02610   {
02611     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02612     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02613     unsigned int digit1 = digit_shift + 1;
02614     bitset_digit_t d0 = (digit1 <= bitset_base<N>::digits) ? this->vector[digit1 - 1] : 0;
02615     for (unsigned int digit_to = 0; digit_to < bitset_base<N>::digits; ++digit_to)
02616     {
02617       bitset_digit_t d1 = (digit1 < bitset_base<N>::digits) ? this->vector[digit1] : 0;
02618       if (bit_shift == 0)
02619         this->vector[digit_to] = d0;
02620       else
02621         this->vector[digit_to] = (d0 >> bit_shift) | (d1 << (bitset_digit_bits - bit_shift));
02622       d0 = d1;
02623       ++digit1;
02624     }
02625   }
02626 
02643 template<unsigned int N>
02644   bitset<N>::bitset(std::string const& input)
02645   {
02646     this->reset();                                      // Reset internal digits to zero.
02647     unsigned int d = 0;                                 // Current index of internal digit.
02648     unsigned int u = 0;                                 // Current bit-shift of input digit relative to internal digit.
02649 
02650     for (std::string::const_reverse_iterator iter = input.rbegin(); iter != input.rend(); ++iter)       // Read right to left.
02651     {
02652       bitset_digit_t c = toupper(*iter);                // Get next hexadecimal input character.
02653       if (c == ' ')                                     // Skip spaces.
02654         continue;
02655       if (c < '0')                                      // Terminate reading when not a hexadecimal character.
02656         break;
02657       if (c <= '9')
02658         c -= '0';                                       // Set c to the value that the input character represents.
02659       else
02660       {
02661         if (c > 'F')
02662           break;
02663         if (c >= 'A')
02664           c -= ('A' - 10);
02665         else
02666           break;
02667       }
02668       this->vector[d] |= c << u;                        // Set internal bits.
02669       if ((u += 4) == bitset_digit_bits)                // Update bit/digit 'pointers'.
02670       {
02671         u = 0;
02672         if (++d == bitset_base<N>::digits)              // Terminate reading when bitset is full.
02673           break;
02674       }
02675     }
02676     if (bitset_base<N>::has_excess_bits)
02677       this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;   // Reset possibly set excess bits.
02678   }
02679 
02683 template<unsigned int N>
02684   std::istream&
02685   operator>>(std::istream& is, bitset<N>& bitsetx)
02686   {
02687     std::string tmp;
02688     is >> tmp;
02689     bitsetx.bitset(tmp);
02690     return is;
02691   }
02692 
02696 template<unsigned int N>
02697   std::ostream&
02698   operator<<(std::ostream& os, bitset<N> const& bits)
02699   {
02700     // Hexadecimal representation
02701     os.fill('0');
02702     os << std::hex;
02703     for (int d = bitset<N>::digits - 1; d >= 0; --d)
02704     {
02705       os.width((d == bitset<N>::digits - 1 && bitset<N>::has_excess_bits) ?
02706           (((N % bitset_digit_bits) - 1) / 4 + 1) :
02707           (bitset_digit_bits / 4));
02708       os << bits.digit(d);
02709       if (d > 0)
02710         os << ' ';
02711     }
02712     os << std::dec;
02713     return os;
02714   }
02715 
02719 template<unsigned int N>
02720   void
02721   bitset_base<N>::reset(void)
02722   {
02723     std::memset(this->vector, 0, sizeof(this->vector));
02724   }
02725 
02729 template<unsigned int N>
02730   inline bool
02731   bitset_base<N>::test(size_t pos) const
02732  {
02733 #ifdef __i386__
02734     int result;
02735     __asm__ __volatile__ (
02736         "btl %2, %1\n\t"
02737         "sbbl %0, %0"
02738         : "=r" (result)
02739         : "m" ((*(bitset_digit_t volatile*)this->vector)), "Ir" (pos)
02740         : "cc");
02741     return result;
02742 #else
02743     unsigned int d = pos / bitset_digit_bits;
02744     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02745     return (this->vector[d] & mask);
02746 #endif
02747   }
02748 
02752 template<unsigned int N>
02753   template<unsigned int pos>
02754     inline bool
02755     bitset_base<N>::test(void) const
02756    {
02757       static unsigned int const d = pos / bitset_digit_bits;
02758       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02759       return (this->vector[d] & mask);
02760     }
02761 
02765 template<unsigned int N>
02766   inline bool
02767   bitset_base<N>::test(bitset_index const& index) const
02768  {
02769 #ifdef __i386__
02770     return this->test(index.get_index());
02771 #else
02772     return (this->vector[index.get_digit()] & index.get_mask());
02773 #endif
02774   }
02775 
02779 template<unsigned int N>
02780   inline void
02781   bitset_base<N>::set(size_t pos)
02782   {
02783 #ifdef __i386__
02784     __asm__ __volatile__ (
02785         "btsl %1, %0"
02786         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02787         : "Ir" (pos)
02788         : "cc");
02789 
02790 #else
02791     unsigned int d = pos / bitset_digit_bits;
02792     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02793     this->vector[d] |= mask;
02794 #endif
02795   }
02796 
02800 template<unsigned int N>
02801   inline void
02802   bitset_base<N>::set(bitset_index const& index)
02803   {
02804 #ifdef __i386__
02805     this->set(index.get_index());
02806 #else
02807     this->vector[index.get_digit()] |= index.get_mask();
02808 #endif
02809   }
02810 
02814 template<unsigned int N>
02815   template<unsigned int pos>
02816     inline void
02817     bitset_base<N>::set(void)
02818     {
02819       static unsigned int const d = pos / bitset_digit_bits;
02820       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02821       this->vector[d] |= mask;
02822     }
02823 
02827 template<unsigned int N>
02828   inline void
02829   bitset_base<N>::clear(size_t pos)
02830   {
02831 #ifdef __i386__
02832     __asm__ __volatile__ (
02833         "btrl %1, %0"
02834         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02835         : "Ir" (pos)
02836         : "cc"
02837     );
02838 #else
02839     unsigned int d = pos / bitset_digit_bits;
02840     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02841     this->vector[d] &= ~mask;
02842 #endif
02843   }
02844 
02848 template<unsigned int N>
02849   inline void
02850   bitset_base<N>::clear(bitset_index const& index)
02851   {
02852 #ifdef __i386__
02853     this->clear(index.get_index());
02854 #else
02855     this->vector[index.get_digit()] &= ~(index.get_mask());
02856 #endif
02857   }
02858 
02862 template<unsigned int N>
02863   template<unsigned int pos>
02864     inline void
02865     bitset_base<N>::clear(void)
02866     {
02867       static unsigned int const d = pos / bitset_digit_bits;
02868       static bitset_digit_t const mask = ~(static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits));
02869       this->vector[d] &= mask;
02870     }
02871 
02875 template<unsigned int N>
02876   inline void
02877   bitset_base<N>::flip(size_t pos)
02878   {
02879 #ifdef __i386__
02880     __asm__ __volatile__ (
02881         "btcl %1, %0"
02882         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02883         : "Ir" (pos)
02884         : "cc"
02885     );
02886 #else
02887     unsigned int d = pos / bitset_digit_bits;
02888     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02889     this->vector[d] ^= mask;
02890 #endif
02891   }
02892 
02896 template<unsigned int N>
02897   inline void
02898   bitset_base<N>::flip(bitset_index const& index)
02899   {
02900 #ifdef __i386__
02901     this->flip(index.get_index());
02902 #else
02903     this->vector[index.get_digit()] ^= index.get_mask();
02904 #endif
02905   }
02906 
02910 template<unsigned int N>
02911   template<unsigned int pos>
02912     inline void
02913     bitset_base<N>::flip(void)
02914     {
02915       static unsigned int const d = pos / bitset_digit_bits;
02916       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02917       this->vector[d] ^= mask;
02918     }
02919 
02923 template<unsigned int N>
02924   bool
02925   bitset_base<N>::any(void) const
02926  {
02927     unsigned int to = bitset_base<N>::digits - 1;
02928     if (bitset_base<N>::digits > 1)
02929       do
02930       {
02931         if (this->vector[to] != 0)
02932           return true;
02933         --to;
02934       }
02935       while(to != 0);
02936     return (this->vector[0] != 0);
02937   }
02938 
02939 static bool const oddnumberofbits[] = {
02940   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02941   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02942   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02943   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02944   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02945   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02946   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02947   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02948   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02949   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02950   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02951   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02952   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02953   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02954   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02955   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false };
02956 
02960 template<unsigned int N>
02961   bool
02962   bitset_base<N>::odd(void) const
02963  {
02964     unsigned int from = bitset_base<N>::digits - 1;
02965     bitset_digit_t sum = this->vector[0];
02966     if (bitset_base<N>::digits > 1)
02967       do
02968       {
02969         sum ^= this->vector[from];
02970         --from;
02971       }
02972       while(from != 0);
02973     bitset_digit_t ssum = sum;
02974     if (sizeof(bitset_digit_t) >= 2)
02975     {
02976       ssum >>= (bitset_digit_bits / 2);
02977       sum ^= ssum;
02978     }
02979     if (sizeof(bitset_digit_t) >= 4)
02980     {
02981       ssum = sum;
02982       ssum >>= (bitset_digit_bits / 4);
02983       sum ^= ssum;
02984     }
02985     if (sizeof(bitset_digit_t) >= 8)
02986     {
02987       ssum = sum;
02988       ssum >>= (bitset_digit_bits / 8);
02989       sum ^= ssum;
02990     }
02991     if (sizeof(bitset_digit_t) == 16)
02992     {
02993       ssum = sum;
02994       ssum >>= (bitset_digit_bits / 16);
02995       sum ^= ssum;
02996     }
02997     return oddnumberofbits[sum & 0xff];
02998   }
02999 
03003 structleft {
03004 public:
03005   typedef structright inverse;
03006   static int const direction = -1;
03007   static bool const __left = true;
03008   static bool const __right = false;
03009   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03010   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03011 };
03012 
03016 structright {
03017 public:
03018   typedef structleft inverse;
03019   static int const direction = 1;
03020   static bool const __left = false;
03021   static bool const __right = true;
03022   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03023   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03024 };
03025 
03034 template<unsigned int N>
03035   template<unsigned int shift, class DIRECTION>
03036     void
03037     bitset<N>::rotate(bitset<N>& result) const
03038    {
03039       LibEccDout(dc::bitsetshift|flush_cf, "Entering bitset<" << N << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03040       LibEccDout(dc::bitsetshift|flush_cf, "Rotate input : " << cwprint_using(*this, &bitset<N>::base2_print_on));
03041       shift_op<shift % N, DIRECTION, rotate_phase1>(result);
03042       LibEccDout(dc::bitsetshift|flush_cf, "After phase1 : " << cwprint_using(result, &bitset<N>::base2_print_on));
03043       shift_op<N - (shift % N), typename DIRECTION::inverse, rotate_phase2>(result);
03044       LibEccDout(dc::bitsetshift|flush_cf, "After phase2 : " << cwprint_using(result, &bitset<N>::base2_print_on));
03045       LibEccDout(dc::bitsetshift|flush_cf, "Leaving bitset<" << N << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03046     }
03047 
03048 } // namespace libecc
03049 
03050 #endif // LIBECC_BITS_H
Copyright © 2002-2008 Carlo Wood.  All rights reserved.