00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef LIBECC_BITS_H
00029 #define LIBECC_BITS_H
00030
00031 #ifndef LIBECC_DEBUG_H
00032 #error "You need to include the appropriate debug.h in the source file, before including this header file."
00033 #endif
00034
00035 #include <libecc/config.h>
00036 #include <iosfwd>
00037 #include <cstddef>
00038 #include <cstring>
00039 #include <string>
00040 #include <inttypes.h>
00041 #include <cassert>
00042 #include <endian.h>
00043 #ifdef CWDEBUG
00044 #include "debug.h"
00045 #include <libcwd/cwprint.h>
00046 #endif
00047 #define LIBECC_TRACK_EXPR_TEMPORARIES (ECC_DEBUG && 1)
00048 #if LIBECC_TRACK_EXPR_TEMPORARIES
00049 #include <set>
00050 #endif
00051
00052 #if defined(__i386__) && defined(HAVE_NASM)
00053
00054 extern "C" int libecc_shift_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00055 extern "C" int libecc_shiftwindow_xorassign(unsigned long* bitset1, unsigned long const* bitset2, int lsb, int msb, int shift);
00056 #endif
00057
00058 namespacelibecc {
00059
00069 typedef unsigned long bitset_digit_t;
00070
00072 static unsigned int const bitset_digit_bits = sizeof(bitset_digit_t) * 8;
00073
00075 #if ECC_BITS == 32
00076 static unsigned int const bitset_digit_bits_log2 = 5;
00077 #elif ECC_BITS == 64
00078 static unsigned int const bitset_digit_bits_log2 = 6;
00079 #elif ECC_BITS == 128
00080 #warning 128 bit code has not been tested. This warning will remain here until you mail me.
00081 static unsigned int const bitset_digit_bits_log2 = 7;
00082 #endif
00083
00084
00085
00086
00087
00097 classbitset_index {
00098 #if defined(__i386__) || defined(LIBECC_DOXYGEN)
00099 protected:
00100 int M_index;
00101
00102 public:
00103
00104 int get_index(void) const;
00105
00106 #else
00107 protected:
00108 int M_digit;
00109 bitset_digit_t M_mask;
00110
00111 public:
00112
00113 int get_digit(void) const;
00114 bitset_digit_t get_mask(void) const;
00115
00116
00117 int get_index(void) const;
00118 #endif
00119
00120 public:
00121
00122 friend bool operator==(bitset_index const& i1, bitset_index const& i2);
00123 friend bool operator!=(bitset_index const& i1, bitset_index const& i2);
00124
00125 protected:
00126
00127 void left(void);
00128 void right(void);
00129
00130
00131 void left(int n);
00132 void right(int n);
00133 friend int subtract(bitset_index const& i1, bitset_index const& i2);
00134
00135 protected:
00136
00137 bitset_index(void);
00138 bitset_index(bitset_index const& index);
00139 bitset_index(int bit);
00140
00141 public:
00142 friend std::ostream& operator<<(std::ostream& os, bitset_index const& i);
00143 };
00144
00145 #if defined(__i386__) || defined(LIBECC_DOXYGEN)
00146
00150 inline int
00151 bitset_index::get_index(void) const
00152 {
00153 return M_index;
00154 }
00155
00156 #else // !defined(__i386__)
00157
00158
00159 inline int
00160 bitset_index::get_digit(void) const
00161 {
00162 return M_digit;
00163 }
00164
00165
00166 inline bitset_digit_t
00167 bitset_index::get_mask(void) const
00168 {
00169 return M_mask;
00170 }
00171
00172 #include <strings.h>
00173 inline int
00174 bitset_index::get_index(void) const
00175 {
00176 return M_digit * bitset_digit_bits + ::ffsl(M_mask) - 1;
00177 }
00178
00179 #endif // !defined(__i386__)
00180
00184 inline bool
00185 operator==(bitset_index const& i1, bitset_index const& i2)
00186 {
00187 #ifdef __i386__
00188 return (i1.M_index == i2.M_index);
00189 #else
00190 return (i1.M_digit == i2.M_digit && i1.M_mask == i2.M_mask);
00191 #endif
00192 }
00193
00197 inline bool
00198 operator!=(bitset_index const& i1, bitset_index const& i2)
00199 {
00200 #ifdef __i386__
00201 return (i1.M_index != i2.M_index);
00202 #else
00203 return (i1.M_digit != i2.M_digit || i1.M_mask != i2.M_mask);
00204 #endif
00205 }
00206
00210 inline
00211 bitset_index::bitset_index(void)
00212 {
00213 }
00214
00218 inline
00219 bitset_index::bitset_index(bitset_index const& index) :
00220 #ifdef __i386__
00221 M_index(index.M_index)
00222 #else
00223 M_digit(index.M_digit), M_mask(index.M_mask)
00224 #endif
00225 {
00226 }
00227
00234 inline
00235 bitset_index::bitset_index(int bit) :
00236 #ifdef __i386__
00237 M_index(bit)
00238 #else
00239
00240 M_digit(bit >> bitset_digit_bits_log2),
00241 M_mask(static_cast<bitset_digit_t>(1) << ((unsigned int)bit & (bitset_digit_bits - 1)))
00242 #endif
00243 {
00244 }
00245
00249 inline void
00250 bitset_index::left(void)
00251 {
00252 #ifdef __i386__
00253 ++M_index;
00254 #else
00255 if ((M_mask <<= 1) == 0)
00256 {
00257 ++M_digit;
00258 M_mask = 1;
00259 }
00260 #endif
00261 }
00262
00266 inline void
00267 bitset_index::right(void)
00268 {
00269 #ifdef __i386__
00270 --M_index;
00271 #else
00272 if ((M_mask >>= 1) == 0)
00273 {
00274 --M_digit;
00275 M_mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
00276 }
00277 #endif
00278 }
00279
00283 inline void
00284 bitset_index::left(int n)
00285 {
00286 #ifdef __i386__
00287 M_index += n;
00288 #else
00289 int const digit_shift = n >> bitset_digit_bits_log2;
00290 int const mask_shift = n & (bitset_digit_bits - 1);
00291 M_digit += digit_shift;
00292 if (mask_shift)
00293 {
00294 bitset_digit_t new_mask = M_mask << mask_shift;
00295 if (new_mask == 0)
00296 {
00297 ++M_digit;
00298 new_mask = M_mask >> (bitset_digit_bits - mask_shift);
00299 }
00300 M_mask = new_mask;
00301 }
00302 #endif
00303 }
00304
00308 inline void
00309 bitset_index::right(int n)
00310 {
00311 #ifdef __i386__
00312 M_index -= n;
00313 #else
00314 int const digit_shift = n >> bitset_digit_bits_log2;
00315 int const mask_shift = n & (bitset_digit_bits - 1);
00316 M_digit -= digit_shift;
00317 if (mask_shift)
00318 {
00319 bitset_digit_t new_mask = M_mask >> mask_shift;
00320 if (new_mask == 0)
00321 {
00322 --M_digit;
00323 new_mask = M_mask << (bitset_digit_bits - mask_shift);
00324 }
00325 M_mask = new_mask;
00326 }
00327 #endif
00328 }
00329
00330 enum {
00331 forwards_iterating,
00332 backwards_iterating
00333 };
00334
00335
00336 template<int DIRECTION> classbitset_index_iterator;
00337 template<int DIRECTION> bool operator<(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
00338 template<int DIRECTION> bool operator>(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
00339 template<int DIRECTION> bool operator<=(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
00340 template<int DIRECTION> bool operator>=(bitset_index_iterator<DIRECTION> const&, bitset_index_iterator<DIRECTION> const&);
00341
00350 template<int DIRECTION>
00351 classbitset_index_iterator : public bitset_index {
00352 public:
00353
00354 friend bool operator< <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
00355 friend bool operator> <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
00356 friend bool operator<= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
00357 friend bool operator>= <>(bitset_index_iterator const& i1, bitset_index_iterator const& i2);
00358
00359 public:
00360
00361 void increment(void);
00362 void decrement(void);
00363
00364
00365 void increment(int n);
00366 void decrement(int n);
00367
00368 friend int operator-(bitset_index const& i1, bitset_index const& i2);
00369
00370 public:
00371
00372 bitset_index_iterator(void);
00373 bitset_index_iterator(bitset_index_iterator const& index);
00374 bitset_index_iterator(int bit);
00375 };
00376
00380 template<int DIRECTION>
00381 inline
00382 bitset_index_iterator<DIRECTION>::bitset_index_iterator(void)
00383 {
00384 }
00385
00389 template<int DIRECTION>
00390 inline
00391 bitset_index_iterator<DIRECTION>::bitset_index_iterator(bitset_index_iterator<DIRECTION> const& index) :
00392 bitset_index(index)
00393 {
00394 }
00395
00402 template<int DIRECTION>
00403 inline
00404 bitset_index_iterator<DIRECTION>::bitset_index_iterator(int bit) : bitset_index(bit)
00405 {
00406 }
00407
00411 template<int DIRECTION>
00412 inline bool
00413 operator<(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00414 {
00415 #ifdef __i386__
00416 if (DIRECTION == forwards_iterating)
00417 return (i1.M_index < i2.M_index);
00418 else
00419 return (i1.M_index > i2.M_index);
00420 #else
00421 if (DIRECTION == forwards_iterating)
00422 return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
00423 else
00424 return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
00425 #endif
00426 }
00427
00431 template<int DIRECTION>
00432 inline bool
00433 operator>(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00434 {
00435 #ifdef __i386__
00436 if (DIRECTION == forwards_iterating)
00437 return (i1.M_index > i2.M_index);
00438 else
00439 return (i1.M_index < i2.M_index);
00440 #else
00441 if (DIRECTION == forwards_iterating)
00442 return (i1.M_digit > i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask > i2.M_mask));
00443 else
00444 return (i1.M_digit < i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask < i2.M_mask));
00445 #endif
00446 }
00447
00451 template<int DIRECTION>
00452 inline bool
00453 operator<=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00454 {
00455 #ifdef __i386__
00456 if (DIRECTION == forwards_iterating)
00457 return (i1.M_index <= i2.M_index);
00458 else
00459 return (i1.M_index >= i2.M_index);
00460 #else
00461 if (DIRECTION == forwards_iterating)
00462 return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
00463 else
00464 return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
00465 #endif
00466 }
00467
00471 template<int DIRECTION>
00472 inline bool
00473 operator>=(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00474 {
00475 #ifdef __i386__
00476 if (DIRECTION == forwards_iterating)
00477 return (i1.M_index >= i2.M_index);
00478 else
00479 return (i1.M_index <= i2.M_index);
00480 #else
00481 if (DIRECTION == forwards_iterating)
00482 return (i1.M_digit >= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask >= i2.M_mask));
00483 else
00484 return (i1.M_digit <= i2.M_digit || (i1.M_digit == i2.M_digit && i1.M_mask <= i2.M_mask));
00485 #endif
00486 }
00487
00491 template<int DIRECTION>
00492 inline void
00493 bitset_index_iterator<DIRECTION>::increment(void)
00494 {
00495 if (DIRECTION == forwards_iterating)
00496 left();
00497 else
00498 right();
00499 }
00500
00504 template<int DIRECTION>
00505 inline void
00506 bitset_index_iterator<DIRECTION>::decrement(void)
00507 {
00508 if (DIRECTION == forwards_iterating)
00509 right();
00510 else
00511 left();
00512 }
00513
00517 template<int DIRECTION>
00518 inline void
00519 bitset_index_iterator<DIRECTION>::increment(int n)
00520 {
00521 if (DIRECTION == forwards_iterating)
00522 left(n);
00523 else
00524 right(n);
00525 }
00526
00530 template<int DIRECTION>
00531 inline void
00532 bitset_index_iterator<DIRECTION>::decrement(int n)
00533 {
00534 if (DIRECTION == forwards_iterating)
00535 right(n);
00536 else
00537 left(n);
00538 }
00539
00540 template<int DIRECTION>
00541 inline int
00542 operator-(bitset_index_iterator<DIRECTION> const& i1, bitset_index_iterator<DIRECTION> const& i2)
00543 {
00544 return (DIRECTION == forwards_iterating) ? subtract(i1, i2) : subtract(i2, i1);
00545 }
00546
00547
00548 template<unsigned int N, int DIRECTION> classbitset_iterator;
00549 template<unsigned int N, int DIRECTION> bitset_iterator<N, DIRECTION> operator+(bitset_iterator<N, DIRECTION> const&, int);
00550 template<unsigned int N, int DIRECTION> bitset_iterator<N, DIRECTION> operator+(int, bitset_iterator<N, DIRECTION> const&);
00551 template<unsigned int N, int DIRECTION> bitset_iterator<N, DIRECTION> operator-(bitset_iterator<N, DIRECTION> const&, int);
00552 template<unsigned int N, int DIRECTION> bitset_iterator<N, DIRECTION> operator-(int, bitset_iterator<N, DIRECTION> const&);
00553 template<unsigned int N> structbitset_base;
00554 template<unsigned int N, bool inverted> classbitset_invertible;
00555
00565 template<unsigned int N, int DIRECTION>
00566 classbitset_iterator : public bitset_index_iterator<DIRECTION>,
00567 public std::iterator<std::random_access_iterator_tag, bitset_digit_t,
00568 int, bitset_digit_t*, bitset_digit_t&> {
00569 protected:
00570 bitset_base<N> const* M_bitset_ptr;
00571
00572 public:
00573
00574 bitset_iterator(void);
00575
00576
00577 bitset_iterator(bitset_iterator const& iter);
00578 bitset_iterator& operator=(bitset_iterator const& iter);
00579 bitset_iterator& operator=(bitset_index_iterator<DIRECTION> const& index);
00580
00581
00582 bitset_digit_t operator*() const;
00583
00584
00585
00586 bitset_iterator& operator++();
00587 bitset_iterator operator++(int);
00588 bitset_iterator& operator--();
00589 bitset_iterator operator--(int);
00590
00591
00592
00593 bitset_iterator& operator+=(int n);
00594 friend bitset_iterator operator+ <>(bitset_iterator const& i, int n);
00595 friend bitset_iterator operator+ <>(int n, bitset_iterator const& i);
00596 bitset_iterator& operator-=(int n);
00597 friend bitset_iterator operator- <>(bitset_iterator const& i, int n);
00598 friend bitset_iterator operator- <>(int n, bitset_iterator const& i);
00599 bitset_digit_t operator[](int n) const;
00600
00601
00602
00603 bitset_iterator(bitset_base<N> const* bitset_ptr, int bit);
00604 void find1(void);
00605
00606 #ifndef __i386__
00607 private:
00608 void find1_forward(void);
00609 void find1_backward(void);
00610 #endif
00611 };
00612
00622 template<unsigned int N>
00623 structbitset_base {
00624 public:
00625
00626 static size_t const offsetof_vector = 0;
00627
00628 public:
00632 static unsigned int const number_of_bits = N;
00633
00635 static unsigned int const digits = (N == 0) ? 0 : ((N - 1) / bitset_digit_bits + 1);
00636
00637
00638 static unsigned int const number_of_valid_bits = bitset_digit_bits - (digits * bitset_digit_bits - N);
00639
00641 static bitset_digit_t const valid_bits = ((static_cast<bitset_digit_t>(1) << (number_of_valid_bits - 1)) << 1) - 1;
00642
00644 static bool const has_excess_bits = ((digits * bitset_digit_bits) != N);
00645
00646 protected:
00653
00654 bitset_digit_t vector[digits];
00655
00656
00657 template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00658 friend bool operator==(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00659
00660 template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00661 friend bool operator!=(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00662
00663 public:
00664
00665 bitset_digit_t& rawdigit(unsigned int d) { return this->vector[d]; }
00666 bitset_digit_t rawdigit(unsigned int d) const{ return this->vector[d]; }
00667 bitset_digit_t* digits_ptr(void) { return this->vector; }
00668 bitset_digit_t const* digits_ptr(void) const{ return this->vector; }
00669 uint32_t digit32(unsigned int d32) const
00670 {
00671 if (sizeof(bitset_digit_t) == 4)
00672 return this->vector[d32];
00673 else
00674 {
00675 unsigned int d = d32 / (sizeof(bitset_digit_t) / 4);
00676 unsigned int r = d32 % (sizeof(bitset_digit_t) / 4);
00677 #if __BYTE_ORDER == __LITTLE_ENDIAN
00678 return (this->vector[d] >> (r * 32));
00679 #elif __BYTE_ORDER == __BIG_ENDIAN
00680 return (this->vector[d] >> (bitset_digit_bits - 32 - (r * 32)));
00681 #endif
00682 }
00683 }
00684
00685 public:
00686
00688 typedef bitset_iterator<N, forwards_iterating> const_iterator;
00690 typedef bitset_iterator<N, backwards_iterating> const_reverse_iterator;
00692 const_iterator begin(void) const{ return const_iterator(this, 0); }
00694 const_iterator end(void) const{ return const_iterator(this, N); }
00696 const_reverse_iterator rbegin(void) const{ return const_reverse_iterator(this, N - 1); }
00698 const_reverse_iterator rend(void) const{ return const_reverse_iterator(this, -1); }
00699
00700 template<unsigned int m>
00701 void xor_with_zero_padded(bitset_base<m> const& bitset, int lsb, int msb, int shift);
00702
00703
00704 void operator<<=(unsigned int shift);
00705 void operator>>=(unsigned int shift);
00706
00707
00708 bool test(size_t n) const;
00709 bool odd(void) const;
00710 void set(size_t n);
00711 void clear(size_t n);
00712 void flip(size_t n);
00713
00714
00715 bool test(bitset_index const& index) const;
00716 void set(bitset_index const& index);
00717 void clear(bitset_index const& index);
00718 void flip(bitset_index const& index);
00719
00720
00721 template<unsigned int pos>
00722 bool test(void) const;
00723 template<unsigned int pos>
00724 void set(void);
00725 template<unsigned int pos>
00726 void clear(void);
00727 template<unsigned int pos>
00728 void flip(void);
00729
00730
00731 void reset(void);
00732 void setall(void);
00733 bool any(void) const;
00734 };
00735
00752 template<unsigned int N>
00753 template<unsigned int m>
00754 #if defined(__i386__) && defined(HAVE_NASM)
00755 inline
00756 #endif
00757 void
00758 bitset_base<N>::xor_with_zero_padded(bitset_base<m> const& bitset, int lsb, int msb, int shift)
00759 {
00760 #if defined(__i386__) && defined(HAVE_NASM)
00761 libecc_shift_xorassign(this->vector, bitset.digits_ptr(), lsb, msb, shift);
00762 #else
00763 int digit1 = lsb >> bitset_digit_bits_log2;
00764 int digit2 = msb >> bitset_digit_bits_log2;
00765 bitset_digit_t d1 = 0;
00766
00767 bitset_digit_t const* const digits_ptr = bitset.digits_ptr();
00768 if (shift < 0)
00769 {
00770 int bitshift = (-shift) & (bitset_digit_bits - 1);
00771 int digitshift = (-shift) >> bitset_digit_bits_log2;
00772 if (bitshift == 0)
00773 {
00774 for (int digit = digit2; digit >= digit1; --digit)
00775 {
00776 bitset_digit_t d2 = digits_ptr[digit];
00777 this->vector[digit - digitshift] ^= d2;
00778 }
00779 }
00780 else
00781 {
00782 for (int digit = digit2; digit >= digit1; --digit)
00783 {
00784 bitset_digit_t d2 = digits_ptr[digit];
00785 this->vector[digit - digitshift] ^= (d2 >> bitshift) | (d1 << (bitset_digit_bits - bitshift));
00786 d1 = d2;
00787 }
00788 this->vector[digit1 - 1 - digitshift] ^= (d1 << (bitset_digit_bits - bitshift));
00789 }
00790 }
00791 else if (shift > 0)
00792 {
00793 int bitshift = shift & (bitset_digit_bits - 1);
00794 int digitshift = shift >> bitset_digit_bits_log2;
00795 if (bitshift == 0)
00796 {
00797 for (int digit = digit1; digit <= digit2; ++digit)
00798 {
00799 bitset_digit_t d2 = digits_ptr[digit];
00800 this->vector[digit + digitshift] ^= d2;
00801 d1 = d2;
00802 }
00803 }
00804 else
00805 {
00806 for (int digit = digit1; digit <= digit2; ++digit)
00807 {
00808 bitset_digit_t d2 = digits_ptr[digit];
00809 this->vector[digit + digitshift] ^= (d2 << bitshift) | (d1 >> (bitset_digit_bits - bitshift));
00810 d1 = d2;
00811 }
00812 this->vector[digit2 + 1 + digitshift] ^= (d1 >> (bitset_digit_bits - bitshift));
00813 }
00814 }
00815 else
00816 {
00817 for (int digit = digit1; digit <= digit2; ++digit)
00818 this->vector[digit] ^= digits_ptr[digit];
00819 }
00820 #endif
00821 }
00822
00823 #ifndef HIDE_FROM_DOXYGEN
00824 namespaceOperator {
00825
00826 #ifdef __i386__
00827
00828
00829
00830
00831
00832
00833
00834 #define LIBECC_INVERT "xorl $-1,%%eax\n\t"
00835 #define LIBECC_NOTHING ""
00836
00837 #define LIBECC_ASMLOOP(destination, source, count, OPCODE, OPTIONAL_INVERT) \
00838 do { \
00839 int __d0, __d1, __d2; \
00840 __asm__ __volatile__ ( \
00841 "\n1:\n\t" \
00842 "movl (%5,%%ecx,4),%%eax\n\t" \
00843 OPTIONAL_INVERT \
00844 OPCODE " %%eax,(%4,%%ecx,4)\n\t" \
00845 "decl %%ecx\n\t" \
00846 "jnz 1b" \
00847 : "=c" (__d0), "=&r" (__d1), "=&r" (__d2) \
00848 : "0" (count), \
00849 "1" ((destination) - 1), \
00850 "2" ((source) - 1) \
00851 : "%eax", "memory" \
00852 ); \
00853 } while(0)
00854
00855 #define LIBECC_ASMLOOP_BODY(OPCODE, destination, source, count, inverted) \
00856 do { \
00857 if (inverted) \
00858 LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_INVERT); \
00859 else \
00860 LIBECC_ASMLOOP(destination, source, count, OPCODE, LIBECC_NOTHING); \
00861 } while(0)
00862
00863 #define LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, OPTIONAL_INVERT1, OPCODE2, OPTIONAL_INVERT3) \
00864 do { \
00865 int __d0, __d1, __d2, __d3; \
00866 __asm__ __volatile__ ( \
00867 "\n1:\n\t" \
00868 "movl (%6,%%ecx,4),%%eax\n\t" \
00869 OPTIONAL_INVERT1 \
00870 OPCODE2 " (%7,%%ecx,4),%%eax\n\t" \
00871 OPTIONAL_INVERT3 \
00872 OPCODE " %%eax,(%5,%%ecx,4)\n\t" \
00873 "decl %%ecx\n\t" \
00874 "jnz 1b" \
00875 : "=c" (__d0), "=&r" (__d1), "=&r" (__d2), "=&r" (__d3) \
00876 : "0" (count), \
00877 "1" ((destination) - 1), \
00878 "2" ((source1) - 1), \
00879 "3" ((source2) - 1) \
00880 : "%eax", "memory" \
00881 ); \
00882 } while(0)
00883
00884 #define LIBECC_ASMLOOP2_BODY(OPCODE, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00885 do { \
00886 if (OPERATOR::id == libecc::Operator::bitsetAND::id) \
00887 { \
00888 if (inverted1 && inverted2) \
00889 LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_INVERT); \
00890 else if (inverted1) \
00891 LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00892 else if (inverted2) \
00893 LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "andl", LIBECC_NOTHING); \
00894 else \
00895 LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_NOTHING); \
00896 } \
00897 else if (OPERATOR::id == libecc::Operator::bitsetOR::id) \
00898 { \
00899 if (inverted1 && inverted2) \
00900 LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "andl", LIBECC_INVERT); \
00901 else if (inverted1) \
00902 LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00903 else if (inverted2) \
00904 LIBECC_ASMLOOP2(destination, source2, source1, count, OPCODE, LIBECC_INVERT, "orl", LIBECC_NOTHING); \
00905 else \
00906 LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "orl", LIBECC_NOTHING); \
00907 } \
00908 else if (OPERATOR::id == libecc::Operator::bitsetXOR::id) \
00909 { \
00910 if (inverted1 == inverted2) \
00911 LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_NOTHING); \
00912 else \
00913 LIBECC_ASMLOOP2(destination, source1, source2, count, OPCODE, LIBECC_NOTHING, "xorl", LIBECC_INVERT); \
00914 } \
00915 } while(0)
00916
00917 #define LIBECC_INLINE_ASMLOOP(ID, destination, source, count, inverted) \
00918 do { \
00919 if (ID == libecc::Operator::bitsetAssign::id) \
00920 { \
00921 LIBECC_ASMLOOP_BODY("movl", destination, source, count, inverted); \
00922 } \
00923 else if (ID == libecc::Operator::bitsetANDAssign::id) \
00924 { \
00925 LIBECC_ASMLOOP_BODY("andl", destination, source, count, inverted); \
00926 } \
00927 else if (ID == libecc::Operator::bitsetORAssign::id) \
00928 { \
00929 LIBECC_ASMLOOP_BODY("orl", destination, source, count, inverted); \
00930 } \
00931 else if (ID == libecc::Operator::bitsetXORAssign::id) \
00932 { \
00933 LIBECC_ASMLOOP_BODY("xorl", destination, source, count, inverted); \
00934 } \
00935 } while(0)
00936
00937 #define LIBECC_INLINE_ASMLOOP2(ID, OPERATOR, inverted1, inverted2, destination, source1, source2, count) \
00938 do { \
00939 if (ID == libecc::Operator::bitsetAssign::id) \
00940 { \
00941 LIBECC_ASMLOOP2_BODY("movl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00942 } \
00943 else if (ID == libecc::Operator::bitsetANDAssign::id) \
00944 { \
00945 LIBECC_ASMLOOP2_BODY("andl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00946 } \
00947 else if (ID == libecc::Operator::bitsetORAssign::id) \
00948 { \
00949 LIBECC_ASMLOOP2_BODY("orl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00950 } \
00951 else if (ID == libecc::Operator::bitsetXORAssign::id) \
00952 { \
00953 LIBECC_ASMLOOP2_BODY("xorl", OPERATOR, inverted1, inverted2, destination, source1, source2, count); \
00954 } \
00955 } while(0)
00956
00957 #define LIBECC_ASMSHIFTRIGHT0(OP1) \
00958 __asm__ __volatile__ ( \
00959 "movl 4(%%esi),%%edx\n\t" \
00960 "shrl $1,%%edx\n\t" \
00961 OP1 \
00962 "movl %%edx,4(%%edi)" \
00963 : "=&S" (ptr1), \
00964 "=&D" (ptr2) \
00965 : "0" (&this->vector[initial - count]), \
00966 "1" (&result.vector[initial - count]) \
00967 : "%eax", "%edx", "memory", "cc" \
00968 )
00969
00970 #if 0 // NOT faster.
00971 #define LIBECC_OP1_SOURCE "(%%esi)"
00972 #define LIBECC_OP2_SOURCE "(%%esi)"
00973 #define LIBECC_OP1_DESTINATION "(%%edi)"
00974 #define LIBECC_OP2_DESTINATION "(%%edi)"
00975 #define LIBECC_WORKREG "%%eax"
00976 #define LIBECC_CLOBBER "%eax"
00977 #define LIBECC_INIT "std\n\t"
00978 #define LIBECC_LOAD1 "lodsl\n\t"
00979 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00980 #define LIBECC_STORE1 "stosl\n\t"
00981 #define LIBECC_LOAD2 "lodsl\n\t"
00982 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
00983 #define LIBECC_STORE2 "stosl\n\t"
00984 #define LIBECC_DEINIT "cld\n\t"
00985 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "setc %%edx\n\t" OPERAND "\n\tbt $0,%%edx\n\t"
00986 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%edx"
00987 #define LIBECC_INITIAL_ESI &this->vector[initial]
00988 #define LIBECC_INITIAL_EDI &result.vector[initial]
00989 #else
00990 #define LIBECC_OP1_SOURCE "4(%%esi,%%ecx,4)"
00991 #define LIBECC_OP2_SOURCE "(%%esi,%%ecx,4)"
00992 #define LIBECC_OP1_DESTINATION "4(%%edi,%%ecx,4)"
00993 #define LIBECC_OP2_DESTINATION "(%%edi,%%ecx,4)"
00994 #define LIBECC_WORKREG "%%edx"
00995 #define LIBECC_CLOBBER "%edx"
00996 #define LIBECC_INIT
00997 #define LIBECC_LOAD1 "movl " LIBECC_OP1_SOURCE "," LIBECC_WORKREG "\n\t"
00998 #define LIBECC_SHIFT "shrl $1," LIBECC_WORKREG "\n\t"
00999 #define LIBECC_STORE1 "movl " LIBECC_WORKREG "," LIBECC_OP1_DESTINATION "\n\t"
01000 #define LIBECC_LOAD2 "movl " LIBECC_OP2_SOURCE "," LIBECC_WORKREG "\n\t"
01001 #define LIBECC_ROTATE "rcrl $1," LIBECC_WORKREG "\n\t"
01002 #define LIBECC_STORE2 "movl " LIBECC_WORKREG "," LIBECC_OP2_DESTINATION "\n\t"
01003 #define LIBECC_DEINIT
01004 #define LIBECC_RIGHT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
01005 #define LIBECC_PRESERVE_CF_CLOBBER LIBECC_CLOBBER,"%eax"
01006 #define LIBECC_INITIAL_ESI &this->vector[initial - count]
01007 #define LIBECC_INITIAL_EDI &result.vector[initial - count]
01008 #endif
01009
01010 #define LIBECC_ASMSHIFTRIGHT1(OP1, OP2, CLOBBER) \
01011 __asm__ __volatile__ ( \
01012 LIBECC_INIT \
01013 LIBECC_LOAD1 \
01014 LIBECC_SHIFT \
01015 OP1 \
01016 LIBECC_STORE1 \
01017 "1:\n\t" \
01018 LIBECC_LOAD2 \
01019 LIBECC_ROTATE \
01020 OP2 \
01021 LIBECC_STORE2 \
01022 "decl %%ecx\n\t" \
01023 "jnz 1b\n\t" \
01024 LIBECC_DEINIT \
01025 : "=&S" (ptr1), \
01026 "=&D" (ptr2), \
01027 "=&c" (c) \
01028 : "0" (LIBECC_INITIAL_ESI), \
01029 "1" (LIBECC_INITIAL_EDI), \
01030 "2" (count - 1) \
01031 : "memory", "cc", CLOBBER \
01032 )
01033
01034 #define LIBECC_ASMSHIFTLEFT(OP1, OP2, FINISH) \
01035 __asm__ __volatile__ ( \
01036 "movl -4(%%esi),%%edx\n\t" \
01037 "shll $1,%%edx\n\t" \
01038 OP1 \
01039 "movl %%edx,-4(%%edi)\n\t" \
01040 "jecxz 2f\n" \
01041 "1:\n\t" \
01042 "movl (%%esi),%%edx\n\t" \
01043 "rcll $1,%%edx\n\t" \
01044 OP2 \
01045 "movl %%edx,(%%edi)\n\t" \
01046 "leal 4(%%esi),%%esi\n\t" \
01047 "leal 4(%%edi),%%edi\n\t" \
01048 "decl %%ecx\n\t" \
01049 "jnz 1b\n" \
01050 "2:\n\t" \
01051 FINISH \
01052 : "=&S" (ptr1), \
01053 "=&D" (ptr2), \
01054 "=&c" (c) \
01055 : "0" (&this->vector[initial + 1]), \
01056 "1" (&result.vector[initial + 1]), \
01057 "2" (count - 1), \
01058 "n" (bitset_base<N>::valid_bits) \
01059 : "%eax", "%edx", "memory", "cc" \
01060 )
01061
01062 #define LIBECC_ASMSHIFTLEFT_FINISH(OP) \
01063 "movl (%%esi),%%edx\n\t" \
01064 "rcll $1,%%edx\n\t" \
01065 "andl %6,%%edx\n\t" \
01066 OP \
01067 "movl %%edx,(%%edi)"
01068
01069 #define LIBECC_LEFT_PRESERVE_CF(OPERAND) "lahf\n\t" OPERAND "\n\tsahf\n\t"
01070
01071 #endif // __i386__
01072
01073
01074
01075
01076 structbitsetAND {
01077 static int const id = 1;
01078 static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 & digit2; }
01079 template<bool inverted1, bool inverted2>
01080 structexecbool {
01081 static bool const value = inverted1 && inverted2;
01082 };
01083 };
01084
01085
01086 structbitsetOR {
01087 static int const id = 2;
01088 static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 | digit2; }
01089 template<bool inverted1, bool inverted2>
01090 structexecbool {
01091 static bool const value = inverted1 || inverted2;
01092 };
01093 };
01094
01095
01096 structbitsetXOR {
01097 static int const id = 3;
01098 static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 ^ digit2; }
01099 template<bool inverted1, bool inverted2>
01100 structexecbool {
01101 static bool const value = (inverted1 != inverted2);
01102 };
01103 };
01104
01105
01106 structbitsetAssign {
01107 static int const id = 1;
01108 static bool const sets_excess_bits = true;
01109 static bool const with_zero_sets_zero = true;
01110 static bool const with_ones_sets_ones = true;
01111 static bool const with_ones_inverts = false;
01112 static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out = in; }
01113 };
01114
01115
01116 structbitsetANDAssign {
01117 static int const id = 2;
01118 static bool const sets_excess_bits = false;
01119 static bool const with_zero_sets_zero = true;
01120 static bool const with_ones_sets_ones = false;
01121 static bool const with_ones_inverts = false;
01122 static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out &= in; }
01123 };
01124
01125
01126 structbitsetORAssign {
01127 static int const id = 3;
01128 static bool const sets_excess_bits = true;
01129 static bool const with_zero_sets_zero = false;
01130 static bool const with_ones_sets_ones = true;
01131 static bool const with_ones_inverts = false;
01132 static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out |= in; }
01133 };
01134
01135
01136 structbitsetXORAssign {
01137 static int const id = 4;
01138 static bool const sets_excess_bits = true;
01139 static bool const with_zero_sets_zero = false;
01140 static bool const with_ones_sets_ones = false;
01141 static bool const with_ones_inverts = true;
01142 static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out ^= in; }
01143 };
01144
01145 #if LIBECC_TRACK_EXPR_TEMPORARIES
01146 extern std::multiset<void const*> bitsetExpression_bitset_invertible_pointers;
01147 #endif
01148
01149 template<unsigned int N, bool inverted1, bool inverted2, typename OP>
01150 structbitsetExpression
01151 {
01152 bitset_invertible<N, inverted1> const& first;
01153 bitset_invertible<N, inverted2> const& second;
01154 OP op;
01155
01156 bitsetExpression(bitset_invertible<N, inverted1> const& arg1, bitset_invertible<N, inverted2> const& arg2) :
01157 first(arg1), second(arg2)
01158 {
01159
01160
01161
01162
01163 #if LIBECC_TRACK_EXPR_TEMPORARIES
01164 bitsetExpression_bitset_invertible_pointers.insert(&arg1);
01165 bitsetExpression_bitset_invertible_pointers.insert(&arg2);
01166 LibEccDout(dc::notice, "Constructed a bitsetExpression with arguments " <<
01167 (void const*)&first << " and " << (void const*)&second);
01168 #endif
01169 }
01170 #if LIBECC_TRACK_EXPR_TEMPORARIES
01171 ~bitsetExpression();
01172 #endif
01173 };
01174
01175 #if LIBECC_TRACK_EXPR_TEMPORARIES
01176 template<unsigned int N, bool inverted1, bool inverted2, typename OP>
01177 bitsetExpression<N, inverted1, inverted2, OP>::~bitsetExpression()
01178 {
01179 bitsetExpression_bitset_invertible_pointers.erase(bitsetExpression_bitset_invertible_pointers.find(&first));
01180 bitsetExpression_bitset_invertible_pointers.erase(bitsetExpression_bitset_invertible_pointers.find(&second));
01181 LibEccDout(dc::notice, "Destructed bitsetExpression with arguments " <<
01182 (void const*)&first << " and " << (void const*)&second);
01183 }
01184 #endif
01185
01186 }
01187 #endif // HIDE_FROM_DOXYGEN
01188
01206 template<unsigned int N, bool inverted>
01207 classbitset_invertible : public bitset_base<N> {
01208 public:
01209
01210 bitset_invertible(void);
01211 template<typename Expression>
01212 explicit bitset_invertible(Expression const&);
01213
01214 #if LIBECC_TRACK_EXPR_TEMPORARIES
01215 ~bitset_invertible();
01216 #endif
01217
01218 protected:
01219 template<typename OP, unsigned int x, bool invertedx>
01220 void assign(bitset_invertible<x, invertedx> const&, OP);
01221 template<typename OP1, unsigned int x, bool inverted1, bool inverted2, typename OP2>
01222 void assign(Operator::bitsetExpression<x, inverted1, inverted2, OP2> const&, OP1);
01223
01224 private:
01225 template<unsigned int m, bool i>
01226 friend classbitset_invertible;
01227
01228 public:
01230 void base2_print_on(std::ostream& os) const;
01231
01233 bitset_digit_t digit(unsigned int d) const{ return inverted ? ~this->vector[d] : this->vector[d]; }
01234 };
01235
01236 #if LIBECC_TRACK_EXPR_TEMPORARIES
01237 template<unsigned int N, bool inverted>
01238 bitset_invertible<N, inverted>::~bitset_invertible()
01239 {
01240 LibEccDout(dc::notice, "Destructing bitset_invertible at " << (void*)this);
01241 if (Operator::bitsetExpression_bitset_invertible_pointers.find(this) !=
01242 Operator::bitsetExpression_bitset_invertible_pointers.end())
01243 LibEccDoutFatal(dc::core, "This object is still in use by a bitsetExpression!");
01244 }
01245 #endif
01246
01258 template<unsigned int N, bool inverted>
01259 void
01260 bitset_invertible<N, inverted>::base2_print_on(std::ostream& os) const
01261 {
01262
01263 for (int d = bitset_base<N>::digits - 1; d >= 0; --d)
01264 for (bitset_digit_t mask = (~static_cast<bitset_digit_t>(0) >> 1) + 1; mask != 0; mask >>= 1)
01265 if (d != bitset_base<N>::digits - 1 || (mask & bitset_base<N>::valid_bits))
01266 {
01267 if ((this->digit(d) & mask) == inverted)
01268 os << '0';
01269 else
01270 os << '1';
01271 }
01272 }
01273
01274
01275 template<unsigned int N, bool inverted>
01276 inline
01277 bitset_invertible<N, inverted>::bitset_invertible(void)
01278 {
01279 if (bitset_base<N>::has_excess_bits)
01280 this->vector[bitset_base<N>::digits - 1] = 0;
01281 }
01282
01283
01284 template<unsigned int N, bool inverted>
01285 template<typename Expression>
01286 inline
01287 bitset_invertible<N, inverted>::bitset_invertible(Expression const& expr)
01288 {
01289 this->assign(expr, Operator::bitsetAssign());
01290 }
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307 template<unsigned int N, bool inverted>
01308 template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted_argument>
01309 inline void
01310 bitset_invertible<N, inverted>::assign(bitset_invertible<x, inverted_argument> const& bits, ASSIGNMENT_OPERATOR)
01311 {
01312
01313 if (bitset_base<N>::digits > bitset_base<x>::digits)
01314 {
01315 if (!inverted_argument)
01316 {
01317
01318 if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
01319 std::memset(&this->vector[bitset_base<x>::digits], 0, (bitset_base<N>::digits - bitset_base<x>::digits) * sizeof(bitset_digit_t));
01320 }
01321 else
01322 {
01323
01324 if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
01325 {
01326 unsigned int const count = bitset_base<N>::digits - bitset_base<x>::digits - 1;
01327 if (count)
01328 std::memset(&this->vector[bitset_base<x>::digits], 0xff, count * sizeof(bitset_digit_t));
01329 this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
01330 }
01331
01332 if (ASSIGNMENT_OPERATOR::with_ones_inverts)
01333 {
01334 #ifdef __i386__
01335 int __d0, __d1;
01336 __asm__ __volatile__ (
01337 "xorl %4,(%1)\n\t"
01338 "jecxz 2f\n\t"
01339 "subl %5,%1\n"
01340 "1:\n\t"
01341 "xorl $-1,(%1,%%ecx,4)\n\t"
01342 "decl %%ecx\n\t"
01343 "jnz 1b\n"
01344 "2:"
01345 : "=&c" (__d0), "=&r" (__d1)
01346 : "0" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "1" (&this->vector[bitset_base<N>::digits - 1]),
01347 "n" (bitset_base<N>::valid_bits), "n" ((bitset_base<N>::digits - bitset_base<x>::digits) * 4)
01348 : "memory", "cc"
01349 );
01350 #else
01351 this->vector[bitset_base<N>::digits - 1] ^= bitset_base<N>::valid_bits;
01352 unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01353 while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
01354 #endif
01355 }
01356 }
01357 }
01358
01359
01360 #ifdef __i386__
01361 LIBECC_INLINE_ASMLOOP(ASSIGNMENT_OPERATOR::id,
01362 this->vector, bits.digits_ptr(),
01363 ((bitset_base<N>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<N>::digits),
01364 inverted_argument);
01365 #else
01366 unsigned int d;
01367 if (bitset_base<N>::digits > bitset_base<x>::digits)
01368 d = bitset_base<x>::digits - 1;
01369 else
01370 d = bitset_base<N>::digits - 1;
01371 ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~bits.rawdigit(d) : bits.rawdigit(d));
01372 while(d) { --d; ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~bits.rawdigit(d) : bits.rawdigit(d)); }
01373 #endif
01374
01375
01376 if (((!inverted_argument && x > N) ||
01377 (inverted_argument && bitset_base<N>::digits <= bitset_base<x>::digits)) &&
01378 bitset_base<N>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
01379 this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
01380 }
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 template<unsigned int N, bool inverted>
01439 template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted1, bool inverted2, typename OPERATOR>
01440 inline void
01441 bitset_invertible<N, inverted>::assign(Operator::bitsetExpression<x, inverted1, inverted2, OPERATOR> const& expr, ASSIGNMENT_OPERATOR)
01442 {
01443 static bool const argument_has_leading_ones = OPERATOR::template execbool<inverted1, inverted2>::value;
01444
01445
01446 if (bitset_base<N>::digits > bitset_base<x>::digits)
01447 {
01448 if (!argument_has_leading_ones)
01449 {
01450
01451 if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
01452 std::memset(&this->vector[bitset_base<x>::digits], 0, (bitset_base<N>::digits - bitset_base<x>::digits) * sizeof(bitset_digit_t));
01453 }
01454 else
01455 {
01456
01457 if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
01458 {
01459 unsigned int const count = bitset_base<N>::digits - bitset_base<x>::digits - 1;
01460 if (count)
01461 std::memset(&this->vector[bitset_base<x>::digits], 0xff, count * sizeof(bitset_digit_t));
01462 this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
01463 }
01464
01465 if (ASSIGNMENT_OPERATOR::with_ones_inverts)
01466 {
01467 #ifdef __i386__
01468 int __d0, __d1;
01469 __asm__ __volatile__ (
01470 "xorl %4,(%1)\n\t"
01471 "jecxz 2f\n\t"
01472 "subl %5,%1\n"
01473 "1:\n\t"
01474 "xorl $-1,(%1,%%ecx,4)\n\t"
01475 "decl %%ecx\n\t"
01476 "jnz 1b\n"
01477 "2:"
01478 : "=&c" (__d0), "=&r" (__d1)
01479 : "0" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "1" (&this->vector[bitset_base<N>::digits - 1]),
01480 "n" (bitset_base<N>::valid_bits), "n" ((bitset_base<N>::digits - bitset_base<x>::digits) * 4)
01481 : "memory", "cc"
01482 );
01483 #else
01484 this->vector[bitset_base<N>::digits - 1] ^= bitset_base<N>::valid_bits;
01485 unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01486 while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
01487 #endif
01488 }
01489 }
01490 }
01491
01492
01493 #ifdef __i386__
01494 LIBECC_INLINE_ASMLOOP2(ASSIGNMENT_OPERATOR::id, OPERATOR, inverted1, inverted2,
01495 this->vector, expr.first.digits_ptr(), expr.second.digits_ptr(),
01496 ((bitset_base<N>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<N>::digits));
01497 #else
01498 unsigned int d;
01499 if (bitset_base<N>::digits < bitset_base<x>::digits)
01500 d = bitset_base<N>::digits - 1;
01501 else
01502 d = bitset_base<x>::digits - 1;
01503 for(;;)
01504 {
01505 ASSIGNMENT_OPERATOR::exec(this->vector[d],
01506 OPERATOR::exec(inverted1 ? ~expr.first.rawdigit(d) : expr.first.rawdigit(d),
01507 inverted2 ? ~expr.second.rawdigit(d) : expr.second.rawdigit(d)));
01508 if (!d)
01509 break;
01510 --d;
01511 }
01512 #endif
01513
01514
01515 if (((!argument_has_leading_ones && x > N) ||
01516 (argument_has_leading_ones && bitset_base<N>::digits <= bitset_base<x>::digits)) &&
01517 bitset_base<N>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
01518 this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
01519 }
01520
01547 template<unsigned int N, bool inverted>
01548 inline bitset_invertible<N, !inverted> const&
01549 operator~(bitset_invertible<N, inverted> const& bits)
01550 {
01551 return *reinterpret_cast<bitset_invertible<N, !inverted> const*>(&bits);
01552 }
01553
01554 #ifndef __i386__
01555 template<unsigned int N, int DIRECTION>
01556 void
01557 bitset_iterator<N, DIRECTION>::find1_forward(void)
01558 {
01559 if (this->M_digit < (int)bitset_base<N>::digits - 1 || (this->M_mask & bitset_base<N>::valid_bits))
01560 {
01561 register bitset_digit_t mask = this->M_mask;
01562 while(!(M_bitset_ptr->rawdigit(this->M_digit) & mask))
01563 {
01564 if ((mask <<= 1))
01565 continue;
01566 mask = 1;
01567 while(++(this->M_digit) < (int)bitset_base<N>::digits)
01568 if (M_bitset_ptr->rawdigit(this->M_digit))
01569 break;
01570 if (this->M_digit == (int)bitset_base<N>::digits)
01571 {
01572 this->M_digit = (N >> bitset_digit_bits_log2);
01573 mask = static_cast<bitset_digit_t>(1) << (N & (bitset_digit_bits - 1));
01574 break;
01575 }
01576 }
01577 this->M_mask = mask;
01578 }
01579 }
01580
01581 template<unsigned int N, int DIRECTION>
01582 void
01583 bitset_iterator<N, DIRECTION>::find1_backward(void)
01584 {
01585 LibEccDout(dc::bitsetfind1, "Entering find1_backward with: " <<
01586 libcwd::cwprint_using(*static_cast<bitset_invertible<N, false> const*>(M_bitset_ptr), &bitset_invertible<N, false>::base2_print_on));
01587 LibEccDout(dc::bitsetfind1, "Input: " << *this);
01588 if (this->M_digit >= 0)
01589 {
01590 register bitset_digit_t mask = this->M_mask;
01591 if (!(M_bitset_ptr->rawdigit(this->M_digit) & (mask | (mask - 1))))
01592 {
01593 mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
01594 do
01595 {
01596 if (--(this->M_digit) < 0)
01597 {
01598 this->M_mask = mask;
01599 return;
01600 }
01601 }
01602 while (!M_bitset_ptr->rawdigit(this->M_digit));
01603 }
01604 while(!(M_bitset_ptr->rawdigit(this->M_digit) & mask))
01605 mask >>= 1;
01606 this->M_mask = mask;
01607 }
01608 LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01609 }
01610 #endif
01611
01615 template<unsigned int N, int DIRECTION>
01616 inline void
01617 bitset_iterator<N, DIRECTION>::find1(void)
01618 {
01619 LibEccDout(dc::bitsetfind1, "Input: " << *this);
01620 LibEccDout(dc::bitsetfind1, "Entering find1 with: " <<
01621 libcwd::cwprint_using(*static_cast<bitset_invertible<N, false> const*>(M_bitset_ptr), &bitset_invertible<N, false>::base2_print_on));
01622 #ifdef __i386__
01623 int bit_index, digit, ptr;
01624 if (DIRECTION == backwards_iterating)
01625 {
01626 __asm__ __volatile__ (
01627
01628
01629
01630
01631
01632
01633 "movl %%eax,%%ecx\n\t"
01634
01635 "sarl $5,%%eax\n\t"
01636
01637 "andl $31,%%ecx\n\t"
01638
01639 "js 1f\n\t"
01640
01641
01642
01643 "movl 4(%%edi),%2\n\t"
01644
01645
01646 "xorl $31,%%ecx\n\t"
01647
01648 "shll %%cl,%2\n\t"
01649
01650
01651
01652 "orl %2,%2\n\t"
01653
01654 "jz 5f\n\t"
01655
01656
01657 "bsrl %2,%2\n\t"
01658
01659
01660 "sall $5,%%eax\n\t"
01661
01662 "subl %%ecx,%2\n\t"
01663
01664 "addl %2,%%eax\n\t"
01665
01666
01667 "jmp 1f\n\t"
01668 ".align 16\n"
01669 "7:\n\t"
01670 "movl (%%edi),%2\n\t"
01671 "subl $4,%%edi\n\t"
01672 "testl %2,%2\n\t"
01673 "jnz 6f\n\t"
01674 "5:\n\t"
01675 "decl %%eax\n\t"
01676
01677 "jns 7b\n"
01678 "4:\n\t"
01679
01680 "movl $-1,%%eax\n\t"
01681
01682
01683 "jmp 1f\n"
01684
01685 "6:\n\t"
01686 "bsrl %2,%2\n\t"
01687
01688 "sall $5,%%eax\n\t"
01689 "addl %2,%%eax\n"
01690 "1:"
01691
01692 : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01693 : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() - 1 + (this->M_index >> 5))
01694 : "cc"
01695 );
01696 }
01697 else
01698 {
01699 __asm__ __volatile__ (
01700
01701
01702
01703
01704
01705
01706 "cmpl %6,%%eax\n\t"
01707 "jge 1f\n\t"
01708
01709 "movl %%eax,%%ecx\n\t"
01710
01711 "sarl $5,%%eax\n\t"
01712
01713 "andl $31,%%ecx\n\t"
01714
01715
01716
01717 "movl -4(%%edi),%2\n\t"
01718
01719
01720 "shrl %%cl,%2\n\t"
01721
01722
01723
01724 "orl %2,%2\n\t"
01725
01726 "jz 5f\n\t"
01727
01728
01729 "bsfl %2,%2\n\t"
01730
01731
01732 "sall $5,%%eax\n\t"
01733
01734 "addl %%ecx,%2\n\t"
01735
01736 "addl %2,%%eax\n\t"
01737
01738
01739 "jmp 1f\n\t"
01740 ".align 16\n"
01741 "7:\n\t"
01742 "movl (%%edi),%2\n\t"
01743 "addl $4,%%edi\n\t"
01744 "testl %2,%2\n\t"
01745 "jnz 6f\n\t"
01746 "5:\n\t"
01747 "incl %%eax\n\t"
01748 "cmpl %7, %%eax\n\t"
01749
01750 "jnz 7b\n"
01751 "4:\n\t"
01752
01753 "movl %6,%%eax\n\t"
01754
01755
01756 "jmp 1f\n"
01757
01758 "6:\n\t"
01759 "bsfl %2,%2\n\t"
01760
01761 "sall $5,%%eax\n\t"
01762 "addl %2,%%eax\n"
01763 "1:"
01764
01765 : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01766 : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() + 1 + (this->M_index >> 5)),
01767 "n" (N), "n" (bitset_base<N>::digits)
01768 : "cc"
01769 );
01770 }
01771 #else
01772 if (DIRECTION == forwards_iterating)
01773 find1_forward();
01774 else
01775 find1_backward();
01776 #endif
01777 LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01778 return;
01779 }
01780
01781
01785 template<unsigned int N, int DIRECTION>
01786 inline
01787 bitset_iterator<N, DIRECTION>::bitset_iterator(void)
01788 {
01789 }
01790
01794 template<unsigned int N, int DIRECTION>
01795 inline
01796 bitset_iterator<N, DIRECTION>::bitset_iterator(bitset_base<N> const* bitset_ptr, int bit) :
01797 bitset_index_iterator<DIRECTION>(bit), M_bitset_ptr(bitset_ptr)
01798 {
01799 }
01800
01804 template<unsigned int N, int DIRECTION>
01805 inline
01806 bitset_iterator<N, DIRECTION>::bitset_iterator(bitset_iterator const& iter) :
01807 bitset_index_iterator<DIRECTION>(iter), M_bitset_ptr(iter.M_bitset_ptr)
01808 {
01809 }
01810
01814 template<unsigned int N, int DIRECTION>
01815 inline bitset_iterator<N, DIRECTION>&
01816 bitset_iterator<N, DIRECTION>::operator=(bitset_iterator<N, DIRECTION> const& iter)
01817 {
01818 #ifdef __i386__
01819 this->M_index = iter.M_index;
01820 #else
01821 this->M_digit = iter.M_digit;
01822 this->M_mask = iter.M_mask;
01823 #endif
01824 M_bitset_ptr = iter.M_bitset_ptr;
01825 return *this;
01826 }
01827
01828 template<unsigned int N, int DIRECTION>
01829 inline bitset_iterator<N, DIRECTION>&
01830 bitset_iterator<N, DIRECTION>::operator=(bitset_index_iterator<DIRECTION> const& index)
01831 {
01832 #ifdef __i386__
01833 this->M_index = index.get_index();
01834 #else
01835 this->M_digit = index.get_digit();
01836 this->M_mask = index.get_mask();
01837 #endif
01838 return *this;
01839 }
01840
01844 template<unsigned int N, int DIRECTION>
01845 inline bitset_iterator<N, DIRECTION>&
01846 bitset_iterator<N, DIRECTION>::operator++()
01847 {
01848 this->increment();
01849 return *this;
01850 }
01851
01855 template<unsigned int N, int DIRECTION>
01856 inline bitset_iterator<N, DIRECTION>
01857 bitset_iterator<N, DIRECTION>::operator++(int)
01858 {
01859 bitset_iterator prev(*this);
01860 this->increment();
01861 return prev;
01862 }
01863
01867 template<unsigned int N, int DIRECTION>
01868 inline bitset_iterator<N, DIRECTION>&
01869 bitset_iterator<N, DIRECTION>::operator--()
01870 {
01871 this->decrement();
01872 return *this;
01873 }
01874
01878 template<unsigned int N, int DIRECTION>
01879 inline bitset_iterator<N, DIRECTION>
01880 bitset_iterator<N, DIRECTION>::operator--(int)
01881 {
01882 bitset_iterator prev(*this);
01883 this->decrement();
01884 return prev;
01885 }
01886
01893 template<unsigned int N, int DIRECTION>
01894 inline bitset_digit_t
01895 bitset_iterator<N, DIRECTION>::operator*() const
01896 {
01897 #ifdef __i386__
01898 register unsigned int digit = this->M_index;
01899 register bitset_digit_t mask = 1;
01900 register unsigned short shift = this->M_index & (ECC_BITS - 1);
01901 digit >>= bitset_digit_bits_log2;
01902 mask <<= shift;
01903 return (M_bitset_ptr->rawdigit(digit) & mask);
01904 #else
01905 return (M_bitset_ptr->rawdigit(this->M_digit) & this->M_mask);
01906 #endif
01907 }
01908
01912 template<unsigned int N, int DIRECTION>
01913 inline bitset_iterator<N, DIRECTION>&
01914 bitset_iterator<N, DIRECTION>::operator+=(int d)
01915 {
01916 this->increment(d);
01917 return *this;
01918 }
01919
01923 template<unsigned int N, int DIRECTION>
01924 inline bitset_iterator<N, DIRECTION>&
01925 bitset_iterator<N, DIRECTION>::operator-=(int d)
01926 {
01927 this->decrement(d);
01928 return *this;
01929 }
01930
01934 template<unsigned int N, int DIRECTION>
01935 inline bitset_iterator<N, DIRECTION>
01936 operator+(bitset_iterator<N, DIRECTION> const& i, int d)
01937 {
01938 bitset_iterator<N, DIRECTION> result(i);
01939 return result += d;
01940 }
01941
01945 template<unsigned int N, int DIRECTION>
01946 inline bitset_iterator<N, DIRECTION>
01947 operator+(int d, bitset_iterator<N, DIRECTION> const& i)
01948 {
01949 bitset_iterator<N, DIRECTION> result(i);
01950 return result += d;
01951 }
01952
01956 template<unsigned int N, int DIRECTION>
01957 inline bitset_iterator<N, DIRECTION>
01958 operator-(bitset_iterator<N, DIRECTION> const& i, int d)
01959 {
01960 bitset_iterator<N, DIRECTION> result(i);
01961 return result -= d;
01962 }
01963
01967 template<unsigned int N, int DIRECTION>
01968 inline bitset_iterator<N, DIRECTION>
01969 operator-(int d, bitset_iterator<N, DIRECTION> const& i)
01970 {
01971 bitset_iterator<N, DIRECTION> result(i);
01972 return result -= d;
01973 }
01974
01978 template<unsigned int N, int DIRECTION>
01979 inline bitset_digit_t
01980 bitset_iterator<N, DIRECTION>::operator[](int d) const
01981 {
01982 return *(*this + d);
01983 }
01984
01985
01992 template<unsigned int N>
01993 classbitset : public bitset_invertible<N, false> {
01994 public:
01995
01996 bitset(void);
01997 bitset(std::string const&);
01998 explicit bitset(bitset_digit_t low_bits);
01999
02000
02006 bitset(bitset_digit_t const (&v)[bitset_base<N>::digits])
02007 {
02008 #if ECC_DEBUG
02009 assert( (v[bitset_base<N>::digits - 1] & ~bitset_base<N>::valid_bits) == 0 );
02010 #endif
02011 std::memcpy(this->vector, v, sizeof(this->vector));
02012 }
02013
02014
02015 template<unsigned int m, bool inverted>
02016 bitset(bitset_invertible<m, inverted> const&);
02017 template<unsigned int m, bool i1, bool i2, typename OP>
02018 bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr);
02019
02020
02021 bitset& operator=(bitset const&);
02022 template<typename Expression>
02023 bitset& operator=(Expression const&);
02024
02025
02026 template<typename Expression>
02027 bitset& operator&=(Expression const&);
02028 template<typename Expression>
02029 bitset& operator|=(Expression const&);
02030 template<typename Expression>
02031 bitset& operator^=(Expression const&);
02032
02033 public:
02034
02035 template<unsigned int shift, class DIRECTION, class OPERATION>
02036 void shift_op(bitset& result) const;
02037
02039 bitset& operator<<=(unsigned int shift) { this->bitset_base<N>::operator<<=(shift); return *this; }
02041 bitset& operator>>=(unsigned int shift) { this->bitset_base<N>::operator>>=(shift); return *this; }
02042
02043
02044 template<unsigned int shift, class DIRECTION>
02045 void rotate(bitset& result) const;
02046 };
02047
02051 template<unsigned int N>
02052 inline
02053 bitset<N>::bitset(void)
02054 {
02055 }
02056
02062 template<unsigned int N>
02063 inline
02064 bitset<N>::bitset(bitset_digit_t low_bits)
02065 {
02066 #if ECC_DEBUG
02067 assert( bitset_base<N>::digits > 1 || (low_bits & ~bitset_base<N>::valid_bits) == 0 );
02068 #endif
02069 std::memset(this->vector, 0, sizeof(this->vector));
02070 this->vector[0] = low_bits;
02071 }
02072
02076 template<unsigned int N>
02077 void
02078 bitset_base<N>::setall(void)
02079 {
02080 this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
02081 if (bitset_base<N>::digits > 1)
02082 {
02083 int d = bitset_base<N>::digits - 2;
02084 do { this->vector[d] = ~static_cast<bitset_digit_t>(0); } while(--d >= 0);
02085 }
02086 }
02087
02112 template<unsigned int N>
02113 template<typename Expression>
02114 inline
02115 bitset<N>& bitset<N>::operator=(Expression const& expr)
02116 {
02117 this->assign(expr, Operator::bitsetAssign());
02118 return *this;
02119 }
02120
02121
02122 template<unsigned int N>
02123 inline bitset<N>&
02124 bitset<N>::operator=(bitset const& expr)
02125 {
02126 this->assign(expr, Operator::bitsetAssign());
02127 return *this;
02128 }
02129
02146 template<unsigned int N>
02147 template<unsigned int m, bool inverted>
02148 inline bitset<N>::bitset(bitset_invertible<m, inverted> const& bits) : bitset_invertible<N, false>(bits)
02149 {
02150 }
02151
02157 template<unsigned int N>
02158 template<unsigned int m, bool i1, bool i2, typename OP>
02159 inline bitset<N>::bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr) : bitset_invertible<N, false>(expr)
02160 {
02161 }
02162
02174 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02175 bool operator==(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02176 {
02177 unsigned int d;
02178 if (bitset_invertible<n1, inverted1>::digits > bitset_invertible<n2, inverted2>::digits)
02179 {
02180 d = bitset_base<n1>::digits - 1;
02181 do
02182 {
02183 if (bits1.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02184 return false;
02185 }
02186 while (--d != bitset_base<n2>::digits - 1);
02187 }
02188 if (bitset_base<n2>::digits > bitset_base<n1>::digits)
02189 {
02190 d = bitset_base<n2>::digits - 1;
02191 do
02192 {
02193 if (bits2.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02194 return false;
02195 }
02196 while (--d != bitset_base<n1>::digits - 1);
02197 }
02198 if (bitset_base<n1>::digits > 1 && bitset_base<n2>::digits > 1)
02199 {
02200 if (bitset_base<n1>::digits == bitset_base<n2>::digits)
02201 d = bitset_base<n1>::digits - 1;
02202 do
02203 {
02204 if (inverted1 == inverted2)
02205 {
02206 if (bits1.vector[d] != bits2.vector[d])
02207 return false;
02208 }
02209 else
02210 {
02211 if (bits1.vector[d] != ~(bits2.vector[d]))
02212 return false;
02213 }
02214 }
02215 while(--d != 0);
02216 }
02217 if (inverted1 != inverted2)
02218 return (bits1.vector[0] == ~(bits2.vector[0]));
02219 return (bits1.vector[0] == bits2.vector[0]);
02220 }
02221
02227 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02228 inline bool
02229 operator!=(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02230 {
02231 return !(bits1 == bits2);
02232 }
02233
02238 template<unsigned int N>
02239 template<typename Expression>
02240 inline bitset<N>&
02241 bitset<N>::operator&=(Expression const& expr)
02242 {
02243 this->assign(expr, Operator::bitsetANDAssign());
02244 return *this;
02245 }
02246
02251 template<unsigned int N>
02252 template<typename Expression>
02253 inline bitset<N>&
02254 bitset<N>::operator|=(Expression const& expr)
02255 {
02256 this->assign(expr, Operator::bitsetORAssign());
02257 return *this;
02258 }
02259
02264 template<unsigned int N>
02265 template<typename Expression>
02266 inline bitset<N>&
02267 bitset<N>::operator^=(Expression const& expr)
02268 {
02269 this->assign(expr, Operator::bitsetXORAssign());
02270 return *this;
02271 }
02272
02277 template<unsigned int m, bool inverted1, bool inverted2>
02278 Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>
02279 operator&(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02280 {
02281 return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>(arg1, arg2);
02282 }
02283
02288 template<unsigned int m, bool inverted1, bool inverted2>
02289 Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>
02290 operator|(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02291 {
02292 return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>(arg1, arg2);
02293 }
02294
02299 template<unsigned int m, bool inverted1, bool inverted2>
02300 Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>
02301 operator^(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02302 {
02303 return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>(arg1, arg2);
02304 }
02305
02309 structassign {
02310 static int const id = 1;
02311 static bool const __clear = true;
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
02319 structexor {
02320 static int const id = 2;
02321 static bool const __clear = false;
02322 static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02323 static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02324 };
02325
02326 #ifndef HIDE_FROM_DOXYGEN
02327 structrotate_phase1 {
02328 static int const id = 3;
02329 static bool const __clear = false;
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
02334 structrotate_phase2 {
02335 public:
02336 static int const id = 4;
02337 static bool const __clear = false;
02338 static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02339 static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 |= digit2; }
02340 };
02341 #endif
02342
02353 template<unsigned int N>
02354 template<unsigned int shift, class DIRECTION, class OPERATION>
02355 void
02356 bitset<N>::shift_op(bitset& result) const
02357 {
02358 LibEccDout(dc::bitsetshift, "Entering shift_op<" << shift << ", " << libcwd::type_info_of<DIRECTION>().demangled_name() <<
02359 ", " << type_info_of<OPERATION>().demangled_name() << '>');
02360 LibEccDout(dc::bitsetshift|flush_cf, "Input : " << cwprint_using(*this, &bitset<N>::base2_print_on));
02361 if (shift == 1)
02362 {
02363
02364
02365
02366
02367
02368 static unsigned int const initial = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02369 static unsigned int const count = bitset_base<N>::digits - ((DIRECTION::__left && bitset_base<N>::has_excess_bits) ? 1 : 0);
02370 #ifdef __i386__
02371 if (count)
02372 {
02373 bitset_digit_t const volatile* ptr1;
02374 bitset_digit_t volatile* ptr2;
02375 int c;
02376 if (DIRECTION::__left)
02377 {
02378 if (OPERATION::id == libecc::exor::id)
02379 {
02380 if (bitset_base<N>::has_excess_bits)
02381 LIBECC_ASMSHIFTLEFT(
02382 LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02383 LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"),
02384 LIBECC_ASMSHIFTLEFT_FINISH("xorl (%%edi),%%edx\n\t"));
02385 else
02386 LIBECC_ASMSHIFTLEFT(
02387 LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02388 LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"), "");
02389 }
02390 else if (OPERATION::id == libecc::rotate_phase2::id)
02391 {
02392 if (bitset_base<N>::has_excess_bits)
02393 LIBECC_ASMSHIFTLEFT(
02394 LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02395 else
02396 LIBECC_ASMSHIFTLEFT(
02397 LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", "");
02398 }
02399 else
02400 {
02401 if (bitset_base<N>::has_excess_bits)
02402 LIBECC_ASMSHIFTLEFT("", "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02403 else
02404 LIBECC_ASMSHIFTLEFT("", "", "");
02405 }
02406 }
02407 else if (count > 1)
02408 {
02409 if (OPERATION::id == libecc::exor::id)
02410 LIBECC_ASMSHIFTRIGHT1(
02411 LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02412 LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP2_DESTINATION "," LIBECC_WORKREG),
02413 LIBECC_PRESERVE_CF_CLOBBER);
02414 else if (OPERATION::id == libecc::rotate_phase2::id)
02415 LIBECC_ASMSHIFTRIGHT1(
02416 LIBECC_RIGHT_PRESERVE_CF("orl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02417 "",
02418 LIBECC_PRESERVE_CF_CLOBBER);
02419 else
02420 LIBECC_ASMSHIFTRIGHT1(
02421 "",
02422 "",
02423 LIBECC_CLOBBER);
02424 }
02425 else
02426 {
02427 if (OPERATION::id == libecc::exor::id)
02428 LIBECC_ASMSHIFTRIGHT0("xorl 4(%%edi), %%edx\n\t");
02429 else if (OPERATION::id == libecc::rotate_phase2::id)
02430 LIBECC_ASMSHIFTRIGHT0("orl 4(%%edi), %%edx\n\t");
02431 else
02432 LIBECC_ASMSHIFTRIGHT0("");
02433 }
02434 }
02435 else if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02436 OPERATION::op(result.vector[0], ((this->vector[0] << 1) & bitset_base<N>::valid_bits));
02437 #else
02438 static unsigned int complement_shift = bitset_digit_bits - 1;
02439 static bitset_digit_t const mask1 = DIRECTION::__left ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02440 static bitset_digit_t const mask2 = DIRECTION::__right ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02441 bitset_digit_t const* ptr1 = &this->vector[initial];
02442 bitset_digit_t* ptr2 = &result.vector[initial];
02443 bool carry;
02444 if (count)
02445 {
02446 bitset_digit_t digit = *ptr1;
02447 carry = (digit & mask1);
02448 if (DIRECTION::__left)
02449 digit <<= 1;
02450 else
02451 digit >>= 1;
02452 OPERATION::mixed_op(*ptr2, digit);
02453 for (int c = count - 1; c; --c)
02454 {
02455 ptr1 -= DIRECTION::direction;
02456 ptr2 -= DIRECTION::direction;
02457 digit = *ptr1;
02458 if (carry)
02459 {
02460 carry = (digit & mask1);
02461 if (DIRECTION::__left)
02462 digit <<= 1;
02463 else
02464 digit >>= 1;
02465 digit |= mask2;
02466 }
02467 else
02468 {
02469 carry = (digit & mask1);
02470 if (DIRECTION::__left)
02471 digit <<= 1;
02472 else
02473 digit >>= 1;
02474 }
02475 OPERATION::op(*ptr2, digit);
02476 }
02477 }
02478 if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02479 {
02480 bitset_digit_t digit;
02481 if (count)
02482 digit = ptr1[-DIRECTION::direction];
02483 else
02484 digit = *ptr1;
02485 digit <<= 1;
02486 if (count && carry)
02487 digit |= mask2;
02488 if (count)
02489 OPERATION::op(ptr2[-DIRECTION::direction], (digit & bitset_base<N>::valid_bits));
02490 else
02491 OPERATION::op(*ptr2, (digit & bitset_base<N>::valid_bits));
02492 }
02493 #endif
02494 }
02495 else
02496 {
02497 static unsigned int const digit_shift = shift / bitset_digit_bits;
02498 static unsigned int const bit_shift = shift % bitset_digit_bits;
02499
02500 static unsigned int const zeroed_digits =
02501 DIRECTION::__left ? ((shift < N) ? digit_shift : bitset_base<N>::digits)
02502 : ((bitset_digit_bits - bitset_base<N>::number_of_valid_bits + shift) / bitset_digit_bits);
02503
02504 if (zeroed_digits < bitset_base<N>::digits)
02505 {
02506 static unsigned int const complement_shift = (bit_shift == 0) ? 0 : bitset_digit_bits - bit_shift;
02507 static unsigned int const initial_to = DIRECTION::__right ? 0 : bitset_base<N>::digits - 1;
02508 static unsigned int const initial_from = initial_to + DIRECTION::direction * digit_shift;
02509 static unsigned int const final_from = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02510
02511 register bitset_digit_t digit = this->vector[initial_from];
02512 if (initial_from != final_from)
02513 {
02514 register bitset_digit_t next_digit;
02515 unsigned int to = initial_to;
02516 unsigned int from = initial_from + DIRECTION::direction;
02517 if (from != final_from)
02518 do
02519 {
02520 next_digit = this->vector[from];
02521 if (bit_shift != 0)
02522 {
02523 if (DIRECTION::direction == -1)
02524 digit <<= bit_shift;
02525 else
02526 digit >>= bit_shift;
02527 digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02528 }
02529 OPERATION::op(result.vector[to], digit);
02530 digit = next_digit;
02531 to += DIRECTION::direction;
02532 from += DIRECTION::direction;
02533 }
02534 while (from != final_from);
02535 if (DIRECTION::__left || bit_shift < bitset_base<N>::number_of_valid_bits || bit_shift != 0)
02536 next_digit = this->vector[final_from];
02537 if (bit_shift != 0)
02538 {
02539 if (DIRECTION::direction == -1)
02540 digit <<= bit_shift;
02541 else
02542 digit >>= bit_shift;
02543 digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02544 }
02545 if (DIRECTION::__left || bit_shift < bitset_base<N>::number_of_valid_bits)
02546 {
02547 OPERATION::op(result.vector[final_from - DIRECTION::direction * (digit_shift + 1)], digit);
02548 digit = DIRECTION::shift_copy(next_digit, bit_shift);
02549 }
02550 }
02551 else
02552 {
02553 if (DIRECTION::direction == -1)
02554 digit <<= bit_shift;
02555 else
02556 digit >>= bit_shift;
02557 }
02558 static bool const have_mixed_digit = shift != 0 && (DIRECTION::__left ? shift : (N - shift)) % bitset_digit_bits != 0;
02559 static unsigned int const last_digit = (DIRECTION::__left ? shift : (N - 1 - shift)) / bitset_digit_bits;
02560 if (have_mixed_digit)
02561 OPERATION::mixed_op(result.vector[last_digit], digit);
02562 else
02563 OPERATION::op(result.vector[last_digit], digit);
02564 if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02565 result.vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
02566 }
02567 if (OPERATION::__clear && zeroed_digits > 0)
02568 {
02569 static unsigned int const final_to = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02570 static unsigned int const initial_to = final_to - DIRECTION::direction * (zeroed_digits - 1);
02571 unsigned int to = initial_to;
02572 if (to != final_to)
02573 do
02574 {
02575 result.vector[to] = 0;
02576 to += DIRECTION::direction;
02577 }
02578 while(to != final_to);
02579 result.vector[to] = 0;
02580 }
02581 }
02582 LibEccDout(dc::bitsetshift|flush_cf, "Output: " << cwprint_using(result, &bitset<N>::base2_print_on));
02583 }
02584
02585 template<unsigned int N>
02586 void
02587 bitset_base<N>::operator<<=(unsigned int shift)
02588 {
02589 unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02590 unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02591 int digit1 = bitset_base<N>::digits - digit_shift - 2;
02592 bitset_digit_t d0 = (digit1 >= -1) ? this->vector[digit1 + 1] : 0;
02593 for (int digit_to = bitset_base<N>::digits - 1; digit_to >= 0; --digit_to)
02594 {
02595 bitset_digit_t d1 = (digit1 >= 0) ? this->vector[digit1] : 0;
02596 if (bit_shift == 0)
02597 this->vector[digit_to] = d0;
02598 else
02599 this->vector[digit_to] = (d0 << bit_shift) | (d1 >> (bitset_digit_bits - bit_shift));
02600 d0 = d1;
02601 --digit1;
02602 }
02603 if (bitset_base<N>::has_excess_bits)
02604 this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
02605 }
02606
02607 template<unsigned int N>
02608 void
02609 bitset_base<N>::operator>>=(unsigned int shift)
02610 {
02611 unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02612 unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02613 unsigned int digit1 = digit_shift + 1;
02614 bitset_digit_t d0 = (digit1 <= bitset_base<N>::digits) ? this->vector[digit1 - 1] : 0;
02615 for (unsigned int digit_to = 0; digit_to < bitset_base<N>::digits; ++digit_to)
02616 {
02617 bitset_digit_t d1 = (digit1 < bitset_base<N>::digits) ? this->vector[digit1] : 0;
02618 if (bit_shift == 0)
02619 this->vector[digit_to] = d0;
02620 else
02621 this->vector[digit_to] = (d0 >> bit_shift) | (d1 << (bitset_digit_bits - bit_shift));
02622 d0 = d1;
02623 ++digit1;
02624 }
02625 }
02626
02643 template<unsigned int N>
02644 bitset<N>::bitset(std::string const& input)
02645 {
02646 this->reset();
02647 unsigned int d = 0;
02648 unsigned int u = 0;
02649
02650 for (std::string::const_reverse_iterator iter = input.rbegin(); iter != input.rend(); ++iter)
02651 {
02652 bitset_digit_t c = toupper(*iter);
02653 if (c == ' ')
02654 continue;
02655 if (c < '0')
02656 break;
02657 if (c <= '9')
02658 c -= '0';
02659 else
02660 {
02661 if (c > 'F')
02662 break;
02663 if (c >= 'A')
02664 c -= ('A' - 10);
02665 else
02666 break;
02667 }
02668 this->vector[d] |= c << u;
02669 if ((u += 4) == bitset_digit_bits)
02670 {
02671 u = 0;
02672 if (++d == bitset_base<N>::digits)
02673 break;
02674 }
02675 }
02676 if (bitset_base<N>::has_excess_bits)
02677 this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
02678 }
02679
02683 template<unsigned int N>
02684 std::istream&
02685 operator>>(std::istream& is, bitset<N>& bitsetx)
02686 {
02687 std::string tmp;
02688 is >> tmp;
02689 bitsetx.bitset(tmp);
02690 return is;
02691 }
02692
02696 template<unsigned int N>
02697 std::ostream&
02698 operator<<(std::ostream& os, bitset<N> const& bits)
02699 {
02700
02701 os.fill('0');
02702 os << std::hex;
02703 for (int d = bitset<N>::digits - 1; d >= 0; --d)
02704 {
02705 os.width((d == bitset<N>::digits - 1 && bitset<N>::has_excess_bits) ?
02706 (((N % bitset_digit_bits) - 1) / 4 + 1) :
02707 (bitset_digit_bits / 4));
02708 os << bits.digit(d);
02709 if (d > 0)
02710 os << ' ';
02711 }
02712 os << std::dec;
02713 return os;
02714 }
02715
02719 template<unsigned int N>
02720 void
02721 bitset_base<N>::reset(void)
02722 {
02723 std::memset(this->vector, 0, sizeof(this->vector));
02724 }
02725
02729 template<unsigned int N>
02730 inline bool
02731 bitset_base<N>::test(size_t pos) const
02732 {
02733 #ifdef __i386__
02734 int result;
02735 __asm__ __volatile__ (
02736 "btl %2, %1\n\t"
02737 "sbbl %0, %0"
02738 : "=r" (result)
02739 : "m" ((*(bitset_digit_t volatile*)this->vector)), "Ir" (pos)
02740 : "cc");
02741 return result;
02742 #else
02743 unsigned int d = pos / bitset_digit_bits;
02744 bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02745 return (this->vector[d] & mask);
02746 #endif
02747 }
02748
02752 template<unsigned int N>
02753 template<unsigned int pos>
02754 inline bool
02755 bitset_base<N>::test(void) const
02756 {
02757 static unsigned int const d = pos / bitset_digit_bits;
02758 static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02759 return (this->vector[d] & mask);
02760 }
02761
02765 template<unsigned int N>
02766 inline bool
02767 bitset_base<N>::test(bitset_index const& index) const
02768 {
02769 #ifdef __i386__
02770 return this->test(index.get_index());
02771 #else
02772 return (this->vector[index.get_digit()] & index.get_mask());
02773 #endif
02774 }
02775
02779 template<unsigned int N>
02780 inline void
02781 bitset_base<N>::set(size_t pos)
02782 {
02783 #ifdef __i386__
02784 __asm__ __volatile__ (
02785 "btsl %1, %0"
02786 : "=m" ((*(bitset_digit_t volatile*)this->vector))
02787 : "Ir" (pos)
02788 : "cc");
02789
02790 #else
02791 unsigned int d = pos / bitset_digit_bits;
02792 bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02793 this->vector[d] |= mask;
02794 #endif
02795 }
02796
02800 template<unsigned int N>
02801 inline void
02802 bitset_base<N>::set(bitset_index const& index)
02803 {
02804 #ifdef __i386__
02805 this->set(index.get_index());
02806 #else
02807 this->vector[index.get_digit()] |= index.get_mask();
02808 #endif
02809 }
02810
02814 template<unsigned int N>
02815 template<unsigned int pos>
02816 inline void
02817 bitset_base<N>::set(void)
02818 {
02819 static unsigned int const d = pos / bitset_digit_bits;
02820 static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02821 this->vector[d] |= mask;
02822 }
02823
02827 template<unsigned int N>
02828 inline void
02829 bitset_base<N>::clear(size_t pos)
02830 {
02831 #ifdef __i386__
02832 __asm__ __volatile__ (
02833 "btrl %1, %0"
02834 : "=m" ((*(bitset_digit_t volatile*)this->vector))
02835 : "Ir" (pos)
02836 : "cc"
02837 );
02838 #else
02839 unsigned int d = pos / bitset_digit_bits;
02840 bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02841 this->vector[d] &= ~mask;
02842 #endif
02843 }
02844
02848 template<unsigned int N>
02849 inline void
02850 bitset_base<N>::clear(bitset_index const& index)
02851 {
02852 #ifdef __i386__
02853 this->clear(index.get_index());
02854 #else
02855 this->vector[index.get_digit()] &= ~(index.get_mask());
02856 #endif
02857 }
02858
02862 template<unsigned int N>
02863 template<unsigned int pos>
02864 inline void
02865 bitset_base<N>::clear(void)
02866 {
02867 static unsigned int const d = pos / bitset_digit_bits;
02868 static bitset_digit_t const mask = ~(static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits));
02869 this->vector[d] &= mask;
02870 }
02871
02875 template<unsigned int N>
02876 inline void
02877 bitset_base<N>::flip(size_t pos)
02878 {
02879 #ifdef __i386__
02880 __asm__ __volatile__ (
02881 "btcl %1, %0"
02882 : "=m" ((*(bitset_digit_t volatile*)this->vector))
02883 : "Ir" (pos)
02884 : "cc"
02885 );
02886 #else
02887 unsigned int d = pos / bitset_digit_bits;
02888 bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02889 this->vector[d] ^= mask;
02890 #endif
02891 }
02892
02896 template<unsigned int N>
02897 inline void
02898 bitset_base<N>::flip(bitset_index const& index)
02899 {
02900 #ifdef __i386__
02901 this->flip(index.get_index());
02902 #else
02903 this->vector[index.get_digit()] ^= index.get_mask();
02904 #endif
02905 }
02906
02910 template<unsigned int N>
02911 template<unsigned int pos>
02912 inline void
02913 bitset_base<N>::flip(void)
02914 {
02915 static unsigned int const d = pos / bitset_digit_bits;
02916 static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02917 this->vector[d] ^= mask;
02918 }
02919
02923 template<unsigned int N>
02924 bool
02925 bitset_base<N>::any(void) const
02926 {
02927 unsigned int to = bitset_base<N>::digits - 1;
02928 if (bitset_base<N>::digits > 1)
02929 do
02930 {
02931 if (this->vector[to] != 0)
02932 return true;
02933 --to;
02934 }
02935 while(to != 0);
02936 return (this->vector[0] != 0);
02937 }
02938
02939 static bool const oddnumberofbits[] = {
02940 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02941 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02942 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02943 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02944 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02945 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02946 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02947 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02948 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02949 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02950 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02951 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02952 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02953 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02954 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02955 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false };
02956
02960 template<unsigned int N>
02961 bool
02962 bitset_base<N>::odd(void) const
02963 {
02964 unsigned int from = bitset_base<N>::digits - 1;
02965 bitset_digit_t sum = this->vector[0];
02966 if (bitset_base<N>::digits > 1)
02967 do
02968 {
02969 sum ^= this->vector[from];
02970 --from;
02971 }
02972 while(from != 0);
02973 bitset_digit_t ssum = sum;
02974 if (sizeof(bitset_digit_t) >= 2)
02975 {
02976 ssum >>= (bitset_digit_bits / 2);
02977 sum ^= ssum;
02978 }
02979 if (sizeof(bitset_digit_t) >= 4)
02980 {
02981 ssum = sum;
02982 ssum >>= (bitset_digit_bits / 4);
02983 sum ^= ssum;
02984 }
02985 if (sizeof(bitset_digit_t) >= 8)
02986 {
02987 ssum = sum;
02988 ssum >>= (bitset_digit_bits / 8);
02989 sum ^= ssum;
02990 }
02991 if (sizeof(bitset_digit_t) == 16)
02992 {
02993 ssum = sum;
02994 ssum >>= (bitset_digit_bits / 16);
02995 sum ^= ssum;
02996 }
02997 return oddnumberofbits[sum & 0xff];
02998 }
02999
03003 structleft {
03004 public:
03005 typedef structright inverse;
03006 static int const direction = -1;
03007 static bool const __left = true;
03008 static bool const __right = false;
03009 static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03010 static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03011 };
03012
03016 structright {
03017 public:
03018 typedef structleft inverse;
03019 static int const direction = 1;
03020 static bool const __left = false;
03021 static bool const __right = true;
03022 static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03023 static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03024 };
03025
03034 template<unsigned int N>
03035 template<unsigned int shift, class DIRECTION>
03036 void
03037 bitset<N>::rotate(bitset<N>& result) const
03038 {
03039 LibEccDout(dc::bitsetshift|flush_cf, "Entering bitset<" << N << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03040 LibEccDout(dc::bitsetshift|flush_cf, "Rotate input : " << cwprint_using(*this, &bitset<N>::base2_print_on));
03041 shift_op<shift % N, DIRECTION, rotate_phase1>(result);
03042 LibEccDout(dc::bitsetshift|flush_cf, "After phase1 : " << cwprint_using(result, &bitset<N>::base2_print_on));
03043 shift_op<N - (shift % N), typename DIRECTION::inverse, rotate_phase2>(result);
03044 LibEccDout(dc::bitsetshift|flush_cf, "After phase2 : " << cwprint_using(result, &bitset<N>::base2_print_on));
03045 LibEccDout(dc::bitsetshift|flush_cf, "Leaving bitset<" << N << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03046 }
03047
03048 }
03049
03050 #endif // LIBECC_BITS_H