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