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