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 #ifdef __i386__
00042 #include <asm/bitops.h>
00043 #endif
00044 #ifdef CWDEBUG
00045 #include <libcw/cwprint.h>
00046 #endif
00047 
00048 #ifdef __i386__
00049 // Assembly code, defined in window.s.
00050 extern "C" int libecc_shift_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00051 extern "C" int libecc_shiftwindow_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00052 #endif
00053 
00054 namespace libecc {
00055 
00065 typedef unsigned long bitset_digit_t;
00066 
00068 static unsigned int const bitset_digit_bits = sizeof(bitset_digit_t) * 8;
00069 
00071 #if ECC_BITS == 32
00072 static unsigned int const bitset_digit_bits_log2 = 5;
00073 #elif ECC_BITS == 64
00074 #warning 64 bit code has not been tested.  This warning will remain here until you mail me.
00075 static unsigned int const bitset_digit_bits_log2 = 6;
00076 #elif ECC_BITS == 128
00077 #warning 128 bit code has not been tested.  This warning will remain here until you mail me.
00078 static unsigned int const bitset_digit_bits_log2 = 7;
00079 #endif
00080 
00081 // Forward declaration.
00082 template<unsigned int n, bool inverted>
00083   class bitset_invertible;
00084 
00094 template<unsigned int n>
00095   struct bitset_base {
00096     public:
00097       // Fix this if you add members in front of vector.
00098       static size_t const offsetof_vector = 0; //sizeof(bitset_digit_t);
00099 
00100     public:
00104       static unsigned int const number_of_bits = n;
00105 
00107       static unsigned int const digits = (n - 1) / bitset_digit_bits + 1;
00108 
00109       // ! The number of valid bits in the most significant digit.
00110       static unsigned int const number_of_valid_bits = bitset_digit_bits - (digits * bitset_digit_bits - n);
00111 
00113       static bitset_digit_t const valid_bits =
00114           ((static_cast<bitset_digit_t>(1) << (number_of_valid_bits - 1)) << 1) - 1;
00115 
00117       static bool const has_excess_bits = ((digits * bitset_digit_bits) != n);
00118 
00119     protected:
00126       //bitset_digit_t empty_space1;
00127       bitset_digit_t vector[digits];
00128       //bitset_digit_t empty_space2;
00129 
00130       template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00131         friend bool operator==(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00132 
00133       template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00134         friend bool operator!=(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00135 
00136     public:
00137       // Digit representation
00138       bitset_digit_t& rawdigit(unsigned int d) { return this->vector[d]; }
00139       bitset_digit_t const* digits_ptr(void) const { return this->vector; }
00140       bitset_digit_t* digits_ptr(void) { return this->vector; }
00141       uint32_t digit32(unsigned int d32) const
00142       {
00143         if (sizeof(bitset_digit_t) == 4)
00144           return this->vector[d32];
00145         else
00146         {
00147           unsigned int d = d32 / (sizeof(bitset_digit_t) / 4);
00148           unsigned int r = d32 % (sizeof(bitset_digit_t) / 4);
00149           return (this->vector[d] >> (r * 32)) & 0xffffffff;
00150         }
00151       }
00152   };
00153 
00154 #ifndef HIDE_FROM_DOXYGEN
00155 namespace Operator {
00156 
00157 #ifdef __i386__
00158 
00159 //
00160 // Due to heavily broken inlining heuristics of gcc,
00161 // we are forced to use macros to do the assembly
00162 // inlining.  There is no alternative, I tried everything.
00163 //
00164 
00165 #define LIBECC_INVERT "xorl $-1,%%eax\n\t"
00166 #define LIBECC_NOTHING ""
00167 
00168 #define LIBECC_ASMLOOP(destination, source, count, OPCODE, OPTIONAL_INVERT)     \
00169   do {                                                  \
00170     int __d0, __d1, __d2;                               \
00171     __asm__ __volatile__ (                              \
00172       "\n1:\n\t"                                        \
00173         "movl (%5,%%ecx,4),%%eax\n\t"                   \
00174         OPTIONAL_INVERT                                 \
00175         OPCODE " %%eax,(%4,%%ecx,4)\n\t"                \
00176         "decl %%ecx\n\t"                                \
00177         "jnz 1b"                                        \
00178         : "=c" (__d0), "=&r" (__d1), "=&r" (__d2)       \
00179         : "0" (count),                                  \
00180           "1" ((destination) - 1),                      \
00181           "2" ((source) - 1)                            \
00182         : "%eax", "memory"                              \
00183     );                                                  \
00184   } while(0)
00185 
00186 #define LIBECC_ASMLOOP_BODY(OPCODE, destination, source, count, inverted) \
00187   do { \
00188     if (inverted) \
00189       LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_INVERT); \
00190     else \
00191       LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_NOTHING); \
00192   } while(0)
00193 
00194 #define LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, OPTIONAL_INVERT1, OPCODE2, OPTIONAL_INVERT3)              \
00195   do {                                                          \
00196     int __d0, __d1, __d2, __d3;                                 \
00197     __asm__ __volatile__ (                                      \
00198       "\n1:\n\t"                                                \
00199         "movl (%6,%%ecx,4),%%eax\n\t"                           \
00200         OPTIONAL_INVERT1                                        \
00201         OPCODE2 " (%7,%%ecx,4),%%eax\n\t"                       \
00202         OPTIONAL_INVERT3                                        \
00203         OPCODE " %%eax,(%5,%%ecx,4)\n\t"                        \
00204         "decl %%ecx\n\t"                                        \
00205         "jnz 1b"                                                \
00206         : "=c" (__d0), "=&r" (__d1), "=&r" (__d2), "=&r" (__d3) \
00207         : "0" (count),                                          \
00208           "1" ((destination) - 1),                              \
00209           "2" ((source1) - 1),                                  \
00210           "3" ((source2) - 1)                                   \
00211         : "%eax", "memory"                                      \
00212     );                                                          \
00213   } while(0)
00214 
00215 #define LIBECC_ASMLOOP2_BODY(OPCODE, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00216   do { \
00217     if (OPERATOR::id == libecc::Operator::bitsetAND::id) \
00218     { \
00219       if (inverted1 && inverted2) \
00220         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_INVERT); \
00221       else if (inverted1) \
00222         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00223       else if (inverted2) \
00224         LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00225       else \
00226         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_NOTHING); \
00227     } \
00228     else if (OPERATOR::id == libecc::Operator::bitsetOR::id) \
00229     { \
00230       if (inverted1 && inverted2) \
00231         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_INVERT); \
00232       else if (inverted1) \
00233         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00234       else if (inverted2) \
00235         LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00236       else \
00237         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_NOTHING); \
00238     } \
00239     else if (OPERATOR::id == libecc::Operator::bitsetXOR::id) \
00240     { \
00241       if (inverted1 == inverted2) \
00242         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_NOTHING); \
00243       else \
00244         LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_INVERT); \
00245     } \
00246   } while(0)
00247 
00248 #define LIBECC_INLINE_ASMLOOP(ID, destination, source, count, inverted) \
00249     do { \
00250       if (ID == libecc::Operator::bitsetAssign::id) \
00251       { \
00252         LIBECC_ASMLOOP_BODY("movl", destination, source, count, inverted); \
00253       } \
00254       else if (ID == libecc::Operator::bitsetANDAssign::id) \
00255       { \
00256         LIBECC_ASMLOOP_BODY("andl", destination, source, count, inverted); \
00257       } \
00258       else if (ID == libecc::Operator::bitsetORAssign::id) \
00259       { \
00260         LIBECC_ASMLOOP_BODY("orl", destination, source, count, inverted); \
00261       } \
00262       else if (ID == libecc::Operator::bitsetXORAssign::id) \
00263       { \
00264         LIBECC_ASMLOOP_BODY("xorl", destination, source, count, inverted); \
00265       } \
00266     } while(0)
00267 
00268 #define LIBECC_INLINE_ASMLOOP2(ID, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00269     do { \
00270       if (ID == libecc::Operator::bitsetAssign::id) \
00271       { \
00272         LIBECC_ASMLOOP2_BODY("movl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00273       } \
00274       else if (ID == libecc::Operator::bitsetANDAssign::id) \
00275       { \
00276         LIBECC_ASMLOOP2_BODY("andl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00277       } \
00278       else if (ID == libecc::Operator::bitsetORAssign::id) \
00279       { \
00280         LIBECC_ASMLOOP2_BODY("orl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00281       } \
00282       else if (ID == libecc::Operator::bitsetXORAssign::id) \
00283       { \
00284         LIBECC_ASMLOOP2_BODY("xorl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00285       } \
00286     } while(0)
00287 
00288 #define LIBECC_ASMSHIFTRIGHT0(OP1)                      \
00289               __asm__ __volatile__ (                    \
00290                   "movl 4(%%esi),%%edx\n\t"             \
00291                   "shrl $1,%%edx\n\t"                   \
00292                   OP1                                   \
00293                   "movl %%edx,4(%%edi)"                 \
00294                 : "=&S" (ptr1),                         \
00295                   "=&D" (ptr2)                          \
00296                 : "0" (&this->vector[initial - count]), \
00297                   "1" (&result.vector[initial - count]) \
00298                 : "%eax", "%edx", "memory", "cc"        \
00299               )
00300 
00301 #if 0   // NOT faster.
00302 #define LIBECC_OP1_SOURCE "(%%esi)"
00303 #define LIBECC_OP2_SOURCE "(%%esi)"
00304 #define LIBECC_OP1_DESTINATION "(%%edi)"
00305 #define LIBECC_OP2_DESTINATION "(%%edi)"
00306 #define LIBECC_WORKREG "%%eax"
00307 #define LIBECC_CLOBBER "%eax"
00308 #define LIBECC_INIT "std\n\t"
00309 #define LIBECC_LOAD1 "lodsl\n\t"
00310 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00311 #define LIBECC_STORE1 "stosl\n\t"
00312 #define LIBECC_LOAD2 "lodsl\n\t"
00313 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
00314 #define LIBECC_STORE2 "stosl\n\t"
00315 #define LIBECC_DEINIT "cld\n\t"
00316 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "setc %%edx\n\t" OPERAND "\n\tbt $0,%%edx\n\t"
00317 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%edx"
00318 #define LIBECC_INITIAL_ESI &this->vector[initial]
00319 #define LIBECC_INITIAL_EDI &result.vector[initial]
00320 #else
00321 #define LIBECC_OP1_SOURCE "4(%%esi,%%ecx,4)"
00322 #define LIBECC_OP2_SOURCE "(%%esi,%%ecx,4)"
00323 #define LIBECC_OP1_DESTINATION "4(%%edi,%%ecx,4)"
00324 #define LIBECC_OP2_DESTINATION "(%%edi,%%ecx,4)"
00325 #define LIBECC_WORKREG "%%edx"
00326 #define LIBECC_CLOBBER "%edx"
00327 #define LIBECC_INIT
00328 #define LIBECC_LOAD1 "movl " LIBECC_OP1_SOURCE "," LIBECC_WORKREG "\n\t"
00329 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00330 #define LIBECC_STORE1 "movl " LIBECC_WORKREG "," LIBECC_OP1_DESTINATION "\n\t"
00331 #define LIBECC_LOAD2 "movl " LIBECC_OP2_SOURCE "," LIBECC_WORKREG "\n\t"
00332 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
00333 #define LIBECC_STORE2 "movl " LIBECC_WORKREG "," LIBECC_OP2_DESTINATION "\n\t"
00334 #define LIBECC_DEINIT
00335 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
00336 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%eax"
00337 #define LIBECC_INITIAL_ESI &this->vector[initial - count]
00338 #define LIBECC_INITIAL_EDI &result.vector[initial - count]
00339 #endif
00340 
00341 #define LIBECC_ASMSHIFTRIGHT1(OP1, OP2, CLOBBER)        \
00342               __asm__ __volatile__ (                    \
00343                   LIBECC_INIT                           \
00344                   LIBECC_LOAD1                          \
00345                   LIBECC_SHIFT                          \
00346                   OP1                                   \
00347                   LIBECC_STORE1                         \
00348                 "1:\n\t"                                \
00349                   LIBECC_LOAD2                          \
00350                   LIBECC_ROTATE                         \
00351                   OP2                                   \
00352                   LIBECC_STORE2                         \
00353                   "decl %%ecx\n\t"                      \
00354                   "jnz 1b\n\t"                          \
00355                   LIBECC_DEINIT                         \
00356                 : "=&S" (ptr1),                         \
00357                   "=&D" (ptr2),                         \
00358                   "=&c" (c)                             \
00359                 : "0" (LIBECC_INITIAL_ESI),             \
00360                   "1" (LIBECC_INITIAL_EDI),             \
00361                   "2" (count - 1)                       \
00362                 : "memory", "cc", CLOBBER               \
00363               )
00364 
00365 #define LIBECC_ASMSHIFTLEFT(OP1, OP2, FINISH)           \
00366               __asm__ __volatile__ (                    \
00367                   "movl -4(%%esi),%%edx\n\t"            \
00368                   "shll $1,%%edx\n\t"                   \
00369                   OP1                                   \
00370                   "movl %%edx,-4(%%edi)\n\t"            \
00371                   "jecxz 2f\n"                          \
00372                 "1:\n\t"                                \
00373                   "movl (%%esi),%%edx\n\t"              \
00374                   "rcll $1,%%edx\n\t"                   \
00375                   OP2                                   \
00376                   "movl %%edx,(%%edi)\n\t"              \
00377                   "leal 4(%%esi),%%esi\n\t"             \
00378                   "leal 4(%%edi),%%edi\n\t"             \
00379                   "decl %%ecx\n\t"                      \
00380                   "jnz 1b\n"                            \
00381                 "2:\n\t"                                \
00382                   FINISH                                \
00383                 : "=&S" (ptr1),                         \
00384                   "=&D" (ptr2),                         \
00385                   "=&c" (c)                             \
00386                 : "0" (&this->vector[initial + 1]),     \
00387                   "1" (&result.vector[initial + 1]),    \
00388                   "2" (count - 1),                      \
00389                   "i" (valid_bits)                      \
00390                 : "%eax", "%edx", "memory", "cc"        \
00391               )
00392 
00393 #define LIBECC_ASMSHIFTLEFT_FINISH(OP)                  \
00394                   "movl (%%esi),%%edx\n\t"              \
00395                   "rcll $1,%%edx\n\t"                   \
00396                   "andl %6,%%edx\n\t"                   \
00397                   OP                                    \
00398                   "movl %%edx,(%%edi)"
00399 
00400 #define LIBECC_LEFT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
00401 
00402 #endif // __i386__
00403 
00404 // Functors.
00405 
00406 // Functor for '&'.
00407 struct bitsetAND {
00408   static int const id = 1;
00409   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 & digit2; }
00410   template<bool inverted1, bool inverted2>
00411    struct execbool {
00412      static bool const value = inverted1 && inverted2;
00413    };
00414 };
00415 
00416 // Functor for '|'.
00417 struct bitsetOR {
00418   static int const id = 2;
00419   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 | digit2; }
00420   template<bool inverted1, bool inverted2>
00421    struct execbool {
00422      static bool const value = inverted1 || inverted2;
00423    };
00424 };
00425 
00426 // Functor for '^'.
00427 struct bitsetXOR {
00428   static int const id = 3;
00429   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 ^ digit2; }
00430   template<bool inverted1, bool inverted2>
00431    struct execbool {
00432      static bool const value = (inverted1 != inverted2);
00433    };
00434 };
00435 
00436 // Functor for '='.
00437 struct bitsetAssign {
00438   static int const id = 1;
00439   static bool const sets_excess_bits = true;
00440   static bool const with_zero_sets_zero = true;
00441   static bool const with_ones_sets_ones = true;
00442   static bool const with_ones_inverts = false;
00443   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out = in; }
00444 };
00445 
00446 // Functor for '&='.
00447 struct bitsetANDAssign {
00448   static int const id = 2;
00449   static bool const sets_excess_bits = false;
00450   static bool const with_zero_sets_zero = true;
00451   static bool const with_ones_sets_ones = false;
00452   static bool const with_ones_inverts = false;
00453   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out &= in; }
00454 };
00455 
00456 // Functor for '|='.
00457 struct bitsetORAssign {
00458   static int const id = 3;
00459   static bool const sets_excess_bits = true;
00460   static bool const with_zero_sets_zero = false;
00461   static bool const with_ones_sets_ones = true;
00462   static bool const with_ones_inverts = false;
00463   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out |= in; }
00464 };
00465 
00466 // Functor for '^='.
00467 struct bitsetXORAssign {
00468   static int const id = 4;
00469   static bool const sets_excess_bits = true;
00470   static bool const with_zero_sets_zero = false;
00471   static bool const with_ones_sets_ones = false;
00472   static bool const with_ones_inverts = true;
00473   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out ^= in; }
00474 };
00475 
00476 template<unsigned int n, bool inverted1, bool inverted2, typename OP>
00477   struct bitsetExpression
00478   {
00479     bitset_invertible<n, inverted1> const& first;
00480     bitset_invertible<n, inverted2> const& second;
00481     OP op;
00482     bitsetExpression(bitset_invertible<n, inverted1> const& arg1, bitset_invertible<n, inverted2> const& arg2) : first(arg1), second(arg2) { }
00483   };
00484 
00485 } // namespace Operator
00486 #endif // HIDE_FROM_DOXYGEN
00487 
00505 template<unsigned int n, bool inverted>
00506   class bitset_invertible : public bitset_base<n> {
00507     public:
00508       // Constructors
00509       bitset_invertible(void);
00510       template<typename Expression>
00511         explicit bitset_invertible<n, inverted>(Expression const&);
00512 
00513     protected:
00514       template<typename OP, unsigned int x, bool invertedx>
00515         void assign(bitset_invertible<x, invertedx> const&, OP);
00516       template<typename OP1, unsigned int x, bool inverted1, bool inverted2, typename OP2>
00517         void assign(Operator::bitsetExpression<x, inverted1, inverted2, OP2> const&, OP1);
00518 
00519     private:
00520       template<unsigned int m, bool i>
00521         friend class bitset_invertible;
00522       template<unsigned int m, int DIRECTION>
00523         friend class bitset_iterator;
00524 
00525     public:
00526       // Printing
00527       void base2_print_on(std::ostream& os) const;
00528 
00529       // Digit access.
00530       bitset_digit_t digit(unsigned int d) const { assert(!inverted); return inverted ? ~this->vector[d] : this->vector[d]; }
00531   };
00532 
00544 template<unsigned int n, bool inverted>
00545   void
00546   bitset_invertible<n, inverted>::base2_print_on(std::ostream& os) const
00547   {
00548     // Binary representation
00549     for (int d = bitset_base<n>::digits - 1; d >= 0; --d)
00550       for (bitset_digit_t mask = (~static_cast<bitset_digit_t>(0) >> 1) + 1; mask != 0; mask >>= 1)
00551         if (d != bitset_base<n>::digits - 1 || (mask & bitset_base<n>::valid_bits))
00552           if ((this->digit(d) & mask) == inverted)
00553             os << '0';
00554           else
00555             os << '1';
00556   }
00557 
00558 // Default constructor.
00559 template<unsigned int n, bool inverted>
00560   inline
00561   bitset_invertible<n, inverted>::bitset_invertible(void)
00562   {
00563     if (has_excess_bits)
00564       this->vector[digits - 1] = 0;                     // Reset the excess bits!
00565   }
00566 
00567 // Copy constructor.
00568 template<unsigned int n, bool inverted>
00569   template<typename Expression>
00570     inline
00571     bitset_invertible<n, inverted>::bitset_invertible(Expression const& expr)
00572     {
00573       this->assign(expr, Operator::bitsetAssign());
00574     }
00575 
00576 //
00577 // Assignment function.
00578 // This function handles:
00579 //
00580 // a = b;
00581 // a = ~b;
00582 // a &= b;
00583 // a &= ~b;
00584 // a |= b;
00585 // a |= ~b;
00586 // a ^= b;
00587 // a ^= ~b;
00588 //
00589 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
00590 //
00591 template<unsigned int n, bool inverted>
00592   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted_argument>
00593     inline void
00594     bitset_invertible<n, inverted>::assign(bitset_invertible<x, inverted_argument> const& bits, ASSIGNMENT_OPERATOR)
00595     {
00596       // Handle excess digits.
00597       if (digits > bitset_base<x>::digits)
00598       {
00599         if (!inverted_argument)
00600         {
00601           // Fill excess digits with 0's when needed.
00602           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
00603           {
00604 #ifdef __i386__
00605             int __d0, __d1;
00606             __asm__ __volatile__ (
00607                 "std; rep; stosl"
00608                 : "=m" (this->vector[digits - 1]), "=&c" (__d0), "=&D" (__d1)
00609                 : "a" (0), "1" (digits - bitset_base<x>::digits), "2" (&this->vector[digits - 1])
00610                 : "memory"
00611             );
00612 #else
00613             unsigned int count = digits - bitset_base<x>::digits;
00614             do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
00615 #endif
00616           }
00617         }
00618         else
00619         {
00620           // Fill excess digits with 1's when needed.
00621           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
00622           {
00623 #ifdef __i386__
00624             int __d0, __d1;
00625             __asm__ __volatile__ (
00626                 "movl %6,4(%%edi); std; rep; stosl"
00627                 : "=m" (this->vector[digits - 2]), "=&c" (__d0), "=&D" (__d1)
00628                 : "a" (-1), "1" (digits - bitset_base<x>::digits - 1), "2" (&this->vector[digits - 2]), "i" (valid_bits)
00629                 : "memory"
00630             );
00631 #else
00632             this->vector[digits - 1] = valid_bits;
00633             unsigned int count = digits - bitset_base<x>::digits;
00634             while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
00635 #endif
00636           }
00637           // Or invert them.
00638           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
00639           {
00640 #ifdef __i386__
00641             int __d0, __d1;
00642             __asm__ __volatile__ (
00643                 "xorl %5,(%2)\n\t"
00644                 "jecxz 2f\n\t"
00645                 "subl %6,%2\n"
00646         "1:\n\t"
00647                 "xorl $-1,(%2,%%ecx,4)\n\t"
00648                 "decl %%ecx\n\t"
00649                 "jnz 1b\n"
00650         "2:"
00651                 : "=m" (this->vector[digits - 1]), "=&c" (__d0), "=&r" (__d1)
00652                 : "1" (digits - bitset_base<x>::digits - 1), "2" (&this->vector[digits - 1]),
00653                   "i" (valid_bits), "i" ((digits - bitset_base<x>::digits) * 4)
00654                 : "memory", "cc"
00655             );
00656 #else
00657             this->vector[digits - 1] ^= valid_bits;
00658             unsigned int count = digits - bitset_base<x>::digits;
00659             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
00660 #endif
00661           }
00662         }
00663       }
00664 
00665       // Handle other digits.
00666 #ifdef __i386__
00667       LIBECC_INLINE_ASMLOOP(ASSIGNMENT_OPERATOR::id,
00668           this->vector, bits.digits_ptr(),
00669           ((digits > bitset_base<x>::digits) ? bitset_base<x>::digits : digits),
00670           inverted_argument);
00671 #else
00672       unsigned int d;
00673       if (digits > bitset_base<x>::digits)
00674         d = bitset_base<x>::digits - 1;
00675       else
00676         d = digits - 1;
00677       ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~*(bits.digits_ptr() + d) : bits.digit(d));
00678       while(d) { --d; ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~*(bits.digits_ptr() + d) : bits.digit(d)); }
00679 #endif
00680 
00681       // Reset excess bits if needed.
00682       if (((!inverted_argument && x > n) ||
00683             (inverted_argument && digits <= bitset_base<x>::digits)) &&
00684           has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
00685         this->vector[digits - 1] &= valid_bits;
00686     }
00687 
00688 //
00689 // Assignment function for expressions.
00690 // This function handles:
00691 //
00692 // a = b & c;
00693 // a = b & ~c;
00694 // a = ~b & c;
00695 // a = ~b & ~b;
00696 // a = b | c;
00697 // a = b | ~c;
00698 // a = ~b | c;
00699 // a = ~b | ~b;
00700 // a = b ^ c;
00701 // a = b ^ ~c;
00702 // a = ~b ^ c;
00703 // a = ~b ^ ~b;
00704 // a &= b & c;
00705 // a &= b & ~c;
00706 // a &= ~b & c;
00707 // a &= ~b & ~b;
00708 // a &= b | c;
00709 // a &= b | ~c;
00710 // a &= ~b | c;
00711 // a &= ~b | ~b;
00712 // a &= b ^ c;
00713 // a &= b ^ ~c;
00714 // a &= ~b ^ c;
00715 // a &= ~b ^ ~b;
00716 // a |= b & c;
00717 // a |= b & ~c;
00718 // a |= ~b & c;
00719 // a |= ~b & ~b;
00720 // a |= b | c;
00721 // a |= b | ~c;
00722 // a |= ~b | c;
00723 // a |= ~b | ~b;
00724 // a |= b ^ c;
00725 // a |= b ^ ~c;
00726 // a |= ~b ^ c;
00727 // a |= ~b ^ ~b;
00728 // a ^= b & c;
00729 // a ^= b & ~c;
00730 // a ^= ~b & c;
00731 // a ^= ~b & ~b;
00732 // a ^= b | c;
00733 // a ^= b | ~c;
00734 // a ^= ~b | c;
00735 // a ^= ~b | ~b;
00736 // a ^= b ^ c;
00737 // a ^= b ^ ~c;
00738 // a ^= ~b ^ c;
00739 // a ^= ~b ^ ~b;
00740 //
00741 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
00742 // OPERATOR is one of bitsetAND, bitsetOR or bitsetXOR.
00743 //
00744 template<unsigned int n, bool inverted>
00745   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted1, bool inverted2, typename OPERATOR>
00746     inline void
00747     bitset_invertible<n, inverted>::assign(Operator::bitsetExpression<x, inverted1, inverted2, OPERATOR> const& expr, ASSIGNMENT_OPERATOR)
00748     {
00749       static bool const argument_has_leading_ones = OPERATOR::template execbool<inverted1, inverted2>::value;
00750 
00751       // Handle excess digits.
00752       if (digits > bitset_base<x>::digits)
00753       {
00754         if (!argument_has_leading_ones)
00755         {
00756           // Fill excess digits with 0's when needed.
00757           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
00758           {
00759 #ifdef __i386__
00760             int __d0, __d1;
00761             __asm__ __volatile__ (
00762                 "std; rep; stosl"
00763                 : "=m" (this->vector[digits - 1]), "=&c" (__d0), "=&D" (__d1)
00764                 : "a" (0), "1" (digits - bitset_base<x>::digits), "2" (&this->vector[digits - 1])
00765                 : "memory"
00766             );
00767 #else
00768             unsigned int count = digits - bitset_base<x>::digits;
00769             do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
00770 #endif
00771           }
00772         }
00773         else
00774         {
00775           // Fill excess digits with 1's when needed.
00776           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
00777           {
00778 #ifdef __i386__
00779             int __d0, __d1;
00780             __asm__ __volatile__ (
00781                 "movl %6,4(%%edi); std; rep; stosl"
00782                 : "=m" (this->vector[digits - 2]), "=&c" (__d0), "=&D" (__d1)
00783                 : "a" (-1), "1" (digits - bitset_base<x>::digits - 1), "2" (&this->vector[digits - 2]), "i" (valid_bits)
00784                 : "memory"
00785             );
00786 #else
00787             this->vector[digits - 1] = valid_bits;
00788             unsigned int count = digits - bitset_base<x>::digits;
00789             while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
00790 #endif
00791           }
00792           // Or invert them.
00793           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
00794           {
00795 #ifdef __i386__
00796             int __d0, __d1;
00797             __asm__ __volatile__ (
00798                 "xorl %5,(%2)\n\t"
00799                 "jecxz 2f\n\t"
00800                 "subl %6,%2\n"
00801         "1:\n\t"
00802                 "xorl $-1,(%2,%%ecx,4)\n\t"
00803                 "decl %%ecx\n\t"
00804                 "jnz 1b\n"
00805         "2:"
00806                 : "=m" (this->vector[digits - 1]), "=&c" (__d0), "=&r" (__d1)
00807                 : "1" (digits - bitset_base<x>::digits - 1), "2" (&this->vector[digits - 1]),
00808                   "i" (valid_bits), "i" ((digits - bitset_base<x>::digits) * 4)
00809                 : "memory", "cc"
00810             );
00811 #else
00812             this->vector[digits - 1] ^= valid_bits;
00813             unsigned int count = digits - bitset_base<x>::digits;
00814             while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
00815 #endif
00816           }
00817         }
00818       }
00819 
00820       // Handle other digits.
00821 #ifdef __i386__
00822       LIBECC_INLINE_ASMLOOP2(ASSIGNMENT_OPERATOR::id, OPERATOR, inverted1, inverted2,
00823           this->vector, expr.first.digits_ptr(), expr.second.digits_ptr(),
00824           ((digits > bitset_base<x>::digits) ? bitset_base<x>::digits : digits));
00825 #else
00826       unsigned int d;
00827       if (digits < bitset_base<x>::digits)
00828         d = digits - 1;
00829       else
00830         d = bitset_base<x>::digits - 1;
00831       for(;;)
00832       {
00833         ASSIGNMENT_OPERATOR::exec(this->vector[d],
00834             OPERATOR::exec(inverted1 ? ~*(expr.first.digits_ptr() + d) : expr.first.digit(d),
00835                            inverted2 ? ~*(expr.second.digits_ptr() + d) : expr.second.digit(d)));
00836         if (!d)
00837           break;
00838         --d;
00839       }
00840 #endif
00841 
00842       // Reset excess bits if needed.
00843       if (((!argument_has_leading_ones && x > n) ||
00844             (argument_has_leading_ones && digits <= bitset_base<x>::digits)) &&
00845           has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
00846         this->vector[digits - 1] &= valid_bits;
00847     }
00848 
00875 template<unsigned int n, bool inverted>
00876   inline bitset_invertible<n, !inverted> const&
00877   operator~(bitset_invertible<n, inverted> const& bits)
00878   {
00879     return *reinterpret_cast<bitset_invertible<n, !inverted> const*>(&bits);
00880   }
00881 
00882 //------------------------------------------------------------------------------------------------------------------
00883 // Iterators
00884 //
00885 
00895 class bitset_index {
00896 #ifdef __i386__
00897   protected:
00898     int M_index;                        
00899 
00900   public:
00901     // Accessors.
00902     int get_index(void) const;
00903 
00904 #else
00905   protected:
00906     int M_digit;                        
00907     bitset_digit_t M_mask;              
00908 
00909   public:
00910     // Accessors.
00911     int get_digit(void) const;
00912     bitset_digit_t get_mask(void) const;
00913 #endif
00914 
00915   public:
00916     // Automatic conversion.
00917     operator unsigned int () const;
00918 
00919   public:
00920     // Equality Comparable.
00921     friend bool operator==(bitset_index const& i1, bitset_index const& i2);
00922     friend bool operator!=(bitset_index const& i1, bitset_index const& i2);
00923 
00924   protected:
00925     // Bidirectional.
00926     void left(void);
00927     void right(void);
00928 
00929     // Random access.
00930     void left(int n);
00931     void right(int n);
00932     friend int subtract(bitset_index const& i1, bitset_index const& i2);
00933 
00934   protected:
00935     // Constructors.
00936     bitset_index(void);
00937     bitset_index(bitset_index const& index);
00938     bitset_index(int bit);
00939 
00940   public:
00941     friend std::ostream& operator<<(std::ostream& os, bitset_index const& i);
00942 };
00943 
00944 #ifdef __i386__
00945 
00948 inline int
00949 bitset_index::get_index(void) const
00950 {
00951   return M_index;
00952 }
00953 
00957 inline
00958 bitset_index::operator unsigned int () const
00959 {
00960   return M_index;
00961 }
00962 
00963 #else
00964 
00968 inline int
00969 bitset_index::get_digit(void) const
00970 {
00971   return M_digit;
00972 }
00973 
00977 inline bitset_digit_t
00978 bitset_index::get_mask(void) const
00979 { 
00980   return M_mask;
00981 }
00982 
00983 #ifndef HIDE_FROM_DOXYGEN
00984 #include <strings.h>    // Needed for ffs.
00985 inline
00986 bitset_index::operator unsigned int () const
00987 {
00988   return M_digit * bitset_digit_bits + ::ffs(M_mask) - 1;
00989 }
00990 #endif
00991 
00992 #endif
00993 
00997 inline bool
00998 operator==(bitset_index const& i1, bitset_index const& i2)
00999 {
01000 #ifdef __i386__
01001   return (i1.M_index == i2.M_index);
01002 #else
01003   return (i1.M_digit == i2.M_digit && i1.M_mask == i2.M_mask);
01004 #endif
01005 }
01006 
01010 inline bool
01011 operator!=(bitset_index const& i1, bitset_index const& i2)
01012 {
01013 #ifdef __i386__
01014   return (i1.M_index != i2.M_index);
01015 #else
01016   return (i1.M_digit != i2.M_digit || i1.M_mask != i2.M_mask);
01017 #endif
01018 }
01019 
01023 inline
01024 bitset_index::bitset_index(void)
01025 {
01026 }
01027 
01031 inline
01032 bitset_index::bitset_index(bitset_index const& index) :
01033 #ifdef __i386__
01034     M_index(index.M_index)
01035 #else
01036     M_digit(index.M_digit), M_mask(index.M_mask)
01037 #endif
01038 { 
01039 }
01040 
01047 inline
01048 bitset_index::bitset_index(int bit) :
01049 #ifdef __i386__
01050     M_index(bit)
01051 #else
01052     // If bit == -1 then M_digit should become -1 and M_mask 0x80000000.
01053     M_digit(bit >> bitset_digit_bits_log2),
01054     M_mask(static_cast<bitset_digit_t>(1) << ((unsigned int)bit & (bitset_digit_bits - 1)))
01055 #endif
01056 {
01057 }
01058 
01062 inline void
01063 bitset_index::left(void)
01064 {
01065 #ifdef __i386__
01066   ++M_index;
01067 #else
01068   if ((M_mask <<= 1) == 0)
01069   {
01070     ++M_digit;
01071     M_mask = 1;
01072   }
01073 #endif
01074 }
01075 
01079 inline void
01080 bitset_index::right(void)
01081 {
01082 #ifdef __i386__
01083   --M_index;
01084 #else
01085   if ((M_mask >>= 1) == 0)
01086   {
01087     --M_digit;
01088     M_mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
01089   }
01090 #endif
01091 }
01092 
01096 inline void
01097 bitset_index::left(int n)
01098 {
01099 #ifdef __i386__
01100   M_index += n;
01101 #else
01102   int const digit_shift = n >> bitset_digit_bits_log2;
01103   int const mask_shift = n & (bitset_digit_bits - 1);
01104   M_digit += digit_shift;
01105   if (mask_shift)
01106   {
01107     bitset_digit_t new_mask = M_mask << mask_shift;
01108     if (new_mask == 0)
01109     {
01110       ++M_digit;
01111       new_mask = M_mask >> (bitset_digit_bits - mask_shift);
01112     }
01113     M_mask = new_mask;
01114   }
01115 #endif
01116 }
01117 
01121 inline void
01122 bitset_index::right(int n)
01123 {
01124 #ifdef __i386__
01125   M_index -= n;
01126 #else
01127   int const digit_shift = n >> bitset_digit_bits_log2;
01128   int const mask_shift = n & (bitset_digit_bits - 1);
01129   M_digit -= digit_shift;
01130   if (mask_shift)
01131   {
01132     bitset_digit_t new_mask = M_mask >> mask_shift;
01133     if (new_mask == 0)
01134     {
01135       --M_digit;
01136       new_mask = M_mask << (bitset_digit_bits - mask_shift);
01137     }
01138     M_mask = new_mask;
01139   }
01140 #endif
01141 }
01142 
01143 enum {
01144   forwards_iterating,
01145   backwards_iterating
01146 };
01147 
01156 template<int DIRECTION>
01157   class bitset_index_iterator : public bitset_index {
01158     public:
01159       // LessThan Comparable.
01160       friend bool operator< <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01161       friend bool operator> <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01162       friend bool operator<= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01163       friend bool operator>= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
01164 
01165     public:
01166       // Bidirectional.
01167       void increment(void);
01168       void decrement(void);
01169 
01170       // Random access.
01171       void increment(int n);
01172       void decrement(int n);
01173 
01174       friend int operator-(bitset_index const& i1, bitset_index const& i2);
01175 
01176     public:
01177       // Constructors.
01178       bitset_index_iterator(void);
01179       bitset_index_iterator(bitset_index_iterator const& index);
01180       bitset_index_iterator(int bit);
01181   };
01182 
01186 template<int DIRECTION>
01187   inline
01188   bitset_index_iterator<DIRECTION>::bitset_index_iterator(void)
01189   {
01190   }
01191 
01195 template<int DIRECTION>
01196   inline
01197   bitset_index_iterator<DIRECTION>::bitset_index_iterator(bitset_index_iterator<DIRECTION> const& index) :
01198       bitset_index(index)
01199   { 
01200   }
01201 
01208 template<int DIRECTION>
01209   inline
01210   bitset_index_iterator<DIRECTION>::bitset_index_iterator(int bit) : bitset_index(bit)
01211   {
01212   }
01213 
01217 template<int DIRECTION>
01218   inline bool
01219   operator<(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01220   {
01221 #ifdef __i386__
01222     if (DIRECTION == forwards_iterating)
01223       return (i1.M_index < i2.M_index);
01224     else
01225       return (i1.M_index > i2.M_index);
01226 #else
01227     if (DIRECTION == forwards_iterating)
01228       return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
01229     else
01230       return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
01231 #endif
01232   }
01233 
01237 template<int DIRECTION>
01238   inline bool
01239   operator>(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01240   {
01241 #ifdef __i386__
01242     if (DIRECTION == forwards_iterating)
01243       return (i1.M_index > i2.M_index);
01244     else
01245       return (i1.M_index < i2.M_index);
01246 #else
01247     if (DIRECTION == forwards_iterating)
01248       return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
01249     else
01250       return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
01251 #endif
01252   }
01253 
01257 template<int DIRECTION>
01258   inline bool
01259   operator<=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01260   {
01261 #ifdef __i386__
01262     if (DIRECTION == forwards_iterating)
01263       return (i1.M_index <= i2.M_index);
01264     else
01265       return (i1.M_index >= i2.M_index);
01266 #else
01267     if (DIRECTION == forwards_iterating)
01268       return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
01269     else
01270       return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
01271 #endif
01272   }
01273 
01277 template<int DIRECTION>
01278   inline bool
01279   operator>=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01280   {
01281 #ifdef __i386__
01282     if (DIRECTION == forwards_iterating)
01283       return (i1.M_index >= i2.M_index);
01284     else
01285       return (i1.M_index <= i2.M_index);
01286 #else
01287     if (DIRECTION == forwards_iterating)
01288       return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
01289     else
01290       return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
01291 #endif
01292   }
01293 
01297 template<int DIRECTION>
01298   inline void
01299   bitset_index_iterator<DIRECTION>::increment(void)
01300   {
01301     if (DIRECTION == forwards_iterating)
01302       left();
01303     else
01304       right();
01305   }
01306 
01310 template<int DIRECTION>
01311   inline void
01312   bitset_index_iterator<DIRECTION>::decrement(void)
01313   {
01314     if (DIRECTION == forwards_iterating)
01315       right();
01316     else
01317       left();
01318   }
01319 
01323 template<int DIRECTION>
01324   inline void
01325   bitset_index_iterator<DIRECTION>::increment(int n)
01326   {
01327     if (DIRECTION == forwards_iterating)
01328       left(n);
01329     else
01330       right(n);
01331   }
01332 
01336 template<int DIRECTION>
01337   inline void
01338   bitset_index_iterator<DIRECTION>::decrement(int n)
01339   {
01340     if (DIRECTION == forwards_iterating)
01341       right(n);
01342     else
01343       left(n);
01344   }
01345 
01346 template<int DIRECTION>
01347   inline int
01348   operator-(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
01349   {
01350     return (DIRECTION == forwards_iterating) ? subtract(i1, i2) : subtract(i2, i1);
01351   }
01352 
01362 template<unsigned int n, int DIRECTION>
01363   class bitset_iterator : public bitset_index_iterator<DIRECTION>,
01364                           public std::iterator<std::random_access_iterator_tag, bitset_digit_t,
01365                                                int, bitset_digit_t*, bitset_digit_t&> {
01366     protected:
01367       bitset_invertible<n, false> const* M_bitset_ptr;
01368     public:
01369       // Default Constructible
01370       bitset_iterator(void);
01371 
01372       // Assignable
01373       bitset_iterator(bitset_iterator const& iter);
01374       bitset_iterator& operator=(bitset_iterator const& iter);
01375       bitset_iterator& operator=(bitset_index_iterator<DIRECTION> const& index);
01376 
01377       // Dereferencable
01378       bitset_digit_t operator*() const;
01379 
01380       // Bi-directional iterator
01381       //
01382       bitset_iterator& operator++();
01383       bitset_iterator operator++(int);
01384       bitset_iterator& operator--();
01385       bitset_iterator operator--(int);
01386 
01387       // Random Access Iterator
01388       //
01389       bitset_iterator& operator+=(int n);
01390       friend bitset_iterator operator+ <>(bitset_iterator const& i, int n);
01391       friend bitset_iterator operator+ <>(int n, bitset_iterator const& i);
01392       bitset_iterator& operator-=(int n);
01393       friend bitset_iterator operator- <>(bitset_iterator const& i, int n);
01394       friend bitset_iterator operator- <>(int n, bitset_iterator const& i);
01395       bitset_digit_t operator[](int n) const;
01396 
01397       // Special
01398       //
01399       bitset_iterator(bitset_invertible<n, false> const* bitset_ptr, int bit);
01400       void find1(void);
01401 
01402 #ifndef __i386__
01403     private:
01404       void find1_forward(void);
01405       void find1_backward(void);
01406 #endif
01407   };
01408 
01409 #ifndef __i386__
01410 template<unsigned int n, int DIRECTION>
01411   void
01412   bitset_iterator<n, DIRECTION>::find1_forward(void)
01413   {
01414     if (M_digit < (int)bitset_base<n>::digits - 1 || (M_mask & bitset_base<n>::valid_bits))
01415     {
01416       register bitset_digit_t mask = M_mask;
01417       while(!(M_bitset_ptr->digit(M_digit) & mask)) 
01418       {
01419         if ((mask <<= 1))
01420           continue;
01421         mask = 1;
01422         while(++M_digit < (int)bitset_base<n>::digits)
01423           if (M_bitset_ptr->digit(M_digit))
01424             break;
01425         if (M_digit == (int)bitset_base<n>::digits)
01426         {
01427           M_digit = (n >> bitset_digit_bits_log2);
01428           mask = static_cast<bitset_digit_t>(1) << (n & (bitset_digit_bits - 1));
01429           break;
01430         }
01431       }
01432       M_mask = mask;
01433     }
01434   }
01435 
01436 template<unsigned int n, int DIRECTION>
01437   void
01438   bitset_iterator<n, DIRECTION>::find1_backward(void)
01439   {
01440     LibEccDout(dc::bitsetfind1, "Entering find1_backward with: " << 
01441         libcw::debug::cwprint_using(*M_bitset_ptr, &bitset_invertible<n, false>::base2_print_on));
01442     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01443     if (M_digit >= 0)
01444     {
01445       register bitset_digit_t mask = M_mask;
01446       if (!(M_bitset_ptr->digit(M_digit) & (mask | (mask - 1))))
01447       {
01448         mask = 1 << (bitset_digit_bits - 1);
01449         do
01450         {
01451           if (--M_digit < 0)
01452           {
01453             M_mask = mask;
01454             return;
01455           }
01456         }
01457         while (!M_bitset_ptr->digit(M_digit));
01458       }
01459       while(!(M_bitset_ptr->digit(M_digit) & mask)) 
01460         mask >>= 1;
01461       M_mask = mask;
01462     }
01463     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01464   }
01465 #endif
01466 
01470 template<unsigned int n, int DIRECTION>
01471   inline void
01472   bitset_iterator<n, DIRECTION>::find1(void)
01473   {
01474     LibEccDout(dc::bitsetfind1, "Input: " << *this);
01475     LibEccDout(dc::bitsetfind1, "Entering find1 with: " << 
01476         libcw::debug::cwprint_using(*M_bitset_ptr, &bitset_invertible<n, false>::base2_print_on));
01477 #ifdef __i386__
01478     int bit_index, digit, ptr;
01479     if (DIRECTION == backwards_iterating)
01480     {
01481       __asm__ __volatile__ (
01482           // %eax: M_index (input) and work variable.
01483           // %ecx: bit_index (work variable).
01484           // %edi: &M_bitset_ptr->digit(M_index/32 - 1) (input) and ptr (work variable).
01485           // %2  : digit (work variable).
01486 
01487           // Make a copy of M_index into %ecx, last time we used M_index.
01488           "movl %%eax,%%ecx\n\t"
01489           // Set %eax to its correct value by deviding it by 32.
01490           "sarl $5,%%eax\n\t"
01491           // Set bit_index to its correct value by taking the modulo 32 of it.
01492           "andl $31,%%ecx\n\t"
01493           // If M_index is -1, do nothing.
01494           "js 1f\n\t"
01495           // Copy the most significant digit, the digit with the
01496           // bit at which we will start the search, into %2.
01497           // digit = M_bitset_ptr->digit(%eax)
01498           "movl 4(%%edi),%2\n\t"
01499           // Shift this digit left until the first bit comes at position 31.
01500           // bit_index = 31 - bit_index
01501           "xorl $31,%%ecx\n\t"
01502           // digit <<= bit_index
01503           "shll %%cl,%2\n\t"
01504           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01505           // This is not needed for the athlon for that reason, but we also need this orl
01506           // for the case that %cl equals zero in which case the ZF is cleared!
01507           "orl %2,%2\n\t"                       
01508           // If there is no bit set in the current digit, goto digit_search.
01509           "jz 5f\n\t"
01510           // Search for the (next) most significant bit set.
01511           // This is slow on i[345]86: 11 + 2*n cycles; only generates 2 uops on a pentium though.
01512           "bsrl %2,%2\n\t"
01513           // Correct M_index to point to this bit.
01514           // %eax <<= 5
01515           "sall $5,%%eax\n\t"
01516           // %2 -= bit_index
01517           "subl %%ecx,%2\n\t"
01518           // M_index = %eax + %2
01519           "addl %2,%%eax\n\t"
01520           // Done.
01521           // goto exit
01522           "jmp 1f\n\t"
01523           ".align 16\n"
01524        "7:\n\t"                         // Main loop.
01525           "movl (%%edi),%2\n\t"
01526           "subl $4,%%edi\n\t"
01527           "testl %2,%2\n\t"
01528           "jnz 6f\n\t"
01529        "5:\n\t"                         // digit_search:
01530           "decl %%eax\n\t"
01531           // Repeat main loop.
01532           "jns 7b\n"    
01533        "4:\n\t"                         // reached_end:
01534           // No set bit found at all.  Set M_index to -1.
01535           "movl $-1,%%eax\n\t"
01536           // Done.
01537           // goto exit
01538           "jmp 1f\n"
01539           // Search for the most significant bit set in this digit.
01540        "6:\n\t"
01541           "bsrl %2,%2\n\t"
01542           // Correct M_index to point to this bit.
01543           "sall $5,%%eax\n\t"
01544           "addl %2,%%eax\n"
01545        "1:"                             // exit:
01546 
01547           : "=a" (M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01548           : "0" (M_index), "3" (M_bitset_ptr->digits_ptr() - 1 + (M_index >> 5))
01549           : "cc"
01550       );
01551     }
01552     else
01553     {
01554       __asm__ __volatile__ (
01555           // %eax: M_index (input) and work variable.
01556           // %ecx: bit_index (work variable).
01557           // %edi: &M_bitset_ptr->digit(M_index/32 + 1) (input) and ptr (work variable).
01558           // %2  : digit (work variable).
01559 
01560           // if (M_index >= n) then goto exit
01561           "cmpl %6,%%eax\n\t"
01562           "jge 1f\n\t"
01563           // Make a copy of M_index into %ecx, last time we used M_index.
01564           "movl %%eax,%%ecx\n\t"
01565           // Set %eax to its correct value by deviding it by 32.
01566           "sarl $5,%%eax\n\t"
01567           // Set bit_index to its correct value by taking the modulo 32 of it.
01568           "andl $31,%%ecx\n\t"
01569           // Copy the least significant digit, the digit with the
01570           // bit at which we will start the search, into %2.
01571           // digit = M_bitset_ptr->digit(%eax)
01572           "movl -4(%%edi),%2\n\t"
01573           // Shift this digit right until the first bit comes at position 0.
01574           // digit >>= bit_index
01575           "shrl %%cl,%2\n\t"
01576           // See http://fatphil.org/x86/pentopt/19.html, chapter 19.3 for why we need the orl.
01577           // This is not needed for the athlon for that reason, but we also need this orl
01578           // for the case that %cl equals zero in which case the ZF is cleared!
01579           "orl %2,%2\n\t"                       
01580           // If there is no bit set in the current digit, goto digit_search.
01581           "jz 5f\n\t"
01582           // Search for the (next) most significant bit set.
01583           // This is slow on i[345]86: 11 + 2*n cycles; only generates 2 uops on a pentium though.
01584           "bsfl %2,%2\n\t"
01585           // Correct M_index to point to this bit.
01586           // %eax <<= 5
01587           "sall $5,%%eax\n\t"
01588           // %2 -= bit_index
01589           "addl %%ecx,%2\n\t"
01590           // M_index = %eax + %2
01591           "addl %2,%%eax\n\t"
01592           // Done.
01593           // goto exit
01594           "jmp 1f\n\t"
01595           ".align 16\n"
01596        "7:\n\t"                         // Main loop.
01597           "movl (%%edi),%2\n\t"
01598           "addl $4,%%edi\n\t"
01599           "testl %2,%2\n\t"
01600           "jnz 6f\n\t"
01601        "5:\n\t"                         // digit_search:
01602           "incl %%eax\n\t"
01603           "cmpl %7, %%eax\n\t"
01604           // Repeat main loop.
01605           "jnz 7b\n"            
01606        "4:\n\t"                         // reached_end:
01607           // No set bit found at all.  Set M_index to n.
01608           "movl %6,%%eax\n\t"
01609           // Done.
01610           // goto exit
01611           "jmp 1f\n"
01612           // Search for the least significant bit set in this digit.
01613        "6:\n\t"
01614           "bsfl %2,%2\n\t"
01615           // Correct M_index to point to this bit.
01616           "sall $5,%%eax\n\t"
01617           "addl %2,%%eax\n"
01618        "1:"                             // exit:
01619 
01620           : "=a" (M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01621           : "0" (M_index), "3" (M_bitset_ptr->digits_ptr() + 1 + (M_index >> 5)), "i" (n), "i" (bitset_base<n>::digits)
01622           : "cc"
01623       );
01624     }
01625 #else
01626     if (DIRECTION == forwards_iterating)
01627       find1_forward();
01628     else
01629       find1_backward();
01630 #endif
01631     LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01632     return;
01633   }
01634 
01635 
01639 template<unsigned int n, int DIRECTION>
01640   inline
01641   bitset_iterator<n, DIRECTION>::bitset_iterator(void)
01642   {
01643   }
01644 
01648 template<unsigned int n, int DIRECTION>
01649   inline
01650   bitset_iterator<n, DIRECTION>::bitset_iterator(bitset_invertible<n, false> const* bitset_ptr, int bit) :
01651       bitset_index_iterator<DIRECTION>(bit), M_bitset_ptr(bitset_ptr)
01652   {
01653   }
01654 
01658 template<unsigned int n, int DIRECTION>
01659   inline
01660   bitset_iterator<n, DIRECTION>::bitset_iterator(bitset_iterator const& iter) :
01661       bitset_index_iterator<DIRECTION>(iter), M_bitset_ptr(iter.M_bitset_ptr)
01662   {
01663   }
01664 
01668 template<unsigned int n, int DIRECTION>
01669   inline bitset_iterator<n, DIRECTION>&
01670   bitset_iterator<n, DIRECTION>::operator=(bitset_iterator<n, DIRECTION> const& iter)
01671   {
01672 #ifdef __i386__
01673     M_index = iter.M_index;
01674 #else
01675     M_digit = iter.M_digit;
01676     M_mask = iter.M_mask;
01677 #endif
01678     M_bitset_ptr = iter.M_bitset_ptr;
01679     return *this;
01680   }
01681 
01682 template<unsigned int n, int DIRECTION>
01683   inline bitset_iterator<n, DIRECTION>&
01684   bitset_iterator<n, DIRECTION>::operator=(bitset_index_iterator<DIRECTION> const& index)
01685   {
01686 #ifdef __i386__
01687     M_index = index.get_index();
01688 #else
01689     M_digit = index.get_digit();
01690     M_mask = index.get_mask();
01691 #endif
01692     return *this;
01693   }
01694 
01698 template<unsigned int n, int DIRECTION>
01699   inline bitset_iterator<n, DIRECTION>&
01700   bitset_iterator<n, DIRECTION>::operator++()
01701   {
01702     increment();
01703     return *this;
01704   }
01705 
01709 template<unsigned int n, int DIRECTION>
01710   inline bitset_iterator<n, DIRECTION>
01711   bitset_iterator<n, DIRECTION>::operator++(int)
01712   {
01713     bitset_iterator prev(*this);
01714     increment();
01715     return prev;
01716   }
01717 
01721 template<unsigned int n, int DIRECTION>
01722   inline bitset_iterator<n, DIRECTION>&
01723   bitset_iterator<n, DIRECTION>::operator--()
01724   {
01725     decrement();
01726     return *this;
01727   }
01728 
01732 template<unsigned int n, int DIRECTION>
01733   inline bitset_iterator<n, DIRECTION>
01734   bitset_iterator<n, DIRECTION>::operator--(int)
01735   {
01736     bitset_iterator prev(*this);
01737     decrement();
01738     return prev;
01739   }
01740 
01747 template<unsigned int n, int DIRECTION>
01748   inline bitset_digit_t
01749   bitset_iterator<n, DIRECTION>::operator*() const
01750   {
01751 #ifdef __i386__
01752     register unsigned int M_digit = M_index;
01753     register bitset_digit_t M_mask = 1;
01754     register unsigned short shift = M_index & (ECC_BITS - 1);
01755     M_digit >>= bitset_digit_bits_log2;
01756     M_mask <<= shift;
01757 #endif
01758     return (M_bitset_ptr->digit(M_digit) & M_mask);
01759   }
01760 
01764 template<unsigned int n, int DIRECTION>
01765   inline bitset_iterator<n, DIRECTION>&
01766   bitset_iterator<n, DIRECTION>::operator+=(int d)
01767   {
01768     increment(d);
01769     return *this;
01770   }
01771 
01775 template<unsigned int n, int DIRECTION>
01776   inline bitset_iterator<n, DIRECTION>&
01777   bitset_iterator<n, DIRECTION>::operator-=(int d)
01778   {
01779     decrement(d);
01780     return *this;
01781   }
01782 
01786 template<unsigned int n, int DIRECTION>
01787   inline bitset_iterator<n, DIRECTION>
01788   operator+(bitset_iterator<n, DIRECTION> const& i, int d)
01789   {
01790     bitset_iterator<n, DIRECTION> result(i);
01791     return result += d;
01792   }
01793 
01797 template<unsigned int n, int DIRECTION>
01798   inline bitset_iterator<n, DIRECTION>
01799   operator+(int d, bitset_iterator<n, DIRECTION> const& i)
01800   {
01801     bitset_iterator<n, DIRECTION> result(i);
01802     return result += d;
01803   }
01804 
01808 template<unsigned int n, int DIRECTION>
01809   inline bitset_iterator<n, DIRECTION>
01810   operator-(bitset_iterator<n, DIRECTION> const& i, int d)
01811   {
01812     bitset_iterator<n, DIRECTION> result(i);
01813     return result -= d;
01814   }
01815 
01819 template<unsigned int n, int DIRECTION>
01820   inline bitset_iterator<n, DIRECTION>
01821   operator-(int d, bitset_iterator<n, DIRECTION> const& i)
01822   {
01823     bitset_iterator<n, DIRECTION> result(i);
01824     return result -= d;
01825   }
01826 
01830 template<unsigned int n, int DIRECTION>
01831   inline bitset_digit_t
01832   bitset_iterator<n, DIRECTION>::operator[](int d) const
01833   {
01834     return *(*this + d);
01835   }
01836 
01837 //--------------------------------------------------------------------------------------------------------------------------
01844 template<unsigned int n>
01845   class bitset : public bitset_invertible<n, false> {
01846     public:
01847       // Constructors.
01848       bitset(void);
01849       bitset(std::string const&);
01850       explicit bitset(bitset_digit_t low_bits);
01851       // This definition must be here, inside the template class declaration because
01852       // otherwise the compiler (2.95 - 3.1) barfs.
01858       bitset(bitset_digit_t const (&v)[bitset_base<n>::digits])
01859       {
01860 #if ECC_DEBUG
01861         assert( (v[digits - 1] & ~valid_bits) == 0 );
01862 #endif
01863         std::memcpy(this->vector, v, sizeof(this->vector));
01864       }
01865 
01866       // Copy constructors.
01867       template<unsigned int m, bool inverted>
01868         bitset(bitset_invertible<m, inverted> const&);
01869       template<unsigned int m, bool i1, bool i2, typename OP>
01870         bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr);
01871 
01872       // Assignment operators.
01873       bitset& operator=(bitset const&);
01874       template<typename Expression>
01875         bitset& operator=(Expression const&);
01876 
01877       // Perform AND, OR, XOR operations
01878       template<typename Expression>
01879         bitset& operator&=(Expression const&);
01880       template<typename Expression>
01881         bitset& operator|=(Expression const&);
01882       template<typename Expression>
01883         bitset& operator^=(Expression const&);
01884 
01885     public:
01886       // Shift bitset left or right and perform operation with result.
01887       template<unsigned int shift, class DIRECTION, class OPERATION>
01888         void shift_op(bitset& result) const;
01889 
01890       // Slower functions for shifting an arbitrary distance.
01891       bitset& operator<<=(unsigned int shift);
01892       bitset& operator>>=(unsigned int shift);
01893 
01894       // Rotate left or right
01895       template<unsigned int shift, class DIRECTION>                     // Return a copy rotated `shift' bits in `DIRECTION'.
01896         void rotate(bitset& result) const;
01897 
01898       // Single bit operations
01899       bool test(size_t n) const;                                        // Return true if bit `n' is set.
01900       bool odd(void) const;                                             // Return true if the vector has an odd number of bits set.
01901       void set(size_t n);                                               // Set bit `n'.
01902       void clear(size_t n);                                             // Clear bit `n'.
01903       void flip(size_t n);                                              // Toggle bit `n'.
01904 
01905       // Single bit operations using iterators.
01906       bool test(bitset_index const& index) const;                       // Return true if bit refered to by `index' is set.
01907       void set(bitset_index const& index);                              // Set bit refered to by `index'.
01908       void clear(bitset_index const& index);                            // Clear bit refered to by `index'.
01909       void flip(bitset_index const& index);                             // Toggle bit refered to by `index'.
01910 
01911       // Single bit operations at a constant position
01912       template<unsigned int pos>
01913         bool test(void) const;                                          // Return true if bit `pos' is set.
01914       template<unsigned int pos>
01915         void set(void);                                                 // Set bit `pos'.
01916       template<unsigned int pos>
01917         void clear(void);                                               // Clear bit `pos'.
01918       template<unsigned int pos>
01919         void flip(void);                                                // Toggle bit `pos'.
01920 
01921       // Other functions
01922       bitset& reset(void);
01923       void setall(void);
01924       bool any(void) const;
01925 
01926     public:
01927       // Iterator stuff.
01929       typedef bitset_iterator<n, forwards_iterating> const_iterator;
01931       typedef bitset_iterator<n, backwards_iterating> const_reverse_iterator;
01933       const_iterator begin(void) const { return const_iterator(this, 0); }
01935       const_iterator end(void) const { return const_iterator(this, n); }
01937       const_reverse_iterator rbegin(void) const { return const_reverse_iterator(this, n - 1); }
01939       const_reverse_iterator rend(void) const { return const_reverse_iterator(this, -1); }
01940 
01941       template<unsigned int m>
01942         void xor_with_zero_padded(bitset<m> const& bitset, int lsb, int msb, int shift);
01943   };
01944 
01961 template<unsigned int n>
01962   template<unsigned int m>
01963 #ifdef __i386__
01964   inline void
01965 #endif
01966   bitset<n>::xor_with_zero_padded(bitset<m> const& bitset, int lsb, int msb, int shift)
01967   {
01968 #ifdef __i386__
01969     libecc_shift_xorassign(vector, bitset.digits_ptr(), lsb, msb, shift);
01970 #else
01971     int digit1 = lsb >> bitset_digit_bits_log2;
01972     int digit2 = msb >> bitset_digit_bits_log2;
01973     bitset_digit_t d1 = 0;
01974     if (shift < 0)
01975     {
01976       unsigned int bitshift = (-shift) & (bitset_digit_bits - 1);
01977       unsigned int digitshift = (-shift) >> bitset_digit_bits_log2;
01978       if (bitshift == 0)
01979       {
01980         for (int digit = digit2; digit >= digit1; --digit)
01981         {
01982           bitset_digit_t d2 = bitset.digit(digit);
01983           vector[digit - digitshift] ^= d2;
01984           d1 = d2;
01985         }
01986       }
01987       else
01988       {
01989         for (int digit = digit2; digit >= digit1; --digit)
01990         {
01991           bitset_digit_t d2 = bitset.digit(digit);
01992           vector[digit - digitshift] ^= (d2 >> bitshift) | (d1 << (32 - bitshift));
01993           d1 = d2;
01994         }
01995         vector[digit1 - 1 - digitshift] ^= (d1 << (32 - bitshift));
01996       }
01997     }
01998     else if (shift > 0)
01999     {
02000       unsigned int bitshift = shift & (bitset_digit_bits - 1);
02001       unsigned int digitshift = shift >> bitset_digit_bits_log2;
02002       if (bitshift == 0)
02003       {
02004         for (int digit = digit1; digit <= digit2; ++digit)
02005         {
02006           bitset_digit_t d2 = bitset.digit(digit);
02007           vector[digit + digitshift] ^= d2;
02008           d1 = d2;
02009         }
02010       }
02011       else
02012       {
02013         for (int digit = digit1; digit <= digit2; ++digit)
02014         {
02015           bitset_digit_t d2 = bitset.digit(digit);
02016           vector[digit + digitshift] ^= (d2 << bitshift) | (d1 >> (32 - bitshift));
02017           d1 = d2;
02018         }
02019         vector[digit2 + 1 + digitshift] ^= (d1 >> (32 - bitshift));
02020       }
02021     }
02022     else
02023     {
02024       for (int digit = digit1; digit <= digit2; ++digit)
02025         vector[digit] ^= bitset.digit(digit);
02026     }
02027 #endif
02028   }
02029 
02033 template<unsigned int n>
02034   inline
02035   bitset<n>::bitset(void)
02036   {
02037   }
02038 
02044 template<unsigned int n>
02045   inline
02046   bitset<n>::bitset(bitset_digit_t low_bits)
02047   {
02048 #if ECC_DEBUG
02049     assert( digits > 1 || (low_bits & ~valid_bits) == 0 );
02050 #endif
02051     std::memset(this->vector, 0, sizeof(this->vector));
02052     this->vector[0] = low_bits;
02053   }
02054 
02058 template<unsigned int n>
02059   void
02060   bitset<n>::setall(void)
02061   {
02062     this->vector[digits - 1] = valid_bits;
02063     if (digits > 1)
02064     {
02065       int d = digits - 2;
02066       do { this->vector[d] = ~static_cast<bitset_digit_t>(0); } while(--d >= 0);
02067     }
02068   }
02069 
02094 template<unsigned int n>
02095   template<typename Expression>
02096     inline
02097     bitset<n>& bitset<n>::operator=(Expression const& expr)
02098     {
02099       this->assign(expr, Operator::bitsetAssign());
02100       return *this;
02101     }
02102 
02103 // Special case, need to define this or else we'd get a default assignment operator.
02104 template<unsigned int n>
02105   inline bitset<n>&
02106   bitset<n>::operator=(bitset const& expr)
02107   {
02108     this->assign(expr, Operator::bitsetAssign());
02109     return *this;
02110   }
02111 
02128 template<unsigned int n>
02129   template<unsigned int m, bool inverted>
02130     inline bitset<n>::bitset(bitset_invertible<m, inverted> const& bits) : bitset_invertible<n, false>(bits)
02131     {
02132     }
02133 
02139 template<unsigned int n>
02140   template<unsigned int m, bool i1, bool i2, typename OP>
02141     inline bitset<n>::bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr) : bitset_invertible<n, false>(expr)
02142     {
02143     }
02144 
02156 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02157   bool operator==(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02158   {
02159     unsigned int d;
02160     if (bitset_invertible<n1, inverted1>::digits > bitset_invertible<n2, inverted2>::digits)
02161     {
02162       d = bitset_base<n1>::digits - 1;
02163       do
02164       {
02165         if (bits1.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02166           return false;
02167       }
02168       while (--d != bitset_base<n2>::digits - 1);
02169     }
02170     if (bitset_base<n2>::digits > bitset_base<n1>::digits)
02171     {
02172       d = bitset_base<n2>::digits - 1;
02173       do
02174       {
02175         if (bits2.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02176           return false;
02177       }
02178       while (--d != bitset_base<n1>::digits - 1);
02179     }
02180     if (bitset_base<n1>::digits > 1 && bitset_base<n2>::digits > 1)
02181     {
02182       if (bitset_base<n1>::digits == bitset_base<n2>::digits)
02183         d = bitset_base<n1>::digits - 1;
02184       do
02185       {
02186         if (inverted1 == inverted2)
02187         {
02188           if (bits1.vector[d] != bits2.vector[d])
02189             return false;
02190         }
02191         else
02192         {
02193           if (bits1.vector[d] != ~(bits2.vector[d]))
02194             return false;
02195         }
02196       }
02197       while(--d != 0);
02198     }
02199     if (inverted1 != inverted2)
02200       return (bits1.vector[0] == ~(bits2.vector[0]));
02201     return (bits1.vector[0] == bits2.vector[0]);
02202   }
02203 
02209 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02210   inline bool
02211   operator!=(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02212   {
02213     return !(bits1 == bits2);
02214   }
02215 
02220 template<unsigned int n>
02221   template<typename Expression>
02222     inline bitset<n>&
02223     bitset<n>::operator&=(Expression const& expr)
02224     {
02225       this->assign(expr, Operator::bitsetANDAssign());
02226       return *this;
02227     }
02228 
02233 template<unsigned int n>
02234   template<typename Expression>
02235     inline bitset<n>&
02236     bitset<n>::operator|=(Expression const& expr)
02237     {
02238       this->assign(expr, Operator::bitsetORAssign());
02239       return *this;
02240     }
02241 
02246 template<unsigned int n>
02247   template<typename Expression>
02248     inline bitset<n>&
02249     bitset<n>::operator^=(Expression const& expr)
02250     {
02251       this->assign(expr, Operator::bitsetXORAssign());
02252       return *this;
02253     }
02254 
02259 template<unsigned int m, bool inverted1, bool inverted2>
02260   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>
02261   operator&(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02262     {
02263       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>(arg1, arg2);
02264     }
02265 
02270 template<unsigned int m, bool inverted1, bool inverted2>
02271   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>
02272   operator|(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02273     {
02274       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>(arg1, arg2);
02275     }
02276 
02281 template<unsigned int m, bool inverted1, bool inverted2>
02282   Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>
02283   operator^(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02284     {
02285       return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>(arg1, arg2);
02286     }
02287 
02291 struct assign {
02292   static int const id = 1;
02293   static bool const __clear = true;
02294   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02295   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02296 };
02297 
02301 struct exor {
02302   static int const id = 2;
02303   static bool const __clear = false;
02304   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02305   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02306 };
02307 
02308 #ifndef HIDE_FROM_DOXYGEN
02309 struct rotate_phase1 {
02310   static int const id = 3;
02311   static bool const __clear = false;
02312   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02313   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02314 };
02315 
02316 struct rotate_phase2 {
02317 public:
02318   static int const id = 4;
02319   static bool const __clear = false;
02320   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02321   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 |= digit2; }
02322 };
02323 #endif
02324 
02335 template<unsigned int n>
02336   template<unsigned int shift, class DIRECTION, class OPERATION>
02337     void
02338     bitset<n>::shift_op(bitset& result) const
02339     {
02340       LibEccDout(dc::bitsetshift, "Entering shift_op<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() <<
02341           ", " << type_info_of<OPERATION>().demangled_name() << '>');
02342       LibEccDout(dc::bitsetshift|flush_cf, "Input : " <<
02343           cwprint_using(*static_cast<bitset_invertible<n, false> const*>(this), &bitset<n>::base2_print_on));
02344       if (shift == 1)
02345       {
02346         // Specialization for shift == 1.
02347         // digit_shift = 0
02348         // bit_shift = 1
02349         // zeroed_digits = 0 (likely and if not - then assumed).
02350         // Here we scan in the opposite direction of when shift > 1.
02351         static unsigned int const initial = DIRECTION::__left ? 0 : digits - 1;
02352         static unsigned int const count = digits - ((DIRECTION::__left && has_excess_bits) ? 1 : 0);
02353 #ifdef __i386__
02354         if (count)
02355         {
02356           bitset_digit_t const volatile* ptr1;
02357           bitset_digit_t volatile* ptr2;
02358           int c;
02359           if (DIRECTION::__left)
02360           {
02361             if (OPERATION::id == libecc::exor::id)
02362             {
02363               if (has_excess_bits)
02364                 LIBECC_ASMSHIFTLEFT(
02365                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02366                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"),
02367                     LIBECC_ASMSHIFTLEFT_FINISH("xorl (%%edi),%%edx\n\t"));
02368               else
02369                 LIBECC_ASMSHIFTLEFT(
02370                     LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02371                     LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"), "");
02372             }
02373             else if (OPERATION::id == libecc::rotate_phase2::id)
02374             {
02375               if (has_excess_bits)
02376                 LIBECC_ASMSHIFTLEFT(
02377                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02378               else
02379                 LIBECC_ASMSHIFTLEFT(
02380                     LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", "");
02381             }
02382             else
02383             {
02384               if (has_excess_bits)
02385                 LIBECC_ASMSHIFTLEFT("", "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02386               else
02387                 LIBECC_ASMSHIFTLEFT("", "", "");
02388             }
02389           }
02390           else if (count > 1)
02391           {
02392             if (OPERATION::id == libecc::exor::id)
02393               LIBECC_ASMSHIFTRIGHT1(
02394                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02395                   LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP2_DESTINATION "," LIBECC_WORKREG),
02396                   LIBECC_PRESERVE_CF_CLOBBER);
02397             else if (OPERATION::id == libecc::rotate_phase2::id)
02398               LIBECC_ASMSHIFTRIGHT1(
02399                   LIBECC_RIGHT_PRESERVE_CF("orl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02400                   "",
02401                   LIBECC_PRESERVE_CF_CLOBBER);
02402             else
02403               LIBECC_ASMSHIFTRIGHT1(
02404                   "",
02405                   "",
02406                   LIBECC_CLOBBER);
02407           }
02408           else
02409           {
02410             if (OPERATION::id == libecc::exor::id)
02411               LIBECC_ASMSHIFTRIGHT0("xorl 4(%%edi), %%edx\n\t");
02412             else if (OPERATION::id == libecc::rotate_phase2::id)
02413               LIBECC_ASMSHIFTRIGHT0("orl 4(%%edi), %%edx\n\t");
02414             else
02415               LIBECC_ASMSHIFTRIGHT0("");
02416           }
02417         }
02418         else if (DIRECTION::__left && has_excess_bits)
02419           OPERATION::op(result.vector[0], ((vector[0] << 1) & valid_bits));
02420 #else
02421         static unsigned int complement_shift = bitset_digit_bits - 1;
02422         static bitset_digit_t const mask1 = DIRECTION::__left ? (1 << complement_shift) : 1;
02423         static bitset_digit_t const mask2 = DIRECTION::__right ? (1 << complement_shift) : 1;
02424         bitset_digit_t const* ptr1 = &this->vector[initial];
02425         bitset_digit_t* ptr2 = &result.vector[initial];
02426         bool carry;
02427         if (count)
02428         {
02429           bitset_digit_t digit = *ptr1;
02430           carry = (digit & mask1);
02431           if (DIRECTION::__left)
02432             digit <<= 1;
02433           else
02434             digit >>= 1;
02435           OPERATION::mixed_op(*ptr2, digit);
02436           for (int c = count - 1; c; --c)
02437           {
02438             ptr1 -= DIRECTION::direction;
02439             ptr2 -= DIRECTION::direction;
02440             digit = *ptr1;
02441             if (carry)
02442             {
02443               carry = (digit & mask1);
02444               if (DIRECTION::__left)
02445                 digit <<= 1;
02446               else
02447                 digit >>= 1;
02448               digit |= mask2;
02449             }
02450             else
02451             {
02452               carry = (digit & mask1);
02453               if (DIRECTION::__left)
02454                 digit <<= 1;
02455               else
02456                 digit >>= 1;
02457             }
02458             OPERATION::op(*ptr2, digit);
02459           }
02460         }
02461         if (DIRECTION::__left && has_excess_bits)
02462         {
02463           bitset_digit_t digit;
02464           if (count)
02465             digit = ptr1[-DIRECTION::direction];
02466           else
02467             digit = *ptr1;
02468           digit <<= 1;
02469           if (count && carry)
02470             digit |= mask2;
02471           if (count)
02472             OPERATION::op(ptr2[-DIRECTION::direction], (digit & valid_bits));
02473           else
02474             OPERATION::op(*ptr2, (digit & valid_bits));
02475         }
02476 #endif
02477       }
02478       else
02479       {
02480         static unsigned int const digit_shift = shift / bitset_digit_bits;
02481         static unsigned int const bit_shift = shift % bitset_digit_bits;
02482 
02483         static unsigned int const zeroed_digits =
02484           DIRECTION::__left ? ((shift < n) ? digit_shift : digits)
02485                             : ((bitset_digit_bits - number_of_valid_bits + shift) / bitset_digit_bits);
02486 
02487         if (zeroed_digits < digits)
02488         {
02489           static unsigned int const complement_shift = (bit_shift == 0) ? 0 : bitset_digit_bits - bit_shift;
02490           static unsigned int const initial_to = DIRECTION::__right ? 0 : digits - 1;
02491           static unsigned int const initial_from = initial_to + DIRECTION::direction * digit_shift;
02492           static unsigned int const final_from = DIRECTION::__left ? 0 : digits - 1;
02493 
02494           register bitset_digit_t digit = this->vector[initial_from];
02495           if (initial_from != final_from)
02496           {
02497             register bitset_digit_t next_digit;
02498             unsigned int to = initial_to;
02499             unsigned int from = initial_from + DIRECTION::direction;
02500             if (from != final_from)
02501               do
02502               {
02503                 next_digit = this->vector[from];
02504                 if (bit_shift != 0)
02505                 {
02506                   if (DIRECTION::direction == -1)
02507                     digit <<= bit_shift;
02508                   else
02509                     digit >>= bit_shift;
02510                   digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02511                 }
02512                 OPERATION::op(result.vector[to], digit);
02513                 digit = next_digit;
02514                 to += DIRECTION::direction;
02515                 from += DIRECTION::direction;
02516               }
02517               while (from != final_from);
02518             if (DIRECTION::__left || bit_shift < number_of_valid_bits || bit_shift != 0)
02519               next_digit = this->vector[final_from];
02520             if (bit_shift != 0)
02521             {
02522               if (DIRECTION::direction == -1)
02523                 digit <<= bit_shift;
02524               else
02525                 digit >>= bit_shift;
02526               digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02527             }
02528             if (DIRECTION::__left || bit_shift < number_of_valid_bits)
02529             {
02530               OPERATION::op(result.vector[final_from - DIRECTION::direction * (digit_shift + 1)], digit);
02531               digit = DIRECTION::shift_copy(next_digit, bit_shift);
02532             }
02533           }
02534           else
02535           {
02536             if (DIRECTION::direction == -1)
02537               digit <<= bit_shift;
02538             else
02539               digit >>= bit_shift;
02540           }
02541           static bool const have_mixed_digit = shift != 0 && (DIRECTION::__left ? shift : (n - shift)) % bitset_digit_bits != 0;
02542           static unsigned int const last_digit = (DIRECTION::__left ? shift : (n - 1 - shift)) / bitset_digit_bits;
02543           if (have_mixed_digit)
02544             OPERATION::mixed_op(result.vector[last_digit], digit);
02545           else
02546             OPERATION::op(result.vector[last_digit], digit);
02547           if (DIRECTION::__left && has_excess_bits)
02548             result.vector[digits - 1] &= valid_bits;
02549         }
02550         if (OPERATION::__clear && zeroed_digits > 0)
02551         {
02552           static unsigned int const final_to = DIRECTION::__left ? 0 : digits - 1;
02553           static unsigned int const initial_to = final_to - DIRECTION::direction * (zeroed_digits - 1);
02554           unsigned int to = initial_to;
02555           if (to != final_to)
02556             do
02557             {
02558               result.vector[to] = 0;
02559               to += DIRECTION::direction;
02560             }
02561             while(to != final_to);
02562           result.vector[to] = 0;
02563         }
02564       }
02565       LibEccDout(dc::bitsetshift|flush_cf, "Output: " <<
02566           cwprint_using(*static_cast<bitset_invertible<n, false> const*>(&result), &bitset<n>::base2_print_on));
02567     }
02568 
02572 template<unsigned int n>
02573   bitset<n>&
02574   bitset<n>::operator<<=(unsigned int shift)
02575   {
02576     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02577     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02578     int digit1 = digits - digit_shift - 2;
02579     bitset_digit_t d0 = (digit1 >= -1) ? vector[digit1 + 1] : 0;
02580     for (int digit_to = digits - 1; digit_to >= 0; --digit_to)
02581     {
02582       bitset_digit_t d1 = (digit1 >= 0) ? vector[digit1] : 0;
02583       if (bit_shift == 0)
02584         vector[digit_to] = d0;
02585       else
02586         vector[digit_to] = (d0 << bit_shift) | (d1 >> (bitset_digit_bits - bit_shift));
02587       d0 = d1;
02588       --digit1;
02589     }
02590     if (has_excess_bits)
02591       this->vector[digits - 1] &= valid_bits;           // Reset possibly set excess bits.
02592     return *this;
02593   }
02594 
02598 template<unsigned int n>
02599   bitset<n>&
02600   bitset<n>::operator>>=(unsigned int shift)
02601   {
02602     unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02603     unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02604     int digit1 = digit_shift + 1;
02605     bitset_digit_t d0 = (digit1 <= digits) ? vector[digit1 - 1] : 0;
02606     for (int digit_to = 0; digit_to < digits; ++digit_to)
02607     {
02608       bitset_digit_t d1 = (digit1 < digits) ? vector[digit1] : 0;
02609       if (bit_shift == 0)
02610         vector[digit_to] = d0;
02611       else
02612         vector[digit_to] = (d0 >> bit_shift) | (d1 << (bitset_digit_bits - bit_shift));
02613       d0 = d1;
02614       ++digit1;
02615     }
02616     return *this;
02617   }
02618 
02635 template<unsigned int n>
02636   bitset<n>::bitset(std::string const& input)
02637   {
02638     reset();                                            // Reset internal digits to zero.
02639     unsigned int d = 0;                                 // Current index of internal digit.
02640     unsigned int u = 0;                                 // Current bit-shift of input digit relative to internal digit.
02641 
02642     for (std::string::const_reverse_iterator iter = input.rbegin(); iter != input.rend(); ++iter)       // Read right to left.
02643     {
02644       bitset_digit_t c = toupper(*iter);                // Get next hexadecimal input character.
02645       if (c == ' ')                                     // Skip spaces.
02646         continue;
02647       if (c < '0')                                      // Terminate reading when not a hexadecimal character.
02648         break;
02649       if (c <= '9')
02650         c -= '0';                                       // Set c to the value that the input character represents.
02651       else
02652       {
02653         if (c > 'F')
02654           break;
02655         if (c >= 'A')
02656           c -= ('A' - 10);
02657         else
02658           break;
02659       }
02660       this->vector[d] |= c << u;                        // Set internal bits.
02661       if ((u += 4) == bitset_digit_bits)                // Update bit/digit 'pointers'.
02662       {
02663         u = 0;
02664         if (++d == digits)                              // Terminate reading when bitset is full.
02665           break;
02666       }
02667     }
02668     if (has_excess_bits)
02669       this->vector[digits - 1] &= valid_bits;           // Reset possibly set excess bits.
02670   }
02671 
02675 template<unsigned int n>
02676   std::istream&
02677   operator>>(std::istream& is, bitset<n>& bitsetx)
02678   {
02679     std::string tmp;
02680     is >> tmp;
02681     bitsetx.bitset(tmp);
02682     return is;
02683   }
02684 
02688 template<unsigned int n>
02689   std::ostream&
02690   operator<<(std::ostream& os, bitset<n> const& bits)
02691   {
02692     // Hexadecimal representation
02693     os.fill('0');
02694     os << std::hex;
02695     for (int d = bitset<n>::digits - 1; d >= 0; --d)
02696     {
02697       os.width((d == bitset<n>::digits - 1 && bitset<n>::has_excess_bits) ?
02698           (((n % bitset_digit_bits) - 1) / 4 + 1) :
02699           (bitset_digit_bits / 4));
02700       os << bits.digit(d);
02701       if (d > 0)
02702         os << ' ';
02703     }
02704     os << std::dec;
02705     return os;
02706   }
02707 
02711 template<unsigned int n>
02712   bitset<n>&
02713   bitset<n>::reset(void)
02714   {
02715     std::memset(this->vector, 0, sizeof(this->vector));
02716     return *this;
02717   }
02718 
02722 template<unsigned int n>
02723   inline bool
02724   bitset<n>::test(size_t pos) const
02725   {
02726 #ifdef __i386__
02727     int result;
02728     __asm__ __volatile__ (
02729         "btl %2, %1\n\t"
02730         "sbbl %0, %0"
02731         : "=r" (result)
02732         : "m" ((*(bitset_digit_t volatile*)this->vector)), "Ir" (pos));
02733     return result;
02734 #else
02735     unsigned int d = pos / bitset_digit_bits;
02736     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02737     return (this->vector[d] & mask);
02738 #endif
02739   }
02740 
02744 template<unsigned int n>
02745   template<unsigned int pos>
02746     inline bool
02747     bitset<n>::test(void) const
02748     {
02749       static unsigned int const d = pos / bitset_digit_bits;
02750       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02751       return (this->vector[d] & mask);
02752     }
02753 
02757 template<unsigned int n>
02758   inline bool
02759   bitset<n>::test(bitset_index const& index) const
02760   {
02761 #ifdef __i386__
02762     return this->test(index.get_index());
02763 #else
02764     return (this->vector[index.get_digit()] & index.get_mask());
02765 #endif
02766   }
02767 
02771 template<unsigned int n>
02772   inline void
02773   bitset<n>::set(size_t pos)
02774   {
02775 #ifdef __i386__
02776     __asm__ __volatile__ (
02777         "btsl %1, %0"
02778         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02779         : "Ir" (pos));
02780 
02781 #else
02782     unsigned int d = pos / bitset_digit_bits;
02783     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02784     this->vector[d] |= mask;
02785 #endif
02786   }
02787 
02791 template<unsigned int n>
02792   inline void
02793   bitset<n>::set(bitset_index const& index)
02794   {
02795 #ifdef __i386__
02796     this->set(index.get_index());
02797 #else
02798     this->vector[index.get_digit()] |= index.get_mask();
02799 #endif
02800   }
02801 
02805 template<unsigned int n>
02806   template<unsigned int pos>
02807     inline void
02808     bitset<n>::set(void)
02809     {
02810       static unsigned int const d = pos / bitset_digit_bits;
02811       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02812       this->vector[d] |= mask;
02813     }
02814 
02818 template<unsigned int n>
02819   inline void
02820   bitset<n>::clear(size_t pos)
02821   {
02822 #ifdef __i386__
02823     __asm__ __volatile__ (
02824         "btrl %1, %0"
02825         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02826         : "Ir" (pos)
02827     );
02828 #else
02829     unsigned int d = pos / bitset_digit_bits;
02830     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02831     this->vector[d] &= ~mask;
02832 #endif
02833   }
02834 
02838 template<unsigned int n>
02839   inline void
02840   bitset<n>::clear(bitset_index const& index)
02841   {
02842 #ifdef __i386__
02843     this->clear(index.get_index());
02844 #else
02845     this->vector[index.get_digit()] &= ~(index.get_mask());
02846 #endif
02847   }
02848 
02852 template<unsigned int n>
02853   template<unsigned int pos>
02854     inline void
02855     bitset<n>::clear(void)
02856     {
02857       static unsigned int const d = pos / bitset_digit_bits;
02858       static bitset_digit_t const mask = ~(static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits));
02859       this->vector[d] &= mask;
02860     }
02861 
02865 template<unsigned int n>
02866   inline void
02867   bitset<n>::flip(size_t pos)
02868   {
02869 #ifdef __i386__
02870     __asm__ __volatile__ (
02871         "btcl %1, %0"
02872         : "=m" ((*(bitset_digit_t volatile*)this->vector))
02873         : "Ir" (pos)
02874     );
02875 #else
02876     unsigned int d = pos / bitset_digit_bits;
02877     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02878     this->vector[d] ^= mask;
02879 #endif
02880   }
02881 
02885 template<unsigned int n>
02886   inline void
02887   bitset<n>::flip(bitset_index const& index)
02888   {
02889 #ifdef __i386__
02890     this->flip(index.get_index());
02891 #else
02892     this->vector[index.get_digit()] ^= index.get_mask();
02893 #endif
02894   }
02895 
02899 template<unsigned int n>
02900   template<unsigned int pos>
02901     inline void
02902     bitset<n>::flip(void)
02903     {
02904       static unsigned int const d = pos / bitset_digit_bits;
02905       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02906       this->vector[d] ^= mask;
02907     }
02908 
02912 template<unsigned int n>
02913   bool
02914   bitset<n>::any(void) const
02915   {
02916     unsigned int to = digits - 1;
02917     if (digits > 1)
02918       do
02919       {
02920         if (this->vector[to] != 0)
02921           return true;
02922         --to;
02923       }
02924       while(to != 0);
02925     return (this->vector[0] != 0);
02926   }
02927 
02928 static bool const oddnumberofbits[] = {
02929   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02930   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02931   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02932   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02933   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02934   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02935   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02936   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02937   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02938   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02939   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02940   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02941   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02942   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02943   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02944   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false };
02945 
02949 template<unsigned int n>
02950   bool
02951   bitset<n>::odd(void) const
02952   {
02953     unsigned int from = digits - 1;
02954     bitset_digit_t sum = this->vector[0];
02955     if (digits > 1)
02956       do
02957       {
02958         sum ^= this->vector[from];
02959         --from;
02960       }
02961       while(from != 0);
02962     bitset_digit_t ssum = sum;
02963     if (sizeof(bitset_digit_t) >= 2)
02964     {
02965       ssum >>= (bitset_digit_bits / 2);
02966       sum ^= ssum;
02967     }
02968     if (sizeof(bitset_digit_t) >= 4)
02969     {
02970       ssum = sum;
02971       ssum >>= (bitset_digit_bits / 4);
02972       sum ^= ssum;
02973     }
02974     if (sizeof(bitset_digit_t) >= 8)
02975     {
02976       ssum = sum;
02977       ssum >>= (bitset_digit_bits / 8);
02978       sum ^= ssum;
02979     }
02980     if (sizeof(bitset_digit_t) == 16)
02981     {
02982       ssum = sum;
02983       ssum >>= (bitset_digit_bits / 16);
02984       sum ^= ssum;
02985     }
02986     return oddnumberofbits[sum & 0xff];
02987   }
02988 
02992 struct left {
02993 public:
02994   typedef struct right inverse;
02995   static int const direction = -1;
02996   static bool const __left = true;
02997   static bool const __right = false;
02998   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
02999   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03000 };
03001 
03005 struct right {
03006 public:
03007   typedef struct left inverse;
03008   static int const direction = 1;
03009   static bool const __left = false;
03010   static bool const __right = true;
03011   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03012   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03013 };
03014 
03023 template<unsigned int n>
03024   template<unsigned int shift, class DIRECTION>
03025     void
03026     bitset<n>::rotate(bitset<n>& result) const
03027     {
03028       LibEccDout(dc::bitsetshift|flush_cf, "Entering bitset<" << n << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03029       LibEccDout(dc::bitsetshift|flush_cf, "Rotate input : " <<
03030           cwprint_using(*static_cast<bitset_invertible<n, false> const*>(this), &bitset<n>::base2_print_on));
03031       shift_op<shift % n, DIRECTION, rotate_phase1>(result);
03032       LibEccDout(dc::bitsetshift|flush_cf, "After phase1 : " <<
03033           cwprint_using(*static_cast<bitset_invertible<n, false> const*>(&result), &bitset<n>::base2_print_on));
03034       shift_op<n - (shift % n), typename DIRECTION::inverse, rotate_phase2>(result);
03035       LibEccDout(dc::bitsetshift|flush_cf, "After phase2 : " <<
03036           cwprint_using(*static_cast<bitset_invertible<n, false> const*>(&result), &bitset<n>::base2_print_on));
03037       LibEccDout(dc::bitsetshift|flush_cf, "Leaving bitset<" << n << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03038     }
03039 
03040 } // namespace libecc
03041 
03042 #endif // LIBECC_BITS_H
Copyright © 2002 Carlo Wood.  All rights reserved.