Main Page   Reference Manual   Compound List   File List  

libecc/bitset.h

Go to the documentation of this file.
00001 //
00006 //
00007 // This file is part of the libecc package.
00008 // Copyright (C) 2002, by
00009 //
00010 // Carlo Wood, Run on IRC <carlo@alinoe.com>
00011 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
00012 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
00013 //
00014 // This program is free software; you can redistribute it and/or
00015 // modify it under the terms of the GNU General Public License
00016 // as published by the Free Software Foundation; either version 2
00017 // of the License, or (at your option) any later version.
00018 //
00019 // This program is distributed in the hope that it will be useful,
00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 // GNU General Public License for more details.
00023 //
00024 // You should have received a copy of the GNU General Public License
00025 // along with this program; if not, write to the Free Software
00026 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00027 
00028 #ifndef LIBECC_BITS_H
00029 #define LIBECC_BITS_H
00030 
00031 #ifndef LIBECC_DEBUG_H
00032 #error "You need to include the appropriate debug.h in the source file, before including this header file."
00033 #endif
00034 
00035 #include <libecc/config.h>
00036 #include <iosfwd>
00037 #include <cstddef>
00038 #include <cstring>
00039 #include <string>
00040 #include <inttypes.h>
00041 #include <cassert>
00042 #include <endian.h>
00043 #ifdef CWDEBUG
00044 #include "debug.h"
00045 #include <libcwd/cwprint.h>
00046 #endif
00047 #define LIBECC_TRACK_EXPR_TEMPORARIES (ECC_DEBUG && 1)
00048 #if LIBECC_TRACK_EXPR_TEMPORARIES
00049 #include <set>
00050 #endif
00051 
00052 #if defined(__i386__) && defined(HAVE_NASM)
00053 // Assembly code, defined in window.s.
00054 extern "C" int libecc_shift_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00055 extern "C" int libecc_shiftwindow_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00056 #endif
00057 
00058 namespacelibecc {
00059 
00069 typedef unsigned long bitset_digit_t;
00070 
00072 static unsigned int const bitset_digit_bits = sizeof(bitset_digit_t) * 8;
00073 
00075 #if ECC_BITS == 32
00076 static unsigned int const bitset_digit_bits_log2 = 5;
00077 #elif ECC_BITS == 64
00078 static unsigned int const bitset_digit_bits_log2 = 6;
00079 #elif ECC_BITS == 128
00080 #warning 128 bit code has not been tested.  This warning will remain here until you mail me.
00081 static unsigned int const bitset_digit_bits_log2 = 7;
00082 #endif
00083 
00084 // Forward declaration.
00085 template<unsigned int n, bool inverted>
00086   classbitset_invertible;
00087 
00097 template<unsigned int n>
00098   structbitset_base {
00099     public:
00100       // Fix this if you add members in front of vector.
00101       static size_t const offsetof_vector = 0; //sizeof(bitset_digit_t);
00102 
00103     public:
00107       static unsigned int const number_of_bits = n;
00108 
00110       static unsigned int const digits = (n == 0) ? 0 : ((n - 1) / bitset_digit_bits + 1);
00111 
00112       // ! The number of valid bits in the most significant digit.
00113       static unsigned int const number_of_valid_bits = bitset_digit_bits - (digits * bitset_digit_bits - n);
00114 
00116       static bitset_digit_t const valid_bits = ((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 #if __BYTE_ORDER == __LITTLE_ENDIAN
00152           return (this->vector[d] >> (r * 32));
00153 #elif __BYTE_ORDER == __BIG_ENDIAN
00154           return (this->vector[d] >> (bitset_digit_bits - 32 - (r * 32)));
00155 #endif
00156         }
00157       }
00158   };
00159 
00160 #ifndef HIDE_FROM_DOXYGEN
00161 namespaceOperator {
00162 
00163 #ifdef __i386__
00164 
00165 //
00166 // Due to heavily broken inlining heuristics of gcc,
00167 // we are forced to use macros to do the assembly
00168 // inlining.  There is no alternative, I tried everything.
00169 //
00170 
00171 #define LIBECC_INVERT "xorl $-1,%%eax\n\t"
00172 #define LIBECC_NOTHING ""
00173 
00174 #define LIBECC_ASMLOOP(destination, source, count, OPCODE, OPTIONAL_INVERT)     \
00175   do {                                                  \
00176     int __d0, __d1, __d2;                               \
00177     __asm__ __volatile__ (                              \
00178       "\n1:\n\t"                                        \
00179         "movl (%5,%%ecx,4),%%eax\n\t"                   \
00180         OPTIONAL_INVERT                                 \
00181         OPCODE " %%eax,(%4,%%ecx,4)\n\t"                \
00182         "decl %%ecx\n\t"                                \
00183         "jnz 1b"                                        \
00184         : "=c" (__d0), "=&r" (__d1), "=&r" (__d2)       \
00185         : "0" (count),                                  \
00186           "1" ((destination) - 1),                      \
00187           "2" ((source) - 1)                            \
00188         : "%eax", "memory"                              \
00189     );                                                  \
00190   } while(0)
00191 
00192 #define LIBECC_ASMLOOP_BODY(OPCODE, destination, source, count, inverted) \
00193   do { \
00194     if (inverted) \
00195       LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_INVERT); \
00196     else \
00197       LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_NOTHING); \
00198   } while(0)
00199 
00200 #define LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, OPTIONAL_INVERT1, OPCODE2, OPTIONAL_INVERT3)              \
00201   do {                                                          \
00202     int __d0, __d1, __d2, __d3;                                 \
00203     __asm__ __volatile__ (                                      \
00204       "\n1:\n\t"                                                \
00205         "movl (%6,%%ecx,4),%%eax\n\t"                           \
00206         OPTIONAL_INVERT1                                        \
00207         OPCODE2 " (%7,%%ecx,4),%%eax\n\t"                       \
00208         OPTIONAL_INVERT3                                        \
00209         OPCODE " %%eax,(%5,%%ecx,4)\n\t"                        \
00210         "decl %%ecx\n\t"                                        \
00211         "jnz 1b"                                                \
00212         : "=c" (__d0), "=&r" (__d1), "=&r" (__d2), "=&r" (__d3) \
00213         : "0" (count),                                          \
00214           "1" ((destination) - 1),                              \
00215           "2" ((source1) - 1),                                  \
00216           "3" ((source2) - 1)                                   \
00217         : "%eax", "memory"                                      \
00218     );                                                          \
00219   } while(0)
00220 
00221 #define LIBECC_ASMLOOP2_BODY(OPCODE, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00222   do { \
00223     if (OPERATOR::id == libecc::Operator::bitsetAND::id) \
00224     { \
00225       if (inverted1 && inverted2) \
00226         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_INVERT); \
00227       else if (inverted1) \
00228         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00229       else if (inverted2) \
00230         LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00231       else \
00232         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_NOTHING); \
00233     } \
00234     else if (OPERATOR::id == libecc::Operator::bitsetOR::id) \
00235     { \
00236       if (inverted1 && inverted2) \
00237         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_INVERT); \
00238       else if (inverted1) \
00239         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00240       else if (inverted2) \
00241         LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00242       else \
00243         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_NOTHING); \
00244     } \
00245     else if (OPERATOR::id == libecc::Operator::bitsetXOR::id) \
00246     { \
00247       if (inverted1 == inverted2) \
00248         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_NOTHING); \
00249       else \
00250         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_INVERT); \
00251     } \
00252   } while(0)
00253 
00254 #define LIBECC_INLINE_ASMLOOP(ID, destination, source, count, inverted) \
00255     do { \
00256       if (ID == libecc::Operator::bitsetAssign::id) \
00257       { \
00258         LIBECC_ASMLOOP_BODY("movl", destination, source, count, inverted); \
00259       } \
00260       else if (ID == libecc::Operator::bitsetANDAssign::id) \
00261       { \
00262         LIBECC_ASMLOOP_BODY("andl", destination, source, count, inverted); \
00263       } \
00264       else if (ID == libecc::Operator::bitsetORAssign::id) \
00265       { \
00266         LIBECC_ASMLOOP_BODY("orl", destination, source, count, inverted); \
00267       } \
00268       else if (ID == libecc::Operator::bitsetXORAssign::id) \
00269       { \
00270         LIBECC_ASMLOOP_BODY("xorl", destination, source, count, inverted); \
00271       } \
00272     } while(0)
00273 
00274 #define LIBECC_INLINE_ASMLOOP2(ID, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00275     do { \
00276       if (ID == libecc::Operator::bitsetAssign::id) \
00277       { \
00278         LIBECC_ASMLOOP2_BODY("movl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00279       } \
00280       else if (ID == libecc::Operator::bitsetANDAssign::id) \
00281       { \
00282         LIBECC_ASMLOOP2_BODY("andl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00283       } \
00284       else if (ID == libecc::Operator::bitsetORAssign::id) \
00285       { \
00286         LIBECC_ASMLOOP2_BODY("orl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00287       } \
00288       else if (ID == libecc::Operator::bitsetXORAssign::id) \
00289       { \
00290         LIBECC_ASMLOOP2_BODY("xorl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00291       } \
00292     } while(0)
00293 
00294 #define LIBECC_ASMSHIFTRIGHT0(OP1)                      \
00295               __asm__ __volatile__ (                    \
00296                   "movl 4(%%esi),%%edx\n\t"             \
00297                   "shrl $1,%%edx\n\t"                   \
00298                   OP1                                   \
00299                   "movl %%edx,4(%%edi)"                 \
00300                 : "=&S" (ptr1),                         \
00301                   "=&D" (ptr2)                          \
00302                 : "0" (&this->vector[initial - count]), \
00303                   "1" (&result.vector[initial - count]) \
00304                 : "%eax", "%edx", "memory", "cc"        \
00305               )
00306 
00307 #if 0   // NOT faster.
00308 #define LIBECC_OP1_SOURCE "(%%esi)"
00309 #define LIBECC_OP2_SOURCE "(%%esi)"
00310 #define LIBECC_OP1_DESTINATION "(%%edi)"
00311 #define LIBECC_OP2_DESTINATION "(%%edi)"
00312 #define LIBECC_WORKREG "%%eax"
00313 #define LIBECC_CLOBBER "%eax"
00314 #define LIBECC_INIT "std\n\t"
00315 #define LIBECC_LOAD1 "lodsl\n\t"
00316 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00317 #define LIBECC_STORE1 "stosl\n\t"
00318 #define LIBECC_LOAD2 "lodsl\n\t"
00319 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
00320 #define LIBECC_STORE2 "stosl\n\t"
00321 #define LIBECC_DEINIT "cld\n\t"
00322 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "setc %%edx\n\t" OPERAND "\n\tbt $0,%%edx\n\t"
00323 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%edx"
00324 #define LIBECC_INITIAL_ESI &this->vector[initial]
00325 #define LIBECC_INITIAL_EDI &result.vector[initial]
00326 #else
00327 #define LIBECC_OP1_SOURCE "4(%%esi,%%ecx,4)"
00328 #define LIBECC_OP2_SOURCE "(%%esi,%%ecx,4)"
00329 #define LIBECC_OP1_DESTINATION "4(%%edi,%%ecx,4)"
00330 #define LIBECC_OP2_DESTINATION "(%%edi,%%ecx,4)"
00331 #define LIBECC_WORKREG "%%edx"
00332 #define LIBECC_CLOBBER "%edx"
00333 #define LIBECC_INIT
00334 #define LIBECC_LOAD1 "movl " LIBECC_OP1_SOURCE "," LIBECC_WORKREG "\n\t"
00335 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00336 #define LIBECC_STORE1 "movl " LIBECC_WORKREG "," LIBECC_OP1_DESTINATION "\n\t"
00337 #define LIBECC_LOAD2 "movl " LIBECC_OP2_SOURCE "," LIBECC_WORKREG "\n\t"
00338 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
00339 #define LIBECC_STORE2 "movl " LIBECC_WORKREG "," LIBECC_OP2_DESTINATION "\n\t"
00340 #define LIBECC_DEINIT
00341 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
00342 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%eax"
00343 #define LIBECC_INITIAL_ESI &this->vector[initial - count]
00344 #define LIBECC_INITIAL_EDI &result.vector[initial - count]
00345 #endif
00346 
00347 #define LIBECC_ASMSHIFTRIGHT1(OP1, OP2, CLOBBER)        \
00348               __asm__ __volatile__ (                    \
00349                   LIBECC_INIT                           \
00350                   LIBECC_LOAD1                          \
00351                   LIBECC_SHIFT                          \
00352                   OP1                                   \
00353                   LIBECC_STORE1                         \
00354                 "1:\n\t"                                \
00355                   LIBECC_LOAD2                          \
00356                   LIBECC_ROTATE                         \
00357                   OP2                                   \
00358                   LIBECC_STORE2                         \
00359                   "decl %%ecx\n\t"                      \
00360                   "jnz 1b\n\t"                          \
00361                   LIBECC_DEINIT                         \
00362                 : "=&S" (ptr1),                         \
00363                   "=&D" (ptr2),                         \
00364                   "=&c" (c)                             \
00365                 : "0" (LIBECC_INITIAL_ESI),             \
00366                   "1" (LIBECC_INITIAL_EDI),             \
00367                   "2" (count - 1)                       \
00368                 : "memory", "cc", CLOBBER               \
00369               )
00370 
00371 #define LIBECC_ASMSHIFTLEFT(OP1, OP2, FINISH)           \
00372               __asm__ __volatile__ (                    \
00373                   "movl -4(%%esi),%%edx\n\t"            \
00374                   "shll $1,%%edx\n\t"                   \
00375                   OP1                                   \
00376                   "movl %%edx,-4(%%edi)\n\t"            \
00377                   "jecxz 2f\n"                          \
00378                 "1:\n\t"                                \
00379                   "movl (%%esi),%%edx\n\t"              \
00380                   "rcll $1,%%edx\n\t"                   \
00381                   OP2                                   \
00382                   "movl %%edx,(%%edi)\n\t"              \
00383                   "leal 4(%%esi),%%esi\n\t"             \
00384                   "leal 4(%%edi),%%edi\n\t"             \
00385                   "decl %%ecx\n\t"                      \
00386                   "jnz 1b\n"                            \
00387                 "2:\n\t"                                \
00388                   FINISH                                \
00389                 : "=&S" (ptr1),                         \
00390                   "=&D" (ptr2),                         \
00391                   "=&c" (c)                             \
00392                 : "0" (&this->vector[initial + 1]),     \
00393                   "1" (&result.vector[initial + 1]),    \
00394                   "2" (count - 1),                      \
00395                   "i" (bitset_base<n>::valid_bits)      \
00396                 : "%eax", "%edx", "memory", "cc"        \
00397               )
00398 
00399 #define LIBECC_ASMSHIFTLEFT_FINISH(OP)                  \
00400                   "movl (%%esi),%%edx\n\t"              \
00401                   "rcll $1,%%edx\n\t"                   \
00402                   "andl %6,%%edx\n\t"                   \
00403                   OP                                    \
00404                   "movl %%edx,(%%edi)"
00405 
00406 #define LIBECC_LEFT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
00407 
00408 #endif // __i386__
00409 
00410 // Functors.
00411 
00412 // Functor for '&'.
00413 structbitsetAND {
00414   static int const id = 1;
00415   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 & digit2; }
00416   template<bool inverted1, bool inverted2>
00417    structexecbool {
00418      static bool const value = inverted1 && inverted2;
00419    };
00420 };
00421 
00422 // Functor for '|'.
00423 structbitsetOR {
00424   static int const id = 2;
00425   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 | digit2; }
00426   template<bool inverted1, bool inverted2>
00427    structexecbool {
00428      static bool const value = inverted1 || inverted2;
00429    };
00430 };
00431 
00432 // Functor for '^'.
00433 structbitsetXOR {
00434   static int const id = 3;
00435   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 ^ digit2; }
00436   template<bool inverted1, bool inverted2>
00437    structexecbool {
00438      static bool const value = (inverted1 != inverted2);
00439    };
00440 };
00441 
00442 // Functor for '='.
00443 structbitsetAssign {
00444   static int const id = 1;
00445   static bool const sets_excess_bits = true;
00446   static bool const with_zero_sets_zero = true;
00447   static bool const with_ones_sets_ones = true;
00448   static bool const with_ones_inverts = false;
00449   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out = in; }
00450 };
00451 
00452 // Functor for '&='.
00453 structbitsetANDAssign {
00454   static int const id = 2;
00455   static bool const sets_excess_bits = false;
00456   static bool const with_zero_sets_zero = true;
00457   static bool const with_ones_sets_ones = false;
00458   static bool const with_ones_inverts = false;
00459   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out &= in; }
00460 };
00461 
00462 // Functor for '|='.
00463 structbitsetORAssign {
00464   static int const id = 3;
00465   static bool const sets_excess_bits = true;
00466   static bool const with_zero_sets_zero = false;
00467   static bool const with_ones_sets_ones = true;
00468   static bool const with_ones_inverts = false;
00469   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out |= in; }
00470 };
00471 
00472 // Functor for '^='.
00473 structbitsetXORAssign {
00474   static int const id = 4;
00475   static bool const sets_excess_bits = true;
00476   static bool const with_zero_sets_zero = false;
00477   static bool const with_ones_sets_ones = false;
00478   static bool const with_ones_inverts = true;
00479   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out ^= in; }
00480 };
00481 
00482 #if LIBECC_TRACK_EXPR_TEMPORARIES
00483 extern std::multiset<void const*> bitsetExpression_bitset_invertible_pointers;
00484 #endif
00485 
00486 template<unsigned int n, bool inverted1, bool inverted2, typename OP>
00487   structbitsetExpression
00488   {
00489     bitset_invertible<n, inverted1> const& first;
00490     bitset_invertible<n, inverted2> const& second;
00491     OP op;
00492 
00493     bitsetExpression(bitset_invertible<n, inverted1> const& arg1, bitset_invertible<n, inverted2> const& arg2) :
00494         first(arg1), second(arg2)
00495     {
00496       // I found a problem with a destructed temporary that was still in use.
00497       // It seems that the pointer to this destructed temporary is stored in
00498       // this object.  The following code is added in order to debug this
00499       // problem.
00500 #if LIBECC_TRACK_EXPR_TEMPORARIES
00501       bitsetExpression_bitset_invertible_pointers.insert(&arg1);
00502       bitsetExpression_bitset_invertible_pointers.insert(&arg2);
00503       LibEccDout(dc::notice, "Constructed a bitsetExpression with arguments " <<
00504           (void const*)&first << " and " << (void const*)&second);
00505 #endif
00506     }
00507 #if LIBECC_TRACK_EXPR_TEMPORARIES
00508     ~bitsetExpression();
00509 #endif
00510   };
00511 
00512 #if LIBECC_TRACK_EXPR_TEMPORARIES
00513 template<unsigned int n, bool inverted1, bool inverted2, typename OP>
00514   bitsetExpression<n, inverted1, inverted2, OP>::~bitsetExpression()
00515   {
00516     bitsetExpression_bitset_invertible_pointers.erase(bitsetExpression_bitset_invertible_pointers.find(&first));
00517     bitsetExpression_bitset_invertible_pointers.erase(bitsetExpression_bitset_invertible_pointers.find(&second));
00518     LibEccDout(dc::notice, "Destructed bitsetExpression with arguments " <<
00519         (void const*)&first << " and " << (void const*)&second);
00520   }
00521 #endif
00522 
00523 } // namespace Operator
00524 #endif // HIDE_FROM_DOXYGEN
00525 
00543 template<unsigned int n, bool inverted>
00544   classbitset_invertible : public bitset_base<n> {
00545     public:
00546       // Constructors
00547       bitset_invertible(void);
00548       template<typename Expression>
00549         explicit bitset_invertible<n, inverted>(Expression const&);
00550 
00551 #if LIBECC_TRACK_EXPR_TEMPORARIES
00552       ~bitset_invertible();
00553 #endif
00554 
00555     protected:
00556       template<typename OP, unsigned int x, bool invertedx>
00557         void assign(bitset_invertible<x, invertedx> const&, OP);
00558       template<typename OP1, unsigned int x, bool inverted1, bool inverted2, typename OP2>
00559         void assign(Operator::bitsetExpression<x, inverted1, inverted2, OP2> const&, OP1);
00560 
00561     private:
00562       template<unsigned int m, bool i>
00563         friend classbitset_invertible;
00564       template<unsigned int m, int DIRECTION>
00565         friend classbitset_iterator;
00566 
00567     public:
00569       void base2_print_on(std::ostream& os) const;
00570 
00572       bitset_digit_t digit(unsigned int d) const{ return inverted ? ~this->vector[d] : this->vector[d]; }
00573   };
00574 
00575 #if LIBECC_TRACK_EXPR_TEMPORARIES
00576 template<unsigned int n, bool inverted>
00577   bitset_invertible<n, inverted>::~bitset_invertible()
00578   {
00579     LibEccDout(dc::notice, "Destructing bitset_invertible at " << (void*)this);
00580     if (Operator::bitsetExpression_bitset_invertible_pointers.find(this) !=
00581         Operator::bitsetExpression_bitset_invertible_pointers.end())
00582       LibEccDoutFatal(dc::core, "This object is still in use by a bitsetExpression!");
00583   }
00584 #endif
00585 
00597 template<unsigned int n, bool inverted>
00598   void
00599   bitset_invertible<n, inverted>::base2_print_on(std::ostream& os) const
00600  {
00601     // Binary representation
00602     for (int d = bitset_base<n>::digits - 1; d >= 0; --d)
00603       for (bitset_digit_t mask = (~static_cast<bitset_digit_t>(0) >> 1) + 1; mask != 0; mask >>= 1)
00604         if (d != bitset_base<n>::digits - 1 || (mask & bitset_base<n>::valid_bits))
00605           if ((this->digit(d) & mask) == inverted)
00606             os << '0';
00607           else
00608             os << '1';
00609   }
00610 
00611 // Default constructor.
00612 template<unsigned int n, bool inverted>
00613   inline
00614   bitset_invertible<n, inverted>::bitset_invertible(void)
00615   {
00616     if (bitset_base<n>::has_excess_bits)
00617       this->vector[bitset_base<n>::digits - 1] = 0;                     // Reset the excess bits!
00618   }
00619 
00620 // Copy constructor.
00621 template<unsigned int n, bool inverted>
00622   template<typename Expression>
00623     inline
00624     bitset_invertible<n, inverted>::bitset_invertible(Expression const& expr)
00625     {
00626       this->assign(expr, Operator::bitsetAssign());
00627     }
00628 
00629 //
00630 // Assignment function.
00631 // This function handles:
00632 //
00633 // a = b;
00634 // a = ~b;
00635 // a &= b;
00636 // a &= ~b;
00637 // a |= b;
00638 // a |= ~b;
00639 // a ^= b;
00640 // a ^= ~b;
00641 //
00642 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
00643 //
00644 template<unsigned int n, bool inverted>
00645   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted_argument>
00646     inline void
00647     bitset_invertible<n, inverted>::assign(bitset_invertible<x, inverted_argument> const& bits, ASSIGNMENT_OPERATOR)
00648     {
00649       // Handle excess digits.
00650       if (bitset_base<n>::digits > bitset_base<x>::digits)
00651       {
00652         if (!inverted_argument)
00653         {
00654           // Fill excess digits with 0's when needed.
00655           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
00656           {
00657 #ifdef __i386__
00658             int __d0, __d1;
00659             __asm__ __volatile__ (
00660                 "std; rep; stosl"
00661                 : "=m" (this->vector[bitset_base<n>::digits - 1]), "=&c" (__d0), "=&D" (__d1)
00662                 : "a" (0), "1" (bitset_base<n>::digits - bitset_base<x>::digits), "2" (&this->vector[bitset_base<n>::digits - 1])
00663                 : "memory"
00664             );
00665 #else
00666             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00667             do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
00668 #endif
00669           }
00670         }
00671         else
00672         {
00673           // Fill excess digits with 1's when needed.
00674           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
00675           {
00676 #ifdef __i386__
00677             int __d0, __d1;
00678             __asm__ __volatile__ (
00679                 "movl %6,4(%%edi); std; rep; stosl"
00680                 : "=m" (this->vector[bitset_base<n>::digits - 2]), "=&c" (__d0), "=&D" (__d1)
00681                 : "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)
00682                 : "memory"
00683             );
00684 #else
00685             this->vector[bitset_base<n>::digits - 1] = bitset_base<n>::valid_bits;
00686             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00687             while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
00688 #endif
00689           }
00690           // Or invert them.
00691           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
00692           {
00693 #ifdef __i386__
00694             int __d0, __d1;
00695             __asm__ __volatile__ (
00696                 "xorl %5,(%2)\n\t"
00697                 "jecxz 2f\n\t"
00698                 "subl %6,%2\n"
00699         "1:\n\t"
00700                 "xorl $-1,(%2,%%ecx,4)\n\t"
00701                 "decl %%ecx\n\t"
00702                 "jnz 1b\n"
00703         "2:"
00704                 : "=m" (this->vector[bitset_base<n>::digits - 1]), "=&c" (__d0), "=&r" (__d1)
00705                 : "1" (bitset_base<n>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<n>::digits - 1]),
00706                   "i" (bitset_base<n>::valid_bits), "i" ((bitset_base<n>::digits - bitset_base<x>::digits) * 4)
00707                 : "memory", "cc"
00708             );
00709 #else
00710             this->vector[bitset_base<n>::digits - 1] ^= bitset_base<n>::valid_bits;
00711             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00712             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
00713 #endif
00714           }
00715         }
00716       }
00717 
00718       // Handle other digits.
00719 #ifdef __i386__
00720       LIBECC_INLINE_ASMLOOP(ASSIGNMENT_OPERATOR::id,
00721           this->vector, bits.digits_ptr(),
00722           ((bitset_base<n>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<n>::digits),
00723           inverted_argument);
00724 #else
00725       unsigned int d;
00726       if (bitset_base<n>::digits > bitset_base<x>::digits)
00727         d = bitset_base<x>::digits - 1;
00728       else
00729         d = bitset_base<n>::digits - 1;
00730       ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~*(bits.digits_ptr() + d) : bits.digit(d));
00731       while(d) { --d; ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~*(bits.digits_ptr() + d) : bits.digit(d)); }
00732 #endif
00733 
00734       // Reset excess bits if needed.
00735       if (((!inverted_argument && x > n) ||
00736             (inverted_argument && bitset_base<n>::digits <= bitset_base<x>::digits)) &&
00737           bitset_base<n>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
00738         this->vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;
00739     }
00740 
00741 //
00742 // Assignment function for expressions.
00743 // This function handles:
00744 //
00745 // a = b & c;
00746 // a = b & ~c;
00747 // a = ~b & c;
00748 // a = ~b & ~b;
00749 // a = b | c;
00750 // a = b | ~c;
00751 // a = ~b | c;
00752 // a = ~b | ~b;
00753 // a = b ^ c;
00754 // a = b ^ ~c;
00755 // a = ~b ^ c;
00756 // a = ~b ^ ~b;
00757 // a &= b & c;
00758 // a &= b & ~c;
00759 // a &= ~b & c;
00760 // a &= ~b & ~b;
00761 // a &= b | c;
00762 // a &= b | ~c;
00763 // a &= ~b | c;
00764 // a &= ~b | ~b;
00765 // a &= b ^ c;
00766 // a &= b ^ ~c;
00767 // a &= ~b ^ c;
00768 // a &= ~b ^ ~b;
00769 // a |= b & c;
00770 // a |= b & ~c;
00771 // a |= ~b & c;
00772 // a |= ~b & ~b;
00773 // a |= b | c;
00774 // a |= b | ~c;
00775 // a |= ~b | c;
00776 // a |= ~b | ~b;
00777 // a |= b ^ c;
00778 // a |= b ^ ~c;
00779 // a |= ~b ^ c;
00780 // a |= ~b ^ ~b;
00781 // a ^= b & c;
00782 // a ^= b & ~c;
00783 // a ^= ~b & c;
00784 // a ^= ~b & ~b;
00785 // a ^= b | c;
00786 // a ^= b | ~c;
00787 // a ^= ~b | c;
00788 // a ^= ~b | ~b;
00789 // a ^= b ^ c;
00790 // a ^= b ^ ~c;
00791 // a ^= ~b ^ c;
00792 // a ^= ~b ^ ~b;
00793 //
00794 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
00795 // OPERATOR is one of bitsetAND, bitsetOR or bitsetXOR.
00796 //
00797 template<unsigned int n, bool inverted>
00798   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted1, bool inverted2, typename OPERATOR>
00799     inline void
00800     bitset_invertible<n, inverted>::assign(Operator::bitsetExpression<x, inverted1, inverted2, OPERATOR> const& expr, ASSIGNMENT_OPERATOR)
00801     {
00802       static bool const argument_has_leading_ones = OPERATOR::template execbool<inverted1, inverted2>::value;
00803 
00804       // Handle excess digits.
00805       if (bitset_base<n>::digits > bitset_base<x>::digits)
00806       {
00807         if (!argument_has_leading_ones)
00808         {
00809           // Fill excess digits with 0's when needed.
00810           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
00811           {
00812 #ifdef __i386__
00813             int __d0, __d1;
00814             __asm__ __volatile__ (
00815                 "std; rep; stosl"
00816                 : "=m" (this->vector[bitset_base<n>::digits - 1]), "=&c" (__d0), "=&D" (__d1)
00817                 : "a" (0), "1" (bitset_base<n>::digits - bitset_base<x>::digits), "2" (&this->vector[bitset_base<n>::digits - 1])
00818                 : "memory"
00819             );
00820 #else
00821             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00822             do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
00823 #endif
00824           }
00825         }
00826         else
00827         {
00828           // Fill excess digits with 1's when needed.
00829           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
00830           {
00831 #ifdef __i386__
00832             int __d0, __d1;
00833             __asm__ __volatile__ (
00834                 "movl %6,4(%%edi); std; rep; stosl"
00835                 : "=m" (this->vector[bitset_base<n>::digits - 2]), "=&c" (__d0), "=&D" (__d1)
00836                 : "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)
00837                 : "memory"
00838             );
00839 #else
00840             this->vector[bitset_base<n>::digits - 1] = bitset_base<n>::valid_bits;
00841             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00842             while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
00843 #endif
00844           }
00845           // Or invert them.
00846           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
00847           {
00848 #ifdef __i386__
00849             int __d0, __d1;
00850             __asm__ __volatile__ (
00851                 "xorl %5,(%2)\n\t"
00852                 "jecxz 2f\n\t"
00853                 "subl %6,%2\n"
00854         "1:\n\t"
00855                 "xorl $-1,(%2,%%ecx,4)\n\t"
00856                 "decl %%ecx\n\t"
00857                 "jnz 1b\n"
00858         "2:"
00859                 : "=m" (this->vector[bitset_base<n>::digits - 1]), "=&c" (__d0), "=&r" (__d1)
00860                 : "1" (bitset_base<n>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<n>::digits - 1]),
00861                   "i" (bitset_base<n>::valid_bits), "i" ((bitset_base<n>::digits - bitset_base<x>::digits) * 4)
00862                 : "memory", "cc"
00863             );
00864 #else
00865             this->vector[bitset_base<n>::digits - 1] ^= bitset_base<n>::valid_bits;
00866             unsigned int count = bitset_base<n>::digits - bitset_base<x>::digits;
00867             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
00868 #endif
00869           }
00870         }
00871       }
00872 
00873       // Handle other digits.
00874 #ifdef __i386__
00875       LIBECC_INLINE_ASMLOOP2(ASSIGNMENT_OPERATOR::id, OPERATOR, inverted1, inverted2,
00876           this->vector, expr.first.digits_ptr(), expr.second.digits_ptr(),
00877           ((bitset_base<n>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<n>::digits));
00878 #else
00879       unsigned int d;
00880       if (bitset_base<n>::digits < bitset_base<x>::digits)
00881         d = bitset_base<n>::digits - 1;
00882       else
00883         d = bitset_base<x>::digits - 1;
00884       for(;;)
00885       {
00886         ASSIGNMENT_OPERATOR::exec(this->vector[d],
00887             OPERATOR::exec(inverted1 ? ~*(expr.first.digits_ptr() + d) : expr.first.digit(d),
00888                            inverted2 ? ~*(expr.second.digits_ptr() + d) : expr.second.digit(d)));
00889         if (!d)
00890           break;
00891         --d;
00892       }
00893 #endif
00894 
00895       // Reset excess bits if needed.
00896       if (((!argument_has_leading_ones && x > n) ||
00897             (argument_has_leading_ones && bitset_base<n>::digits <= bitset_base<x>::digits)) &&
00898           bitset_base<n>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
00899         this->vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;
00900     }
00901 
00928 template<unsigned int n, bool inverted>
00929   inline bitset_invertible<n, !inverted> const&
00930   operator~(bitset_invertible<n, inverted> const& bits)
00931   {
00932     return *reinterpret_cast<bitset_invertible<n, !inverted> const*>(&bits);
00933   }
00934 
00935 //------------------------------------------------------------------------------------------------------------------
00936 // Iterators
00937 //
00938 
00948 classbitset_index {
00949 #if defined(__i386__) || defined(LIBECC_DOXYGEN)
00950   protected:
00951     int M_index;                        
00952 
00953   public:
00954     // Accessors.
00955     int get_index(void) const;
00956 
00957 #else
00958   protected:
00959     int M_digit;                        
00960     bitset_digit_t M_mask;              
00961 
00962   public:
00963     // Accessors.
00964     int get_digit(void) const;
00965     bitset_digit_t get_mask(void) const;
00966 
00967     // Used in polynomial.h
00968     int get_index(void) const;
00969 #endif
00970 
00971   public:
00972     // Equality Comparable.
00973     friend bool operator==(bitset_index const& i1, bitset_index const& i2);
00974     friend bool operator!=(bitset_index const& i1, bitset_index const& i2);
00975 
00976   protected:
00977     // Bidirectional.
00978     void left(void);
00979     void right(void);
00980 
00981     // Random access.
00982     void left(int n);
00983     void right(int n);
00984     friend int subtract(bitset_index const& i1, bitset_index const& i2);
00985 
00986   protected:
00987     // Constructors.
00988     bitset_index(void);
00989     bitset_index(bitset_index const& index);
00990     bitset_index(int bit);
00991 
00992   public:
00993     friend std::ostream& operator<<(std::ostream& os, bitset_index const& i);
00994 };
00995 
00996 #if defined(__i386__) || defined(LIBECC_DOXYGEN)
00997 
01001 inline int
01002 bitset_index::get_index(void) const
01003 {
01004   return M_index;
01005 }
01006 
01007 #else // !defined(__i386__)
01008 
01009 // Accessor for the current digit index.
01010 inline int
01011 bitset_index::get_digit(void) const
01012 {
01013   return M_digit;
01014 }
01015 
01016 // Accessor for the current digit mask.
01017 inline bitset_digit_t
01018 bitset_index::get_mask(void) const
01019 { 
01020   return M_mask;
01021 }
01022 
01023 #include <strings.h>   // Needed for ffsl.
01024 inline int
01025 bitset_index::get_index(void) const
01026 {
01027   return M_digit * bitset_digit_bits + ::ffsl(M_mask) - 1;
01028 }
01029 
01030 #endif // !defined(__i386__)
01031 
01035 inline bool
01036 operator==(bitset_index const& i1, bitset_index const& i2)
01037 {
01038 #ifdef __i386__
01039   return (i1.M_index == i2.M_index);
01040 #else
01041   return (i1.M_digit == i2.M_digit && i1.M_mask == i2.M_mask);
01042 #endif
01043 }
01044 
01048 inline bool
01049 operator!=(bitset_index const& i1, bitset_index const& i2)
01050 {
01051 #ifdef __i386__
01052   return (i1.M_index != i2.M_index);
01053 #else
01054   return (i1.M_digit != i2.M_digit || i1.M_mask != i2.M_mask);
01055 #endif
01056 }
01057 
01061 inline
01062 bitset_index::bitset_index(void)
01063 {
01064 }
01065 
01069 inline
01070 bitset_index::bitset_index(bitset_index const& index) :
01071 #ifdef __i386__
01072     M_index(index.M_index)
01073 #else
01074     M_digit(index.M_digit), M_mask(index.M_mask)
01075 #endif
01076 { 
01077 }
01078 
01085 inline
01086 bitset_index::bitset_index(int bit) :
01087 #ifdef __i386__
01088     M_index(bit)
01089 #else
01090     // If bit == -1 then M_digit should become -1 and M_mask 0x80000000.
01091     M_digit(bit >> bitset_digit_bits_log2),
01092     M_mask(static_cast<bitset_digit_t>(1) << ((unsigned int)bit & (bitset_digit_bits - 1)))
01093 #endif
01094 {
01095 }
01096 
01100 inline void
01101 bitset_index::left(void)
01102 {
01103 #ifdef __i386__
01104   ++M_index;
01105 #else
01106   if ((M_mask <<= 1) == 0)
01107   {
01108     ++M_digit;
01109     M_mask = 1;
01110   }
01111 #endif
01112 }
01113 
01117 inline void
01118 bitset_index::right(void)
01119 {
01120 #ifdef __i386__
01121   --M_index;
01122 #else
01123   if ((M_mask >>= 1) == 0)
01124   {
01125     --M_digit;
01126     M_mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
01127   }
01128 #endif
01129 }
01130 
01134 inline void
01135 bitset_index::left(int n)
01136 {
01137 #ifdef __i386__
01138   M_index += n;
01139 #else
01140   int const digit_shift = n >> bitset_digit_bits_log2;
01141   int const mask_shift = n & (bitset_digit_bits - 1);
01142   M_digit += digit_shift;
01143   if (mask_shift)
01144   {
01145     bitset_digit_t new_mask = M_mask << mask_shift;
01146     if (new_mask == 0)
01147     {
01148       ++M_digit;
01149       new_mask = M_mask >> (bitset_digit_bits - mask_shift);
01150     }
01151     M_mask = new_mask;
01152   }
01153 #endif
01154 }
01155 
01159 inline void
01160 bitset_index::right(int n)
01161 {
01162 #ifdef __i386__
01163   M_index -= n;
01164 #else
01165   int const digit_shift = n >> bitset_digit_bits_log2;
01166   int const mask_shift = n & (bitset_digit_bits - 1);
01167   M_digit -= digit_shift;
01168   if (mask_shift)
01169   {
01170     bitset_digit_t new_mask = M_mask >> mask_shift;
01171     if (new_mask == 0)
01172     {
01173       --M_digit;
01174       new_mask = M_mask << (bitset_digit_bits - mask_shift);
01175     }
01176     M_mask = new_mask;
01177   }
01178 #endif
01179 }
01180 
01181 enum {
01182   forwards_iterating,
01183   backwards_iterating
01184 };
01185 
01186 // Forward declarations.
01187 template<int DIRECTION> classbitset_index_iterator;
01188 template<int DIRECTION> bool operator<(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
01189 template<int DIRECTION> bool operator>(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
01190 template<int DIRECTION> bool operator<=(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
01191 template<int DIRECTION> bool operator>=(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
01192 
01201 template<int DIRECTION>
01202   classbitset_index_iterator : public bitset_index {
01203     public:
01204       // LessThan Comparable.
01205       friend bool operator< <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01206       friend bool operator> <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01207       friend bool operator<= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01208       friend bool operator>= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01209 
01210     public:
01211       // Bidirectional.
01212       void increment(void);
01213       void decrement(void);
01214 
01215       // Random access.
01216       void increment(int n);
01217       void decrement(int n);
01218 
01219       friend int operator-(bitset_index const& i1, bitset_index const& i2);
01220 
01221     public:
01222       // Constructors.
01223       bitset_index_iterator(void);
01224       bitset_index_iterator(bitset_index_iterator const& index);
01225       bitset_index_iterator(int bit);
01226   };
01227 
01231 template<int DIRECTION>
01232   inline
01233   bitset_index_iterator<DIRECTION>::bitset_index_iterator(void)
01234   {
01235   }
01236 
01240 template<int DIRECTION>
01241   inline
01242   bitset_index_iterator<DIRECTION>::bitset_index_iterator(bitset_index_iterator<DIRECTION> const& index) :
01243       bitset_index(index)
01244   { 
01245   }
01246 
01253 template<int DIRECTION>
01254   inline
01255   bitset_index_iterator<DIRECTION>::bitset_index_iterator(int bit) : bitset_index(bit)
01256   {
01257   }
01258 
01262 template<int DIRECTION>
01263   inline bool
01264   operator<(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01265   {
01266 #ifdef __i386__
01267     if (DIRECTION == forwards_iterating)
01268       return (i1.M_index < i2.M_index);
01269     else
01270       return (i1.M_index > i2.M_index);
01271 #else
01272     if (DIRECTION == forwards_iterating)
01273       return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
01274     else
01275       return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
01276 #endif
01277   }
01278 
01282 template<int DIRECTION>
01283   inline bool
01284   operator>(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01285   {
01286 #ifdef __i386__
01287     if (DIRECTION == forwards_iterating)
01288       return (i1.M_index > i2.M_index);
01289     else
01290       return (i1.M_index < i2.M_index);
01291 #else
01292     if (DIRECTION == forwards_iterating)
01293       return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
01294     else
01295       return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
01296 #endif
01297   }
01298 
01302 template<int DIRECTION>
01303   inline bool
01304   operator<=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01305   {
01306 #ifdef __i386__
01307     if (DIRECTION == forwards_iterating)
01308       return (i1.M_index <= i2.M_index);
01309     else
01310       return (i1.M_index >= i2.M_index);
01311 #else
01312     if (DIRECTION == forwards_iterating)
01313       return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
01314     else
01315       return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
01316 #endif
01317   }
01318 
01322 template<int DIRECTION>
01323   inline bool
01324   operator>=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01325   {
01326 #ifdef __i386__
01327     if (DIRECTION == forwards_iterating)
01328       return (i1.M_index >= i2.M_index);
01329     else
01330       return (i1.M_index <= i2.M_index);
01331 #else
01332     if (DIRECTION == forwards_iterating)
01333       return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
01334     else
01335       return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
01336 #endif
01337   }
01338 
01342 template<int DIRECTION>
01343   inline void
01344   bitset_index_iterator<DIRECTION>::increment(void)
01345   {
01346     if (DIRECTION == forwards_iterating)
01347       left();
01348     else
01349       right();
01350   }
01351 
01355 template<int DIRECTION>
01356   inline void
01357   bitset_index_iterator<DIRECTION>::decrement(void)
01358   {
01359     if (DIRECTION == forwards_iterating)
01360       right();
01361     else
01362       left();
01363   }
01364 
01368 template<int DIRECTION>
01369   inline void
01370   bitset_index_iterator<DIRECTION>::increment(int n)
01371   {
01372     if (DIRECTION == forwards_iterating)
01373       left(n);
01374     else
01375       right(n);
01376   }
01377 
01381 template<int DIRECTION>
01382   inline void
01383   bitset_index_iterator<DIRECTION>::decrement(int n)
01384   {
01385     if (DIRECTION == forwards_iterating)
01386       right(n);
01387     else
01388       left(n);
01389   }
01390 
01391 template<int DIRECTION>
01392   inline int
01393   operator-(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01394   {
01395     return (DIRECTION == forwards_iterating) ? subtract(i1, i2) : subtract(i2, i1);
01396   }
01397 
01398 // Forward declarations.
01399 template<unsigned int n, int DIRECTION> classbitset_iterator;
01400 template<unsigned int n, int DIRECTION> bitset_iterator<n, DIRECTION> operator+(bitset_iterator<n, DIRECTION> const&, int);
01401 template<unsigned int n, int DIRECTION> bitset_iterator<n, DIRECTION> operator+(int, bitset_iterator<n, DIRECTION> const&);
01402 template<unsigned int n, int DIRECTION> bitset_iterator<n, DIRECTION> operator-(bitset_iterator<n, DIRECTION> const&, int);
01403 template<unsigned int n, int DIRECTION> bitset_iterator<n, DIRECTION> operator-(int, bitset_iterator<n, DIRECTION> const&);
01404 
01414 template<unsigned int n, int DIRECTION>
01415   classbitset_iterator : public bitset_index_iterator<DIRECTION>,
01416                           public std::iterator<std::random_access_iterator_tag, bitset_digit_t,
01417                                                int, bitset_digit_t*, bitset_digit_t&> {
01418     protected:
01419       bitset_invertible<n, false> const* M_bitset_ptr;
01420     public:
01421       // Default Constructible
01422       bitset_iterator(void);
01423 
01424       // Assignable
01425       bitset_iterator(bitset_iterator const& iter);
01426       bitset_iterator& operator=(bitset_iterator const& iter);
01427       bitset_iterator& operator=(bitset_index_iterator<DIRECTION> const& index);
01428 
01429       // Dereferencable
01430       bitset_digit_t operator*() const;
01431 
01432       // Bi-directional iterator
01433       //
01434       bitset_iterator& operator++();
01435       bitset_iterator operator++(int);
01436       bitset_iterator& operator--();
01437       bitset_iterator operator--(int);
01438 
01439       // Random Access Iterator
01440       //
01441       bitset_iterator& operator+=(int n);
01442       friend bitset_iterator operator+ <>(bitset_iterator const& i, int n);
01443       friend bitset_iterator operator+ <>(int n, bitset_iterator const& i);
01444       bitset_iterator& operator-=(int n);
01445       friend bitset_iterator operator- <>(bitset_iterator const& i, int n);
01446       friend bitset_iterator operator- <>(int n, bitset_iterator const& i);
01447       bitset_digit_t operator[](int n) const;
01448 
01449       // Special
01450       //
01451       bitset_iterator(bitset_invertible<n, false> const* bitset_ptr, int bit);
01452       void find1(void);
01453 
01454 #ifndef __i386__
01455     private:
01456       void find1_forward(void);
01457       void find1_backward(void);
01458 #endif
01459   };
01460 
01461 #ifndef __i386__
01462 template<unsigned int n, int DIRECTION>
01463   void
01464   bitset_iterator<n, DIRECTION>::find1_forward(void)
01465   {
01466     if (this->M_digit < (int)bitset_base<n>::digits - 1 || (this->M_mask & bitset_base<n>::valid_bits))
01467     {
01468       register bitset_digit_t mask = this->M_mask;
01469       while(!(M_bitset_ptr->digit(this->M_digit) & mask)) 
01470       {
01471         if ((mask <<= 1))
01472           continue;
01473         mask = 1;
01474         while(++(this->M_digit) < (int)bitset_base<n>::digits)
01475           if (M_bitset_ptr->digit(this->M_digit))
01476             break;
01477         if (this->M_digit == (int)bitset_base<n>::digits)
01478         {
01479           this->M_digit = (n >> bitset_digit_bits_log2);
01480           mask = static_cast<bitset_digit_t>(1) << (n & (bitset_digit_bits - 1));
01481           break;
01482         }
01483       }
01484       this->M_mask = mask;
01485     }
01486   }
01487 
01488 template<unsigned int n, int DIRECTION>
01489   void
01490   bitset_iterator<n, DIRECTION>::find1_backward(void)
01491   {
01492     LibEccDout(dc::bitsetfind1, "Entering find1_backward with: " << 
01493         libcwd::cwprint_using(*M_bitset_ptr, &bitset_invertible<n, false>::base2_print_on));
01494     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01495     if (this->M_digit >= 0)
01496     {
01497       register bitset_digit_t mask = this->M_mask;
01498       if (!(M_bitset_ptr->digit(this->M_digit) & (mask | (mask - 1))))
01499       {
01500         mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
01501         do
01502         {
01503           if (--(this->M_digit) < 0)
01504           {
01505             this->M_mask = mask;
01506             return;
01507           }
01508         }
01509         while (!M_bitset_ptr->digit(this->M_digit));
01510       }
01511       while(!(M_bitset_ptr->digit(this->M_digit) & mask)) 
01512         mask >>= 1;
01513       this->M_mask = mask;
01514     }
01515     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01516   }
01517 #endif
01518 
01522 template<unsigned int n, int DIRECTION>
01523   inline void
01524   bitset_iterator<n, DIRECTION>::find1(void)
01525   {
01526     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01527     LibEccDout(dc::bitsetfind1, "Entering find1 with: " << 
01528         libcwd::cwprint_using(*M_bitset_ptr, &bitset_invertible<n, false>::base2_print_on));
01529 #ifdef __i386__
01530     int bit_index, digit, ptr;
01531     if (DIRECTION == backwards_iterating)
01532     {
01533       __asm__ __volatile__ (
01534           // %eax: M_index (input) and work variable.
01535           // %ecx: bit_index (work variable).
01536           // %edi: &M_bitset_ptr->digit(M_index/32 - 1) (input) and ptr (work variable).
01537           // %2  : digit (work variable).
01538 
01539           // Make a copy of M_index into %ecx, last time we used M_index.
01540           "movl %%eax,%%ecx\n\t"
01541           // Set %eax to its correct value by deviding it by 32.
01542           "sarl $5,%%eax\n\t"
01543           // Set bit_index to its correct value by taking the modulo 32 of it.
01544           "andl $31,%%ecx\n\t"
01545           // If M_index is -1, do nothing.
01546           "js 1f\n\t"
01547           // Copy the most significant digit, the digit with the
01548           // bit at which we will start the search, into %2.
01549           // digit = M_bitset_ptr->digit(%eax)
01550           "movl 4(%%edi),%2\n\t"
01551           // Shift this digit left until the first bit comes at position 31.
01552           // bit_index = 31 - bit_index
01553           "xorl $31,%%ecx\n\t"
01554           // digit <<= bit_index
01555           "shll %%cl,%2\n\t"
01556           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01557           // This is not needed for the athlon for that reason, but we also need this orl
01558           // for the case that %cl equals zero in which case the ZF is cleared!
01559           "orl %2,%2\n\t"                       
01560           // If there is no bit set in the current digit, goto digit_search.
01561           "jz 5f\n\t"
01562           // Search for the (next) most significant bit set.
01563           // This is slow on i[345]86: 11 + 2*n cycles; only generates 2 uops on a pentium though.
01564           "bsrl %2,%2\n\t"
01565           // Correct M_index to point to this bit.
01566           // %eax <<= 5
01567           "sall $5,%%eax\n\t"
01568           // %2 -= bit_index
01569           "subl %%ecx,%2\n\t"
01570           // M_index = %eax + %2
01571           "addl %2,%%eax\n\t"
01572           // Done.
01573           // goto exit
01574           "jmp 1f\n\t"
01575           ".align 16\n"
01576        "7:\n\t"                         // Main loop.
01577           "movl (%%edi),%2\n\t"
01578           "subl $4,%%edi\n\t"
01579           "testl %2,%2\n\t"
01580           "jnz 6f\n\t"
01581        "5:\n\t"                         // digit_search:
01582           "decl %%eax\n\t"
01583           // Repeat main loop.
01584           "jns 7b\n"    
01585        "4:\n\t"                         // reached_end:
01586           // No set bit found at all.  Set M_index to -1.
01587           "movl $-1,%%eax\n\t"
01588           // Done.
01589           // goto exit
01590           "jmp 1f\n"
01591           // Search for the most significant bit set in this digit.
01592        "6:\n\t"
01593           "bsrl %2,%2\n\t"
01594           // Correct M_index to point to this bit.
01595           "sall $5,%%eax\n\t"
01596           "addl %2,%%eax\n"
01597        "1:"                             // exit:
01598 
01599           : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01600           : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() - 1 + (this->M_index >> 5))
01601           : "cc"
01602       );
01603     }
01604     else
01605     {
01606       __asm__ __volatile__ (
01607           // %eax: M_index (input) and work variable.
01608           // %ecx: bit_index (work variable).
01609           // %edi: &M_bitset_ptr->digit(M_index/32 + 1) (input) and ptr (work variable).
01610           // %2  : digit (work variable).
01611 
01612           // if (M_index >= n) then goto exit
01613           "cmpl %6,%%eax\n\t"
01614           "jge 1f\n\t"
01615           // Make a copy of M_index into %ecx, last time we used M_index.
01616           "movl %%eax,%%ecx\n\t"
01617           // Set %eax to its correct value by deviding it by 32.
01618           "sarl $5,%%eax\n\t"
01619           // Set bit_index to its correct value by taking the modulo 32 of it.
01620           "andl $31,%%ecx\n\t"
01621           // Copy the least significant digit, the digit with the
01622           // bit at which we will start the search, into %2.
01623           // digit = M_bitset_ptr->digit(%eax)
01624           "movl -4(%%edi),%2\n\t"
01625           // Shift this digit right until the first bit comes at position 0.
01626           // digit >>= bit_index
01627           "shrl %%cl,%2\n\t"
01628           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01629           // This is not needed for the athlon for that reason, but we also need this orl
01630           // for the case that %cl equals zero in which case the ZF is cleared!
01631           "orl %2,%2\n\t"                       
01632           // If there is no bit set in the current digit, goto digit_search.
01633           "jz 5f\n\t"
01634           // Search for the (next) most significant bit set.
01635           // This is slow on i[345]86: 11 + 2*n cycles; only generates 2 uops on a pentium though.
01636           "bsfl %2,%2\n\t"
01637           // Correct M_index to point to this bit.
01638           // %eax <<= 5
01639           "sall $5,%%eax\n\t"
01640           // %2 -= bit_index
01641           "addl %%ecx,%2\n\t"
01642           // M_index = %eax + %2
01643           "addl %2,%%eax\n\t"
01644           // Done.
01645           // goto exit
01646           "jmp 1f\n\t"
01647           ".align 16\n"
01648        "7:\n\t"                         // Main loop.
01649           "movl (%%edi),%2\n\t"
01650           "addl $4,%%edi\n\t"
01651           "testl %2,%2\n\t"
01652           "jnz 6f\n\t"
01653        "5:\n\t"                         // digit_search:
01654           "incl %%eax\n\t"
01655           "cmpl %7, %%eax\n\t"
01656           // Repeat main loop.
01657           "jnz 7b\n"            
01658        "4:\n\t"                         // reached_end:
01659           // No set bit found at all.  Set M_index to n.
01660           "movl %6,%%eax\n\t"
01661           // Done.
01662           // goto exit
01663           "jmp 1f\n"
01664           // Search for the least significant bit set in this digit.
01665        "6:\n\t"
01666           "bsfl %2,%2\n\t"
01667           // Correct M_index to point to this bit.
01668           "sall $5,%%eax\n\t"
01669           "addl %2,%%eax\n"
01670        "1:"                             // exit:
01671 
01672           : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01673           : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() + 1 + (this->M_index >> 5)),
01674             "i" (n), "i" (bitset_base<n>::digits)
01675           : "cc"
01676       );
01677     }
01678 #else
01679     if (DIRECTION == forwards_iterating)
01680       find1_forward();
01681     else
01682       find1_backward();
01683 #endif
01684     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01685     return;
01686   }
01687 
01688 
01692 template<unsigned int n, int DIRECTION>
01693   inline
01694   bitset_iterator<n, DIRECTION>::bitset_iterator(void)
01695   {
01696   }
01697 
01701 template<unsigned int n, int DIRECTION>
01702   inline
01703   bitset_iterator<n, DIRECTION>::bitset_iterator(bitset_invertible<n, false> const* bitset_ptr, int bit) :
01704       bitset_index_iterator<DIRECTION>(bit), M_bitset_ptr(bitset_ptr)
01705   {
01706   }
01707 
01711 template<unsigned int n, int DIRECTION>
01712   inline
01713   bitset_iterator<n, DIRECTION>::bitset_iterator(bitset_iterator const& iter) :
01714       bitset_index_iterator<DIRECTION>(iter), M_bitset_ptr(iter.M_bitset_ptr)
01715   {
01716   }
01717 
01721 template<unsigned int n, int DIRECTION>
01722   inline bitset_iterator<n, DIRECTION>&
01723   bitset_iterator<n, DIRECTION>::operator=(bitset_iterator<n, DIRECTION> const& iter)
01724   {
01725 #ifdef __i386__
01726     this->M_index = iter.M_index;
01727 #else
01728     this->M_digit = iter.M_digit;
01729     this->M_mask = iter.M_mask;
01730 #endif
01731     M_bitset_ptr = iter.M_bitset_ptr;
01732     return *this;
01733   }
01734 
01735 template<unsigned int n, int DIRECTION>
01736   inline bitset_iterator<n, DIRECTION>&
01737   bitset_iterator<n, DIRECTION>::operator=(bitset_index_iterator<DIRECTION> const& index)
01738   {
01739 #ifdef __i386__
01740     this->M_index = index.get_index();
01741 #else
01742     this->M_digit = index.get_digit();
01743     this->M_mask = index.get_mask();
01744 #endif
01745     return *this;
01746   }
01747 
01751 template<unsigned int n, int DIRECTION>
01752   inline bitset_iterator<n, DIRECTION>&
01753   bitset_iterator<n, DIRECTION>::operator++()
01754   {
01755     this->increment();
01756     return *this;
01757   }
01758 
01762 template<unsigned int n, int DIRECTION>
01763   inline bitset_iterator<n, DIRECTION>
01764   bitset_iterator<n, DIRECTION>::operator++(int)
01765   {
01766     bitset_iterator prev(*this);
01767     this->increment();
01768     return prev;
01769   }
01770 
01774 template<unsigned int n, int DIRECTION>
01775   inline bitset_iterator<n, DIRECTION>&
01776   bitset_iterator<n, DIRECTION>::operator--()
01777   {
01778     this->decrement();
01779     return *this;
01780   }
01781 
01785 template<unsigned int n, int DIRECTION>
01786   inline bitset_iterator<n, DIRECTION>
01787   bitset_iterator<n, DIRECTION>::operator--(int)
01788   {
01789     bitset_iterator prev(*this);
01790     this->decrement();
01791     return prev;
01792   }
01793 
01800 template<unsigned int n, int DIRECTION>
01801   inline bitset_digit_t
01802   bitset_iterator<n, DIRECTION>::operator*() const
01803  {
01804 #ifdef __i386__
01805     register unsigned int digit = this->M_index;
01806     register bitset_digit_t mask = 1;
01807     register unsigned short shift = this->M_index & (ECC_BITS - 1);
01808     digit >>= bitset_digit_bits_log2;
01809     mask <<= shift;
01810     return (M_bitset_ptr->digit(digit) & mask);
01811 #else
01812     return (M_bitset_ptr->digit(this->M_digit) & this->M_mask);
01813 #endif
01814   }
01815 
01819 template<unsigned int n, int DIRECTION>
01820   inline bitset_iterator<n, DIRECTION>&
01821   bitset_iterator<n, DIRECTION>::operator+=(int d)
01822   {
01823     this->increment(d);
01824     return *this;
01825   }
01826 
01830 template<unsigned int n, int DIRECTION>
01831   inline bitset_iterator<n, DIRECTION>&
01832   bitset_iterator<n, DIRECTION>::operator-=(int d)
01833   {
01834     this->decrement(d);
01835     return *this;
01836   }
01837 
01841 template<unsigned int n, int DIRECTION>
01842   inline bitset_iterator<n, DIRECTION>
01843   operator+(bitset_iterator<n, DIRECTION> const& i, int d)
01844   {
01845     bitset_iterator<n, DIRECTION> result(i);
01846     return result += d;
01847   }
01848 
01852 template<unsigned int n, int DIRECTION>
01853   inline bitset_iterator<n, DIRECTION>
01854   operator+(int d, bitset_iterator<n, DIRECTION> const& i)
01855   {
01856     bitset_iterator<n, DIRECTION> result(i);
01857     return result += d;
01858   }
01859 
01863 template<unsigned int n, int DIRECTION>
01864   inline bitset_iterator<n, DIRECTION>
01865   operator-(bitset_iterator<n, DIRECTION> const& i, int d)
01866   {
01867     bitset_iterator<n, DIRECTION> result(i);
01868     return result -= d;
01869   }
01870 
01874 template<unsigned int n, int DIRECTION>
01875   inline bitset_iterator<n, DIRECTION>
01876   operator-(int d, bitset_iterator<n, DIRECTION> const& i)
01877   {
01878     bitset_iterator<n, DIRECTION> result(i);
01879     return result -= d;
01880   }
01881 
01885 template<unsigned int n, int DIRECTION>
01886   inline bitset_digit_t
01887   bitset_iterator<n, DIRECTION>::operator[](int d) const
01888  {
01889     return *(*this + d);
01890   }
01891 
01892 //--------------------------------------------------------------------------------------------------------------------------
01899 template<unsigned int n>
01900   classbitset : public bitset_invertible<n, false> {
01901     public:
01902       // Constructors.
01903       bitset(void);
01904       bitset(std::string const&);
01905       explicit bitset(bitset_digit_t low_bits);
01906       // This definition must be here, inside the template class declaration because
01907       // otherwise the compiler (2.95 - 3.1) barfs.
01913       bitset(bitset_digit_t const (&v)[bitset_base<n>::digits])
01914       {
01915 #if ECC_DEBUG
01916         assert( (v[bitset_base<n>::digits - 1] & ~bitset_base<n>::valid_bits) == 0 );
01917 #endif
01918         std::memcpy(this->vector, v, sizeof(this->vector));
01919       }
01920 
01921       // Copy constructors.
01922       template<unsigned int m, bool inverted>
01923         bitset(bitset_invertible<m, inverted> const&);
01924       template<unsigned int m, bool i1, bool i2, typename OP>
01925         bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr);
01926 
01927       // Assignment operators.
01928       bitset& operator=(bitset const&);
01929       template<typename Expression>
01930         bitset& operator=(Expression const&);
01931 
01932       // Perform AND, OR, XOR operations
01933       template<typename Expression>
01934         bitset& operator&=(Expression const&);
01935       template<typename Expression>
01936         bitset& operator|=(Expression const&);
01937       template<typename Expression>
01938         bitset& operator^=(Expression const&);
01939 
01940     public:
01941       // Shift bitset left or right and perform operation with result.
01942       template<unsigned int shift, class DIRECTION, class OPERATION>
01943         void shift_op(bitset& result) const;
01944 
01945       // Slower functions for shifting an arbitrary distance.
01946       bitset& operator<<=(unsigned int shift);
01947       bitset& operator>>=(unsigned int shift);
01948 
01949       // Rotate left or right
01950       template<unsigned int shift, class DIRECTION>                     // Return a copy rotated `shift' bits in `DIRECTION'.
01951         void rotate(bitset& result) const;
01952 
01953       // Single bit operations
01954       bool test(size_t n) const;                                        // Return true if bit `n' is set.
01955       bool odd(void) const;                                             // Return true if the vector has an odd number of bits set.
01956       void set(size_t n);                                               // Set bit `n'.
01957       void clear(size_t n);                                             // Clear bit `n'.
01958       void flip(size_t n);                                              // Toggle bit `n'.
01959 
01960       // Single bit operations using iterators.
01961       bool test(bitset_index const& index) const;                       // Return true if bit refered to by `index' is set.
01962       void set(bitset_index const& index);                              // Set bit refered to by `index'.
01963       void clear(bitset_index const& index);                            // Clear bit refered to by `index'.
01964       void flip(bitset_index const& index);                             // Toggle bit refered to by `index'.
01965 
01966       // Single bit operations at a constant position
01967       template<unsigned int pos>
01968         bool test(void) const;                                          // Return true if bit `pos' is set.
01969       template<unsigned int pos>
01970         void set(void);                                                 // Set bit `pos'.
01971       template<unsigned int pos>
01972         void clear(void);                                               // Clear bit `pos'.
01973       template<unsigned int pos>
01974         void flip(void);                                                // Toggle bit `pos'.
01975 
01976       // Other functions
01977       bitset& reset(void);
01978       void setall(void);
01979       bool any(void) const;
01980 
01981     public:
01982       // Iterator stuff.
01984       typedef bitset_iterator<n, forwards_iterating> const_iterator;
01986       typedef bitset_iterator<n, backwards_iterating> const_reverse_iterator;
01988       const_iterator begin(void) const{ return const_iterator(this, 0); }
01990       const_iterator end(void) const{ return const_iterator(this, n); }
01992       const_reverse_iterator rbegin(void) const{ return const_reverse_iterator(this, n - 1); }
01994       const_reverse_iterator rend(void) const{ return const_reverse_iterator(this, -1); }
01995 
01996       template<unsigned int m>
01997         void xor_with_zero_padded(bitset<m> const& bitset, int lsb, int msb, int shift);
01998   };
01999 
02016 template<unsigned int n>
02017   template<unsigned int m>
02018 #if defined(__i386__) && defined(HAVE_NASM)
02019   inline
02020 #endif
02021   void
02022   bitset<n>::xor_with_zero_padded(bitset<m> const& bitset, int lsb, int msb, int shift)
02023   {
02024 #if defined(__i386__) && defined(HAVE_NASM)
02025     libecc_shift_xorassign(this->vector, bitset.digits_ptr(), lsb, msb, shift);
02026 #else
02027     int digit1 = lsb >> bitset_digit_bits_log2;
02028     int digit2 = msb >> bitset_digit_bits_log2;
02029     bitset_digit_t d1 = 0;
02030     // We can't use bitset.digit() because we need access to negative indexes.
02031     bitset_digit_t const* const digits_ptr = bitset.digits_ptr();
02032     if (shift < 0)
02033     {
02034       int bitshift = (-shift) & (bitset_digit_bits - 1);
02035       int digitshift = (-shift) >> bitset_digit_bits_log2;
02036       if (bitshift == 0)
02037       {
02038         for (int digit = digit2; digit >= digit1; --digit)
02039         {
02040           bitset_digit_t d2 = digits_ptr[digit];
02041           this->vector[digit - digitshift] ^= d2;
02042         }
02043       }
02044       else
02045       {
02046         for (int digit = digit2; digit >= digit1; --digit)
02047         {
02048           bitset_digit_t d2 = digits_ptr[digit];
02049           this->vector[digit - digitshift] ^= (d2 >> bitshift) | (d1 << (bitset_digit_bits - bitshift));
02050           d1 = d2;
02051         }
02052         this->vector[digit1 - 1 - digitshift] ^= (d1 << (bitset_digit_bits - bitshift));
02053       }
02054     }
02055     else if (shift > 0)
02056     {
02057       int bitshift = shift & (bitset_digit_bits - 1);
02058       int digitshift = shift >> bitset_digit_bits_log2;
02059       if (bitshift == 0)
02060       {
02061         for (int digit = digit1; digit <= digit2; ++digit)
02062         {
02063           bitset_digit_t d2 = digits_ptr[digit];
02064           this->vector[digit + digitshift] ^= d2;
02065           d1 = d2;
02066         }
02067       }
02068       else
02069       {
02070         for (int digit = digit1; digit <= digit2; ++digit)
02071         {
02072           bitset_digit_t d2 = digits_ptr[digit];
02073           this->vector[digit + digitshift] ^= (d2 << bitshift) | (d1 >> (bitset_digit_bits - bitshift));
02074           d1 = d2;
02075         }
02076         this->vector[digit2 + 1 + digitshift] ^= (d1 >> (bitset_digit_bits - bitshift));
02077       }
02078     }
02079     else
02080     {
02081       for (int digit = digit1; digit <= digit2; ++digit)
02082         this->vector[digit] ^= digits_ptr[digit];
02083     }
02084 #endif
02085   }
02086 
02090 template<unsigned int n>
02091   inline
02092   bitset<n>::bitset(void)
02093   {
02094   }
02095 
02101 template<unsigned int n>
02102   inline
02103   bitset<n>::bitset(bitset_digit_t low_bits)
02104   {
02105 #if ECC_DEBUG
02106     assert( bitset_base<n>::digits > 1 || (low_bits & ~bitset_base<n>::valid_bits) == 0 );
02107 #endif
02108     std::memset(this->vector, 0, sizeof(this->vector));
02109     this->vector[0] = low_bits;
02110   }
02111 
02115 template<unsigned int n>
02116   void
02117   bitset<n>::setall(void)
02118   {
02119     this->vector[bitset_base<n>::digits - 1] = bitset_base<n>::valid_bits;
02120     if (bitset_base<n>::digits > 1)
02121     {
02122       int d = bitset_base<n>::digits - 2;
02123       do { this->vector[d] = ~static_cast<bitset_digit_t>(0); } while(--d >= 0);
02124     }
02125   }
02126 
02151 template<unsigned int n>
02152   template<typename Expression>
02153     inline
02154     bitset<n>& bitset<n>::operator=(Expression const& expr)
02155     {
02156       this->assign(expr, Operator::bitsetAssign());
02157       return *this;
02158     }
02159 
02160 // Special case, need to define this or else we'd get a default assignment operator.
02161 template<unsigned int n>
02162   inline bitset<n>&
02163   bitset<n>::operator=(bitset const& expr)
02164   {
02165     this->assign(expr, Operator::bitsetAssign());
02166     return *this;
02167   }
02168 
02185 template<unsigned int n>
02186   template<unsigned int m, bool inverted>
02187     inline bitset<n>::bitset(bitset_invertible<m, inverted> const& bits) : bitset_invertible<n, false>(bits)
02188     {
02189     }
02190 
02196 template<unsigned int n>
02197   template<unsigned int m, bool i1, bool i2, typename OP>
02198     inline bitset<n>::bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr) : bitset_invertible<n, false>(expr)
02199     {
02200     }
02201 
02213 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02214   bool operator==(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02215   {
02216     unsigned int d;
02217     if (bitset_invertible<n1, inverted1>::digits > bitset_invertible<n2, inverted2>::digits)
02218     {
02219       d = bitset_base<n1>::digits - 1;
02220       do
02221       {
02222         if (bits1.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02223           return false;
02224       }
02225       while (--d != bitset_base<n2>::digits - 1);
02226     }
02227     if (bitset_base<n2>::digits > bitset_base<n1>::digits)
02228     {
02229       d = bitset_base<n2>::digits - 1;
02230       do
02231       {
02232         if (bits2.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02233           return false;
02234       }
02235       while (--d != bitset_base<n1>::digits - 1);
02236     }
02237     if (bitset_base<n1>::digits > 1 && bitset_base<n2>::digits > 1)
02238     {
02239       if (bitset_base<n1>::digits == bitset_base<n2>::digits)
02240         d = bitset_base<n1>::digits - 1;
02241       do
02242       {
02243         if (inverted1 == inverted2)
02244         {
02245           if (bits1.vector[d] != bits2.vector[d])
02246             return false;
02247         }
02248         else
02249         {
02250           if (bits1.vector[d] != ~(bits2.vector[d]))
02251             return false;
02252         }
02253       }
02254       while(--d != 0);
02255     }
02256     if (inverted1 != inverted2)
02257       return (bits1.vector[0] == ~(bits2.vector[0]));
02258     return (bits1.vector[0] == bits2.vector[0]);
02259   }
02260 
02266 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02267   inline bool
02268   operator!=(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02269   {
02270     return !(bits1 == bits2);
02271   }
02272 
02277 template<unsigned int n>
02278   template<typename Expression>
02279     inline bitset<n>&
02280     bitset<n>::operator&=(Expression const& expr)
02281     {
02282       this->assign(expr, Operator::bitsetANDAssign());
02283       return *this;
02284     }
02285 
02290 template<unsigned int n>
02291   template<typename Expression>
02292     inline bitset<n>&
02293     bitset<n>::operator|=(Expression const& expr)
02294     {
02295       this->assign(expr, Operator::bitsetORAssign());
02296       return *this;
02297     }
02298 
02303 template<unsigned int n>
02304   template<typename Expression>
02305     inline bitset<n>&
02306     bitset<n>::operator^=(Expression const& expr)
02307     {
02308       this->assign(expr, Operator::bitsetXORAssign());
02309       return *this;
02310     }
02311 
02316 template<unsigned int m, bool inverted1, bool inverted2>
02317   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>
02318   operator&(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02319     {
02320       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>(arg1, arg2);
02321     }
02322 
02327 template<unsigned int m, bool inverted1, bool inverted2>
02328   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>
02329   operator|(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02330     {
02331       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>(arg1, arg2);
02332     }
02333 
02338 template<unsigned int m, bool inverted1, bool inverted2>
02339   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>
02340   operator^(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02341     {
02342       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>(arg1, arg2);
02343     }
02344 
02348 structassign {
02349   static int const id = 1;
02350   static bool const __clear = true;
02351   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02352   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02353 };
02354 
02358 structexor {
02359   static int const id = 2;
02360   static bool const __clear = false;
02361   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02362   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02363 };
02364 
02365 #ifndef HIDE_FROM_DOXYGEN
02366 structrotate_phase1 {
02367   static int const id = 3;
02368   static bool const __clear = false;
02369   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02370   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02371 };
02372 
02373 structrotate_phase2 {
02374 public:
02375   static int const id = 4;
02376   static bool const __clear = false;
02377   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02378   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 |= digit2; }
02379 };
02380 #endif
02381 
02392 template<unsigned int n>
02393   template<unsigned int shift, class DIRECTION, class OPERATION>
02394     void
02395     bitset<n>::shift_op(bitset& result) const
02396    {
02397       LibEccDout(dc::bitsetshift, "Entering shift_op<" << shift << ", " << libcwd::type_info_of<DIRECTION>().demangled_name() <<
02398           ", " << type_info_of<OPERATION>().demangled_name() << '>');
02399       LibEccDout(dc::bitsetshift|flush_cf, "Input : " << cwprint_using(*this, &bitset<n>::base2_print_on));
02400       if (shift == 1)
02401       {
02402         // Specialization for shift == 1.
02403         // digit_shift = 0
02404         // bit_shift = 1
02405         // zeroed_digits = 0 (likely and if not - then assumed).
02406         // Here we scan in the opposite direction of when shift > 1.
02407         static unsigned int const initial = DIRECTION::__left ? 0 : bitset_base<n>::digits - 1;
02408         static unsigned int const count = bitset_base<n>::digits - ((DIRECTION::__left && bitset_base<n>::has_excess_bits) ? 1 : 0);
02409 #ifdef __i386__
02410         if (count)
02411         {
02412           bitset_digit_t const volatile* ptr1;
02413           bitset_digit_t volatile* ptr2;
02414           int c;
02415           if (DIRECTION::__left)
02416           {
02417             if (OPERATION::id == libecc::exor::id)
02418             {
02419               if (bitset_base<n>::has_excess_bits)
02420                 LIBECC_ASMSHIFTLEFT(
02421                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02422                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"),
02423                     LIBECC_ASMSHIFTLEFT_FINISH("xorl (%%edi),%%edx\n\t"));
02424               else
02425                 LIBECC_ASMSHIFTLEFT(
02426                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02427                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"), "");
02428             }
02429             else if (OPERATION::id == libecc::rotate_phase2::id)
02430             {
02431               if (bitset_base<n>::has_excess_bits)
02432                 LIBECC_ASMSHIFTLEFT(
02433                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02434               else
02435                 LIBECC_ASMSHIFTLEFT(
02436                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", "");
02437             }
02438             else
02439             {
02440               if (bitset_base<n>::has_excess_bits)
02441                 LIBECC_ASMSHIFTLEFT("", "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02442               else
02443                 LIBECC_ASMSHIFTLEFT("", "", "");
02444             }
02445           }
02446           else if (count > 1)
02447           {
02448             if (OPERATION::id == libecc::exor::id)
02449               LIBECC_ASMSHIFTRIGHT1(
02450                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02451                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP2_DESTINATION "," LIBECC_WORKREG),
02452                   LIBECC_PRESERVE_CF_CLOBBER);
02453             else if (OPERATION::id == libecc::rotate_phase2::id)
02454               LIBECC_ASMSHIFTRIGHT1(
02455                   LIBECC_RIGHT_PRESERVE_CF("orl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02456                   "",
02457                   LIBECC_PRESERVE_CF_CLOBBER);
02458             else
02459               LIBECC_ASMSHIFTRIGHT1(
02460                   "",
02461                   "",
02462                   LIBECC_CLOBBER);
02463           }
02464           else
02465           {
02466             if (OPERATION::id == libecc::exor::id)
02467               LIBECC_ASMSHIFTRIGHT0("xorl 4(%%edi), %%edx\n\t");
02468             else if (OPERATION::id == libecc::rotate_phase2::id)
02469               LIBECC_ASMSHIFTRIGHT0("orl 4(%%edi), %%edx\n\t");
02470             else
02471               LIBECC_ASMSHIFTRIGHT0("");
02472           }
02473         }
02474         else if (DIRECTION::__left && bitset_base<n>::has_excess_bits)
02475           OPERATION::op(result.vector[0], ((this->vector[0] << 1) & bitset_base<n>::valid_bits));
02476 #else
02477         static unsigned int complement_shift = bitset_digit_bits - 1;
02478         static bitset_digit_t const mask1 = DIRECTION::__left ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02479         static bitset_digit_t const mask2 = DIRECTION::__right ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02480         bitset_digit_t const* ptr1 = &this->vector[initial];
02481         bitset_digit_t* ptr2 = &result.vector[initial];
02482         bool carry;
02483         if (count)
02484         {
02485           bitset_digit_t digit = *ptr1;
02486           carry = (digit & mask1);
02487           if (DIRECTION::__left)
02488             digit <<= 1;
02489           else
02490             digit >>= 1;
02491           OPERATION::mixed_op(*ptr2, digit);
02492           for (int c = count - 1; c; --c)
02493           {
02494             ptr1 -= DIRECTION::direction;
02495             ptr2 -= DIRECTION::direction;
02496             digit = *ptr1;
02497             if (carry)
02498             {
02499               carry = (digit & mask1);
02500               if (DIRECTION::__left)
02501                 digit <<= 1;
02502               else
02503                 digit >>= 1;
02504               digit |= mask2;
02505             }
02506             else
02507             {
02508               carry = (digit & mask1);
02509               if (DIRECTION::__left)
02510                 digit <<= 1;
02511               else
02512                 digit >>= 1;
02513             }
02514             OPERATION::op(*ptr2, digit);
02515           }
02516         }
02517         if (DIRECTION::__left && bitset_base<n>::has_excess_bits)
02518         {
02519           bitset_digit_t digit;
02520           if (count)
02521             digit = ptr1[-DIRECTION::direction];
02522           else
02523             digit = *ptr1;
02524           digit <<= 1;
02525           if (count && carry)
02526             digit |= mask2;
02527           if (count)
02528             OPERATION::op(ptr2[-DIRECTION::direction], (digit & bitset_base<n>::valid_bits));
02529           else
02530             OPERATION::op(*ptr2, (digit & bitset_base<n>::valid_bits));
02531         }
02532 #endif
02533       }
02534       else
02535       {
02536         static unsigned int const digit_shift = shift / bitset_digit_bits;
02537         static unsigned int const bit_shift = shift % bitset_digit_bits;
02538 
02539         static unsigned int const zeroed_digits =
02540           DIRECTION::__left ? ((shift < n) ? digit_shift : bitset_base<n>::digits)
02541                             : ((bitset_digit_bits - bitset_base<n>::number_of_valid_bits + shift) / bitset_digit_bits);
02542 
02543         if (zeroed_digits < bitset_base<n>::digits)
02544         {
02545           static unsigned int const complement_shift = (bit_shift == 0) ? 0 : bitset_digit_bits - bit_shift;
02546           static unsigned int const initial_to = DIRECTION::__right ? 0 : bitset_base<n>::digits - 1;
02547           static unsigned int const initial_from = initial_to + DIRECTION::direction * digit_shift;
02548           static unsigned int const final_from = DIRECTION::__left ? 0 : bitset_base<n>::digits - 1;
02549 
02550           register bitset_digit_t digit = this->vector[initial_from];
02551           if (initial_from != final_from)
02552           {
02553             register bitset_digit_t next_digit;
02554             unsigned int to = initial_to;
02555             unsigned int from = initial_from + DIRECTION::direction;
02556             if (from != final_from)
02557               do
02558               {
02559                 next_digit = this->vector[from];
02560                 if (bit_shift != 0)
02561                 {
02562                   if (DIRECTION::direction == -1)
02563                     digit <<= bit_shift;
02564                   else
02565                     digit >>= bit_shift;
02566                   digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02567                 }
02568                 OPERATION::op(result.vector[to], digit);
02569                 digit = next_digit;
02570                 to += DIRECTION::direction;
02571                 from += DIRECTION::direction;
02572               }
02573               while (from != final_from);
02574             if (DIRECTION::__left || bit_shift < bitset_base<n>::number_of_valid_bits || bit_shift != 0)
02575               next_digit = this->vector[final_from];
02576             if (bit_shift != 0)
02577             {
02578               if (DIRECTION::direction == -1)
02579                 digit <<= bit_shift;
02580               else
02581                 digit >>= bit_shift;
02582               digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02583             }
02584             if (DIRECTION::__left || bit_shift < bitset_base<n>::number_of_valid_bits)
02585             {
02586               OPERATION::op(result.vector[final_from - DIRECTION::direction * (digit_shift + 1)], digit);
02587               digit = DIRECTION::shift_copy(next_digit, bit_shift);
02588             }
02589           }
02590           else
02591           {
02592             if (DIRECTION::direction == -1)
02593               digit <<= bit_shift;
02594             else
02595               digit >>= bit_shift;
02596           }
02597           static bool const have_mixed_digit = shift != 0 && (DIRECTION::__left ? shift : (n - shift)) % bitset_digit_bits != 0;
02598           static unsigned int const last_digit = (DIRECTION::__left ? shift : (n - 1 - shift)) / bitset_digit_bits;
02599           if (have_mixed_digit)
02600             OPERATION::mixed_op(result.vector[last_digit], digit);
02601           else
02602             OPERATION::op(result.vector[last_digit], digit);
02603           if (DIRECTION::__left && bitset_base<n>::has_excess_bits)
02604             result.vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;
02605         }
02606         if (OPERATION::__clear && zeroed_digits > 0)
02607         {
02608           static unsigned int const final_to = DIRECTION::__left ? 0 : bitset_base<n>::digits - 1;
02609           static unsigned int const initial_to = final_to - DIRECTION::direction * (zeroed_digits - 1);
02610           unsigned int to = initial_to;
02611           if (to != final_to)
02612             do
02613             {
02614               result.vector[to] = 0;
02615               to += DIRECTION::direction;
02616             }
02617             while(to != final_to);
02618           result.vector[to] = 0;
02619         }
02620       }
02621       LibEccDout(dc::bitsetshift|flush_cf, "Output: " << cwprint_using(result, &bitset<n>::base2_print_on));
02622     }
02623 
02627 template<unsigned int n>
02628   bitset<n>&
02629   bitset<n>::operator<<=(unsigned int shift)
02630   {
02631     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02632     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02633     int digit1 = bitset_base<n>::digits - digit_shift - 2;
02634     bitset_digit_t d0 = (digit1 >= -1) ? this->vector[digit1 + 1] : 0;
02635     for (int digit_to = bitset_base<n>::digits - 1; digit_to >= 0; --digit_to)
02636     {
02637       bitset_digit_t d1 = (digit1 >= 0) ? this->vector[digit1] : 0;
02638       if (bit_shift == 0)
02639         this->vector[digit_to] = d0;
02640       else
02641         this->vector[digit_to] = (d0 << bit_shift) | (d1 >> (bitset_digit_bits - bit_shift));
02642       d0 = d1;
02643       --digit1;
02644     }
02645     if (bitset_base<n>::has_excess_bits)
02646       this->vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;           // Reset possibly set excess bits.
02647     return *this;
02648   }
02649 
02653 template<unsigned int n>
02654   bitset<n>&
02655   bitset<n>::operator>>=(unsigned int shift)
02656   {
02657     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02658     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02659     unsigned int digit1 = digit_shift + 1;
02660     bitset_digit_t d0 = (digit1 <= bitset_base<n>::digits) ? this->vector[digit1 - 1] : 0;
02661     for (unsigned int digit_to = 0; digit_to < bitset_base<n>::digits; ++digit_to)
02662     {
02663       bitset_digit_t d1 = (digit1 < bitset_base<n>::digits) ? this->vector[digit1] : 0;
02664       if (bit_shift == 0)
02665         this->vector[digit_to] = d0;
02666       else
02667         this->vector[digit_to] = (d0 >> bit_shift) | (d1 << (bitset_digit_bits - bit_shift));
02668       d0 = d1;
02669       ++digit1;
02670     }
02671     return *this;
02672   }
02673 
02690 template<unsigned int n>
02691   bitset<n>::bitset(std::string const& input)
02692   {
02693     reset();                                            // Reset internal digits to zero.
02694     unsigned int d = 0;                                 // Current index of internal digit.
02695     unsigned int u = 0;                                 // Current bit-shift of input digit relative to internal digit.
02696 
02697     for (std::string::const_reverse_iterator iter = input.rbegin(); iter != input.rend(); ++iter)       // Read right to left.
02698     {
02699       bitset_digit_t c = toupper(*iter);                // Get next hexadecimal input character.
02700       if (c == ' ')                                     // Skip spaces.
02701         continue;
02702       if (c < '0')                                      // Terminate reading when not a hexadecimal character.
02703         break;
02704       if (c <= '9')
02705         c -= '0';                                       // Set c to the value that the input character represents.
02706       else
02707       {
02708         if (c > 'F')
02709           break;
02710         if (c >= 'A')
02711           c -= ('A' - 10);
02712         else
02713           break;
02714       }
02715       this->vector[d] |= c << u;                        // Set internal bits.
02716       if ((u += 4) == bitset_digit_bits)                // Update bit/digit 'pointers'.
02717       {
02718         u = 0;
02719         if (++d == bitset_base<n>::digits)              // Terminate reading when bitset is full.
02720           break;
02721       }
02722     }
02723     if (bitset_base<n>::has_excess_bits)
02724       this->vector[bitset_base<n>::digits - 1] &= bitset_base<n>::valid_bits;   // Reset possibly set excess bits.
02725   }
02726 
02730 template<unsigned int n>
02731   std::istream&
02732   operator>>(std::istream& is, bitset<n>& bitsetx)
02733   {
02734     std::string tmp;
02735     is >> tmp;
02736     bitsetx.bitset(tmp);
02737     return is;
02738   }
02739 
02743 template<unsigned int n>
02744   std::ostream&
02745   operator<<(std::ostream& os, bitset<n> const& bits)
02746   {
02747     // Hexadecimal representation
02748     os.fill('0');
02749     os << std::hex;
02750     for (int d = bitset<n>::digits - 1; d >= 0; --d)
02751     {
02752       os.width((d == bitset<n>::digits - 1 && bitset<n>::has_excess_bits) ?
02753           (((n % bitset_digit_bits) - 1) / 4 + 1) :
02754           (bitset_digit_bits / 4));
02755       os << bits.digit(d);
02756       if (d > 0)
02757         os << ' ';
02758     }
02759     os << std::dec;
02760     return os;
02761   }
02762 
02766 template<unsigned int n>
02767   bitset<n>&
02768   bitset<n>::reset(void)
02769   {
02770     std::memset(this->vector, 0, sizeof(this->vector));
02771     return *this;
02772   }
02773 
02777 template<unsigned int n>
02778   inline bool
02779   bitset<n>::test(size_t pos) const
02780  {
02781 #ifdef __i386__
02782     int result;
02783     __asm__ __volatile__ (
02784         "btl %2, %1\n\t"
02785         "sbbl %0, %0"
02786         : "=r" (result)
02787         : "m" ((*(bitset_digit_t volatile*)this->vector)), "Ir" (pos));
02788     return result;
02789 #else
02790     unsigned int d = pos / bitset_digit_bits;
02791     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02792     return (this->vector[d] & mask);
02793 #endif
02794   }
02795 
02799 template<unsigned int n>
02800   template<unsigned int pos>
02801     inline bool
02802     bitset<n>::test(void) const
02803    {
02804       static unsigned int const d = pos / bitset_digit_bits;
02805       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02806       return (this->vector[d] & mask);
02807     }
02808 
02812 template<unsigned int n>
02813   inline bool
02814   bitset<n>::test(bitset_index const& index) const
02815  {
02816 #ifdef __i386__
02817     return this->test(index.get_index());
02818 #else
02819     return (this->vector[index.get_digit()] & index.get_mask());
02820 #endif
02821   }
02822 
02826 template<unsigned int n>
02827   inline void
02828   bitset<n>::set(size_t pos)
02829   {
02830 #ifdef __i386__
02831     __asm__ __volatile__ (
02832         "btsl %1, %0"
02833         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02834         : "Ir" (pos));
02835 
02836 #else
02837     unsigned int d = pos / bitset_digit_bits;
02838     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02839     this->vector[d] |= mask;
02840 #endif
02841   }
02842 
02846 template<unsigned int n>
02847   inline void
02848   bitset<n>::set(bitset_index const& index)
02849   {
02850 #ifdef __i386__
02851     this->set(index.get_index());
02852 #else
02853     this->vector[index.get_digit()] |= index.get_mask();
02854 #endif
02855   }
02856 
02860 template<unsigned int n>
02861   template<unsigned int pos>
02862     inline void
02863     bitset<n>::set(void)
02864     {
02865       static unsigned int const d = pos / bitset_digit_bits;
02866       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02867       this->vector[d] |= mask;
02868     }
02869 
02873 template<unsigned int n>
02874   inline void
02875   bitset<n>::clear(size_t pos)
02876   {
02877 #ifdef __i386__
02878     __asm__ __volatile__ (
02879         "btrl %1, %0"
02880         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02881         : "Ir" (pos)
02882     );
02883 #else
02884     unsigned int d = pos / bitset_digit_bits;
02885     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02886     this->vector[d] &= ~mask;
02887 #endif
02888   }
02889 
02893 template<unsigned int n>
02894   inline void
02895   bitset<n>::clear(bitset_index const& index)
02896   {
02897 #ifdef __i386__
02898     this->clear(index.get_index());
02899 #else
02900     this->vector[index.get_digit()] &= ~(index.get_mask());
02901 #endif
02902   }
02903 
02907 template<unsigned int n>
02908   template<unsigned int pos>
02909     inline void
02910     bitset<n>::clear(void)
02911     {
02912       static unsigned int const d = pos / bitset_digit_bits;
02913       static bitset_digit_t const mask = ~(static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits));
02914       this->vector[d] &= mask;
02915     }
02916 
02920 template<unsigned int n>
02921   inline void
02922   bitset<n>::flip(size_t pos)
02923   {
02924 #ifdef __i386__
02925     __asm__ __volatile__ (
02926         "btcl %1, %0"
02927         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02928         : "Ir" (pos)
02929     );
02930 #else
02931     unsigned int d = pos / bitset_digit_bits;
02932     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02933     this->vector[d] ^= mask;
02934 #endif
02935   }
02936 
02940 template<unsigned int n>
02941   inline void
02942   bitset<n>::flip(bitset_index const& index)
02943   {
02944 #ifdef __i386__
02945     this->flip(index.get_index());
02946 #else
02947     this->vector[index.get_digit()] ^= index.get_mask();
02948 #endif
02949   }
02950 
02954 template<unsigned int n>
02955   template<unsigned int pos>
02956     inline void
02957     bitset<n>::flip(void)
02958     {
02959       static unsigned int const d = pos / bitset_digit_bits;
02960       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02961       this->vector[d] ^= mask;
02962     }
02963 
02967 template<unsigned int n>
02968   bool
02969   bitset<n>::any(void) const
02970  {
02971     unsigned int to = bitset_base<n>::digits - 1;
02972     if (bitset_base<n>::digits > 1)
02973       do
02974       {
02975         if (this->vector[to] != 0)
02976           return true;
02977         --to;
02978       }
02979       while(to != 0);
02980     return (this->vector[0] != 0);
02981   }
02982 
02983 static bool const oddnumberofbits[] = {
02984   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02985   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02986   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02987   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02988   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02989   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02990   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02991   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02992   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02993   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02994   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02995   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02996   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02997   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02998   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02999   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false };
03000 
03004 template<unsigned int n>
03005   bool
03006   bitset<n>::odd(void) const
03007  {
03008     unsigned int from = bitset_base<n>::digits - 1;
03009     bitset_digit_t sum = this->vector[0];
03010     if (bitset_base<n>::digits > 1)
03011       do
03012       {
03013         sum ^= this->vector[from];
03014         --from;
03015       }
03016       while(from != 0);
03017     bitset_digit_t ssum = sum;
03018     if (sizeof(bitset_digit_t) >= 2)
03019     {
03020       ssum >>= (bitset_digit_bits / 2);
03021       sum ^= ssum;
03022     }
03023     if (sizeof(bitset_digit_t) >= 4)
03024     {
03025       ssum = sum;
03026       ssum >>= (bitset_digit_bits / 4);
03027       sum ^= ssum;
03028     }
03029     if (sizeof(bitset_digit_t) >= 8)
03030     {
03031       ssum = sum;
03032       ssum >>= (bitset_digit_bits / 8);
03033       sum ^= ssum;
03034     }
03035     if (sizeof(bitset_digit_t) == 16)
03036     {
03037       ssum = sum;
03038       ssum >>= (bitset_digit_bits / 16);
03039       sum ^= ssum;
03040     }
03041     return oddnumberofbits[sum & 0xff];
03042   }
03043 
03047 structleft {
03048 public:
03049   typedef structright inverse;
03050   static int const direction = -1;
03051   static bool const __left = true;
03052   static bool const __right = false;
03053   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03054   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03055 };
03056 
03060 structright {
03061 public:
03062   typedef structleft inverse;
03063   static int const direction = 1;
03064   static bool const __left = false;
03065   static bool const __right = true;
03066   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03067   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03068 };
03069 
03078 template<unsigned int n>
03079   template<unsigned int shift, class DIRECTION>
03080     void
03081     bitset<n>::rotate(bitset<n>& result) const
03082    {
03083       LibEccDout(dc::bitsetshift|flush_cf, "Entering bitset<" << n << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03084       LibEccDout(dc::bitsetshift|flush_cf, "Rotate input : " << cwprint_using(*this, &bitset<n>::base2_print_on));
03085       shift_op<shift % n, DIRECTION, rotate_phase1>(result);
03086       LibEccDout(dc::bitsetshift|flush_cf, "After phase1 : " << cwprint_using(result, &bitset<n>::base2_print_on));
03087       shift_op<n - (shift % n), typename DIRECTION::inverse, rotate_phase2>(result);
03088       LibEccDout(dc::bitsetshift|flush_cf, "After phase2 : " << cwprint_using(result, &bitset<n>::base2_print_on));
03089       LibEccDout(dc::bitsetshift|flush_cf, "Leaving bitset<" << n << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03090     }
03091 
03092 } // namespace libecc
03093 
03094 #endif // LIBECC_BITS_H
Copyright © 2002-2008 Carlo Wood.  All rights reserved.