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 #ifdef CWDEBUG
00043 #include <libcwd/cwprint.h>
00044 #endif
00045 #define LIBECC_TRACK_EXPR_TEMPORARIES (ECC_DEBUG && 1)
00046 #if LIBECC_TRACK_EXPR_TEMPORARIES
00047 #include <set>
00048 #endif
00049 
00050 #ifdef __i386__
00051 // Assembly code, defined in window.s.
00052 extern "C" int libecc_shift_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00053 extern "C" int libecc_shiftwindow_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00054 #endif
00055 
00056 namespacelibecc {
00057 
00067 typedef unsigned long bitset_digit_t;
00068 
00070 static unsigned int const bitset_digit_bits = sizeof(bitset_digit_t) * 8;
00071 
00073 #if ECC_BITS == 32
00074 static unsigned int const bitset_digit_bits_log2 = 5;
00075 #elif ECC_BITS == 64
00076 #warning 64 bit code has not been tested.  This warning will remain here until you mail me.
00077 static unsigned int const bitset_digit_bits_log2 = 6;
00078 #elif ECC_BITS == 128
00079 #warning 128 bit code has not been tested.  This warning will remain here until you mail me.
00080 static unsigned int const bitset_digit_bits_log2 = 7;
00081 #endif
00082 
00083 // Forward declaration.
00084 template<unsigned int n, bool inverted>
00085   classbitset_invertible;
00086 
00096 template<unsigned int n>
00097   structbitset_base {
00098     public:
00099       // Fix this if you add members in front of vector.
00100       static size_t const offsetof_vector = 0; //sizeof(bitset_digit_t);
00101 
00102     public:
00106       static unsigned int const number_of_bits = n;
00107 
00109       static unsigned int const digits = (n - 1) / bitset_digit_bits + 1;
00110 
00111       // ! The number of valid bits in the most significant digit.
00112       static unsigned int const number_of_valid_bits = bitset_digit_bits - (digits * bitset_digit_bits - n);
00113 
00115       static bitset_digit_t const valid_bits =
00116           ((static_cast<bitset_digit_t>(1) << (number_of_valid_bits - 1)) << 1) - 1;
00117 
00119       static bool const has_excess_bits = ((digits * bitset_digit_bits) != n);
00120 
00121     protected:
00128       //bitset_digit_t empty_space1;
00129       bitset_digit_t vector[digits];
00130       //bitset_digit_t empty_space2;
00131 
00132       template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00133         friend bool operator==(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00134 
00135       template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00136         friend bool operator!=(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00137 
00138     public:
00139       // Digit representation
00140       bitset_digit_t& rawdigit(unsigned int d) { return this->vector[d]; }
00141       bitset_digit_t const* digits_ptr(void) const{ return this->vector; }
00142       bitset_digit_t* digits_ptr(void) { return this->vector; }
00143       uint32_t digit32(unsigned int d32) const
00144      {
00145         if (sizeof(bitset_digit_t) == 4)
00146           return this->vector[d32];
00147         else
00148         {
00149           unsigned int d = d32 / (sizeof(bitset_digit_t) / 4);
00150           unsigned int r = d32 % (sizeof(bitset_digit_t) / 4);
00151           return (this->vector[d] >> (r * 32)) & 0xffffffff;
00152         }
00153       }
00154   };
00155 
00156 #ifndef HIDE_FROM_DOXYGEN
00157 namespaceOperator {
00158 
00159 #ifdef __i386__
00160 
00161 //
00162 // Due to heavily broken inlining heuristics of gcc,
00163 // we are forced to use macros to do the assembly
00164 // inlining.  There is no alternative, I tried everything.
00165 //
00166 
00167 #define LIBECC_INVERT "xorl $-1,%%eax\n\t"
00168 #define LIBECC_NOTHING ""
00169 
00170 #define LIBECC_ASMLOOP(destination, source, count, OPCODE, OPTIONAL_INVERT)     \
00171   do {                                                  \
00172     int __d0, __d1, __d2;                               \
00173     __asm__ __volatile__ (                              \
00174       "\n1:\n\t"                                        \
00175         "movl (%5,%%ecx,4),%%eax\n\t"                   \
00176         OPTIONAL_INVERT                                 \
00177         OPCODE " %%eax,(%4,%%ecx,4)\n\t"                \
00178         "decl %%ecx\n\t"                                \
00179         "jnz 1b"                                        \
00180         : "=c" (__d0), "=&r" (__d1), "=&r" (__d2)       \
00181         : "0" (count),                                  \
00182           "1" ((destination) - 1),                      \
00183           "2" ((source) - 1)                            \
00184         : "%eax", "memory"                              \
00185     );                                                  \
00186   } while(0)
00187 
00188 #define LIBECC_ASMLOOP_BODY(OPCODE, destination, source, count, inverted) \
00189   do { \
00190     if (inverted) \
00191       LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_INVERT); \
00192     else \
00193       LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_NOTHING); \
00194   } while(0)
00195 
00196 #define LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, OPTIONAL_INVERT1, OPCODE2, OPTIONAL_INVERT3)              \
00197   do {                                                          \
00198     int __d0, __d1, __d2, __d3;                                 \
00199     __asm__ __volatile__ (                                      \
00200       "\n1:\n\t"                                                \
00201         "movl (%6,%%ecx,4),%%eax\n\t"                           \
00202         OPTIONAL_INVERT1                                        \
00203         OPCODE2 " (%7,%%ecx,4),%%eax\n\t"                       \
00204         OPTIONAL_INVERT3                                        \
00205         OPCODE " %%eax,(%5,%%ecx,4)\n\t"                        \
00206         "decl %%ecx\n\t"                                        \
00207         "jnz 1b"                                                \
00208         : "=c" (__d0), "=&r" (__d1), "=&r" (__d2), "=&r" (__d3) \
00209         : "0" (count),                                          \
00210           "1" ((destination) - 1),                              \
00211           "2" ((source1) - 1),                                  \
00212           "3" ((source2) - 1)                                   \
00213         : "%eax", "memory"                                      \
00214     );                                                          \
00215   } while(0)
00216 
00217 #define LIBECC_ASMLOOP2_BODY(OPCODE, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00218   do { \
00219     if (OPERATOR::id == libecc::Operator::bitsetAND::id) \
00220     { \
00221       if (inverted1 && inverted2) \
00222         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_INVERT); \
00223       else if (inverted1) \
00224         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00225       else if (inverted2) \
00226         LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00227       else \
00228         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_NOTHING); \
00229     } \
00230     else if (OPERATOR::id == libecc::Operator::bitsetOR::id) \
00231     { \
00232       if (inverted1 && inverted2) \
00233         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_INVERT); \
00234       else if (inverted1) \
00235         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00236       else if (inverted2) \
00237         LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00238       else \
00239         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_NOTHING); \
00240     } \
00241     else if (OPERATOR::id == libecc::Operator::bitsetXOR::id) \
00242     { \
00243       if (inverted1 == inverted2) \
00244         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_NOTHING); \
00245       else \
00246         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_INVERT); \
00247     } \
00248   } while(0)
00249 
00250 #define LIBECC_INLINE_ASMLOOP(ID, destination, source, count, inverted) \
00251     do { \
00252       if (ID == libecc::Operator::bitsetAssign::id) \
00253       { \
00254         LIBECC_ASMLOOP_BODY("movl", destination, source, count, inverted); \
00255       } \
00256       else if (ID == libecc::Operator::bitsetANDAssign::id) \
00257       { \
00258         LIBECC_ASMLOOP_BODY("andl", destination, source, count, inverted); \
00259       } \
00260       else if (ID == libecc::Operator::bitsetORAssign::id) \
00261       { \
00262         LIBECC_ASMLOOP_BODY("orl", destination, source, count, inverted); \
00263       } \
00264       else if (ID == libecc::Operator::bitsetXORAssign::id) \
00265       { \
00266         LIBECC_ASMLOOP_BODY("xorl", destination, source, count, inverted); \
00267       } \
00268     } while(0)
00269 
00270 #define LIBECC_INLINE_ASMLOOP2(ID, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00271     do { \
00272       if (ID == libecc::Operator::bitsetAssign::id) \
00273       { \
00274         LIBECC_ASMLOOP2_BODY("movl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00275       } \
00276       else if (ID == libecc::Operator::bitsetANDAssign::id) \
00277       { \
00278         LIBECC_ASMLOOP2_BODY("andl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00279       } \
00280       else if (ID == libecc::Operator::bitsetORAssign::id) \
00281       { \
00282         LIBECC_ASMLOOP2_BODY("orl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00283       } \
00284       else if (ID == libecc::Operator::bitsetXORAssign::id) \
00285       { \
00286         LIBECC_ASMLOOP2_BODY("xorl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00287       } \
00288     } while(0)
00289 
00290 #define LIBECC_ASMSHIFTRIGHT0(OP1)                      \
00291               __asm__ __volatile__ (                    \
00292                   "movl 4(%%esi),%%edx\n\t"             \
00293                   "shrl $1,%%edx\n\t"                   \
00294                   OP1                                   \
00295                   "movl %%edx,4(%%edi)"                 \
00296                 : "=&S" (ptr1),                         \
00297                   "=&D" (ptr2)                          \
00298                 : "0" (&this->vector[initial - count]), \
00299                   "1" (&result.vector[initial - count]) \
00300                 : "%eax", "%edx", "memory", "cc"        \
00301               )
00302 
00303 #if 0   // NOT faster.
00304 #define LIBECC_OP1_SOURCE "(%%esi)"
00305 #define LIBECC_OP2_SOURCE "(%%esi)"
00306 #define LIBECC_OP1_DESTINATION "(%%edi)"
00307 #define LIBECC_OP2_DESTINATION "(%%edi)"
00308 #define LIBECC_WORKREG "%%eax"
00309 #define LIBECC_CLOBBER "%eax"
00310 #define LIBECC_INIT "std\n\t"
00311 #define LIBECC_LOAD1 "lodsl\n\t"
00312 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00313 #define LIBECC_STORE1 "stosl\n\t"
00314 #define LIBECC_LOAD2 "lodsl\n\t"
00315 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
00316 #define LIBECC_STORE2 "stosl\n\t"
00317 #define LIBECC_DEINIT "cld\n\t"
00318 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "setc %%edx\n\t" OPERAND "\n\tbt $0,%%edx\n\t"
00319 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%edx"
00320 #define LIBECC_INITIAL_ESI &this->vector[initial]
00321 #define LIBECC_INITIAL_EDI &result.vector[initial]
00322 #else
00323 #define LIBECC_OP1_SOURCE "4(%%esi,%%ecx,4)"
00324 #define LIBECC_OP2_SOURCE "(%%esi,%%ecx,4)"
00325 #define LIBECC_OP1_DESTINATION "4(%%edi,%%ecx,4)"
00326 #define LIBECC_OP2_DESTINATION "(%%edi,%%ecx,4)"
00327 #define LIBECC_WORKREG "%%edx"
00328 #define LIBECC_CLOBBER "%edx"
00329 #define LIBECC_INIT
00330 #define LIBECC_LOAD1 "movl " LIBECC_OP1_SOURCE "," LIBECC_WORKREG "\n\t"
00331 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00332 #define LIBECC_STORE1 "movl " LIBECC_WORKREG "," LIBECC_OP1_DESTINATION "\n\t"
00333 #define LIBECC_LOAD2 "movl " LIBECC_OP2_SOURCE "," LIBECC_WORKREG "\n\t"
00334 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
00335 #define LIBECC_STORE2 "movl " LIBECC_WORKREG "," LIBECC_OP2_DESTINATION "\n\t"
00336 #define LIBECC_DEINIT
00337 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
00338 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%eax"
00339 #define LIBECC_INITIAL_ESI &this->vector[initial - count]
00340 #define LIBECC_INITIAL_EDI &result.vector[initial - count]
00341 #endif
00342 
00343 #define LIBECC_ASMSHIFTRIGHT1(OP1, OP2, CLOBBER)        \
00344               __asm__ __volatile__ (                    \
00345                   LIBECC_INIT                           \
00346                   LIBECC_LOAD1                          \
00347                   LIBECC_SHIFT                          \
00348                   OP1                                   \
00349                   LIBECC_STORE1                         \
00350                 "1:\n\t"                                \
00351                   LIBECC_LOAD2                          \
00352                   LIBECC_ROTATE                         \
00353                   OP2                                   \
00354                   LIBECC_STORE2                         \
00355                   "decl %%ecx\n\t"                      \
00356                   "jnz 1b\n\t"                          \
00357                   LIBECC_DEINIT                         \
00358                 : "=&S" (ptr1),                         \
00359                   "=&D" (ptr2),                         \
00360                   "=&c" (c)                             \
00361                 : "0" (LIBECC_INITIAL_ESI),             \
00362                   "1" (LIBECC_INITIAL_EDI),             \
00363                   "2" (count - 1)                       \
00364                 : "memory", "cc", CLOBBER               \
00365               )
00366 
00367 #define LIBECC_ASMSHIFTLEFT(OP1, OP2, FINISH)           \
00368               __asm__ __volatile__ (                    \
00369                   "movl -4(%%esi),%%edx\n\t"            \
00370                   "shll $1,%%edx\n\t"                   \
00371                   OP1                                   \
00372                   "movl %%edx,-4(%%edi)\n\t"            \
00373                   "jecxz 2f\n"                          \
00374                 "1:\n\t"                                \
00375                   "movl (%%esi),%%edx\n\t"              \
00376                   "rcll $1,%%edx\n\t"                   \
00377                   OP2                                   \
00378                   "movl %%edx,(%%edi)\n\t"              \
00379                   "leal 4(%%esi),%%esi\n\t"             \
00380                   "leal 4(%%edi),%%edi\n\t"             \
00381                   "decl %%ecx\n\t"                      \
00382                   "jnz 1b\n"                            \
00383                 "2:\n\t"                                \
00384                   FINISH                                \
00385                 : "=&S" (ptr1),                         \
00386                   "=&D" (ptr2),                         \
00387                   "=&c" (c)                             \
00388                 : "0" (&this->vector[initial + 1]),     \
00389                   "1" (&result.vector[initial + 1]),    \
00390                   "2" (count - 1),                      \
00391                   "i" (bitset_base<n>::valid_bits)      \
00392                 : "%eax", "%edx", "memory", "cc"        \
00393               )
00394 
00395 #define LIBECC_ASMSHIFTLEFT_FINISH(OP)                  \
00396                   "movl (%%esi),%%edx\n\t"              \
00397                   "rcll $1,%%edx\n\t"                   \
00398                   "andl %6,%%edx\n\t"                   \
00399                   OP                                    \
00400                   "movl %%edx,(%%edi)"
00401 
00402 #define LIBECC_LEFT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
00403 
00404 #endif // __i386__
00405 
00406 // Functors.
00407 
00408 // Functor for '&'.
00409 structbitsetAND {
00410   static int const id = 1;
00411   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 & digit2; }
00412   template<bool inverted1, bool inverted2>
00413    structexecbool {
00414      static bool const value = inverted1 && inverted2;
00415    };
00416 };
00417 
00418 // Functor for '|'.
00419 structbitsetOR {
00420   static int const id = 2;
00421   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 | digit2; }
00422   template<bool inverted1, bool inverted2>
00423    structexecbool {
00424      static bool const value = inverted1 || inverted2;
00425    };
00426 };
00427 
00428 // Functor for '^'.
00429 structbitsetXOR {
00430   static int const id = 3;
00431   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 ^ digit2; }
00432   template<bool inverted1, bool inverted2>
00433    structexecbool {
00434      static bool const value = (inverted1 != inverted2);
00435    };
00436 };
00437 
00438 // Functor for '='.
00439 structbitsetAssign {
00440   static int const id = 1;
00441   static bool const sets_excess_bits = true;
00442   static bool const with_zero_sets_zero = true;
00443   static bool const with_ones_sets_ones = true;
00444   static bool const with_ones_inverts = false;
00445   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out = in; }
00446 };
00447 
00448 // Functor for '&='.
00449 structbitsetANDAssign {
00450   static int const id = 2;
00451   static bool const sets_excess_bits = false;
00452   static bool const with_zero_sets_zero = true;
00453   static bool const with_ones_sets_ones = false;
00454   static bool const with_ones_inverts = false;
00455   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out &= in; }
00456 };
00457 
00458 // Functor for '|='.
00459 structbitsetORAssign {
00460   static int const id = 3;
00461   static bool const sets_excess_bits = true;
00462   static bool const with_zero_sets_zero = false;
00463   static bool const with_ones_sets_ones = true;
00464   static bool const with_ones_inverts = false;
00465   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out |= in; }
00466 };
00467 
00468 // Functor for '^='.
00469 structbitsetXORAssign {
00470   static int const id = 4;
00471   static bool const sets_excess_bits = true;
00472   static bool const with_zero_sets_zero = false;
00473   static bool const with_ones_sets_ones = false;
00474   static bool const with_ones_inverts = true;
00475   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out ^= in; }
00476 };
00477 
00478 #if LIBECC_TRACK_EXPR_TEMPORARIES
00479 extern std::multiset<void const*> bitsetExpression_bitset_invertible_pointers;
00480 #endif
00481 
00482 template<unsigned int n, bool inverted1, bool inverted2, typename OP>
00483   structbitsetExpression
00484   {
00485     bitset_invertible<n, inverted1> const& first;
00486     bitset_invertible<n, inverted2> const& second;
00487     OP op;
00488 
00489     bitsetExpression(bitset_invertible<n, inverted1> const& arg1, bitset_invertible<n, inverted2> const& arg2) :
00490         first(arg1), second(arg2)
00491     {
00492       // I found a problem with a destructed temporary that was still in use.
00493       // It seems that the pointer to this destructed temporary is stored in
00494       // this object.  The following code is added in order to debug this
00495       // problem.
00496 #if LIBECC_TRACK_EXPR_TEMPORARIES
00497       bitsetExpression_bitset_invertible_pointers.insert(&arg1);
00498       bitsetExpression_bitset_invertible_pointers.insert(&arg2);
00499       LibEccDout(dc::notice, "Constructed a bitsetExpression with arguments " <<
00500           (void const*)&first << " and " << (void const*)&second);
00501 #endif
00502     }
00503 #if LIBECC_TRACK_EXPR_TEMPORARIES
00504     ~bitsetExpression()
00505     {
00506       bitsetExpression_bitset_invertible_pointers.erase(bitsetExpression_bitset_invertible_pointers.find(&first));
00507       bitsetExpression_bitset_invertible_pointers.erase(bitsetExpression_bitset_invertible_pointers.find(&second));
00508       LibEccDout(dc::notice, "Destructed bitsetExpression with arguments " <<
00509           (void const*)&first << " and " << (void const*)&second);
00510     }
00511 #endif
00512   };
00513 
00514 } // namespace Operator
00515 #endif // HIDE_FROM_DOXYGEN
00516 
00534 template<unsigned int n, bool inverted>
00535   classbitset_invertible : public bitset_base<n> {
00536     public:
00537       // Constructors
00538       bitset_invertible(void);
00539       template<typename Expression>
00540         explicit bitset_invertible<n, inverted>(Expression const&);
00541 
00542 #if LIBECC_TRACK_EXPR_TEMPORARIES
00543       ~bitset_invertible()
00544       {
00545         LibEccDout(dc::notice, "Destructing bitset_invertible at " << (void*)this);
00546         if (Operator::bitsetExpression_bitset_invertible_pointers.find(this) !=
00547             Operator::bitsetExpression_bitset_invertible_pointers.end())
00548           LibEccDoutFatal(dc::core, "This object is still in use by a bitsetExpression!");
00549       }
00550 #endif
00551 
00552     protected:
00553       template<typename OP, unsigned int x, bool invertedx>
00554         void assign(bitset_invertible<x, invertedx> const&, OP);
00555       template<typename OP1, unsigned int x, bool inverted1, bool inverted2, typename OP2>
00556         void assign(Operator::bitsetExpression<x, inverted1, inverted2, OP2> const&, OP1);
00557 
00558     private:
00559       template<unsigned int m, bool i>
00560         friend classbitset_invertible;
00561       template<unsigned int m, int DIRECTION>
00562         friend classbitset_iterator;
00563 
00564     public:
00566       void base2_print_on(std::ostream& os) const;
00567 
00569       bitset_digit_t digit(unsigned int d) const{ assert(!inverted); return inverted ? ~this->vector[d] : this->vector[d]; }
00570   };
00571 
00583 template<unsigned int n, bool inverted>
00584   void
00585   bitset_invertible<n, inverted>::base2_print_on(std::ostream& os) const
00586  {
00587     // Binary representation
00588     for (int d = bitset_base<n>::digits - 1; d >= 0; --d)
00589       for (bitset_digit_t mask = (~static_cast<bitset_digit_t>(0) >> 1) + 1; mask != 0; mask >>= 1)
00590         if (d != bitset_base<n>::digits - 1 || (mask & bitset_base<n>::valid_bits))
00591           if ((this->digit(d) & mask) == inverted)
00592             os << '0';
00593           else
00594             os << '1';
00595   }
00596 
00597 // Default constructor.
00598 template<unsigned int n, bool inverted>
00599   inline
00600   bitset_invertible<n, inverted>::bitset_invertible(void)
00601   {
00602     if (bitset_base<n>::has_excess_bits)
00603       this->vector[bitset_base<n>::digits - 1] = 0;                     // Reset the excess bits!
00604   }
00605 
00606 // Copy constructor.
00607 template<unsigned int n, bool inverted>
00608   template<typename Expression>
00609     inline
00610     bitset_invertible<n, inverted>::bitset_invertible(Expression const& expr)
00611     {
00612       this->assign(expr, Operator::bitsetAssign());
00613     }
00614 
00615 //
00616 // Assignment function.
00617 // This function handles:
00618 //
00619 // a = b;
00620 // a = ~b;
00621 // a &= b;
00622 // a &= ~b;
00623 // a |= b;
00624 // a |= ~b;
00625 // a ^= b;
00626 // a ^= ~b;
00627 //
00628 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
00629 //
00630 template<unsigned int n, bool inverted>
00631   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted_argument>
00632     inline void
00633     bitset_invertible<n, inverted>::assign(bitset_invertible<x, inverted_argument> const& bits, ASSIGNMENT_OPERATOR)
00634     {
00635       // Handle excess digits.
00636       if (bitset_base<n>::digits > bitset_base<x>::digits)
00637       {
00638         if (!inverted_argument)
00639         {
00640           // Fill excess digits with 0's when needed.
00641           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
00642           {
00643 #ifdef __i386__
00644             int __d0, __d1;
00645             __asm__ __volatile__ (
00646                 "std; rep; stosl"
00647                 : "=m" (this->vector[bitset_base<n>::digits - 1]), "=&c" (__d0), "=&D" (__d1)
00648                 : "a" (0), "1" (bitset_base<n>::digits - bitset_base<x>::digits), "2" (&this->vector[bitset_base<n>::digits - 1])
00649                 : "memory"
00650             );
00651 #else
00652             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00653             do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
00654 #endif
00655           }
00656         }
00657         else
00658         {
00659           // Fill excess digits with 1's when needed.
00660           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
00661           {
00662 #ifdef __i386__
00663             int __d0, __d1;
00664             __asm__ __volatile__ (
00665                 "movl %6,4(%%edi); std; rep; stosl"
00666                 : "=m" (this->vector[bitset_base<n>::digits - 2]), "=&c" (__d0), "=&D" (__d1)
00667                 : "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)
00668                 : "memory"
00669             );
00670 #else
00671             this->vector[bitset_base<n>::digits - 1] = bitset_base<n>::valid_bits;
00672             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00673             while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
00674 #endif
00675           }
00676           // Or invert them.
00677           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
00678           {
00679 #ifdef __i386__
00680             int __d0, __d1;
00681             __asm__ __volatile__ (
00682                 "xorl %5,(%2)\n\t"
00683                 "jecxz 2f\n\t"
00684                 "subl %6,%2\n"
00685         "1:\n\t"
00686                 "xorl $-1,(%2,%%ecx,4)\n\t"
00687                 "decl %%ecx\n\t"
00688                 "jnz 1b\n"
00689         "2:"
00690                 : "=m" (this->vector[bitset_base<n>::digits - 1]), "=&c" (__d0), "=&r" (__d1)
00691                 : "1" (bitset_base<n>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<n>::digits - 1]),
00692                   "i" (bitset_base<n>::valid_bits), "i" ((bitset_base<n>::digits - bitset_base<x>::digits) * 4)
00693                 : "memory", "cc"
00694             );
00695 #else
00696             this->vector[bitset_base<n>::digits - 1] ^= bitset_base<n>::valid_bits;
00697             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00698             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
00699 #endif
00700           }
00701         }
00702       }
00703 
00704       // Handle other digits.
00705 #ifdef __i386__
00706       LIBECC_INLINE_ASMLOOP(ASSIGNMENT_OPERATOR::id,
00707           this->vector, bits.digits_ptr(),
00708           ((bitset_base<n>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<n>::digits),
00709           inverted_argument);
00710 #else
00711       unsigned int d;
00712       if (bitset_base<n>::digits > bitset_base<x>::digits)
00713         d = bitset_base<x>::digits - 1;
00714       else
00715         d = bitset_base<n>::digits - 1;
00716       ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~*(bits.digits_ptr() + d) : bits.digit(d));
00717       while(d) { --d; ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~*(bits.digits_ptr() + d) : bits.digit(d)); }
00718 #endif
00719 
00720       // Reset excess bits if needed.
00721       if (((!inverted_argument && x > n) ||
00722             (inverted_argument && bitset_base<n>::digits <= bitset_base<x>::digits)) &&
00723           bitset_base<n>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
00724         this->vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;
00725     }
00726 
00727 //
00728 // Assignment function for expressions.
00729 // This function handles:
00730 //
00731 // a = b & c;
00732 // a = b & ~c;
00733 // a = ~b & c;
00734 // a = ~b & ~b;
00735 // a = b | c;
00736 // a = b | ~c;
00737 // a = ~b | c;
00738 // a = ~b | ~b;
00739 // a = b ^ c;
00740 // a = b ^ ~c;
00741 // a = ~b ^ c;
00742 // a = ~b ^ ~b;
00743 // a &= b & c;
00744 // a &= b & ~c;
00745 // a &= ~b & c;
00746 // a &= ~b & ~b;
00747 // a &= b | c;
00748 // a &= b | ~c;
00749 // a &= ~b | c;
00750 // a &= ~b | ~b;
00751 // a &= b ^ c;
00752 // a &= b ^ ~c;
00753 // a &= ~b ^ c;
00754 // a &= ~b ^ ~b;
00755 // a |= b & c;
00756 // a |= b & ~c;
00757 // a |= ~b & c;
00758 // a |= ~b & ~b;
00759 // a |= b | c;
00760 // a |= b | ~c;
00761 // a |= ~b | c;
00762 // a |= ~b | ~b;
00763 // a |= b ^ c;
00764 // a |= b ^ ~c;
00765 // a |= ~b ^ c;
00766 // a |= ~b ^ ~b;
00767 // a ^= b & c;
00768 // a ^= b & ~c;
00769 // a ^= ~b & c;
00770 // a ^= ~b & ~b;
00771 // a ^= b | c;
00772 // a ^= b | ~c;
00773 // a ^= ~b | c;
00774 // a ^= ~b | ~b;
00775 // a ^= b ^ c;
00776 // a ^= b ^ ~c;
00777 // a ^= ~b ^ c;
00778 // a ^= ~b ^ ~b;
00779 //
00780 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
00781 // OPERATOR is one of bitsetAND, bitsetOR or bitsetXOR.
00782 //
00783 template<unsigned int n, bool inverted>
00784   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted1, bool inverted2, typename OPERATOR>
00785     inline void
00786     bitset_invertible<n, inverted>::assign(Operator::bitsetExpression<x, inverted1, inverted2, OPERATOR> const& expr, ASSIGNMENT_OPERATOR)
00787     {
00788       static bool const argument_has_leading_ones = OPERATOR::template execbool<inverted1, inverted2>::value;
00789 
00790       // Handle excess digits.
00791       if (bitset_base<n>::digits > bitset_base<x>::digits)
00792       {
00793         if (!argument_has_leading_ones)
00794         {
00795           // Fill excess digits with 0's when needed.
00796           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
00797           {
00798 #ifdef __i386__
00799             int __d0, __d1;
00800             __asm__ __volatile__ (
00801                 "std; rep; stosl"
00802                 : "=m" (this->vector[bitset_base<n>::digits - 1]), "=&c" (__d0), "=&D" (__d1)
00803                 : "a" (0), "1" (bitset_base<n>::digits - bitset_base<x>::digits), "2" (&this->vector[bitset_base<n>::digits - 1])
00804                 : "memory"
00805             );
00806 #else
00807             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00808             do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
00809 #endif
00810           }
00811         }
00812         else
00813         {
00814           // Fill excess digits with 1's when needed.
00815           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
00816           {
00817 #ifdef __i386__
00818             int __d0, __d1;
00819             __asm__ __volatile__ (
00820                 "movl %6,4(%%edi); std; rep; stosl"
00821                 : "=m" (this->vector[bitset_base<n>::digits - 2]), "=&c" (__d0), "=&D" (__d1)
00822                 : "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)
00823                 : "memory"
00824             );
00825 #else
00826             this->vector[bitset_base<n>::digits - 1] = bitset_base<n>::valid_bits;
00827             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00828             while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
00829 #endif
00830           }
00831           // Or invert them.
00832           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
00833           {
00834 #ifdef __i386__
00835             int __d0, __d1;
00836             __asm__ __volatile__ (
00837                 "xorl %5,(%2)\n\t"
00838                 "jecxz 2f\n\t"
00839                 "subl %6,%2\n"
00840         "1:\n\t"
00841                 "xorl $-1,(%2,%%ecx,4)\n\t"
00842                 "decl %%ecx\n\t"
00843                 "jnz 1b\n"
00844         "2:"
00845                 : "=m" (this->vector[bitset_base<n>::digits - 1]), "=&c" (__d0), "=&r" (__d1)
00846                 : "1" (bitset_base<n>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<n>::digits - 1]),
00847                   "i" (bitset_base<n>::valid_bits), "i" ((bitset_base<n>::digits - bitset_base<x>::digits) * 4)
00848                 : "memory", "cc"
00849             );
00850 #else
00851             this->vector[bitset_base<n>::digits - 1] ^= bitset_base<n>::valid_bits;
00852             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00853             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
00854 #endif
00855           }
00856         }
00857       }
00858 
00859       // Handle other digits.
00860 #ifdef __i386__
00861       LIBECC_INLINE_ASMLOOP2(ASSIGNMENT_OPERATOR::id, OPERATOR, inverted1, inverted2,
00862           this->vector, expr.first.digits_ptr(), expr.second.digits_ptr(),
00863           ((bitset_base<n>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<n>::digits));
00864 #else
00865       unsigned int d;
00866       if (bitset_base<n>::digits < bitset_base<x>::digits)
00867         d = bitset_base<n>::digits - 1;
00868       else
00869         d = bitset_base<x>::digits - 1;
00870       for(;;)
00871       {
00872         ASSIGNMENT_OPERATOR::exec(this->vector[d],
00873             OPERATOR::exec(inverted1 ? ~*(expr.first.digits_ptr() + d) : expr.first.digit(d),
00874                            inverted2 ? ~*(expr.second.digits_ptr() + d) : expr.second.digit(d)));
00875         if (!d)
00876           break;
00877         --d;
00878       }
00879 #endif
00880 
00881       // Reset excess bits if needed.
00882       if (((!argument_has_leading_ones && x > n) ||
00883             (argument_has_leading_ones && bitset_base<n>::digits <= bitset_base<x>::digits)) &&
00884           bitset_base<n>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
00885         this->vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;
00886     }
00887 
00914 template<unsigned int n, bool inverted>
00915   inline bitset_invertible<n, !inverted> const&
00916   operator~(bitset_invertible<n, inverted> const& bits)
00917   {
00918     return *reinterpret_cast<bitset_invertible<n, !inverted> const*>(&bits);
00919   }
00920 
00921 //------------------------------------------------------------------------------------------------------------------
00922 // Iterators
00923 //
00924 
00934 classbitset_index {
00935 #if defined(__i386__) || defined(LIBECC_DOXYGEN)
00936   protected:
00937     int M_index;                        
00938 
00939   public:
00940     // Accessors.
00941     int get_index(void) const;
00942 
00943 #else
00944   protected:
00945     int M_digit;                        
00946     bitset_digit_t M_mask;              
00947 
00948   public:
00949     // Accessors.
00950     int get_digit(void) const;
00951     bitset_digit_t get_mask(void) const;
00952 #endif
00953 
00954   public:
00955     // Equality Comparable.
00956     friend bool operator==(bitset_index const& i1, bitset_index const& i2);
00957     friend bool operator!=(bitset_index const& i1, bitset_index const& i2);
00958 
00959   protected:
00960     // Bidirectional.
00961     void left(void);
00962     void right(void);
00963 
00964     // Random access.
00965     void left(int n);
00966     void right(int n);
00967     friend int subtract(bitset_index const& i1, bitset_index const& i2);
00968 
00969   protected:
00970     // Constructors.
00971     bitset_index(void);
00972     bitset_index(bitset_index const& index);
00973     bitset_index(int bit);
00974 
00975   public:
00976     friend std::ostream& operator<<(std::ostream& os, bitset_index const& i);
00977 };
00978 
00979 #if defined(__i386__) || defined(LIBECC_DOXYGEN)
00980 
00984 inline int
00985 bitset_index::get_index(void) const
00986 {
00987   return M_index;
00988 }
00989 
00990 #else // !defined(__i386__)
00991 
00992 // Accessor for the current digit index.
00993 inline int
00994 bitset_index::get_digit(void) const
00995 {
00996   return M_digit;
00997 }
00998 
00999 // Accessor for the current digit mask.
01000 inline bitset_digit_t
01001 bitset_index::get_mask(void) const
01002 { 
01003   return M_mask;
01004 }
01005 
01006 #include <strings.h>   // Needed for ffs.
01007 inline int
01008 bitset_index::get_index(void) const
01009 {
01010   return M_digit * bitset_digit_bits + ::ffs(M_mask) - 1;
01011 }
01012 
01013 #endif // !defined(__i386__)
01014 
01018 inline bool
01019 operator==(bitset_index const& i1, bitset_index const& i2)
01020 {
01021 #ifdef __i386__
01022   return (i1.M_index == i2.M_index);
01023 #else
01024   return (i1.M_digit == i2.M_digit && i1.M_mask == i2.M_mask);
01025 #endif
01026 }
01027 
01031 inline bool
01032 operator!=(bitset_index const& i1, bitset_index const& i2)
01033 {
01034 #ifdef __i386__
01035   return (i1.M_index != i2.M_index);
01036 #else
01037   return (i1.M_digit != i2.M_digit || i1.M_mask != i2.M_mask);
01038 #endif
01039 }
01040 
01044 inline
01045 bitset_index::bitset_index(void)
01046 {
01047 }
01048 
01052 inline
01053 bitset_index::bitset_index(bitset_index const& index) :
01054 #ifdef __i386__
01055     M_index(index.M_index)
01056 #else
01057     M_digit(index.M_digit), M_mask(index.M_mask)
01058 #endif
01059 { 
01060 }
01061 
01068 inline
01069 bitset_index::bitset_index(int bit) :
01070 #ifdef __i386__
01071     M_index(bit)
01072 #else
01073     // If bit == -1 then M_digit should become -1 and M_mask 0x80000000.
01074     M_digit(bit >> bitset_digit_bits_log2),
01075     M_mask(static_cast<bitset_digit_t>(1) << ((unsigned int)bit & (bitset_digit_bits - 1)))
01076 #endif
01077 {
01078 }
01079 
01083 inline void
01084 bitset_index::left(void)
01085 {
01086 #ifdef __i386__
01087   ++M_index;
01088 #else
01089   if ((M_mask <<= 1) == 0)
01090   {
01091     ++M_digit;
01092     M_mask = 1;
01093   }
01094 #endif
01095 }
01096 
01100 inline void
01101 bitset_index::right(void)
01102 {
01103 #ifdef __i386__
01104   --M_index;
01105 #else
01106   if ((M_mask >>= 1) == 0)
01107   {
01108     --M_digit;
01109     M_mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
01110   }
01111 #endif
01112 }
01113 
01117 inline void
01118 bitset_index::left(int n)
01119 {
01120 #ifdef __i386__
01121   M_index += n;
01122 #else
01123   int const digit_shift = n >> bitset_digit_bits_log2;
01124   int const mask_shift = n & (bitset_digit_bits - 1);
01125   M_digit += digit_shift;
01126   if (mask_shift)
01127   {
01128     bitset_digit_t new_mask = M_mask << mask_shift;
01129     if (new_mask == 0)
01130     {
01131       ++M_digit;
01132       new_mask = M_mask >> (bitset_digit_bits - mask_shift);
01133     }
01134     M_mask = new_mask;
01135   }
01136 #endif
01137 }
01138 
01142 inline void
01143 bitset_index::right(int n)
01144 {
01145 #ifdef __i386__
01146   M_index -= n;
01147 #else
01148   int const digit_shift = n >> bitset_digit_bits_log2;
01149   int const mask_shift = n & (bitset_digit_bits - 1);
01150   M_digit -= digit_shift;
01151   if (mask_shift)
01152   {
01153     bitset_digit_t new_mask = M_mask >> mask_shift;
01154     if (new_mask == 0)
01155     {
01156       --M_digit;
01157       new_mask = M_mask << (bitset_digit_bits - mask_shift);
01158     }
01159     M_mask = new_mask;
01160   }
01161 #endif
01162 }
01163 
01164 enum {
01165   forwards_iterating,
01166   backwards_iterating
01167 };
01168 
01169 // Forward declarations.
01170 template<int DIRECTION> classbitset_index_iterator;
01171 template<int DIRECTION> bool operator<(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
01172 template<int DIRECTION> bool operator>(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
01173 template<int DIRECTION> bool operator<=(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
01174 template<int DIRECTION> bool operator>=(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
01175 
01184 template<int DIRECTION>
01185   classbitset_index_iterator : public bitset_index {
01186     public:
01187       // LessThan Comparable.
01188       friend bool operator< <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01189       friend bool operator> <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01190       friend bool operator<= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01191       friend bool operator>= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01192 
01193     public:
01194       // Bidirectional.
01195       void increment(void);
01196       void decrement(void);
01197 
01198       // Random access.
01199       void increment(int n);
01200       void decrement(int n);
01201 
01202       friend int operator-(bitset_index const& i1, bitset_index const& i2);
01203 
01204     public:
01205       // Constructors.
01206       bitset_index_iterator(void);
01207       bitset_index_iterator(bitset_index_iterator const& index);
01208       bitset_index_iterator(int bit);
01209   };
01210 
01214 template<int DIRECTION>
01215   inline
01216   bitset_index_iterator<DIRECTION>::bitset_index_iterator(void)
01217   {
01218   }
01219 
01223 template<int DIRECTION>
01224   inline
01225   bitset_index_iterator<DIRECTION>::bitset_index_iterator(bitset_index_iterator<DIRECTION> const& index) :
01226       bitset_index(index)
01227   { 
01228   }
01229 
01236 template<int DIRECTION>
01237   inline
01238   bitset_index_iterator<DIRECTION>::bitset_index_iterator(int bit) : bitset_index(bit)
01239   {
01240   }
01241 
01245 template<int DIRECTION>
01246   inline bool
01247   operator<(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01248   {
01249 #ifdef __i386__
01250     if (DIRECTION == forwards_iterating)
01251       return (i1.M_index < i2.M_index);
01252     else
01253       return (i1.M_index > i2.M_index);
01254 #else
01255     if (DIRECTION == forwards_iterating)
01256       return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
01257     else
01258       return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
01259 #endif
01260   }
01261 
01265 template<int DIRECTION>
01266   inline bool
01267   operator>(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01268   {
01269 #ifdef __i386__
01270     if (DIRECTION == forwards_iterating)
01271       return (i1.M_index > i2.M_index);
01272     else
01273       return (i1.M_index < i2.M_index);
01274 #else
01275     if (DIRECTION == forwards_iterating)
01276       return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
01277     else
01278       return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
01279 #endif
01280   }
01281 
01285 template<int DIRECTION>
01286   inline bool
01287   operator<=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01288   {
01289 #ifdef __i386__
01290     if (DIRECTION == forwards_iterating)
01291       return (i1.M_index <= i2.M_index);
01292     else
01293       return (i1.M_index >= i2.M_index);
01294 #else
01295     if (DIRECTION == forwards_iterating)
01296       return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
01297     else
01298       return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
01299 #endif
01300   }
01301 
01305 template<int DIRECTION>
01306   inline bool
01307   operator>=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01308   {
01309 #ifdef __i386__
01310     if (DIRECTION == forwards_iterating)
01311       return (i1.M_index >= i2.M_index);
01312     else
01313       return (i1.M_index <= i2.M_index);
01314 #else
01315     if (DIRECTION == forwards_iterating)
01316       return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
01317     else
01318       return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
01319 #endif
01320   }
01321 
01325 template<int DIRECTION>
01326   inline void
01327   bitset_index_iterator<DIRECTION>::increment(void)
01328   {
01329     if (DIRECTION == forwards_iterating)
01330       left();
01331     else
01332       right();
01333   }
01334 
01338 template<int DIRECTION>
01339   inline void
01340   bitset_index_iterator<DIRECTION>::decrement(void)
01341   {
01342     if (DIRECTION == forwards_iterating)
01343       right();
01344     else
01345       left();
01346   }
01347 
01351 template<int DIRECTION>
01352   inline void
01353   bitset_index_iterator<DIRECTION>::increment(int n)
01354   {
01355     if (DIRECTION == forwards_iterating)
01356       left(n);
01357     else
01358       right(n);
01359   }
01360 
01364 template<int DIRECTION>
01365   inline void
01366   bitset_index_iterator<DIRECTION>::decrement(int n)
01367   {
01368     if (DIRECTION == forwards_iterating)
01369       right(n);
01370     else
01371       left(n);
01372   }
01373 
01374 template<int DIRECTION>
01375   inline int
01376   operator-(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01377   {
01378     return (DIRECTION == forwards_iterating) ? subtract(i1, i2) : subtract(i2, i1);
01379   }
01380 
01381 // Forward declarations.
01382 template<unsigned int n, int DIRECTION> classbitset_iterator;
01383 template<unsigned int n, int DIRECTION> bitset_iterator<n, DIRECTION> operator+(bitset_iterator<n, DIRECTION> const&, int);
01384 template<unsigned int n, int DIRECTION> bitset_iterator<n, DIRECTION> operator+(int, bitset_iterator<n, DIRECTION> const&);
01385 template<unsigned int n, int DIRECTION> bitset_iterator<n, DIRECTION> operator-(bitset_iterator<n, DIRECTION> const&, int);
01386 template<unsigned int n, int DIRECTION> bitset_iterator<n, DIRECTION> operator-(int, bitset_iterator<n, DIRECTION> const&);
01387 
01397 template<unsigned int n, int DIRECTION>
01398   classbitset_iterator : public bitset_index_iterator<DIRECTION>,
01399                           public std::iterator<std::random_access_iterator_tag, bitset_digit_t,
01400                                                int, bitset_digit_t*, bitset_digit_t&> {
01401     protected:
01402       bitset_invertible<n, false> const* M_bitset_ptr;
01403     public:
01404       // Default Constructible
01405       bitset_iterator(void);
01406 
01407       // Assignable
01408       bitset_iterator(bitset_iterator const& iter);
01409       bitset_iterator& operator=(bitset_iterator const& iter);
01410       bitset_iterator& operator=(bitset_index_iterator<DIRECTION> const& index);
01411 
01412       // Dereferencable
01413       bitset_digit_t operator*() const;
01414 
01415       // Bi-directional iterator
01416       //
01417       bitset_iterator& operator++();
01418       bitset_iterator operator++(int);
01419       bitset_iterator& operator--();
01420       bitset_iterator operator--(int);
01421 
01422       // Random Access Iterator
01423       //
01424       bitset_iterator& operator+=(int n);
01425       friend bitset_iterator operator+ <>(bitset_iterator const& i, int n);
01426       friend bitset_iterator operator+ <>(int n, bitset_iterator const& i);
01427       bitset_iterator& operator-=(int n);
01428       friend bitset_iterator operator- <>(bitset_iterator const& i, int n);
01429       friend bitset_iterator operator- <>(int n, bitset_iterator const& i);
01430       bitset_digit_t operator[](int n) const;
01431 
01432       // Special
01433       //
01434       bitset_iterator(bitset_invertible<n, false> const* bitset_ptr, int bit);
01435       void find1(void);
01436 
01437 #ifndef __i386__
01438     private:
01439       void find1_forward(void);
01440       void find1_backward(void);
01441 #endif
01442   };
01443 
01444 #ifndef __i386__
01445 template<unsigned int n, int DIRECTION>
01446   void
01447   bitset_iterator<n, DIRECTION>::find1_forward(void)
01448   {
01449     if (M_digit < (int)bitset_base<n>::digits - 1 || (M_mask & bitset_base<n>::valid_bits))
01450     {
01451       register bitset_digit_t mask = M_mask;
01452       while(!(M_bitset_ptr->digit(M_digit) & mask)) 
01453       {
01454         if ((mask <<= 1))
01455           continue;
01456         mask = 1;
01457         while(++M_digit < (int)bitset_base<n>::digits)
01458           if (M_bitset_ptr->digit(M_digit))
01459             break;
01460         if (M_digit == (int)bitset_base<n>::digits)
01461         {
01462           M_digit = (n >> bitset_digit_bits_log2);
01463           mask = static_cast<bitset_digit_t>(1) << (n & (bitset_digit_bits - 1));
01464           break;
01465         }
01466       }
01467       M_mask = mask;
01468     }
01469   }
01470 
01471 template<unsigned int n, int DIRECTION>
01472   void
01473   bitset_iterator<n, DIRECTION>::find1_backward(void)
01474   {
01475     LibEccDout(dc::bitsetfind1, "Entering find1_backward with: " << 
01476         libcwd::cwprint_using(*M_bitset_ptr, &bitset_invertible<n, false>::base2_print_on));
01477     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01478     if (M_digit >= 0)
01479     {
01480       register bitset_digit_t mask = M_mask;
01481       if (!(M_bitset_ptr->digit(M_digit) & (mask | (mask - 1))))
01482       {
01483         mask = 1 << (bitset_digit_bits - 1);
01484         do
01485         {
01486           if (--M_digit < 0)
01487           {
01488             M_mask = mask;
01489             return;
01490           }
01491         }
01492         while (!M_bitset_ptr->digit(M_digit));
01493       }
01494       while(!(M_bitset_ptr->digit(M_digit) & mask)) 
01495         mask >>= 1;
01496       M_mask = mask;
01497     }
01498     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01499   }
01500 #endif
01501 
01505 template<unsigned int n, int DIRECTION>
01506   inline void
01507   bitset_iterator<n, DIRECTION>::find1(void)
01508   {
01509     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01510     LibEccDout(dc::bitsetfind1, "Entering find1 with: " << 
01511         libcwd::cwprint_using(*M_bitset_ptr, &bitset_invertible<n, false>::base2_print_on));
01512 #ifdef __i386__
01513     int bit_index, digit, ptr;
01514     if (DIRECTION == backwards_iterating)
01515     {
01516       __asm__ __volatile__ (
01517           // %eax: M_index (input) and work variable.
01518           // %ecx: bit_index (work variable).
01519           // %edi: &M_bitset_ptr->digit(M_index/32 - 1) (input) and ptr (work variable).
01520           // %2  : digit (work variable).
01521 
01522           // Make a copy of M_index into %ecx, last time we used M_index.
01523           "movl %%eax,%%ecx\n\t"
01524           // Set %eax to its correct value by deviding it by 32.
01525           "sarl $5,%%eax\n\t"
01526           // Set bit_index to its correct value by taking the modulo 32 of it.
01527           "andl $31,%%ecx\n\t"
01528           // If M_index is -1, do nothing.
01529           "js 1f\n\t"
01530           // Copy the most significant digit, the digit with the
01531           // bit at which we will start the search, into %2.
01532           // digit = M_bitset_ptr->digit(%eax)
01533           "movl 4(%%edi),%2\n\t"
01534           // Shift this digit left until the first bit comes at position 31.
01535           // bit_index = 31 - bit_index
01536           "xorl $31,%%ecx\n\t"
01537           // digit <<= bit_index
01538           "shll %%cl,%2\n\t"
01539           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01540           // This is not needed for the athlon for that reason, but we also need this orl
01541           // for the case that %cl equals zero in which case the ZF is cleared!
01542           "orl %2,%2\n\t"                       
01543           // If there is no bit set in the current digit, goto digit_search.
01544           "jz 5f\n\t"
01545           // Search for the (next) most significant bit set.
01546           // This is slow on i[345]86: 11 + 2*n cycles; only generates 2 uops on a pentium though.
01547           "bsrl %2,%2\n\t"
01548           // Correct M_index to point to this bit.
01549           // %eax <<= 5
01550           "sall $5,%%eax\n\t"
01551           // %2 -= bit_index
01552           "subl %%ecx,%2\n\t"
01553           // M_index = %eax + %2
01554           "addl %2,%%eax\n\t"
01555           // Done.
01556           // goto exit
01557           "jmp 1f\n\t"
01558           ".align 16\n"
01559        "7:\n\t"                         // Main loop.
01560           "movl (%%edi),%2\n\t"
01561           "subl $4,%%edi\n\t"
01562           "testl %2,%2\n\t"
01563           "jnz 6f\n\t"
01564        "5:\n\t"                         // digit_search:
01565           "decl %%eax\n\t"
01566           // Repeat main loop.
01567           "jns 7b\n"    
01568        "4:\n\t"                         // reached_end:
01569           // No set bit found at all.  Set M_index to -1.
01570           "movl $-1,%%eax\n\t"
01571           // Done.
01572           // goto exit
01573           "jmp 1f\n"
01574           // Search for the most significant bit set in this digit.
01575        "6:\n\t"
01576           "bsrl %2,%2\n\t"
01577           // Correct M_index to point to this bit.
01578           "sall $5,%%eax\n\t"
01579           "addl %2,%%eax\n"
01580        "1:"                             // exit:
01581 
01582           : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01583           : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() - 1 + (this->M_index >> 5))
01584           : "cc"
01585       );
01586     }
01587     else
01588     {
01589       __asm__ __volatile__ (
01590           // %eax: M_index (input) and work variable.
01591           // %ecx: bit_index (work variable).
01592           // %edi: &M_bitset_ptr->digit(M_index/32 + 1) (input) and ptr (work variable).
01593           // %2  : digit (work variable).
01594 
01595           // if (M_index >= n) then goto exit
01596           "cmpl %6,%%eax\n\t"
01597           "jge 1f\n\t"
01598           // Make a copy of M_index into %ecx, last time we used M_index.
01599           "movl %%eax,%%ecx\n\t"
01600           // Set %eax to its correct value by deviding it by 32.
01601           "sarl $5,%%eax\n\t"
01602           // Set bit_index to its correct value by taking the modulo 32 of it.
01603           "andl $31,%%ecx\n\t"
01604           // Copy the least significant digit, the digit with the
01605           // bit at which we will start the search, into %2.
01606           // digit = M_bitset_ptr->digit(%eax)
01607           "movl -4(%%edi),%2\n\t"
01608           // Shift this digit right until the first bit comes at position 0.
01609           // digit >>= bit_index
01610           "shrl %%cl,%2\n\t"
01611           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01612           // This is not needed for the athlon for that reason, but we also need this orl
01613           // for the case that %cl equals zero in which case the ZF is cleared!
01614           "orl %2,%2\n\t"                       
01615           // If there is no bit set in the current digit, goto digit_search.
01616           "jz 5f\n\t"
01617           // Search for the (next) most significant bit set.
01618           // This is slow on i[345]86: 11 + 2*n cycles; only generates 2 uops on a pentium though.
01619           "bsfl %2,%2\n\t"
01620           // Correct M_index to point to this bit.
01621           // %eax <<= 5
01622           "sall $5,%%eax\n\t"
01623           // %2 -= bit_index
01624           "addl %%ecx,%2\n\t"
01625           // M_index = %eax + %2
01626           "addl %2,%%eax\n\t"
01627           // Done.
01628           // goto exit
01629           "jmp 1f\n\t"
01630           ".align 16\n"
01631        "7:\n\t"                         // Main loop.
01632           "movl (%%edi),%2\n\t"
01633           "addl $4,%%edi\n\t"
01634           "testl %2,%2\n\t"
01635           "jnz 6f\n\t"
01636        "5:\n\t"                         // digit_search:
01637           "incl %%eax\n\t"
01638           "cmpl %7, %%eax\n\t"
01639           // Repeat main loop.
01640           "jnz 7b\n"            
01641        "4:\n\t"                         // reached_end:
01642           // No set bit found at all.  Set M_index to n.
01643           "movl %6,%%eax\n\t"
01644           // Done.
01645           // goto exit
01646           "jmp 1f\n"
01647           // Search for the least significant bit set in this digit.
01648        "6:\n\t"
01649           "bsfl %2,%2\n\t"
01650           // Correct M_index to point to this bit.
01651           "sall $5,%%eax\n\t"
01652           "addl %2,%%eax\n"
01653        "1:"                             // exit:
01654 
01655           : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01656           : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() + 1 + (this->M_index >> 5)),
01657             "i" (n), "i" (bitset_base<n>::digits)
01658           : "cc"
01659       );
01660     }
01661 #else
01662     if (DIRECTION == forwards_iterating)
01663       find1_forward();
01664     else
01665       find1_backward();
01666 #endif
01667     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01668     return;
01669   }
01670 
01671 
01675 template<unsigned int n, int DIRECTION>
01676   inline
01677   bitset_iterator<n, DIRECTION>::bitset_iterator(void)
01678   {
01679   }
01680 
01684 template<unsigned int n, int DIRECTION>
01685   inline
01686   bitset_iterator<n, DIRECTION>::bitset_iterator(bitset_invertible<n, false> const* bitset_ptr, int bit) :
01687       bitset_index_iterator<DIRECTION>(bit), M_bitset_ptr(bitset_ptr)
01688   {
01689   }
01690 
01694 template<unsigned int n, int DIRECTION>
01695   inline
01696   bitset_iterator<n, DIRECTION>::bitset_iterator(bitset_iterator const& iter) :
01697       bitset_index_iterator<DIRECTION>(iter), M_bitset_ptr(iter.M_bitset_ptr)
01698   {
01699   }
01700 
01704 template<unsigned int n, int DIRECTION>
01705   inline bitset_iterator<n, DIRECTION>&
01706   bitset_iterator<n, DIRECTION>::operator=(bitset_iterator<n, DIRECTION> const& iter)
01707   {
01708 #ifdef __i386__
01709     this->M_index = iter.M_index;
01710 #else
01711     this->M_digit = iter.M_digit;
01712     this->M_mask = iter.M_mask;
01713 #endif
01714     M_bitset_ptr = iter.M_bitset_ptr;
01715     return *this;
01716   }
01717 
01718 template<unsigned int n, int DIRECTION>
01719   inline bitset_iterator<n, DIRECTION>&
01720   bitset_iterator<n, DIRECTION>::operator=(bitset_index_iterator<DIRECTION> const& index)
01721   {
01722 #ifdef __i386__
01723     this->M_index = index.get_index();
01724 #else
01725     this->M_digit = index.get_digit();
01726     this->M_mask = index.get_mask();
01727 #endif
01728     return *this;
01729   }
01730 
01734 template<unsigned int n, int DIRECTION>
01735   inline bitset_iterator<n, DIRECTION>&
01736   bitset_iterator<n, DIRECTION>::operator++()
01737   {
01738     this->increment();
01739     return *this;
01740   }
01741 
01745 template<unsigned int n, int DIRECTION>
01746   inline bitset_iterator<n, DIRECTION>
01747   bitset_iterator<n, DIRECTION>::operator++(int)
01748   {
01749     bitset_iterator prev(*this);
01750     this->increment();
01751     return prev;
01752   }
01753 
01757 template<unsigned int n, int DIRECTION>
01758   inline bitset_iterator<n, DIRECTION>&
01759   bitset_iterator<n, DIRECTION>::operator--()
01760   {
01761     this->decrement();
01762     return *this;
01763   }
01764 
01768 template<unsigned int n, int DIRECTION>
01769   inline bitset_iterator<n, DIRECTION>
01770   bitset_iterator<n, DIRECTION>::operator--(int)
01771   {
01772     bitset_iterator prev(*this);
01773     this->decrement();
01774     return prev;
01775   }
01776 
01783 template<unsigned int n, int DIRECTION>
01784   inline bitset_digit_t
01785   bitset_iterator<n, DIRECTION>::operator*() const
01786  {
01787 #ifdef __i386__
01788     register unsigned int M_digit = this->M_index;
01789     register bitset_digit_t M_mask = 1;
01790     register unsigned short shift = this->M_index & (ECC_BITS - 1);
01791     M_digit >>= bitset_digit_bits_log2;
01792     M_mask <<= shift;
01793 #endif
01794     return (M_bitset_ptr->digit(M_digit) & M_mask);
01795   }
01796 
01800 template<unsigned int n, int DIRECTION>
01801   inline bitset_iterator<n, DIRECTION>&
01802   bitset_iterator<n, DIRECTION>::operator+=(int d)
01803   {
01804     this->increment(d);
01805     return *this;
01806   }
01807 
01811 template<unsigned int n, int DIRECTION>
01812   inline bitset_iterator<n, DIRECTION>&
01813   bitset_iterator<n, DIRECTION>::operator-=(int d)
01814   {
01815     this->decrement(d);
01816     return *this;
01817   }
01818 
01822 template<unsigned int n, int DIRECTION>
01823   inline bitset_iterator<n, DIRECTION>
01824   operator+(bitset_iterator<n, DIRECTION> const& i, int d)
01825   {
01826     bitset_iterator<n, DIRECTION> result(i);
01827     return result += d;
01828   }
01829 
01833 template<unsigned int n, int DIRECTION>
01834   inline bitset_iterator<n, DIRECTION>
01835   operator+(int d, bitset_iterator<n, DIRECTION> const& i)
01836   {
01837     bitset_iterator<n, DIRECTION> result(i);
01838     return result += d;
01839   }
01840 
01844 template<unsigned int n, int DIRECTION>
01845   inline bitset_iterator<n, DIRECTION>
01846   operator-(bitset_iterator<n, DIRECTION> const& i, int d)
01847   {
01848     bitset_iterator<n, DIRECTION> result(i);
01849     return result -= d;
01850   }
01851 
01855 template<unsigned int n, int DIRECTION>
01856   inline bitset_iterator<n, DIRECTION>
01857   operator-(int d, bitset_iterator<n, DIRECTION> const& i)
01858   {
01859     bitset_iterator<n, DIRECTION> result(i);
01860     return result -= d;
01861   }
01862 
01866 template<unsigned int n, int DIRECTION>
01867   inline bitset_digit_t
01868   bitset_iterator<n, DIRECTION>::operator[](int d) const
01869  {
01870     return *(*this + d);
01871   }
01872 
01873 //--------------------------------------------------------------------------------------------------------------------------
01880 template<unsigned int n>
01881   classbitset : public bitset_invertible<n, false> {
01882     public:
01883       // Constructors.
01884       bitset(void);
01885       bitset(std::string const&);
01886       explicit bitset(bitset_digit_t low_bits);
01887       // This definition must be here, inside the template class declaration because
01888       // otherwise the compiler (2.95 - 3.1) barfs.
01894       bitset(bitset_digit_t const (&v)[bitset_base<n>::digits])
01895       {
01896 #if ECC_DEBUG
01897         assert( (v[bitset_base<n>::digits - 1] & ~bitset_base<n>::valid_bits) == 0 );
01898 #endif
01899         std::memcpy(this->vector, v, sizeof(this->vector));
01900       }
01901 
01902       // Copy constructors.
01903       template<unsigned int m, bool inverted>
01904         bitset(bitset_invertible<m, inverted> const&);
01905       template<unsigned int m, bool i1, bool i2, typename OP>
01906         bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr);
01907 
01908       // Assignment operators.
01909       bitset& operator=(bitset const&);
01910       template<typename Expression>
01911         bitset& operator=(Expression const&);
01912 
01913       // Perform AND, OR, XOR operations
01914       template<typename Expression>
01915         bitset& operator&=(Expression const&);
01916       template<typename Expression>
01917         bitset& operator|=(Expression const&);
01918       template<typename Expression>
01919         bitset& operator^=(Expression const&);
01920 
01921     public:
01922       // Shift bitset left or right and perform operation with result.
01923       template<unsigned int shift, class DIRECTION, class OPERATION>
01924         void shift_op(bitset& result) const;
01925 
01926       // Slower functions for shifting an arbitrary distance.
01927       bitset& operator<<=(unsigned int shift);
01928       bitset& operator>>=(unsigned int shift);
01929 
01930       // Rotate left or right
01931       template<unsigned int shift, class DIRECTION>                     // Return a copy rotated `shift' bits in `DIRECTION'.
01932         void rotate(bitset& result) const;
01933 
01934       // Single bit operations
01935       bool test(size_t n) const;                                        // Return true if bit `n' is set.
01936       bool odd(void) const;                                             // Return true if the vector has an odd number of bits set.
01937       void set(size_t n);                                               // Set bit `n'.
01938       void clear(size_t n);                                             // Clear bit `n'.
01939       void flip(size_t n);                                              // Toggle bit `n'.
01940 
01941       // Single bit operations using iterators.
01942       bool test(bitset_index const& index) const;                       // Return true if bit refered to by `index' is set.
01943       void set(bitset_index const& index);                              // Set bit refered to by `index'.
01944       void clear(bitset_index const& index);                            // Clear bit refered to by `index'.
01945       void flip(bitset_index const& index);                             // Toggle bit refered to by `index'.
01946 
01947       // Single bit operations at a constant position
01948       template<unsigned int pos>
01949         bool test(void) const;                                          // Return true if bit `pos' is set.
01950       template<unsigned int pos>
01951         void set(void);                                                 // Set bit `pos'.
01952       template<unsigned int pos>
01953         void clear(void);                                               // Clear bit `pos'.
01954       template<unsigned int pos>
01955         void flip(void);                                                // Toggle bit `pos'.
01956 
01957       // Other functions
01958       bitset& reset(void);
01959       void setall(void);
01960       bool any(void) const;
01961 
01962     public:
01963       // Iterator stuff.
01965       typedef bitset_iterator<n, forwards_iterating> const_iterator;
01967       typedef bitset_iterator<n, backwards_iterating> const_reverse_iterator;
01969       const_iterator begin(void) const{ return const_iterator(this, 0); }
01971       const_iterator end(void) const{ return const_iterator(this, n); }
01973       const_reverse_iterator rbegin(void) const{ return const_reverse_iterator(this, n - 1); }
01975       const_reverse_iterator rend(void) const{ return const_reverse_iterator(this, -1); }
01976 
01977       template<unsigned int m>
01978         void xor_with_zero_padded(bitset<m> const& bitset, int lsb, int msb, int shift);
01979   };
01980 
01997 template<unsigned int n>
01998   template<unsigned int m>
01999 #ifdef __i386__
02000   inline void
02001 #endif
02002   bitset<n>::xor_with_zero_padded(bitset<m> const& bitset, int lsb, int msb, int shift)
02003   {
02004 #ifdef __i386__
02005     libecc_shift_xorassign(this->vector, bitset.digits_ptr(), lsb, msb, shift);
02006 #else
02007     int digit1 = lsb >> bitset_digit_bits_log2;
02008     int digit2 = msb >> bitset_digit_bits_log2;
02009     bitset_digit_t d1 = 0;
02010     if (shift < 0)
02011     {
02012       unsigned int bitshift = (-shift) & (bitset_digit_bits - 1);
02013       unsigned int digitshift = (-shift) >> bitset_digit_bits_log2;
02014       if (bitshift == 0)
02015       {
02016         for (int digit = digit2; digit >= digit1; --digit)
02017         {
02018           bitset_digit_t d2 = bitset.digit(digit);
02019           vector[digit - digitshift] ^= d2;
02020           d1 = d2;
02021         }
02022       }
02023       else
02024       {
02025         for (int digit = digit2; digit >= digit1; --digit)
02026         {
02027           bitset_digit_t d2 = bitset.digit(digit);
02028           vector[digit - digitshift] ^= (d2 >> bitshift) | (d1 << (32 - bitshift));
02029           d1 = d2;
02030         }
02031         vector[digit1 - 1 - digitshift] ^= (d1 << (32 - bitshift));
02032       }
02033     }
02034     else if (shift > 0)
02035     {
02036       unsigned int bitshift = shift & (bitset_digit_bits - 1);
02037       unsigned int digitshift = shift >> bitset_digit_bits_log2;
02038       if (bitshift == 0)
02039       {
02040         for (int digit = digit1; digit <= digit2; ++digit)
02041         {
02042           bitset_digit_t d2 = bitset.digit(digit);
02043           vector[digit + digitshift] ^= d2;
02044           d1 = d2;
02045         }
02046       }
02047       else
02048       {
02049         for (int digit = digit1; digit <= digit2; ++digit)
02050         {
02051           bitset_digit_t d2 = bitset.digit(digit);
02052           vector[digit + digitshift] ^= (d2 << bitshift) | (d1 >> (32 - bitshift));
02053           d1 = d2;
02054         }
02055         vector[digit2 + 1 + digitshift] ^= (d1 >> (32 - bitshift));
02056       }
02057     }
02058     else
02059     {
02060       for (int digit = digit1; digit <= digit2; ++digit)
02061         vector[digit] ^= bitset.digit(digit);
02062     }
02063 #endif
02064   }
02065 
02069 template<unsigned int n>
02070   inline
02071   bitset<n>::bitset(void)
02072   {
02073   }
02074 
02080 template<unsigned int n>
02081   inline
02082   bitset<n>::bitset(bitset_digit_t low_bits)
02083   {
02084 #if ECC_DEBUG
02085     assert( bitset_base<n>::digits > 1 || (low_bits & ~bitset_base<n>::valid_bits) == 0 );
02086 #endif
02087     std::memset(this->vector, 0, sizeof(this->vector));
02088     this->vector[0] = low_bits;
02089   }
02090 
02094 template<unsigned int n>
02095   void
02096   bitset<n>::setall(void)
02097   {
02098     this->vector[bitset_base<n>::digits - 1] = bitset_base<n>::valid_bits;
02099     if (bitset_base<n>::digits > 1)
02100     {
02101       int d = bitset_base<n>::digits - 2;
02102       do { this->vector[d] = ~static_cast<bitset_digit_t>(0); } while(--d >= 0);
02103     }
02104   }
02105 
02130 template<unsigned int n>
02131   template<typename Expression>
02132     inline
02133     bitset<n>& bitset<n>::operator=(Expression const& expr)
02134     {
02135       this->assign(expr, Operator::bitsetAssign());
02136       return *this;
02137     }
02138 
02139 // Special case, need to define this or else we'd get a default assignment operator.
02140 template<unsigned int n>
02141   inline bitset<n>&
02142   bitset<n>::operator=(bitset const& expr)
02143   {
02144     this->assign(expr, Operator::bitsetAssign());
02145     return *this;
02146   }
02147 
02164 template<unsigned int n>
02165   template<unsigned int m, bool inverted>
02166     inline bitset<n>::bitset(bitset_invertible<m, inverted> const& bits) : bitset_invertible<n, false>(bits)
02167     {
02168     }
02169 
02175 template<unsigned int n>
02176   template<unsigned int m, bool i1, bool i2, typename OP>
02177     inline bitset<n>::bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr) : bitset_invertible<n, false>(expr)
02178     {
02179     }
02180 
02192 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02193   bool operator==(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02194   {
02195     unsigned int d;
02196     if (bitset_invertible<n1, inverted1>::digits > bitset_invertible<n2, inverted2>::digits)
02197     {
02198       d = bitset_base<n1>::digits - 1;
02199       do
02200       {
02201         if (bits1.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02202           return false;
02203       }
02204       while (--d != bitset_base<n2>::digits - 1);
02205     }
02206     if (bitset_base<n2>::digits > bitset_base<n1>::digits)
02207     {
02208       d = bitset_base<n2>::digits - 1;
02209       do
02210       {
02211         if (bits2.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02212           return false;
02213       }
02214       while (--d != bitset_base<n1>::digits - 1);
02215     }
02216     if (bitset_base<n1>::digits > 1 && bitset_base<n2>::digits > 1)
02217     {
02218       if (bitset_base<n1>::digits == bitset_base<n2>::digits)
02219         d = bitset_base<n1>::digits - 1;
02220       do
02221       {
02222         if (inverted1 == inverted2)
02223         {
02224           if (bits1.vector[d] != bits2.vector[d])
02225             return false;
02226         }
02227         else
02228         {
02229           if (bits1.vector[d] != ~(bits2.vector[d]))
02230             return false;
02231         }
02232       }
02233       while(--d != 0);
02234     }
02235     if (inverted1 != inverted2)
02236       return (bits1.vector[0] == ~(bits2.vector[0]));
02237     return (bits1.vector[0] == bits2.vector[0]);
02238   }
02239 
02245 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02246   inline bool
02247   operator!=(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02248   {
02249     return !(bits1 == bits2);
02250   }
02251 
02256 template<unsigned int n>
02257   template<typename Expression>
02258     inline bitset<n>&
02259     bitset<n>::operator&=(Expression const& expr)
02260     {
02261       this->assign(expr, Operator::bitsetANDAssign());
02262       return *this;
02263     }
02264 
02269 template<unsigned int n>
02270   template<typename Expression>
02271     inline bitset<n>&
02272     bitset<n>::operator|=(Expression const& expr)
02273     {
02274       this->assign(expr, Operator::bitsetORAssign());
02275       return *this;
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::bitsetXORAssign());
02288       return *this;
02289     }
02290 
02295 template<unsigned int m, bool inverted1, bool inverted2>
02296   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>
02297   operator&(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02298     {
02299       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>(arg1, arg2);
02300     }
02301 
02306 template<unsigned int m, bool inverted1, bool inverted2>
02307   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>
02308   operator|(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02309     {
02310       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>(arg1, arg2);
02311     }
02312 
02317 template<unsigned int m, bool inverted1, bool inverted2>
02318   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>
02319   operator^(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02320     {
02321       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>(arg1, arg2);
02322     }
02323 
02327 structassign {
02328   static int const id = 1;
02329   static bool const __clear = true;
02330   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02331   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02332 };
02333 
02337 structexor {
02338   static int const id = 2;
02339   static bool const __clear = false;
02340   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02341   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02342 };
02343 
02344 #ifndef HIDE_FROM_DOXYGEN
02345 structrotate_phase1 {
02346   static int const id = 3;
02347   static bool const __clear = false;
02348   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02349   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02350 };
02351 
02352 structrotate_phase2 {
02353 public:
02354   static int const id = 4;
02355   static bool const __clear = false;
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 #endif
02360 
02371 template<unsigned int n>
02372   template<unsigned int shift, class DIRECTION, class OPERATION>
02373     void
02374     bitset<n>::shift_op(bitset& result) const
02375    {
02376       LibEccDout(dc::bitsetshift, "Entering shift_op<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() <<
02377           ", " << type_info_of<OPERATION>().demangled_name() << '>');
02378       LibEccDout(dc::bitsetshift|flush_cf, "Input : " << cwprint_using(*this, &bitset<n>::base2_print_on));
02379       if (shift == 1)
02380       {
02381         // Specialization for shift == 1.
02382         // digit_shift = 0
02383         // bit_shift = 1
02384         // zeroed_digits = 0 (likely and if not - then assumed).
02385         // Here we scan in the opposite direction of when shift > 1.
02386         static unsigned int const initial = DIRECTION::__left ? 0 : bitset_base<n>::digits - 1;
02387         static unsigned int const count = bitset_base<n>::digits - ((DIRECTION::__left && bitset_base<n>::has_excess_bits) ? 1 : 0);
02388 #ifdef __i386__
02389         if (count)
02390         {
02391           bitset_digit_t const volatile* ptr1;
02392           bitset_digit_t volatile* ptr2;
02393           int c;
02394           if (DIRECTION::__left)
02395           {
02396             if (OPERATION::id == libecc::exor::id)
02397             {
02398               if (bitset_base<n>::has_excess_bits)
02399                 LIBECC_ASMSHIFTLEFT(
02400                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02401                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"),
02402                     LIBECC_ASMSHIFTLEFT_FINISH("xorl (%%edi),%%edx\n\t"));
02403               else
02404                 LIBECC_ASMSHIFTLEFT(
02405                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02406                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"), "");
02407             }
02408             else if (OPERATION::id == libecc::rotate_phase2::id)
02409             {
02410               if (bitset_base<n>::has_excess_bits)
02411                 LIBECC_ASMSHIFTLEFT(
02412                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02413               else
02414                 LIBECC_ASMSHIFTLEFT(
02415                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", "");
02416             }
02417             else
02418             {
02419               if (bitset_base<n>::has_excess_bits)
02420                 LIBECC_ASMSHIFTLEFT("", "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02421               else
02422                 LIBECC_ASMSHIFTLEFT("", "", "");
02423             }
02424           }
02425           else if (count > 1)
02426           {
02427             if (OPERATION::id == libecc::exor::id)
02428               LIBECC_ASMSHIFTRIGHT1(
02429                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02430                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP2_DESTINATION "," LIBECC_WORKREG),
02431                   LIBECC_PRESERVE_CF_CLOBBER);
02432             else if (OPERATION::id == libecc::rotate_phase2::id)
02433               LIBECC_ASMSHIFTRIGHT1(
02434                   LIBECC_RIGHT_PRESERVE_CF("orl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02435                   "",
02436                   LIBECC_PRESERVE_CF_CLOBBER);
02437             else
02438               LIBECC_ASMSHIFTRIGHT1(
02439                   "",
02440                   "",
02441                   LIBECC_CLOBBER);
02442           }
02443           else
02444           {
02445             if (OPERATION::id == libecc::exor::id)
02446               LIBECC_ASMSHIFTRIGHT0("xorl 4(%%edi), %%edx\n\t");
02447             else if (OPERATION::id == libecc::rotate_phase2::id)
02448               LIBECC_ASMSHIFTRIGHT0("orl 4(%%edi), %%edx\n\t");
02449             else
02450               LIBECC_ASMSHIFTRIGHT0("");
02451           }
02452         }
02453         else if (DIRECTION::__left && bitset_base<n>::has_excess_bits)
02454           OPERATION::op(result.vector[0], ((this->vector[0] << 1) & bitset_base<n>::valid_bits));
02455 #else
02456         static unsigned int complement_shift = bitset_digit_bits - 1;
02457         static bitset_digit_t const mask1 = DIRECTION::__left ? (1 << complement_shift) : 1;
02458         static bitset_digit_t const mask2 = DIRECTION::__right ? (1 << complement_shift) : 1;
02459         bitset_digit_t const* ptr1 = &this->vector[initial];
02460         bitset_digit_t* ptr2 = &result.vector[initial];
02461         bool carry;
02462         if (count)
02463         {
02464           bitset_digit_t digit = *ptr1;
02465           carry = (digit & mask1);
02466           if (DIRECTION::__left)
02467             digit <<= 1;
02468           else
02469             digit >>= 1;
02470           OPERATION::mixed_op(*ptr2, digit);
02471           for (int c = count - 1; c; --c)
02472           {
02473             ptr1 -= DIRECTION::direction;
02474             ptr2 -= DIRECTION::direction;
02475             digit = *ptr1;
02476             if (carry)
02477             {
02478               carry = (digit & mask1);
02479               if (DIRECTION::__left)
02480                 digit <<= 1;
02481               else
02482                 digit >>= 1;
02483               digit |= mask2;
02484             }
02485             else
02486             {
02487               carry = (digit & mask1);
02488               if (DIRECTION::__left)
02489                 digit <<= 1;
02490               else
02491                 digit >>= 1;
02492             }
02493             OPERATION::op(*ptr2, digit);
02494           }
02495         }
02496         if (DIRECTION::__left && bitset_base<n>::has_excess_bits)
02497         {
02498           bitset_digit_t digit;
02499           if (count)
02500             digit = ptr1[-DIRECTION::direction];
02501           else
02502             digit = *ptr1;
02503           digit <<= 1;
02504           if (count && carry)
02505             digit |= mask2;
02506           if (count)
02507             OPERATION::op(ptr2[-DIRECTION::direction], (digit & bitset_base<n>::valid_bits));
02508           else
02509             OPERATION::op(*ptr2, (digit & bitset_base<n>::valid_bits));
02510         }
02511 #endif
02512       }
02513       else
02514       {
02515         static unsigned int const digit_shift = shift / bitset_digit_bits;
02516         static unsigned int const bit_shift = shift % bitset_digit_bits;
02517 
02518         static unsigned int const zeroed_digits =
02519           DIRECTION::__left ? ((shift < n) ? digit_shift : bitset_base<n>::digits)
02520                             : ((bitset_digit_bits - bitset_base<n>::number_of_valid_bits + shift) / bitset_digit_bits);
02521 
02522         if (zeroed_digits < bitset_base<n>::digits)
02523         {
02524           static unsigned int const complement_shift = (bit_shift == 0) ? 0 : bitset_digit_bits - bit_shift;
02525           static unsigned int const initial_to = DIRECTION::__right ? 0 : bitset_base<n>::digits - 1;
02526           static unsigned int const initial_from = initial_to + DIRECTION::direction * digit_shift;
02527           static unsigned int const final_from = DIRECTION::__left ? 0 : bitset_base<n>::digits - 1;
02528 
02529           register bitset_digit_t digit = this->vector[initial_from];
02530           if (initial_from != final_from)
02531           {
02532             register bitset_digit_t next_digit;
02533             unsigned int to = initial_to;
02534             unsigned int from = initial_from + DIRECTION::direction;
02535             if (from != final_from)
02536               do
02537               {
02538                 next_digit = this->vector[from];
02539                 if (bit_shift != 0)
02540                 {
02541                   if (DIRECTION::direction == -1)
02542                     digit <<= bit_shift;
02543                   else
02544                     digit >>= bit_shift;
02545                   digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02546                 }
02547                 OPERATION::op(result.vector[to], digit);
02548                 digit = next_digit;
02549                 to += DIRECTION::direction;
02550                 from += DIRECTION::direction;
02551               }
02552               while (from != final_from);
02553             if (DIRECTION::__left || bit_shift < bitset_base<n>::number_of_valid_bits || bit_shift != 0)
02554               next_digit = this->vector[final_from];
02555             if (bit_shift != 0)
02556             {
02557               if (DIRECTION::direction == -1)
02558                 digit <<= bit_shift;
02559               else
02560                 digit >>= bit_shift;
02561               digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02562             }
02563             if (DIRECTION::__left || bit_shift < bitset_base<n>::number_of_valid_bits)
02564             {
02565               OPERATION::op(result.vector[final_from - DIRECTION::direction * (digit_shift + 1)], digit);
02566               digit = DIRECTION::shift_copy(next_digit, bit_shift);
02567             }
02568           }
02569           else
02570           {
02571             if (DIRECTION::direction == -1)
02572               digit <<= bit_shift;
02573             else
02574               digit >>= bit_shift;
02575           }
02576           static bool const have_mixed_digit = shift != 0 && (DIRECTION::__left ? shift : (n - shift)) % bitset_digit_bits != 0;
02577           static unsigned int const last_digit = (DIRECTION::__left ? shift : (n - 1 - shift)) / bitset_digit_bits;
02578           if (have_mixed_digit)
02579             OPERATION::mixed_op(result.vector[last_digit], digit);
02580           else
02581             OPERATION::op(result.vector[last_digit], digit);
02582           if (DIRECTION::__left && bitset_base<n>::has_excess_bits)
02583             result.vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;
02584         }
02585         if (OPERATION::__clear && zeroed_digits > 0)
02586         {
02587           static unsigned int const final_to = DIRECTION::__left ? 0 : bitset_base<n>::digits - 1;
02588           static unsigned int const initial_to = final_to - DIRECTION::direction * (zeroed_digits - 1);
02589           unsigned int to = initial_to;
02590           if (to != final_to)
02591             do
02592             {
02593               result.vector[to] = 0;
02594               to += DIRECTION::direction;
02595             }
02596             while(to != final_to);
02597           result.vector[to] = 0;
02598         }
02599       }
02600       LibEccDout(dc::bitsetshift|flush_cf, "Output: " << cwprint_using(result, &bitset<n>::base2_print_on));
02601     }
02602 
02606 template<unsigned int n>
02607   bitset<n>&
02608   bitset<n>::operator<<=(unsigned int shift)
02609   {
02610     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02611     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02612     int digit1 = bitset_base<n>::digits - digit_shift - 2;
02613     bitset_digit_t d0 = (digit1 >= -1) ? this->vector[digit1 + 1] : 0;
02614     for (int digit_to = bitset_base<n>::digits - 1; digit_to >= 0; --digit_to)
02615     {
02616       bitset_digit_t d1 = (digit1 >= 0) ? this->vector[digit1] : 0;
02617       if (bit_shift == 0)
02618         this->vector[digit_to] = d0;
02619       else
02620         this->vector[digit_to] = (d0 << bit_shift) | (d1 >> (bitset_digit_bits - bit_shift));
02621       d0 = d1;
02622       --digit1;
02623     }
02624     if (bitset_base<n>::has_excess_bits)
02625       this->vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;           // Reset possibly set excess bits.
02626     return *this;
02627   }
02628 
02632 template<unsigned int n>
02633   bitset<n>&
02634   bitset<n>::operator>>=(unsigned int shift)
02635   {
02636     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02637     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02638     int digit1 = digit_shift + 1;
02639     bitset_digit_t d0 = (digit1 <= bitset_base<n>::digits) ? this->vector[digit1 - 1] : 0;
02640     for (int digit_to = 0; digit_to < bitset_base<n>::digits; ++digit_to)
02641     {
02642       bitset_digit_t d1 = (digit1 < bitset_base<n>::digits) ? this->vector[digit1] : 0;
02643       if (bit_shift == 0)
02644         this->vector[digit_to] = d0;
02645       else
02646         this->vector[digit_to] = (d0 >> bit_shift) | (d1 << (bitset_digit_bits - bit_shift));
02647       d0 = d1;
02648       ++digit1;
02649     }
02650     return *this;
02651   }
02652 
02669 template<unsigned int n>
02670   bitset<n>::bitset(std::string const& input)
02671   {
02672     reset();                                            // Reset internal digits to zero.
02673     unsigned int d = 0;                                 // Current index of internal digit.
02674     unsigned int u = 0;                                 // Current bit-shift of input digit relative to internal digit.
02675 
02676     for (std::string::const_reverse_iterator iter = input.rbegin(); iter != input.rend(); ++iter)       // Read right to left.
02677     {
02678       bitset_digit_t c = toupper(*iter);                // Get next hexadecimal input character.
02679       if (c == ' ')                                     // Skip spaces.
02680         continue;
02681       if (c < '0')                                      // Terminate reading when not a hexadecimal character.
02682         break;
02683       if (c <= '9')
02684         c -= '0';                                       // Set c to the value that the input character represents.
02685       else
02686       {
02687         if (c > 'F')
02688           break;
02689         if (c >= 'A')
02690           c -= ('A' - 10);
02691         else
02692           break;
02693       }
02694       this->vector[d] |= c << u;                        // Set internal bits.
02695       if ((u += 4) == bitset_digit_bits)                // Update bit/digit 'pointers'.
02696       {
02697         u = 0;
02698         if (++d == bitset_base<n>::digits)              // Terminate reading when bitset is full.
02699           break;
02700       }
02701     }
02702     if (bitset_base<n>::has_excess_bits)
02703       this->vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;   // Reset possibly set excess bits.
02704   }
02705 
02709 template<unsigned int n>
02710   std::istream&
02711   operator>>(std::istream& is, bitset<n>& bitsetx)
02712   {
02713     std::string tmp;
02714     is >> tmp;
02715     bitsetx.bitset(tmp);
02716     return is;
02717   }
02718 
02722 template<unsigned int n>
02723   std::ostream&
02724   operator<<(std::ostream& os, bitset<n> const& bits)
02725   {
02726     // Hexadecimal representation
02727     os.fill('0');
02728     os << std::hex;
02729     for (int d = bitset<n>::digits - 1; d >= 0; --d)
02730     {
02731       os.width((d == bitset<n>::digits - 1 && bitset<n>::has_excess_bits) ?
02732           (((n % bitset_digit_bits) - 1) / 4 + 1) :
02733           (bitset_digit_bits / 4));
02734       os << bits.digit(d);
02735       if (d > 0)
02736         os << ' ';
02737     }
02738     os << std::dec;
02739     return os;
02740   }
02741 
02745 template<unsigned int n>
02746   bitset<n>&
02747   bitset<n>::reset(void)
02748   {
02749     std::memset(this->vector, 0, sizeof(this->vector));
02750     return *this;
02751   }
02752 
02756 template<unsigned int n>
02757   inline bool
02758   bitset<n>::test(size_t pos) const
02759  {
02760 #ifdef __i386__
02761     int result;
02762     __asm__ __volatile__ (
02763         "btl %2, %1\n\t"
02764         "sbbl %0, %0"
02765         : "=r" (result)
02766         : "m" ((*(bitset_digit_t volatile*)this->vector)), "Ir" (pos));
02767     return result;
02768 #else
02769     unsigned int d = pos / bitset_digit_bits;
02770     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02771     return (this->vector[d] & mask);
02772 #endif
02773   }
02774 
02778 template<unsigned int n>
02779   template<unsigned int pos>
02780     inline bool
02781     bitset<n>::test(void) const
02782    {
02783       static unsigned int const d = pos / bitset_digit_bits;
02784       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02785       return (this->vector[d] & mask);
02786     }
02787 
02791 template<unsigned int n>
02792   inline bool
02793   bitset<n>::test(bitset_index const& index) const
02794  {
02795 #ifdef __i386__
02796     return this->test(index.get_index());
02797 #else
02798     return (this->vector[index.get_digit()] & index.get_mask());
02799 #endif
02800   }
02801 
02805 template<unsigned int n>
02806   inline void
02807   bitset<n>::set(size_t pos)
02808   {
02809 #ifdef __i386__
02810     __asm__ __volatile__ (
02811         "btsl %1, %0"
02812         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02813         : "Ir" (pos));
02814 
02815 #else
02816     unsigned int d = pos / bitset_digit_bits;
02817     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02818     this->vector[d] |= mask;
02819 #endif
02820   }
02821 
02825 template<unsigned int n>
02826   inline void
02827   bitset<n>::set(bitset_index const& index)
02828   {
02829 #ifdef __i386__
02830     this->set(index.get_index());
02831 #else
02832     this->vector[index.get_digit()] |= index.get_mask();
02833 #endif
02834   }
02835 
02839 template<unsigned int n>
02840   template<unsigned int pos>
02841     inline void
02842     bitset<n>::set(void)
02843     {
02844       static unsigned int const d = pos / bitset_digit_bits;
02845       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02846       this->vector[d] |= mask;
02847     }
02848 
02852 template<unsigned int n>
02853   inline void
02854   bitset<n>::clear(size_t pos)
02855   {
02856 #ifdef __i386__
02857     __asm__ __volatile__ (
02858         "btrl %1, %0"
02859         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02860         : "Ir" (pos)
02861     );
02862 #else
02863     unsigned int d = pos / bitset_digit_bits;
02864     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02865     this->vector[d] &= ~mask;
02866 #endif
02867   }
02868 
02872 template<unsigned int n>
02873   inline void
02874   bitset<n>::clear(bitset_index const& index)
02875   {
02876 #ifdef __i386__
02877     this->clear(index.get_index());
02878 #else
02879     this->vector[index.get_digit()] &= ~(index.get_mask());
02880 #endif
02881   }
02882 
02886 template<unsigned int n>
02887   template<unsigned int pos>
02888     inline void
02889     bitset<n>::clear(void)
02890     {
02891       static unsigned int const d = pos / bitset_digit_bits;
02892       static bitset_digit_t const mask = ~(static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits));
02893       this->vector[d] &= mask;
02894     }
02895 
02899 template<unsigned int n>
02900   inline void
02901   bitset<n>::flip(size_t pos)
02902   {
02903 #ifdef __i386__
02904     __asm__ __volatile__ (
02905         "btcl %1, %0"
02906         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02907         : "Ir" (pos)
02908     );
02909 #else
02910     unsigned int d = pos / bitset_digit_bits;
02911     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02912     this->vector[d] ^= mask;
02913 #endif
02914   }
02915 
02919 template<unsigned int n>
02920   inline void
02921   bitset<n>::flip(bitset_index const& index)
02922   {
02923 #ifdef __i386__
02924     this->flip(index.get_index());
02925 #else
02926     this->vector[index.get_digit()] ^= index.get_mask();
02927 #endif
02928   }
02929 
02933 template<unsigned int n>
02934   template<unsigned int pos>
02935     inline void
02936     bitset<n>::flip(void)
02937     {
02938       static unsigned int const d = pos / bitset_digit_bits;
02939       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02940       this->vector[d] ^= mask;
02941     }
02942 
02946 template<unsigned int n>
02947   bool
02948   bitset<n>::any(void) const
02949  {
02950     unsigned int to = bitset_base<n>::digits - 1;
02951     if (bitset_base<n>::digits > 1)
02952       do
02953       {
02954         if (this->vector[to] != 0)
02955           return true;
02956         --to;
02957       }
02958       while(to != 0);
02959     return (this->vector[0] != 0);
02960   }
02961 
02962 static bool const oddnumberofbits[] = {
02963   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02964   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02965   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02966   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02967   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02968   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02969   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02970   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02971   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02972   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02973   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02974   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02975   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02976   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02977   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02978   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false };
02979 
02983 template<unsigned int n>
02984   bool
02985   bitset<n>::odd(void) const
02986  {
02987     unsigned int from = bitset_base<n>::digits - 1;
02988     bitset_digit_t sum = this->vector[0];
02989     if (bitset_base<n>::digits > 1)
02990       do
02991       {
02992         sum ^= this->vector[from];
02993         --from;
02994       }
02995       while(from != 0);
02996     bitset_digit_t ssum = sum;
02997     if (sizeof(bitset_digit_t) >= 2)
02998     {
02999       ssum >>= (bitset_digit_bits / 2);
03000       sum ^= ssum;
03001     }
03002     if (sizeof(bitset_digit_t) >= 4)
03003     {
03004       ssum = sum;
03005       ssum >>= (bitset_digit_bits / 4);
03006       sum ^= ssum;
03007     }
03008     if (sizeof(bitset_digit_t) >= 8)
03009     {
03010       ssum = sum;
03011       ssum >>= (bitset_digit_bits / 8);
03012       sum ^= ssum;
03013     }
03014     if (sizeof(bitset_digit_t) == 16)
03015     {
03016       ssum = sum;
03017       ssum >>= (bitset_digit_bits / 16);
03018       sum ^= ssum;
03019     }
03020     return oddnumberofbits[sum & 0xff];
03021   }
03022 
03026 structleft {
03027 public:
03028   typedef structright inverse;
03029   static int const direction = -1;
03030   static bool const __left = true;
03031   static bool const __right = false;
03032   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03033   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03034 };
03035 
03039 structright {
03040 public:
03041   typedef structleft inverse;
03042   static int const direction = 1;
03043   static bool const __left = false;
03044   static bool const __right = true;
03045   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03046   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03047 };
03048 
03057 template<unsigned int n>
03058   template<unsigned int shift, class DIRECTION>
03059     void
03060     bitset<n>::rotate(bitset<n>& result) const
03061    {
03062       LibEccDout(dc::bitsetshift|flush_cf, "Entering bitset<" << n << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03063       LibEccDout(dc::bitsetshift|flush_cf, "Rotate input : " << cwprint_using(*this, &bitset<n>::base2_print_on));
03064       shift_op<shift % n, DIRECTION, rotate_phase1>(result);
03065       LibEccDout(dc::bitsetshift|flush_cf, "After phase1 : " << cwprint_using(result, &bitset<n>::base2_print_on));
03066       shift_op<n - (shift % n), typename DIRECTION::inverse, rotate_phase2>(result);
03067       LibEccDout(dc::bitsetshift|flush_cf, "After phase2 : " << cwprint_using(result, &bitset<n>::base2_print_on));
03068       LibEccDout(dc::bitsetshift|flush_cf, "Leaving bitset<" << n << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03069     }
03070 
03071 } // namespace libecc
03072 
03073 #endif // LIBECC_BITS_H
Copyright © 2002-2004 Carlo Wood.  All rights reserved.