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