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                   "i" (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           {
01320 #ifdef __i386__
01321             int __d0, __d1;
01322             __asm__ __volatile__ (
01323                 "std; rep; stosl"
01324                 : "=m" (this->vector[bitset_base<N>::digits - 1]), "=&c" (__d0), "=&D" (__d1)
01325                 : "a" (0), "1" (bitset_base<N>::digits - bitset_base<x>::digits), "2" (&this->vector[bitset_base<N>::digits - 1])
01326                 : "memory"
01327             );
01328 #else
01329             unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01330             do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
01331 #endif
01332           }
01333         }
01334         else
01335         {
01336           // Fill excess digits with 1's when needed.
01337           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
01338           {
01339 #ifdef __i386__
01340             int __d0, __d1;
01341             __asm__ __volatile__ (
01342                 "movl %6,4(%%edi); std; rep; stosl"
01343                 : "=m" (this->vector[bitset_base<N>::digits - 2]), "=&c" (__d0), "=&D" (__d1)
01344                 : "a" (-1), "1" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<N>::digits - 2]), "i" (bitset_base<N>::valid_bits)
01345                 : "memory"
01346             );
01347 #else
01348             this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
01349             unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01350             while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
01351 #endif
01352           }
01353           // Or invert them.
01354           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
01355           {
01356 #ifdef __i386__
01357             int __d0, __d1;
01358             __asm__ __volatile__ (
01359                 "xorl %5,(%2)\n\t"
01360                 "jecxz 2f\n\t"
01361                 "subl %6,%2\n"
01362         "1:\n\t"
01363                 "xorl $-1,(%2,%%ecx,4)\n\t"
01364                 "decl %%ecx\n\t"
01365                 "jnz 1b\n"
01366         "2:"
01367                 : "=m" (this->vector[bitset_base<N>::digits - 1]), "=&c" (__d0), "=&r" (__d1)
01368                 : "1" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<N>::digits - 1]),
01369                   "i" (bitset_base<N>::valid_bits), "i" ((bitset_base<N>::digits - bitset_base<x>::digits) * 4)
01370                 : "memory", "cc"
01371             );
01372 #else
01373             this->vector[bitset_base<N>::digits - 1] ^= bitset_base<N>::valid_bits;
01374             unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01375             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
01376 #endif
01377           }
01378         }
01379       }
01380 
01381       // Handle other digits.
01382 #ifdef __i386__
01383       LIBECC_INLINE_ASMLOOP(ASSIGNMENT_OPERATOR::id,
01384           this->vector, bits.digits_ptr(),
01385           ((bitset_base<N>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<N>::digits),
01386           inverted_argument);
01387 #else
01388       unsigned int d;
01389       if (bitset_base<N>::digits > bitset_base<x>::digits)
01390         d = bitset_base<x>::digits - 1;
01391       else
01392         d = bitset_base<N>::digits - 1;
01393       ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~bits.rawdigit(d) : bits.rawdigit(d));
01394       while(d) { --d; ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~bits.rawdigit(d) : bits.rawdigit(d)); }
01395 #endif
01396 
01397       // Reset excess bits if needed.
01398       if (((!inverted_argument && x > N) ||
01399             (inverted_argument && bitset_base<N>::digits <= bitset_base<x>::digits)) &&
01400           bitset_base<N>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
01401         this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
01402     }
01403 
01404 //
01405 // Assignment function for expressions.
01406 // This function handles:
01407 //
01408 // a = b & c;
01409 // a = b & ~c;
01410 // a = ~b & c;
01411 // a = ~b & ~b;
01412 // a = b | c;
01413 // a = b | ~c;
01414 // a = ~b | c;
01415 // a = ~b | ~b;
01416 // a = b ^ c;
01417 // a = b ^ ~c;
01418 // a = ~b ^ c;
01419 // a = ~b ^ ~b;
01420 // a &= b & c;
01421 // a &= b & ~c;
01422 // a &= ~b & c;
01423 // a &= ~b & ~b;
01424 // a &= b | c;
01425 // a &= b | ~c;
01426 // a &= ~b | c;
01427 // a &= ~b | ~b;
01428 // a &= b ^ c;
01429 // a &= b ^ ~c;
01430 // a &= ~b ^ c;
01431 // a &= ~b ^ ~b;
01432 // a |= b & c;
01433 // a |= b & ~c;
01434 // a |= ~b & c;
01435 // a |= ~b & ~b;
01436 // a |= b | c;
01437 // a |= b | ~c;
01438 // a |= ~b | c;
01439 // a |= ~b | ~b;
01440 // a |= b ^ c;
01441 // a |= b ^ ~c;
01442 // a |= ~b ^ c;
01443 // a |= ~b ^ ~b;
01444 // a ^= b & c;
01445 // a ^= b & ~c;
01446 // a ^= ~b & c;
01447 // a ^= ~b & ~b;
01448 // a ^= b | c;
01449 // a ^= b | ~c;
01450 // a ^= ~b | c;
01451 // a ^= ~b | ~b;
01452 // a ^= b ^ c;
01453 // a ^= b ^ ~c;
01454 // a ^= ~b ^ c;
01455 // a ^= ~b ^ ~b;
01456 //
01457 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
01458 // OPERATOR is one of bitsetAND, bitsetOR or bitsetXOR.
01459 //
01460 template<unsigned int N, bool inverted>
01461   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted1, bool inverted2, typename OPERATOR>
01462     inline void
01463     bitset_invertible<N, inverted>::assign(Operator::bitsetExpression<x, inverted1, inverted2, OPERATOR> const& expr, ASSIGNMENT_OPERATOR)
01464     {
01465       static bool const argument_has_leading_ones = OPERATOR::template execbool<inverted1, inverted2>::value;
01466 
01467       // Handle excess digits.
01468       if (bitset_base<N>::digits > bitset_base<x>::digits)
01469       {
01470         if (!argument_has_leading_ones)
01471         {
01472           // Fill excess digits with 0's when needed.
01473           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
01474           {
01475 #ifdef __i386__
01476             int __d0, __d1;
01477             __asm__ __volatile__ (
01478                 "std; rep; stosl"
01479                 : "=m" (this->vector[bitset_base<N>::digits - 1]), "=&c" (__d0), "=&D" (__d1)
01480                 : "a" (0), "1" (bitset_base<N>::digits - bitset_base<x>::digits), "2" (&this->vector[bitset_base<N>::digits - 1])
01481                 : "memory"
01482             );
01483 #else
01484             unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01485             do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
01486 #endif
01487           }
01488         }
01489         else
01490         {
01491           // Fill excess digits with 1's when needed.
01492           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
01493           {
01494 #ifdef __i386__
01495             int __d0, __d1;
01496             __asm__ __volatile__ (
01497                 "movl %6,4(%%edi); std; rep; stosl"
01498                 : "=m" (this->vector[bitset_base<N>::digits - 2]), "=&c" (__d0), "=&D" (__d1)
01499                 : "a" (-1), "1" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<N>::digits - 2]), "i" (bitset_base<N>::valid_bits)
01500                 : "memory"
01501             );
01502 #else
01503             this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
01504             unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01505             while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
01506 #endif
01507           }
01508           // Or invert them.
01509           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
01510           {
01511 #ifdef __i386__
01512             int __d0, __d1;
01513             __asm__ __volatile__ (
01514                 "xorl %5,(%2)\n\t"
01515                 "jecxz 2f\n\t"
01516                 "subl %6,%2\n"
01517         "1:\n\t"
01518                 "xorl $-1,(%2,%%ecx,4)\n\t"
01519                 "decl %%ecx\n\t"
01520                 "jnz 1b\n"
01521         "2:"
01522                 : "=m" (this->vector[bitset_base<N>::digits - 1]), "=&c" (__d0), "=&r" (__d1)
01523                 : "1" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<N>::digits - 1]),
01524                   "i" (bitset_base<N>::valid_bits), "i" ((bitset_base<N>::digits - bitset_base<x>::digits) * 4)
01525                 : "memory", "cc"
01526             );
01527 #else
01528             this->vector[bitset_base<N>::digits - 1] ^= bitset_base<N>::valid_bits;
01529             unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01530             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
01531 #endif
01532           }
01533         }
01534       }
01535 
01536       // Handle other digits.
01537 #ifdef __i386__
01538       LIBECC_INLINE_ASMLOOP2(ASSIGNMENT_OPERATOR::id, OPERATOR, inverted1, inverted2,
01539           this->vector, expr.first.digits_ptr(), expr.second.digits_ptr(),
01540           ((bitset_base<N>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<N>::digits));
01541 #else
01542       unsigned int d;
01543       if (bitset_base<N>::digits < bitset_base<x>::digits)
01544         d = bitset_base<N>::digits - 1;
01545       else
01546         d = bitset_base<x>::digits - 1;
01547       for(;;)
01548       {
01549         ASSIGNMENT_OPERATOR::exec(this->vector[d],
01550             OPERATOR::exec(inverted1 ? ~expr.first.rawdigit(d) : expr.first.rawdigit(d),
01551                            inverted2 ? ~expr.second.rawdigit(d) : expr.second.rawdigit(d)));
01552         if (!d)
01553           break;
01554         --d;
01555       }
01556 #endif
01557 
01558       // Reset excess bits if needed.
01559       if (((!argument_has_leading_ones && x > N) ||
01560             (argument_has_leading_ones && bitset_base<N>::digits <= bitset_base<x>::digits)) &&
01561           bitset_base<N>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
01562         this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
01563     }
01564 
01591 template<unsigned int N, bool inverted>
01592   inline bitset_invertible<N, !inverted> const&
01593   operator~(bitset_invertible<N, inverted> const& bits)
01594   {
01595     return *reinterpret_cast<bitset_invertible<N, !inverted> const*>(&bits);
01596   }
01597 
01598 #ifndef __i386__
01599 template<unsigned int N, int DIRECTION>
01600   void
01601   bitset_iterator<N, DIRECTION>::find1_forward(void)
01602   {
01603     if (this->M_digit < (int)bitset_base<N>::digits - 1 || (this->M_mask & bitset_base<N>::valid_bits))
01604     {
01605       register bitset_digit_t mask = this->M_mask;
01606       while(!(M_bitset_ptr->rawdigit(this->M_digit) & mask)) 
01607       {
01608         if ((mask <<= 1))
01609           continue;
01610         mask = 1;
01611         while(++(this->M_digit) < (int)bitset_base<N>::digits)
01612           if (M_bitset_ptr->rawdigit(this->M_digit))
01613             break;
01614         if (this->M_digit == (int)bitset_base<N>::digits)
01615         {
01616           this->M_digit = (N >> bitset_digit_bits_log2);
01617           mask = static_cast<bitset_digit_t>(1) << (N & (bitset_digit_bits - 1));
01618           break;
01619         }
01620       }
01621       this->M_mask = mask;
01622     }
01623   }
01624 
01625 template<unsigned int N, int DIRECTION>
01626   void
01627   bitset_iterator<N, DIRECTION>::find1_backward(void)
01628   {
01629     LibEccDout(dc::bitsetfind1, "Entering find1_backward with: " << 
01630         libcwd::cwprint_using(*static_cast<bitset_invertible<N, false> const*>(M_bitset_ptr), &bitset_invertible<N, false>::base2_print_on));
01631     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01632     if (this->M_digit >= 0)
01633     {
01634       register bitset_digit_t mask = this->M_mask;
01635       if (!(M_bitset_ptr->rawdigit(this->M_digit) & (mask | (mask - 1))))
01636       {
01637         mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
01638         do
01639         {
01640           if (--(this->M_digit) < 0)
01641           {
01642             this->M_mask = mask;
01643             return;
01644           }
01645         }
01646         while (!M_bitset_ptr->rawdigit(this->M_digit));
01647       }
01648       while(!(M_bitset_ptr->rawdigit(this->M_digit) & mask)) 
01649         mask >>= 1;
01650       this->M_mask = mask;
01651     }
01652     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01653   }
01654 #endif
01655 
01659 template<unsigned int N, int DIRECTION>
01660   inline void
01661   bitset_iterator<N, DIRECTION>::find1(void)
01662   {
01663     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01664     LibEccDout(dc::bitsetfind1, "Entering find1 with: " << 
01665         libcwd::cwprint_using(*static_cast<bitset_invertible<N, false> const*>(M_bitset_ptr), &bitset_invertible<N, false>::base2_print_on));
01666 #ifdef __i386__
01667     int bit_index, digit, ptr;
01668     if (DIRECTION == backwards_iterating)
01669     {
01670       __asm__ __volatile__ (
01671           // %eax: M_index (input) and work variable.
01672           // %ecx: bit_index (work variable).
01673           // %edi: &M_bitset_ptr->rawdigit(M_index/32 - 1) (input) and ptr (work variable).
01674           // %2  : digit (work variable).
01675 
01676           // Make a copy of M_index into %ecx, last time we used M_index.
01677           "movl %%eax,%%ecx\n\t"
01678           // Set %eax to its correct value by deviding it by 32.
01679           "sarl $5,%%eax\n\t"
01680           // Set bit_index to its correct value by taking the modulo 32 of it.
01681           "andl $31,%%ecx\n\t"
01682           // If M_index is -1, do nothing.
01683           "js 1f\n\t"
01684           // Copy the most significant digit, the digit with the
01685           // bit at which we will start the search, into %2.
01686           // digit = M_bitset_ptr->rawdigit(%eax)
01687           "movl 4(%%edi),%2\n\t"
01688           // Shift this digit left until the first bit comes at position 31.
01689           // bit_index = 31 - bit_index
01690           "xorl $31,%%ecx\n\t"
01691           // digit <<= bit_index
01692           "shll %%cl,%2\n\t"
01693           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01694           // This is not needed for the athlon for that reason, but we also need this orl
01695           // for the case that %cl equals zero in which case the ZF is cleared!
01696           "orl %2,%2\n\t"                       
01697           // If there is no bit set in the current digit, goto digit_search.
01698           "jz 5f\n\t"
01699           // Search for the (next) most significant bit set.
01700           // This is slow on i[345]86: 11 + 2*N cycles; only generates 2 uops on a pentium though.
01701           "bsrl %2,%2\n\t"
01702           // Correct M_index to point to this bit.
01703           // %eax <<= 5
01704           "sall $5,%%eax\n\t"
01705           // %2 -= bit_index
01706           "subl %%ecx,%2\n\t"
01707           // M_index = %eax + %2
01708           "addl %2,%%eax\n\t"
01709           // Done.
01710           // goto exit
01711           "jmp 1f\n\t"
01712           ".align 16\n"
01713        "7:\n\t"                         // Main loop.
01714           "movl (%%edi),%2\n\t"
01715           "subl $4,%%edi\n\t"
01716           "testl %2,%2\n\t"
01717           "jnz 6f\n\t"
01718        "5:\n\t"                         // digit_search:
01719           "decl %%eax\n\t"
01720           // Repeat main loop.
01721           "jns 7b\n"    
01722        "4:\n\t"                         // reached_end:
01723           // No set bit found at all.  Set M_index to -1.
01724           "movl $-1,%%eax\n\t"
01725           // Done.
01726           // goto exit
01727           "jmp 1f\n"
01728           // Search for the most significant bit set in this digit.
01729        "6:\n\t"
01730           "bsrl %2,%2\n\t"
01731           // Correct M_index to point to this bit.
01732           "sall $5,%%eax\n\t"
01733           "addl %2,%%eax\n"
01734        "1:"                             // exit:
01735 
01736           : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01737           : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() - 1 + (this->M_index >> 5))
01738           : "cc"
01739       );
01740     }
01741     else
01742     {
01743       __asm__ __volatile__ (
01744           // %eax: M_index (input) and work variable.
01745           // %ecx: bit_index (work variable).
01746           // %edi: &M_bitset_ptr->rawdigit(M_index/32 + 1) (input) and ptr (work variable).
01747           // %2  : digit (work variable).
01748 
01749           // if (M_index >= N) then goto exit
01750           "cmpl %6,%%eax\n\t"
01751           "jge 1f\n\t"
01752           // Make a copy of M_index into %ecx, last time we used M_index.
01753           "movl %%eax,%%ecx\n\t"
01754           // Set %eax to its correct value by deviding it by 32.
01755           "sarl $5,%%eax\n\t"
01756           // Set bit_index to its correct value by taking the modulo 32 of it.
01757           "andl $31,%%ecx\n\t"
01758           // Copy the least significant digit, the digit with the
01759           // bit at which we will start the search, into %2.
01760           // digit = M_bitset_ptr->rawdigit(%eax)
01761           "movl -4(%%edi),%2\n\t"
01762           // Shift this digit right until the first bit comes at position 0.
01763           // digit >>= bit_index
01764           "shrl %%cl,%2\n\t"
01765           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01766           // This is not needed for the athlon for that reason, but we also need this orl
01767           // for the case that %cl equals zero in which case the ZF is cleared!
01768           "orl %2,%2\n\t"                       
01769           // If there is no bit set in the current digit, goto digit_search.
01770           "jz 5f\n\t"
01771           // Search for the (next) most significant bit set.
01772           // This is slow on i[345]86: 11 + 2*N cycles; only generates 2 uops on a pentium though.
01773           "bsfl %2,%2\n\t"
01774           // Correct M_index to point to this bit.
01775           // %eax <<= 5
01776           "sall $5,%%eax\n\t"
01777           // %2 -= bit_index
01778           "addl %%ecx,%2\n\t"
01779           // M_index = %eax + %2
01780           "addl %2,%%eax\n\t"
01781           // Done.
01782           // goto exit
01783           "jmp 1f\n\t"
01784           ".align 16\n"
01785        "7:\n\t"                         // Main loop.
01786           "movl (%%edi),%2\n\t"
01787           "addl $4,%%edi\n\t"
01788           "testl %2,%2\n\t"
01789           "jnz 6f\n\t"
01790        "5:\n\t"                         // digit_search:
01791           "incl %%eax\n\t"
01792           "cmpl %7, %%eax\n\t"
01793           // Repeat main loop.
01794           "jnz 7b\n"            
01795        "4:\n\t"                         // reached_end:
01796           // No set bit found at all.  Set M_index to N.
01797           "movl %6,%%eax\n\t"
01798           // Done.
01799           // goto exit
01800           "jmp 1f\n"
01801           // Search for the least significant bit set in this digit.
01802        "6:\n\t"
01803           "bsfl %2,%2\n\t"
01804           // Correct M_index to point to this bit.
01805           "sall $5,%%eax\n\t"
01806           "addl %2,%%eax\n"
01807        "1:"                             // exit:
01808 
01809           : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01810           : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() + 1 + (this->M_index >> 5)),
01811             "i" (N), "i" (bitset_base<N>::digits)
01812           : "cc"
01813       );
01814     }
01815 #else
01816     if (DIRECTION == forwards_iterating)
01817       find1_forward();
01818     else
01819       find1_backward();
01820 #endif
01821     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01822     return;
01823   }
01824 
01825 
01829 template<unsigned int N, int DIRECTION>
01830   inline
01831   bitset_iterator<N, DIRECTION>::bitset_iterator(void)
01832   {
01833   }
01834 
01838 template<unsigned int N, int DIRECTION>
01839   inline
01840   bitset_iterator<N, DIRECTION>::bitset_iterator(bitset_base<N> const* bitset_ptr, int bit) :
01841       bitset_index_iterator<DIRECTION>(bit), M_bitset_ptr(bitset_ptr)
01842   {
01843   }
01844 
01848 template<unsigned int N, int DIRECTION>
01849   inline
01850   bitset_iterator<N, DIRECTION>::bitset_iterator(bitset_iterator const& iter) :
01851       bitset_index_iterator<DIRECTION>(iter), M_bitset_ptr(iter.M_bitset_ptr)
01852   {
01853   }
01854 
01858 template<unsigned int N, int DIRECTION>
01859   inline bitset_iterator<N, DIRECTION>&
01860   bitset_iterator<N, DIRECTION>::operator=(bitset_iterator<N, DIRECTION> const& iter)
01861   {
01862 #ifdef __i386__
01863     this->M_index = iter.M_index;
01864 #else
01865     this->M_digit = iter.M_digit;
01866     this->M_mask = iter.M_mask;
01867 #endif
01868     M_bitset_ptr = iter.M_bitset_ptr;
01869     return *this;
01870   }
01871 
01872 template<unsigned int N, int DIRECTION>
01873   inline bitset_iterator<N, DIRECTION>&
01874   bitset_iterator<N, DIRECTION>::operator=(bitset_index_iterator<DIRECTION> const& index)
01875   {
01876 #ifdef __i386__
01877     this->M_index = index.get_index();
01878 #else
01879     this->M_digit = index.get_digit();
01880     this->M_mask = index.get_mask();
01881 #endif
01882     return *this;
01883   }
01884 
01888 template<unsigned int N, int DIRECTION>
01889   inline bitset_iterator<N, DIRECTION>&
01890   bitset_iterator<N, DIRECTION>::operator++()
01891   {
01892     this->increment();
01893     return *this;
01894   }
01895 
01899 template<unsigned int N, int DIRECTION>
01900   inline bitset_iterator<N, DIRECTION>
01901   bitset_iterator<N, DIRECTION>::operator++(int)
01902   {
01903     bitset_iterator prev(*this);
01904     this->increment();
01905     return prev;
01906   }
01907 
01911 template<unsigned int N, int DIRECTION>
01912   inline bitset_iterator<N, DIRECTION>&
01913   bitset_iterator<N, DIRECTION>::operator--()
01914   {
01915     this->decrement();
01916     return *this;
01917   }
01918 
01922 template<unsigned int N, int DIRECTION>
01923   inline bitset_iterator<N, DIRECTION>
01924   bitset_iterator<N, DIRECTION>::operator--(int)
01925   {
01926     bitset_iterator prev(*this);
01927     this->decrement();
01928     return prev;
01929   }
01930 
01937 template<unsigned int N, int DIRECTION>
01938   inline bitset_digit_t
01939   bitset_iterator<N, DIRECTION>::operator*() const
01940  {
01941 #ifdef __i386__
01942     register unsigned int digit = this->M_index;
01943     register bitset_digit_t mask = 1;
01944     register unsigned short shift = this->M_index & (ECC_BITS - 1);
01945     digit >>= bitset_digit_bits_log2;
01946     mask <<= shift;
01947     return (M_bitset_ptr->rawdigit(digit) & mask);
01948 #else
01949     return (M_bitset_ptr->rawdigit(this->M_digit) & this->M_mask);
01950 #endif
01951   }
01952 
01956 template<unsigned int N, int DIRECTION>
01957   inline bitset_iterator<N, DIRECTION>&
01958   bitset_iterator<N, DIRECTION>::operator+=(int d)
01959   {
01960     this->increment(d);
01961     return *this;
01962   }
01963 
01967 template<unsigned int N, int DIRECTION>
01968   inline bitset_iterator<N, DIRECTION>&
01969   bitset_iterator<N, DIRECTION>::operator-=(int d)
01970   {
01971     this->decrement(d);
01972     return *this;
01973   }
01974 
01978 template<unsigned int N, int DIRECTION>
01979   inline bitset_iterator<N, DIRECTION>
01980   operator+(bitset_iterator<N, DIRECTION> const& i, int d)
01981   {
01982     bitset_iterator<N, DIRECTION> result(i);
01983     return result += d;
01984   }
01985 
01989 template<unsigned int N, int DIRECTION>
01990   inline bitset_iterator<N, DIRECTION>
01991   operator+(int d, bitset_iterator<N, DIRECTION> const& i)
01992   {
01993     bitset_iterator<N, DIRECTION> result(i);
01994     return result += d;
01995   }
01996 
02000 template<unsigned int N, int DIRECTION>
02001   inline bitset_iterator<N, DIRECTION>
02002   operator-(bitset_iterator<N, DIRECTION> const& i, int d)
02003   {
02004     bitset_iterator<N, DIRECTION> result(i);
02005     return result -= d;
02006   }
02007 
02011 template<unsigned int N, int DIRECTION>
02012   inline bitset_iterator<N, DIRECTION>
02013   operator-(int d, bitset_iterator<N, DIRECTION> const& i)
02014   {
02015     bitset_iterator<N, DIRECTION> result(i);
02016     return result -= d;
02017   }
02018 
02022 template<unsigned int N, int DIRECTION>
02023   inline bitset_digit_t
02024   bitset_iterator<N, DIRECTION>::operator[](int d) const
02025  {
02026     return *(*this + d);
02027   }
02028 
02029 //--------------------------------------------------------------------------------------------------------------------------
02036 template<unsigned int N>
02037   classbitset : public bitset_invertible<N, false> {
02038     public:
02039       // Constructors.
02040       bitset(void);
02041       bitset(std::string const&);
02042       explicit bitset(bitset_digit_t low_bits);
02043       // This definition must be here, inside the template class declaration because
02044       // otherwise the compiler (2.95 - 3.1) barfs.
02050       bitset(bitset_digit_t const (&v)[bitset_base<N>::digits])
02051       {
02052 #if ECC_DEBUG
02053         assert( (v[bitset_base<N>::digits - 1] & ~bitset_base<N>::valid_bits) == 0 );
02054 #endif
02055         std::memcpy(this->vector, v, sizeof(this->vector));
02056       }
02057 
02058       // Copy constructors.
02059       template<unsigned int m, bool inverted>
02060         bitset(bitset_invertible<m, inverted> const&);
02061       template<unsigned int m, bool i1, bool i2, typename OP>
02062         bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr);
02063 
02064       // Assignment operators.
02065       bitset& operator=(bitset const&);
02066       template<typename Expression>
02067         bitset& operator=(Expression const&);
02068 
02069       // Perform AND, OR, XOR operations
02070       template<typename Expression>
02071         bitset& operator&=(Expression const&);
02072       template<typename Expression>
02073         bitset& operator|=(Expression const&);
02074       template<typename Expression>
02075         bitset& operator^=(Expression const&);
02076 
02077     public:
02078       // Shift bitset left or right and perform operation with result.
02079       template<unsigned int shift, class DIRECTION, class OPERATION>
02080         void shift_op(bitset& result) const;
02081 
02083       bitset& operator<<=(unsigned int shift) { this->bitset_base<N>::operator<<=(shift); return *this; }
02085       bitset& operator>>=(unsigned int shift) { this->bitset_base<N>::operator>>=(shift); return *this; }
02086 
02087       // Rotate left or right
02088       template<unsigned int shift, class DIRECTION>                     // Return a copy rotated `shift' bits in `DIRECTION'.
02089         void rotate(bitset& result) const;
02090   };
02091 
02095 template<unsigned int N>
02096   inline
02097   bitset<N>::bitset(void)
02098   {
02099   }
02100 
02106 template<unsigned int N>
02107   inline
02108   bitset<N>::bitset(bitset_digit_t low_bits)
02109   {
02110 #if ECC_DEBUG
02111     assert( bitset_base<N>::digits > 1 || (low_bits & ~bitset_base<N>::valid_bits) == 0 );
02112 #endif
02113     std::memset(this->vector, 0, sizeof(this->vector));
02114     this->vector[0] = low_bits;
02115   }
02116 
02120 template<unsigned int N>
02121   void
02122   bitset_base<N>::setall(void)
02123   {
02124     this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
02125     if (bitset_base<N>::digits > 1)
02126     {
02127       int d = bitset_base<N>::digits - 2;
02128       do { this->vector[d] = ~static_cast<bitset_digit_t>(0); } while(--d >= 0);
02129     }
02130   }
02131 
02156 template<unsigned int N>
02157   template<typename Expression>
02158     inline
02159     bitset<N>& bitset<N>::operator=(Expression const& expr)
02160     {
02161       this->assign(expr, Operator::bitsetAssign());
02162       return *this;
02163     }
02164 
02165 // Special case, need to define this or else we'd get a default assignment operator.
02166 template<unsigned int N>
02167   inline bitset<N>&
02168   bitset<N>::operator=(bitset const& expr)
02169   {
02170     this->assign(expr, Operator::bitsetAssign());
02171     return *this;
02172   }
02173 
02190 template<unsigned int N>
02191   template<unsigned int m, bool inverted>
02192     inline bitset<N>::bitset(bitset_invertible<m, inverted> const& bits) : bitset_invertible<N, false>(bits)
02193     {
02194     }
02195 
02201 template<unsigned int N>
02202   template<unsigned int m, bool i1, bool i2, typename OP>
02203     inline bitset<N>::bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr) : bitset_invertible<N, false>(expr)
02204     {
02205     }
02206 
02218 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02219   bool operator==(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02220   {
02221     unsigned int d;
02222     if (bitset_invertible<n1, inverted1>::digits > bitset_invertible<n2, inverted2>::digits)
02223     {
02224       d = bitset_base<n1>::digits - 1;
02225       do
02226       {
02227         if (bits1.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02228           return false;
02229       }
02230       while (--d != bitset_base<n2>::digits - 1);
02231     }
02232     if (bitset_base<n2>::digits > bitset_base<n1>::digits)
02233     {
02234       d = bitset_base<n2>::digits - 1;
02235       do
02236       {
02237         if (bits2.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02238           return false;
02239       }
02240       while (--d != bitset_base<n1>::digits - 1);
02241     }
02242     if (bitset_base<n1>::digits > 1 && bitset_base<n2>::digits > 1)
02243     {
02244       if (bitset_base<n1>::digits == bitset_base<n2>::digits)
02245         d = bitset_base<n1>::digits - 1;
02246       do
02247       {
02248         if (inverted1 == inverted2)
02249         {
02250           if (bits1.vector[d] != bits2.vector[d])
02251             return false;
02252         }
02253         else
02254         {
02255           if (bits1.vector[d] != ~(bits2.vector[d]))
02256             return false;
02257         }
02258       }
02259       while(--d != 0);
02260     }
02261     if (inverted1 != inverted2)
02262       return (bits1.vector[0] == ~(bits2.vector[0]));
02263     return (bits1.vector[0] == bits2.vector[0]);
02264   }
02265 
02271 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02272   inline bool
02273   operator!=(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02274   {
02275     return !(bits1 == bits2);
02276   }
02277 
02282 template<unsigned int N>
02283   template<typename Expression>
02284     inline bitset<N>&
02285     bitset<N>::operator&=(Expression const& expr)
02286     {
02287       this->assign(expr, Operator::bitsetANDAssign());
02288       return *this;
02289     }
02290 
02295 template<unsigned int N>
02296   template<typename Expression>
02297     inline bitset<N>&
02298     bitset<N>::operator|=(Expression const& expr)
02299     {
02300       this->assign(expr, Operator::bitsetORAssign());
02301       return *this;
02302     }
02303 
02308 template<unsigned int N>
02309   template<typename Expression>
02310     inline bitset<N>&
02311     bitset<N>::operator^=(Expression const& expr)
02312     {
02313       this->assign(expr, Operator::bitsetXORAssign());
02314       return *this;
02315     }
02316 
02321 template<unsigned int m, bool inverted1, bool inverted2>
02322   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>
02323   operator&(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02324     {
02325       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>(arg1, arg2);
02326     }
02327 
02332 template<unsigned int m, bool inverted1, bool inverted2>
02333   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>
02334   operator|(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02335     {
02336       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>(arg1, arg2);
02337     }
02338 
02343 template<unsigned int m, bool inverted1, bool inverted2>
02344   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>
02345   operator^(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02346     {
02347       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>(arg1, arg2);
02348     }
02349 
02353 structassign {
02354   static int const id = 1;
02355   static bool const __clear = true;
02356   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02357   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02358 };
02359 
02363 structexor {
02364   static int const id = 2;
02365   static bool const __clear = false;
02366   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02367   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02368 };
02369 
02370 #ifndef HIDE_FROM_DOXYGEN
02371 structrotate_phase1 {
02372   static int const id = 3;
02373   static bool const __clear = false;
02374   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02375   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02376 };
02377 
02378 structrotate_phase2 {
02379 public:
02380   static int const id = 4;
02381   static bool const __clear = false;
02382   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02383   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 |= digit2; }
02384 };
02385 #endif
02386 
02397 template<unsigned int N>
02398   template<unsigned int shift, class DIRECTION, class OPERATION>
02399     void
02400     bitset<N>::shift_op(bitset& result) const
02401    {
02402       LibEccDout(dc::bitsetshift, "Entering shift_op<" << shift << ", " << libcwd::type_info_of<DIRECTION>().demangled_name() <<
02403           ", " << type_info_of<OPERATION>().demangled_name() << '>');
02404       LibEccDout(dc::bitsetshift|flush_cf, "Input : " << cwprint_using(*this, &bitset<N>::base2_print_on));
02405       if (shift == 1)
02406       {
02407         // Specialization for shift == 1.
02408         // digit_shift = 0
02409         // bit_shift = 1
02410         // zeroed_digits = 0 (likely and if not - then assumed).
02411         // Here we scan in the opposite direction of when shift > 1.
02412         static unsigned int const initial = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02413         static unsigned int const count = bitset_base<N>::digits - ((DIRECTION::__left && bitset_base<N>::has_excess_bits) ? 1 : 0);
02414 #ifdef __i386__
02415         if (count)
02416         {
02417           bitset_digit_t const volatile* ptr1;
02418           bitset_digit_t volatile* ptr2;
02419           int c;
02420           if (DIRECTION::__left)
02421           {
02422             if (OPERATION::id == libecc::exor::id)
02423             {
02424               if (bitset_base<N>::has_excess_bits)
02425                 LIBECC_ASMSHIFTLEFT(
02426                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02427                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"),
02428                     LIBECC_ASMSHIFTLEFT_FINISH("xorl (%%edi),%%edx\n\t"));
02429               else
02430                 LIBECC_ASMSHIFTLEFT(
02431                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02432                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"), "");
02433             }
02434             else if (OPERATION::id == libecc::rotate_phase2::id)
02435             {
02436               if (bitset_base<N>::has_excess_bits)
02437                 LIBECC_ASMSHIFTLEFT(
02438                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02439               else
02440                 LIBECC_ASMSHIFTLEFT(
02441                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", "");
02442             }
02443             else
02444             {
02445               if (bitset_base<N>::has_excess_bits)
02446                 LIBECC_ASMSHIFTLEFT("", "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02447               else
02448                 LIBECC_ASMSHIFTLEFT("", "", "");
02449             }
02450           }
02451           else if (count > 1)
02452           {
02453             if (OPERATION::id == libecc::exor::id)
02454               LIBECC_ASMSHIFTRIGHT1(
02455                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02456                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP2_DESTINATION "," LIBECC_WORKREG),
02457                   LIBECC_PRESERVE_CF_CLOBBER);
02458             else if (OPERATION::id == libecc::rotate_phase2::id)
02459               LIBECC_ASMSHIFTRIGHT1(
02460                   LIBECC_RIGHT_PRESERVE_CF("orl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02461                   "",
02462                   LIBECC_PRESERVE_CF_CLOBBER);
02463             else
02464               LIBECC_ASMSHIFTRIGHT1(
02465                   "",
02466                   "",
02467                   LIBECC_CLOBBER);
02468           }
02469           else
02470           {
02471             if (OPERATION::id == libecc::exor::id)
02472               LIBECC_ASMSHIFTRIGHT0("xorl 4(%%edi), %%edx\n\t");
02473             else if (OPERATION::id == libecc::rotate_phase2::id)
02474               LIBECC_ASMSHIFTRIGHT0("orl 4(%%edi), %%edx\n\t");
02475             else
02476               LIBECC_ASMSHIFTRIGHT0("");
02477           }
02478         }
02479         else if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02480           OPERATION::op(result.vector[0], ((this->vector[0] << 1) & bitset_base<N>::valid_bits));
02481 #else
02482         static unsigned int complement_shift = bitset_digit_bits - 1;
02483         static bitset_digit_t const mask1 = DIRECTION::__left ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02484         static bitset_digit_t const mask2 = DIRECTION::__right ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02485         bitset_digit_t const* ptr1 = &this->vector[initial];
02486         bitset_digit_t* ptr2 = &result.vector[initial];
02487         bool carry;
02488         if (count)
02489         {
02490           bitset_digit_t digit = *ptr1;
02491           carry = (digit & mask1);
02492           if (DIRECTION::__left)
02493             digit <<= 1;
02494           else
02495             digit >>= 1;
02496           OPERATION::mixed_op(*ptr2, digit);
02497           for (int c = count - 1; c; --c)
02498           {
02499             ptr1 -= DIRECTION::direction;
02500             ptr2 -= DIRECTION::direction;
02501             digit = *ptr1;
02502             if (carry)
02503             {
02504               carry = (digit & mask1);
02505               if (DIRECTION::__left)
02506                 digit <<= 1;
02507               else
02508                 digit >>= 1;
02509               digit |= mask2;
02510             }
02511             else
02512             {
02513               carry = (digit & mask1);
02514               if (DIRECTION::__left)
02515                 digit <<= 1;
02516               else
02517                 digit >>= 1;
02518             }
02519             OPERATION::op(*ptr2, digit);
02520           }
02521         }
02522         if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02523         {
02524           bitset_digit_t digit;
02525           if (count)
02526             digit = ptr1[-DIRECTION::direction];
02527           else
02528             digit = *ptr1;
02529           digit <<= 1;
02530           if (count && carry)
02531             digit |= mask2;
02532           if (count)
02533             OPERATION::op(ptr2[-DIRECTION::direction], (digit & bitset_base<N>::valid_bits));
02534           else
02535             OPERATION::op(*ptr2, (digit & bitset_base<N>::valid_bits));
02536         }
02537 #endif
02538       }
02539       else
02540       {
02541         static unsigned int const digit_shift = shift / bitset_digit_bits;
02542         static unsigned int const bit_shift = shift % bitset_digit_bits;
02543 
02544         static unsigned int const zeroed_digits =
02545           DIRECTION::__left ? ((shift < N) ? digit_shift : bitset_base<N>::digits)
02546                             : ((bitset_digit_bits - bitset_base<N>::number_of_valid_bits + shift) / bitset_digit_bits);
02547 
02548         if (zeroed_digits < bitset_base<N>::digits)
02549         {
02550           static unsigned int const complement_shift = (bit_shift == 0) ? 0 : bitset_digit_bits - bit_shift;
02551           static unsigned int const initial_to = DIRECTION::__right ? 0 : bitset_base<N>::digits - 1;
02552           static unsigned int const initial_from = initial_to + DIRECTION::direction * digit_shift;
02553           static unsigned int const final_from = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02554 
02555           register bitset_digit_t digit = this->vector[initial_from];
02556           if (initial_from != final_from)
02557           {
02558             register bitset_digit_t next_digit;
02559             unsigned int to = initial_to;
02560             unsigned int from = initial_from + DIRECTION::direction;
02561             if (from != final_from)
02562               do
02563               {
02564                 next_digit = this->vector[from];
02565                 if (bit_shift != 0)
02566                 {
02567                   if (DIRECTION::direction == -1)
02568                     digit <<= bit_shift;
02569                   else
02570                     digit >>= bit_shift;
02571                   digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02572                 }
02573                 OPERATION::op(result.vector[to], digit);
02574                 digit = next_digit;
02575                 to += DIRECTION::direction;
02576                 from += DIRECTION::direction;
02577               }
02578               while (from != final_from);
02579             if (DIRECTION::__left || bit_shift < bitset_base<N>::number_of_valid_bits || bit_shift != 0)
02580               next_digit = this->vector[final_from];
02581             if (bit_shift != 0)
02582             {
02583               if (DIRECTION::direction == -1)
02584                 digit <<= bit_shift;
02585               else
02586                 digit >>= bit_shift;
02587               digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02588             }
02589             if (DIRECTION::__left || bit_shift < bitset_base<N>::number_of_valid_bits)
02590             {
02591               OPERATION::op(result.vector[final_from - DIRECTION::direction * (digit_shift + 1)], digit);
02592               digit = DIRECTION::shift_copy(next_digit, bit_shift);
02593             }
02594           }
02595           else
02596           {
02597             if (DIRECTION::direction == -1)
02598               digit <<= bit_shift;
02599             else
02600               digit >>= bit_shift;
02601           }
02602           static bool const have_mixed_digit = shift != 0 && (DIRECTION::__left ? shift : (N - shift)) % bitset_digit_bits != 0;
02603           static unsigned int const last_digit = (DIRECTION::__left ? shift : (N - 1 - shift)) / bitset_digit_bits;
02604           if (have_mixed_digit)
02605             OPERATION::mixed_op(result.vector[last_digit], digit);
02606           else
02607             OPERATION::op(result.vector[last_digit], digit);
02608           if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02609             result.vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
02610         }
02611         if (OPERATION::__clear && zeroed_digits > 0)
02612         {
02613           static unsigned int const final_to = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02614           static unsigned int const initial_to = final_to - DIRECTION::direction * (zeroed_digits - 1);
02615           unsigned int to = initial_to;
02616           if (to != final_to)
02617             do
02618             {
02619               result.vector[to] = 0;
02620               to += DIRECTION::direction;
02621             }
02622             while(to != final_to);
02623           result.vector[to] = 0;
02624         }
02625       }
02626       LibEccDout(dc::bitsetshift|flush_cf, "Output: " << cwprint_using(result, &bitset<N>::base2_print_on));
02627     }
02628 
02629 template<unsigned int N>
02630   void
02631   bitset_base<N>::operator<<=(unsigned int shift)
02632   {
02633     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02634     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02635     int digit1 = bitset_base<N>::digits - digit_shift - 2;
02636     bitset_digit_t d0 = (digit1 >= -1) ? this->vector[digit1 + 1] : 0;
02637     for (int digit_to = bitset_base<N>::digits - 1; digit_to >= 0; --digit_to)
02638     {
02639       bitset_digit_t d1 = (digit1 >= 0) ? this->vector[digit1] : 0;
02640       if (bit_shift == 0)
02641         this->vector[digit_to] = d0;
02642       else
02643         this->vector[digit_to] = (d0 << bit_shift) | (d1 >> (bitset_digit_bits - bit_shift));
02644       d0 = d1;
02645       --digit1;
02646     }
02647     if (bitset_base<N>::has_excess_bits)
02648       this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;           // Reset possibly set excess bits.
02649   }
02650 
02651 template<unsigned int N>
02652   void
02653   bitset_base<N>::operator>>=(unsigned int shift)
02654   {
02655     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02656     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02657     unsigned int digit1 = digit_shift + 1;
02658     bitset_digit_t d0 = (digit1 <= bitset_base<N>::digits) ? this->vector[digit1 - 1] : 0;
02659     for (unsigned int digit_to = 0; digit_to < bitset_base<N>::digits; ++digit_to)
02660     {
02661       bitset_digit_t d1 = (digit1 < bitset_base<N>::digits) ? this->vector[digit1] : 0;
02662       if (bit_shift == 0)
02663         this->vector[digit_to] = d0;
02664       else
02665         this->vector[digit_to] = (d0 >> bit_shift) | (d1 << (bitset_digit_bits - bit_shift));
02666       d0 = d1;
02667       ++digit1;
02668     }
02669   }
02670 
02687 template<unsigned int N>
02688   bitset<N>::bitset(std::string const& input)
02689   {
02690     this->reset();                                      // Reset internal digits to zero.
02691     unsigned int d = 0;                                 // Current index of internal digit.
02692     unsigned int u = 0;                                 // Current bit-shift of input digit relative to internal digit.
02693 
02694     for (std::string::const_reverse_iterator iter = input.rbegin(); iter != input.rend(); ++iter)       // Read right to left.
02695     {
02696       bitset_digit_t c = toupper(*iter);                // Get next hexadecimal input character.
02697       if (c == ' ')                                     // Skip spaces.
02698         continue;
02699       if (c < '0')                                      // Terminate reading when not a hexadecimal character.
02700         break;
02701       if (c <= '9')
02702         c -= '0';                                       // Set c to the value that the input character represents.
02703       else
02704       {
02705         if (c > 'F')
02706           break;
02707         if (c >= 'A')
02708           c -= ('A' - 10);
02709         else
02710           break;
02711       }
02712       this->vector[d] |= c << u;                        // Set internal bits.
02713       if ((u += 4) == bitset_digit_bits)                // Update bit/digit 'pointers'.
02714       {
02715         u = 0;
02716         if (++d == bitset_base<N>::digits)              // Terminate reading when bitset is full.
02717           break;
02718       }
02719     }
02720     if (bitset_base<N>::has_excess_bits)
02721       this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;   // Reset possibly set excess bits.
02722   }
02723 
02727 template<unsigned int N>
02728   std::istream&
02729   operator>>(std::istream& is, bitset<N>& bitsetx)
02730   {
02731     std::string tmp;
02732     is >> tmp;
02733     bitsetx.bitset(tmp);
02734     return is;
02735   }
02736 
02740 template<unsigned int N>
02741   std::ostream&
02742   operator<<(std::ostream& os, bitset<N> const& bits)
02743   {
02744     // Hexadecimal representation
02745     os.fill('0');
02746     os << std::hex;
02747     for (int d = bitset<N>::digits - 1; d >= 0; --d)
02748     {
02749       os.width((d == bitset<N>::digits - 1 && bitset<N>::has_excess_bits) ?
02750           (((N % bitset_digit_bits) - 1) / 4 + 1) :
02751           (bitset_digit_bits / 4));
02752       os << bits.digit(d);
02753       if (d > 0)
02754         os << ' ';
02755     }
02756     os << std::dec;
02757     return os;
02758   }
02759 
02763 template<unsigned int N>
02764   void
02765   bitset_base<N>::reset(void)
02766   {
02767     std::memset(this->vector, 0, sizeof(this->vector));
02768   }
02769 
02773 template<unsigned int N>
02774   inline bool
02775   bitset_base<N>::test(size_t pos) const
02776  {
02777 #ifdef __i386__
02778     int result;
02779     __asm__ __volatile__ (
02780         "btl %2, %1\n\t"
02781         "sbbl %0, %0"
02782         : "=r" (result)
02783         : "m" ((*(bitset_digit_t volatile*)this->vector)), "Ir" (pos));
02784     return result;
02785 #else
02786     unsigned int d = pos / bitset_digit_bits;
02787     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02788     return (this->vector[d] & mask);
02789 #endif
02790   }
02791 
02795 template<unsigned int N>
02796   template<unsigned int pos>
02797     inline bool
02798     bitset_base<N>::test(void) const
02799    {
02800       static unsigned int const d = pos / bitset_digit_bits;
02801       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02802       return (this->vector[d] & mask);
02803     }
02804 
02808 template<unsigned int N>
02809   inline bool
02810   bitset_base<N>::test(bitset_index const& index) const
02811  {
02812 #ifdef __i386__
02813     return this->test(index.get_index());
02814 #else
02815     return (this->vector[index.get_digit()] & index.get_mask());
02816 #endif
02817   }
02818 
02822 template<unsigned int N>
02823   inline void
02824   bitset_base<N>::set(size_t pos)
02825   {
02826 #ifdef __i386__
02827     __asm__ __volatile__ (
02828         "btsl %1, %0"
02829         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02830         : "Ir" (pos));
02831 
02832 #else
02833     unsigned int d = pos / bitset_digit_bits;
02834     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02835     this->vector[d] |= mask;
02836 #endif
02837   }
02838 
02842 template<unsigned int N>
02843   inline void
02844   bitset_base<N>::set(bitset_index const& index)
02845   {
02846 #ifdef __i386__
02847     this->set(index.get_index());
02848 #else
02849     this->vector[index.get_digit()] |= index.get_mask();
02850 #endif
02851   }
02852 
02856 template<unsigned int N>
02857   template<unsigned int pos>
02858     inline void
02859     bitset_base<N>::set(void)
02860     {
02861       static unsigned int const d = pos / bitset_digit_bits;
02862       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02863       this->vector[d] |= mask;
02864     }
02865 
02869 template<unsigned int N>
02870   inline void
02871   bitset_base<N>::clear(size_t pos)
02872   {
02873 #ifdef __i386__
02874     __asm__ __volatile__ (
02875         "btrl %1, %0"
02876         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02877         : "Ir" (pos)
02878     );
02879 #else
02880     unsigned int d = pos / bitset_digit_bits;
02881     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02882     this->vector[d] &= ~mask;
02883 #endif
02884   }
02885 
02889 template<unsigned int N>
02890   inline void
02891   bitset_base<N>::clear(bitset_index const& index)
02892   {
02893 #ifdef __i386__
02894     this->clear(index.get_index());
02895 #else
02896     this->vector[index.get_digit()] &= ~(index.get_mask());
02897 #endif
02898   }
02899 
02903 template<unsigned int N>
02904   template<unsigned int pos>
02905     inline void
02906     bitset_base<N>::clear(void)
02907     {
02908       static unsigned int const d = pos / bitset_digit_bits;
02909       static bitset_digit_t const mask = ~(static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits));
02910       this->vector[d] &= mask;
02911     }
02912 
02916 template<unsigned int N>
02917   inline void
02918   bitset_base<N>::flip(size_t pos)
02919   {
02920 #ifdef __i386__
02921     __asm__ __volatile__ (
02922         "btcl %1, %0"
02923         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02924         : "Ir" (pos)
02925     );
02926 #else
02927     unsigned int d = pos / bitset_digit_bits;
02928     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02929     this->vector[d] ^= mask;
02930 #endif
02931   }
02932 
02936 template<unsigned int N>
02937   inline void
02938   bitset_base<N>::flip(bitset_index const& index)
02939   {
02940 #ifdef __i386__
02941     this->flip(index.get_index());
02942 #else
02943     this->vector[index.get_digit()] ^= index.get_mask();
02944 #endif
02945   }
02946 
02950 template<unsigned int N>
02951   template<unsigned int pos>
02952     inline void
02953     bitset_base<N>::flip(void)
02954     {
02955       static unsigned int const d = pos / bitset_digit_bits;
02956       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02957       this->vector[d] ^= mask;
02958     }
02959 
02963 template<unsigned int N>
02964   bool
02965   bitset_base<N>::any(void) const
02966  {
02967     unsigned int to = bitset_base<N>::digits - 1;
02968     if (bitset_base<N>::digits > 1)
02969       do
02970       {
02971         if (this->vector[to] != 0)
02972           return true;
02973         --to;
02974       }
02975       while(to != 0);
02976     return (this->vector[0] != 0);
02977   }
02978 
02979 static bool const oddnumberofbits[] = {
02980   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02981   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02982   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02983   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02984   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02985   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02986   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02987   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02988   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02989   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02990   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02991   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02992   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02993   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02994   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02995   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false };
02996 
03000 template<unsigned int N>
03001   bool
03002   bitset_base<N>::odd(void) const
03003  {
03004     unsigned int from = bitset_base<N>::digits - 1;
03005     bitset_digit_t sum = this->vector[0];
03006     if (bitset_base<N>::digits > 1)
03007       do
03008       {
03009         sum ^= this->vector[from];
03010         --from;
03011       }
03012       while(from != 0);
03013     bitset_digit_t ssum = sum;
03014     if (sizeof(bitset_digit_t) >= 2)
03015     {
03016       ssum >>= (bitset_digit_bits / 2);
03017       sum ^= ssum;
03018     }
03019     if (sizeof(bitset_digit_t) >= 4)
03020     {
03021       ssum = sum;
03022       ssum >>= (bitset_digit_bits / 4);
03023       sum ^= ssum;
03024     }
03025     if (sizeof(bitset_digit_t) >= 8)
03026     {
03027       ssum = sum;
03028       ssum >>= (bitset_digit_bits / 8);
03029       sum ^= ssum;
03030     }
03031     if (sizeof(bitset_digit_t) == 16)
03032     {
03033       ssum = sum;
03034       ssum >>= (bitset_digit_bits / 16);
03035       sum ^= ssum;
03036     }
03037     return oddnumberofbits[sum & 0xff];
03038   }
03039 
03043 structleft {
03044 public:
03045   typedef structright inverse;
03046   static int const direction = -1;
03047   static bool const __left = true;
03048   static bool const __right = false;
03049   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03050   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03051 };
03052 
03056 structright {
03057 public:
03058   typedef structleft inverse;
03059   static int const direction = 1;
03060   static bool const __left = false;
03061   static bool const __right = true;
03062   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03063   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03064 };
03065 
03074 template<unsigned int N>
03075   template<unsigned int shift, class DIRECTION>
03076     void
03077     bitset<N>::rotate(bitset<N>& result) const
03078    {
03079       LibEccDout(dc::bitsetshift|flush_cf, "Entering bitset<" << N << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03080       LibEccDout(dc::bitsetshift|flush_cf, "Rotate input : " << cwprint_using(*this, &bitset<N>::base2_print_on));
03081       shift_op<shift % N, DIRECTION, rotate_phase1>(result);
03082       LibEccDout(dc::bitsetshift|flush_cf, "After phase1 : " << cwprint_using(result, &bitset<N>::base2_print_on));
03083       shift_op<N - (shift % N), typename DIRECTION::inverse, rotate_phase2>(result);
03084       LibEccDout(dc::bitsetshift|flush_cf, "After phase2 : " << cwprint_using(result, &bitset<N>::base2_print_on));
03085       LibEccDout(dc::bitsetshift|flush_cf, "Leaving bitset<" << N << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03086     }
03087 
03088 } // namespace libecc
03089 
03090 #endif // LIBECC_BITS_H
Copyright © 2002-2008 Carlo Wood.  All rights reserved.