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 "i" (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 {
01320 #ifdef __i386__
01321 int __d0, __d1;
01322 __asm__ __volatile__ (
01323 "std; rep; stosl"
01324 : "=m" (this->vector[bitset_base<N>::digits - 1]), "=&c" (__d0), "=&D" (__d1)
01325 : "a" (0), "1" (bitset_base<N>::digits - bitset_base<x>::digits), "2" (&this->vector[bitset_base<N>::digits - 1])
01326 : "memory"
01327 );
01328 #else
01329 unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01330 do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
01331 #endif
01332 }
01333 }
01334 else
01335 {
01336
01337 if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
01338 {
01339 #ifdef __i386__
01340 int __d0, __d1;
01341 __asm__ __volatile__ (
01342 "movl %6,4(%%edi); std; rep; stosl"
01343 : "=m" (this->vector[bitset_base<N>::digits - 2]), "=&c" (__d0), "=&D" (__d1)
01344 : "a" (-1), "1" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<N>::digits - 2]), "i" (bitset_base<N>::valid_bits)
01345 : "memory"
01346 );
01347 #else
01348 this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
01349 unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01350 while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
01351 #endif
01352 }
01353
01354 if (ASSIGNMENT_OPERATOR::with_ones_inverts)
01355 {
01356 #ifdef __i386__
01357 int __d0, __d1;
01358 __asm__ __volatile__ (
01359 "xorl %5,(%2)\n\t"
01360 "jecxz 2f\n\t"
01361 "subl %6,%2\n"
01362 "1:\n\t"
01363 "xorl $-1,(%2,%%ecx,4)\n\t"
01364 "decl %%ecx\n\t"
01365 "jnz 1b\n"
01366 "2:"
01367 : "=m" (this->vector[bitset_base<N>::digits - 1]), "=&c" (__d0), "=&r" (__d1)
01368 : "1" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<N>::digits - 1]),
01369 "i" (bitset_base<N>::valid_bits), "i" ((bitset_base<N>::digits - bitset_base<x>::digits) * 4)
01370 : "memory", "cc"
01371 );
01372 #else
01373 this->vector[bitset_base<N>::digits - 1] ^= bitset_base<N>::valid_bits;
01374 unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01375 while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
01376 #endif
01377 }
01378 }
01379 }
01380
01381
01382 #ifdef __i386__
01383 LIBECC_INLINE_ASMLOOP(ASSIGNMENT_OPERATOR::id,
01384 this->vector, bits.digits_ptr(),
01385 ((bitset_base<N>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<N>::digits),
01386 inverted_argument);
01387 #else
01388 unsigned int d;
01389 if (bitset_base<N>::digits > bitset_base<x>::digits)
01390 d = bitset_base<x>::digits - 1;
01391 else
01392 d = bitset_base<N>::digits - 1;
01393 ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~bits.rawdigit(d) : bits.rawdigit(d));
01394 while(d) { --d; ASSIGNMENT_OPERATOR::exec(this->vector[d], inverted_argument ? ~bits.rawdigit(d) : bits.rawdigit(d)); }
01395 #endif
01396
01397
01398 if (((!inverted_argument && x > N) ||
01399 (inverted_argument && bitset_base<N>::digits <= bitset_base<x>::digits)) &&
01400 bitset_base<N>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
01401 this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
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
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460 template<unsigned int N, bool inverted>
01461 template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted1, bool inverted2, typename OPERATOR>
01462 inline void
01463 bitset_invertible<N, inverted>::assign(Operator::bitsetExpression<x, inverted1, inverted2, OPERATOR> const& expr, ASSIGNMENT_OPERATOR)
01464 {
01465 static bool const argument_has_leading_ones = OPERATOR::template execbool<inverted1, inverted2>::value;
01466
01467
01468 if (bitset_base<N>::digits > bitset_base<x>::digits)
01469 {
01470 if (!argument_has_leading_ones)
01471 {
01472
01473 if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
01474 {
01475 #ifdef __i386__
01476 int __d0, __d1;
01477 __asm__ __volatile__ (
01478 "std; rep; stosl"
01479 : "=m" (this->vector[bitset_base<N>::digits - 1]), "=&c" (__d0), "=&D" (__d1)
01480 : "a" (0), "1" (bitset_base<N>::digits - bitset_base<x>::digits), "2" (&this->vector[bitset_base<N>::digits - 1])
01481 : "memory"
01482 );
01483 #else
01484 unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01485 do { this->vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
01486 #endif
01487 }
01488 }
01489 else
01490 {
01491
01492 if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
01493 {
01494 #ifdef __i386__
01495 int __d0, __d1;
01496 __asm__ __volatile__ (
01497 "movl %6,4(%%edi); std; rep; stosl"
01498 : "=m" (this->vector[bitset_base<N>::digits - 2]), "=&c" (__d0), "=&D" (__d1)
01499 : "a" (-1), "1" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<N>::digits - 2]), "i" (bitset_base<N>::valid_bits)
01500 : "memory"
01501 );
01502 #else
01503 this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
01504 unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01505 while(--count) { this->vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
01506 #endif
01507 }
01508
01509 if (ASSIGNMENT_OPERATOR::with_ones_inverts)
01510 {
01511 #ifdef __i386__
01512 int __d0, __d1;
01513 __asm__ __volatile__ (
01514 "xorl %5,(%2)\n\t"
01515 "jecxz 2f\n\t"
01516 "subl %6,%2\n"
01517 "1:\n\t"
01518 "xorl $-1,(%2,%%ecx,4)\n\t"
01519 "decl %%ecx\n\t"
01520 "jnz 1b\n"
01521 "2:"
01522 : "=m" (this->vector[bitset_base<N>::digits - 1]), "=&c" (__d0), "=&r" (__d1)
01523 : "1" (bitset_base<N>::digits - bitset_base<x>::digits - 1), "2" (&this->vector[bitset_base<N>::digits - 1]),
01524 "i" (bitset_base<N>::valid_bits), "i" ((bitset_base<N>::digits - bitset_base<x>::digits) * 4)
01525 : "memory", "cc"
01526 );
01527 #else
01528 this->vector[bitset_base<N>::digits - 1] ^= bitset_base<N>::valid_bits;
01529 unsigned int count = bitset_base<N>::digits - bitset_base<x>::digits;
01530 while(--count) { this->vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
01531 #endif
01532 }
01533 }
01534 }
01535
01536
01537 #ifdef __i386__
01538 LIBECC_INLINE_ASMLOOP2(ASSIGNMENT_OPERATOR::id, OPERATOR, inverted1, inverted2,
01539 this->vector, expr.first.digits_ptr(), expr.second.digits_ptr(),
01540 ((bitset_base<N>::digits > bitset_base<x>::digits) ? bitset_base<x>::digits : bitset_base<N>::digits));
01541 #else
01542 unsigned int d;
01543 if (bitset_base<N>::digits < bitset_base<x>::digits)
01544 d = bitset_base<N>::digits - 1;
01545 else
01546 d = bitset_base<x>::digits - 1;
01547 for(;;)
01548 {
01549 ASSIGNMENT_OPERATOR::exec(this->vector[d],
01550 OPERATOR::exec(inverted1 ? ~expr.first.rawdigit(d) : expr.first.rawdigit(d),
01551 inverted2 ? ~expr.second.rawdigit(d) : expr.second.rawdigit(d)));
01552 if (!d)
01553 break;
01554 --d;
01555 }
01556 #endif
01557
01558
01559 if (((!argument_has_leading_ones && x > N) ||
01560 (argument_has_leading_ones && bitset_base<N>::digits <= bitset_base<x>::digits)) &&
01561 bitset_base<N>::has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
01562 this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
01563 }
01564
01591 template<unsigned int N, bool inverted>
01592 inline bitset_invertible<N, !inverted> const&
01593 operator~(bitset_invertible<N, inverted> const& bits)
01594 {
01595 return *reinterpret_cast<bitset_invertible<N, !inverted> const*>(&bits);
01596 }
01597
01598 #ifndef __i386__
01599 template<unsigned int N, int DIRECTION>
01600 void
01601 bitset_iterator<N, DIRECTION>::find1_forward(void)
01602 {
01603 if (this->M_digit < (int)bitset_base<N>::digits - 1 || (this->M_mask & bitset_base<N>::valid_bits))
01604 {
01605 register bitset_digit_t mask = this->M_mask;
01606 while(!(M_bitset_ptr->rawdigit(this->M_digit) & mask))
01607 {
01608 if ((mask <<= 1))
01609 continue;
01610 mask = 1;
01611 while(++(this->M_digit) < (int)bitset_base<N>::digits)
01612 if (M_bitset_ptr->rawdigit(this->M_digit))
01613 break;
01614 if (this->M_digit == (int)bitset_base<N>::digits)
01615 {
01616 this->M_digit = (N >> bitset_digit_bits_log2);
01617 mask = static_cast<bitset_digit_t>(1) << (N & (bitset_digit_bits - 1));
01618 break;
01619 }
01620 }
01621 this->M_mask = mask;
01622 }
01623 }
01624
01625 template<unsigned int N, int DIRECTION>
01626 void
01627 bitset_iterator<N, DIRECTION>::find1_backward(void)
01628 {
01629 LibEccDout(dc::bitsetfind1, "Entering find1_backward with: " <<
01630 libcwd::cwprint_using(*static_cast<bitset_invertible<N, false> const*>(M_bitset_ptr), &bitset_invertible<N, false>::base2_print_on));
01631 LibEccDout(dc::bitsetfind1, "Input: " << *this);
01632 if (this->M_digit >= 0)
01633 {
01634 register bitset_digit_t mask = this->M_mask;
01635 if (!(M_bitset_ptr->rawdigit(this->M_digit) & (mask | (mask - 1))))
01636 {
01637 mask = static_cast<bitset_digit_t>(1) << (bitset_digit_bits - 1);
01638 do
01639 {
01640 if (--(this->M_digit) < 0)
01641 {
01642 this->M_mask = mask;
01643 return;
01644 }
01645 }
01646 while (!M_bitset_ptr->rawdigit(this->M_digit));
01647 }
01648 while(!(M_bitset_ptr->rawdigit(this->M_digit) & mask))
01649 mask >>= 1;
01650 this->M_mask = mask;
01651 }
01652 LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01653 }
01654 #endif
01655
01659 template<unsigned int N, int DIRECTION>
01660 inline void
01661 bitset_iterator<N, DIRECTION>::find1(void)
01662 {
01663 LibEccDout(dc::bitsetfind1, "Input: " << *this);
01664 LibEccDout(dc::bitsetfind1, "Entering find1 with: " <<
01665 libcwd::cwprint_using(*static_cast<bitset_invertible<N, false> const*>(M_bitset_ptr), &bitset_invertible<N, false>::base2_print_on));
01666 #ifdef __i386__
01667 int bit_index, digit, ptr;
01668 if (DIRECTION == backwards_iterating)
01669 {
01670 __asm__ __volatile__ (
01671
01672
01673
01674
01675
01676
01677 "movl %%eax,%%ecx\n\t"
01678
01679 "sarl $5,%%eax\n\t"
01680
01681 "andl $31,%%ecx\n\t"
01682
01683 "js 1f\n\t"
01684
01685
01686
01687 "movl 4(%%edi),%2\n\t"
01688
01689
01690 "xorl $31,%%ecx\n\t"
01691
01692 "shll %%cl,%2\n\t"
01693
01694
01695
01696 "orl %2,%2\n\t"
01697
01698 "jz 5f\n\t"
01699
01700
01701 "bsrl %2,%2\n\t"
01702
01703
01704 "sall $5,%%eax\n\t"
01705
01706 "subl %%ecx,%2\n\t"
01707
01708 "addl %2,%%eax\n\t"
01709
01710
01711 "jmp 1f\n\t"
01712 ".align 16\n"
01713 "7:\n\t"
01714 "movl (%%edi),%2\n\t"
01715 "subl $4,%%edi\n\t"
01716 "testl %2,%2\n\t"
01717 "jnz 6f\n\t"
01718 "5:\n\t"
01719 "decl %%eax\n\t"
01720
01721 "jns 7b\n"
01722 "4:\n\t"
01723
01724 "movl $-1,%%eax\n\t"
01725
01726
01727 "jmp 1f\n"
01728
01729 "6:\n\t"
01730 "bsrl %2,%2\n\t"
01731
01732 "sall $5,%%eax\n\t"
01733 "addl %2,%%eax\n"
01734 "1:"
01735
01736 : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01737 : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() - 1 + (this->M_index >> 5))
01738 : "cc"
01739 );
01740 }
01741 else
01742 {
01743 __asm__ __volatile__ (
01744
01745
01746
01747
01748
01749
01750 "cmpl %6,%%eax\n\t"
01751 "jge 1f\n\t"
01752
01753 "movl %%eax,%%ecx\n\t"
01754
01755 "sarl $5,%%eax\n\t"
01756
01757 "andl $31,%%ecx\n\t"
01758
01759
01760
01761 "movl -4(%%edi),%2\n\t"
01762
01763
01764 "shrl %%cl,%2\n\t"
01765
01766
01767
01768 "orl %2,%2\n\t"
01769
01770 "jz 5f\n\t"
01771
01772
01773 "bsfl %2,%2\n\t"
01774
01775
01776 "sall $5,%%eax\n\t"
01777
01778 "addl %%ecx,%2\n\t"
01779
01780 "addl %2,%%eax\n\t"
01781
01782
01783 "jmp 1f\n\t"
01784 ".align 16\n"
01785 "7:\n\t"
01786 "movl (%%edi),%2\n\t"
01787 "addl $4,%%edi\n\t"
01788 "testl %2,%2\n\t"
01789 "jnz 6f\n\t"
01790 "5:\n\t"
01791 "incl %%eax\n\t"
01792 "cmpl %7, %%eax\n\t"
01793
01794 "jnz 7b\n"
01795 "4:\n\t"
01796
01797 "movl %6,%%eax\n\t"
01798
01799
01800 "jmp 1f\n"
01801
01802 "6:\n\t"
01803 "bsfl %2,%2\n\t"
01804
01805 "sall $5,%%eax\n\t"
01806 "addl %2,%%eax\n"
01807 "1:"
01808
01809 : "=a" (this->M_index), "=&c" (bit_index), "=r" (digit), "=&D" (ptr)
01810 : "0" (this->M_index), "3" (M_bitset_ptr->digits_ptr() + 1 + (this->M_index >> 5)),
01811 "i" (N), "i" (bitset_base<N>::digits)
01812 : "cc"
01813 );
01814 }
01815 #else
01816 if (DIRECTION == forwards_iterating)
01817 find1_forward();
01818 else
01819 find1_backward();
01820 #endif
01821 LibEccDout(dc::bitsetfind1|flush_cf, "Output: " << *this);
01822 return;
01823 }
01824
01825
01829 template<unsigned int N, int DIRECTION>
01830 inline
01831 bitset_iterator<N, DIRECTION>::bitset_iterator(void)
01832 {
01833 }
01834
01838 template<unsigned int N, int DIRECTION>
01839 inline
01840 bitset_iterator<N, DIRECTION>::bitset_iterator(bitset_base<N> const* bitset_ptr, int bit) :
01841 bitset_index_iterator<DIRECTION>(bit), M_bitset_ptr(bitset_ptr)
01842 {
01843 }
01844
01848 template<unsigned int N, int DIRECTION>
01849 inline
01850 bitset_iterator<N, DIRECTION>::bitset_iterator(bitset_iterator const& iter) :
01851 bitset_index_iterator<DIRECTION>(iter), M_bitset_ptr(iter.M_bitset_ptr)
01852 {
01853 }
01854
01858 template<unsigned int N, int DIRECTION>
01859 inline bitset_iterator<N, DIRECTION>&
01860 bitset_iterator<N, DIRECTION>::operator=(bitset_iterator<N, DIRECTION> const& iter)
01861 {
01862 #ifdef __i386__
01863 this->M_index = iter.M_index;
01864 #else
01865 this->M_digit = iter.M_digit;
01866 this->M_mask = iter.M_mask;
01867 #endif
01868 M_bitset_ptr = iter.M_bitset_ptr;
01869 return *this;
01870 }
01871
01872 template<unsigned int N, int DIRECTION>
01873 inline bitset_iterator<N, DIRECTION>&
01874 bitset_iterator<N, DIRECTION>::operator=(bitset_index_iterator<DIRECTION> const& index)
01875 {
01876 #ifdef __i386__
01877 this->M_index = index.get_index();
01878 #else
01879 this->M_digit = index.get_digit();
01880 this->M_mask = index.get_mask();
01881 #endif
01882 return *this;
01883 }
01884
01888 template<unsigned int N, int DIRECTION>
01889 inline bitset_iterator<N, DIRECTION>&
01890 bitset_iterator<N, DIRECTION>::operator++()
01891 {
01892 this->increment();
01893 return *this;
01894 }
01895
01899 template<unsigned int N, int DIRECTION>
01900 inline bitset_iterator<N, DIRECTION>
01901 bitset_iterator<N, DIRECTION>::operator++(int)
01902 {
01903 bitset_iterator prev(*this);
01904 this->increment();
01905 return prev;
01906 }
01907
01911 template<unsigned int N, int DIRECTION>
01912 inline bitset_iterator<N, DIRECTION>&
01913 bitset_iterator<N, DIRECTION>::operator--()
01914 {
01915 this->decrement();
01916 return *this;
01917 }
01918
01922 template<unsigned int N, int DIRECTION>
01923 inline bitset_iterator<N, DIRECTION>
01924 bitset_iterator<N, DIRECTION>::operator--(int)
01925 {
01926 bitset_iterator prev(*this);
01927 this->decrement();
01928 return prev;
01929 }
01930
01937 template<unsigned int N, int DIRECTION>
01938 inline bitset_digit_t
01939 bitset_iterator<N, DIRECTION>::operator*() const
01940 {
01941 #ifdef __i386__
01942 register unsigned int digit = this->M_index;
01943 register bitset_digit_t mask = 1;
01944 register unsigned short shift = this->M_index & (ECC_BITS - 1);
01945 digit >>= bitset_digit_bits_log2;
01946 mask <<= shift;
01947 return (M_bitset_ptr->rawdigit(digit) & mask);
01948 #else
01949 return (M_bitset_ptr->rawdigit(this->M_digit) & this->M_mask);
01950 #endif
01951 }
01952
01956 template<unsigned int N, int DIRECTION>
01957 inline bitset_iterator<N, DIRECTION>&
01958 bitset_iterator<N, DIRECTION>::operator+=(int d)
01959 {
01960 this->increment(d);
01961 return *this;
01962 }
01963
01967 template<unsigned int N, int DIRECTION>
01968 inline bitset_iterator<N, DIRECTION>&
01969 bitset_iterator<N, DIRECTION>::operator-=(int d)
01970 {
01971 this->decrement(d);
01972 return *this;
01973 }
01974
01978 template<unsigned int N, int DIRECTION>
01979 inline bitset_iterator<N, DIRECTION>
01980 operator+(bitset_iterator<N, DIRECTION> const& i, int d)
01981 {
01982 bitset_iterator<N, DIRECTION> result(i);
01983 return result += d;
01984 }
01985
01989 template<unsigned int N, int DIRECTION>
01990 inline bitset_iterator<N, DIRECTION>
01991 operator+(int d, bitset_iterator<N, DIRECTION> const& i)
01992 {
01993 bitset_iterator<N, DIRECTION> result(i);
01994 return result += d;
01995 }
01996
02000 template<unsigned int N, int DIRECTION>
02001 inline bitset_iterator<N, DIRECTION>
02002 operator-(bitset_iterator<N, DIRECTION> const& i, int d)
02003 {
02004 bitset_iterator<N, DIRECTION> result(i);
02005 return result -= d;
02006 }
02007
02011 template<unsigned int N, int DIRECTION>
02012 inline bitset_iterator<N, DIRECTION>
02013 operator-(int d, bitset_iterator<N, DIRECTION> const& i)
02014 {
02015 bitset_iterator<N, DIRECTION> result(i);
02016 return result -= d;
02017 }
02018
02022 template<unsigned int N, int DIRECTION>
02023 inline bitset_digit_t
02024 bitset_iterator<N, DIRECTION>::operator[](int d) const
02025 {
02026 return *(*this + d);
02027 }
02028
02029
02036 template<unsigned int N>
02037 classbitset : public bitset_invertible<N, false> {
02038 public:
02039
02040 bitset(void);
02041 bitset(std::string const&);
02042 explicit bitset(bitset_digit_t low_bits);
02043
02044
02050 bitset(bitset_digit_t const (&v)[bitset_base<N>::digits])
02051 {
02052 #if ECC_DEBUG
02053 assert( (v[bitset_base<N>::digits - 1] & ~bitset_base<N>::valid_bits) == 0 );
02054 #endif
02055 std::memcpy(this->vector, v, sizeof(this->vector));
02056 }
02057
02058
02059 template<unsigned int m, bool inverted>
02060 bitset(bitset_invertible<m, inverted> const&);
02061 template<unsigned int m, bool i1, bool i2, typename OP>
02062 bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr);
02063
02064
02065 bitset& operator=(bitset const&);
02066 template<typename Expression>
02067 bitset& operator=(Expression const&);
02068
02069
02070 template<typename Expression>
02071 bitset& operator&=(Expression const&);
02072 template<typename Expression>
02073 bitset& operator|=(Expression const&);
02074 template<typename Expression>
02075 bitset& operator^=(Expression const&);
02076
02077 public:
02078
02079 template<unsigned int shift, class DIRECTION, class OPERATION>
02080 void shift_op(bitset& result) const;
02081
02083 bitset& operator<<=(unsigned int shift) { this->bitset_base<N>::operator<<=(shift); return *this; }
02085 bitset& operator>>=(unsigned int shift) { this->bitset_base<N>::operator>>=(shift); return *this; }
02086
02087
02088 template<unsigned int shift, class DIRECTION>
02089 void rotate(bitset& result) const;
02090 };
02091
02095 template<unsigned int N>
02096 inline
02097 bitset<N>::bitset(void)
02098 {
02099 }
02100
02106 template<unsigned int N>
02107 inline
02108 bitset<N>::bitset(bitset_digit_t low_bits)
02109 {
02110 #if ECC_DEBUG
02111 assert( bitset_base<N>::digits > 1 || (low_bits & ~bitset_base<N>::valid_bits) == 0 );
02112 #endif
02113 std::memset(this->vector, 0, sizeof(this->vector));
02114 this->vector[0] = low_bits;
02115 }
02116
02120 template<unsigned int N>
02121 void
02122 bitset_base<N>::setall(void)
02123 {
02124 this->vector[bitset_base<N>::digits - 1] = bitset_base<N>::valid_bits;
02125 if (bitset_base<N>::digits > 1)
02126 {
02127 int d = bitset_base<N>::digits - 2;
02128 do { this->vector[d] = ~static_cast<bitset_digit_t>(0); } while(--d >= 0);
02129 }
02130 }
02131
02156 template<unsigned int N>
02157 template<typename Expression>
02158 inline
02159 bitset<N>& bitset<N>::operator=(Expression const& expr)
02160 {
02161 this->assign(expr, Operator::bitsetAssign());
02162 return *this;
02163 }
02164
02165
02166 template<unsigned int N>
02167 inline bitset<N>&
02168 bitset<N>::operator=(bitset const& expr)
02169 {
02170 this->assign(expr, Operator::bitsetAssign());
02171 return *this;
02172 }
02173
02190 template<unsigned int N>
02191 template<unsigned int m, bool inverted>
02192 inline bitset<N>::bitset(bitset_invertible<m, inverted> const& bits) : bitset_invertible<N, false>(bits)
02193 {
02194 }
02195
02201 template<unsigned int N>
02202 template<unsigned int m, bool i1, bool i2, typename OP>
02203 inline bitset<N>::bitset(Operator::bitsetExpression<m, i1, i2, OP> const& expr) : bitset_invertible<N, false>(expr)
02204 {
02205 }
02206
02218 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02219 bool operator==(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02220 {
02221 unsigned int d;
02222 if (bitset_invertible<n1, inverted1>::digits > bitset_invertible<n2, inverted2>::digits)
02223 {
02224 d = bitset_base<n1>::digits - 1;
02225 do
02226 {
02227 if (bits1.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02228 return false;
02229 }
02230 while (--d != bitset_base<n2>::digits - 1);
02231 }
02232 if (bitset_base<n2>::digits > bitset_base<n1>::digits)
02233 {
02234 d = bitset_base<n2>::digits - 1;
02235 do
02236 {
02237 if (bits2.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
02238 return false;
02239 }
02240 while (--d != bitset_base<n1>::digits - 1);
02241 }
02242 if (bitset_base<n1>::digits > 1 && bitset_base<n2>::digits > 1)
02243 {
02244 if (bitset_base<n1>::digits == bitset_base<n2>::digits)
02245 d = bitset_base<n1>::digits - 1;
02246 do
02247 {
02248 if (inverted1 == inverted2)
02249 {
02250 if (bits1.vector[d] != bits2.vector[d])
02251 return false;
02252 }
02253 else
02254 {
02255 if (bits1.vector[d] != ~(bits2.vector[d]))
02256 return false;
02257 }
02258 }
02259 while(--d != 0);
02260 }
02261 if (inverted1 != inverted2)
02262 return (bits1.vector[0] == ~(bits2.vector[0]));
02263 return (bits1.vector[0] == bits2.vector[0]);
02264 }
02265
02271 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
02272 inline bool
02273 operator!=(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
02274 {
02275 return !(bits1 == bits2);
02276 }
02277
02282 template<unsigned int N>
02283 template<typename Expression>
02284 inline bitset<N>&
02285 bitset<N>::operator&=(Expression const& expr)
02286 {
02287 this->assign(expr, Operator::bitsetANDAssign());
02288 return *this;
02289 }
02290
02295 template<unsigned int N>
02296 template<typename Expression>
02297 inline bitset<N>&
02298 bitset<N>::operator|=(Expression const& expr)
02299 {
02300 this->assign(expr, Operator::bitsetORAssign());
02301 return *this;
02302 }
02303
02308 template<unsigned int N>
02309 template<typename Expression>
02310 inline bitset<N>&
02311 bitset<N>::operator^=(Expression const& expr)
02312 {
02313 this->assign(expr, Operator::bitsetXORAssign());
02314 return *this;
02315 }
02316
02321 template<unsigned int m, bool inverted1, bool inverted2>
02322 Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>
02323 operator&(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02324 {
02325 return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetAND>(arg1, arg2);
02326 }
02327
02332 template<unsigned int m, bool inverted1, bool inverted2>
02333 Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>
02334 operator|(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02335 {
02336 return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetOR>(arg1, arg2);
02337 }
02338
02343 template<unsigned int m, bool inverted1, bool inverted2>
02344 Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>
02345 operator^(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
02346 {
02347 return Operator::bitsetExpression<m, inverted1, inverted2, Operator::bitsetXOR>(arg1, arg2);
02348 }
02349
02353 structassign {
02354 static int const id = 1;
02355 static bool const __clear = true;
02356 static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02357 static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02358 };
02359
02363 structexor {
02364 static int const id = 2;
02365 static bool const __clear = false;
02366 static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02367 static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
02368 };
02369
02370 #ifndef HIDE_FROM_DOXYGEN
02371 structrotate_phase1 {
02372 static int const id = 3;
02373 static bool const __clear = false;
02374 static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02375 static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02376 };
02377
02378 structrotate_phase2 {
02379 public:
02380 static int const id = 4;
02381 static bool const __clear = false;
02382 static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
02383 static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 |= digit2; }
02384 };
02385 #endif
02386
02397 template<unsigned int N>
02398 template<unsigned int shift, class DIRECTION, class OPERATION>
02399 void
02400 bitset<N>::shift_op(bitset& result) const
02401 {
02402 LibEccDout(dc::bitsetshift, "Entering shift_op<" << shift << ", " << libcwd::type_info_of<DIRECTION>().demangled_name() <<
02403 ", " << type_info_of<OPERATION>().demangled_name() << '>');
02404 LibEccDout(dc::bitsetshift|flush_cf, "Input : " << cwprint_using(*this, &bitset<N>::base2_print_on));
02405 if (shift == 1)
02406 {
02407
02408
02409
02410
02411
02412 static unsigned int const initial = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02413 static unsigned int const count = bitset_base<N>::digits - ((DIRECTION::__left && bitset_base<N>::has_excess_bits) ? 1 : 0);
02414 #ifdef __i386__
02415 if (count)
02416 {
02417 bitset_digit_t const volatile* ptr1;
02418 bitset_digit_t volatile* ptr2;
02419 int c;
02420 if (DIRECTION::__left)
02421 {
02422 if (OPERATION::id == libecc::exor::id)
02423 {
02424 if (bitset_base<N>::has_excess_bits)
02425 LIBECC_ASMSHIFTLEFT(
02426 LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02427 LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"),
02428 LIBECC_ASMSHIFTLEFT_FINISH("xorl (%%edi),%%edx\n\t"));
02429 else
02430 LIBECC_ASMSHIFTLEFT(
02431 LIBECC_LEFT_PRESERVE_CF("xorl -4(%%edi), %%edx"),
02432 LIBECC_LEFT_PRESERVE_CF("xorl (%%edi), %%edx"), "");
02433 }
02434 else if (OPERATION::id == libecc::rotate_phase2::id)
02435 {
02436 if (bitset_base<N>::has_excess_bits)
02437 LIBECC_ASMSHIFTLEFT(
02438 LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02439 else
02440 LIBECC_ASMSHIFTLEFT(
02441 LIBECC_LEFT_PRESERVE_CF("orl -4(%%edi), %%edx"), "", "");
02442 }
02443 else
02444 {
02445 if (bitset_base<N>::has_excess_bits)
02446 LIBECC_ASMSHIFTLEFT("", "", LIBECC_ASMSHIFTLEFT_FINISH(""));
02447 else
02448 LIBECC_ASMSHIFTLEFT("", "", "");
02449 }
02450 }
02451 else if (count > 1)
02452 {
02453 if (OPERATION::id == libecc::exor::id)
02454 LIBECC_ASMSHIFTRIGHT1(
02455 LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02456 LIBECC_RIGHT_PRESERVE_CF("xorl " LIBECC_OP2_DESTINATION "," LIBECC_WORKREG),
02457 LIBECC_PRESERVE_CF_CLOBBER);
02458 else if (OPERATION::id == libecc::rotate_phase2::id)
02459 LIBECC_ASMSHIFTRIGHT1(
02460 LIBECC_RIGHT_PRESERVE_CF("orl " LIBECC_OP1_DESTINATION "," LIBECC_WORKREG),
02461 "",
02462 LIBECC_PRESERVE_CF_CLOBBER);
02463 else
02464 LIBECC_ASMSHIFTRIGHT1(
02465 "",
02466 "",
02467 LIBECC_CLOBBER);
02468 }
02469 else
02470 {
02471 if (OPERATION::id == libecc::exor::id)
02472 LIBECC_ASMSHIFTRIGHT0("xorl 4(%%edi), %%edx\n\t");
02473 else if (OPERATION::id == libecc::rotate_phase2::id)
02474 LIBECC_ASMSHIFTRIGHT0("orl 4(%%edi), %%edx\n\t");
02475 else
02476 LIBECC_ASMSHIFTRIGHT0("");
02477 }
02478 }
02479 else if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02480 OPERATION::op(result.vector[0], ((this->vector[0] << 1) & bitset_base<N>::valid_bits));
02481 #else
02482 static unsigned int complement_shift = bitset_digit_bits - 1;
02483 static bitset_digit_t const mask1 = DIRECTION::__left ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02484 static bitset_digit_t const mask2 = DIRECTION::__right ? (static_cast<bitset_digit_t>(1) << complement_shift) : static_cast<bitset_digit_t>(1);
02485 bitset_digit_t const* ptr1 = &this->vector[initial];
02486 bitset_digit_t* ptr2 = &result.vector[initial];
02487 bool carry;
02488 if (count)
02489 {
02490 bitset_digit_t digit = *ptr1;
02491 carry = (digit & mask1);
02492 if (DIRECTION::__left)
02493 digit <<= 1;
02494 else
02495 digit >>= 1;
02496 OPERATION::mixed_op(*ptr2, digit);
02497 for (int c = count - 1; c; --c)
02498 {
02499 ptr1 -= DIRECTION::direction;
02500 ptr2 -= DIRECTION::direction;
02501 digit = *ptr1;
02502 if (carry)
02503 {
02504 carry = (digit & mask1);
02505 if (DIRECTION::__left)
02506 digit <<= 1;
02507 else
02508 digit >>= 1;
02509 digit |= mask2;
02510 }
02511 else
02512 {
02513 carry = (digit & mask1);
02514 if (DIRECTION::__left)
02515 digit <<= 1;
02516 else
02517 digit >>= 1;
02518 }
02519 OPERATION::op(*ptr2, digit);
02520 }
02521 }
02522 if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02523 {
02524 bitset_digit_t digit;
02525 if (count)
02526 digit = ptr1[-DIRECTION::direction];
02527 else
02528 digit = *ptr1;
02529 digit <<= 1;
02530 if (count && carry)
02531 digit |= mask2;
02532 if (count)
02533 OPERATION::op(ptr2[-DIRECTION::direction], (digit & bitset_base<N>::valid_bits));
02534 else
02535 OPERATION::op(*ptr2, (digit & bitset_base<N>::valid_bits));
02536 }
02537 #endif
02538 }
02539 else
02540 {
02541 static unsigned int const digit_shift = shift / bitset_digit_bits;
02542 static unsigned int const bit_shift = shift % bitset_digit_bits;
02543
02544 static unsigned int const zeroed_digits =
02545 DIRECTION::__left ? ((shift < N) ? digit_shift : bitset_base<N>::digits)
02546 : ((bitset_digit_bits - bitset_base<N>::number_of_valid_bits + shift) / bitset_digit_bits);
02547
02548 if (zeroed_digits < bitset_base<N>::digits)
02549 {
02550 static unsigned int const complement_shift = (bit_shift == 0) ? 0 : bitset_digit_bits - bit_shift;
02551 static unsigned int const initial_to = DIRECTION::__right ? 0 : bitset_base<N>::digits - 1;
02552 static unsigned int const initial_from = initial_to + DIRECTION::direction * digit_shift;
02553 static unsigned int const final_from = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02554
02555 register bitset_digit_t digit = this->vector[initial_from];
02556 if (initial_from != final_from)
02557 {
02558 register bitset_digit_t next_digit;
02559 unsigned int to = initial_to;
02560 unsigned int from = initial_from + DIRECTION::direction;
02561 if (from != final_from)
02562 do
02563 {
02564 next_digit = this->vector[from];
02565 if (bit_shift != 0)
02566 {
02567 if (DIRECTION::direction == -1)
02568 digit <<= bit_shift;
02569 else
02570 digit >>= bit_shift;
02571 digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02572 }
02573 OPERATION::op(result.vector[to], digit);
02574 digit = next_digit;
02575 to += DIRECTION::direction;
02576 from += DIRECTION::direction;
02577 }
02578 while (from != final_from);
02579 if (DIRECTION::__left || bit_shift < bitset_base<N>::number_of_valid_bits || bit_shift != 0)
02580 next_digit = this->vector[final_from];
02581 if (bit_shift != 0)
02582 {
02583 if (DIRECTION::direction == -1)
02584 digit <<= bit_shift;
02585 else
02586 digit >>= bit_shift;
02587 digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
02588 }
02589 if (DIRECTION::__left || bit_shift < bitset_base<N>::number_of_valid_bits)
02590 {
02591 OPERATION::op(result.vector[final_from - DIRECTION::direction * (digit_shift + 1)], digit);
02592 digit = DIRECTION::shift_copy(next_digit, bit_shift);
02593 }
02594 }
02595 else
02596 {
02597 if (DIRECTION::direction == -1)
02598 digit <<= bit_shift;
02599 else
02600 digit >>= bit_shift;
02601 }
02602 static bool const have_mixed_digit = shift != 0 && (DIRECTION::__left ? shift : (N - shift)) % bitset_digit_bits != 0;
02603 static unsigned int const last_digit = (DIRECTION::__left ? shift : (N - 1 - shift)) / bitset_digit_bits;
02604 if (have_mixed_digit)
02605 OPERATION::mixed_op(result.vector[last_digit], digit);
02606 else
02607 OPERATION::op(result.vector[last_digit], digit);
02608 if (DIRECTION::__left && bitset_base<N>::has_excess_bits)
02609 result.vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
02610 }
02611 if (OPERATION::__clear && zeroed_digits > 0)
02612 {
02613 static unsigned int const final_to = DIRECTION::__left ? 0 : bitset_base<N>::digits - 1;
02614 static unsigned int const initial_to = final_to - DIRECTION::direction * (zeroed_digits - 1);
02615 unsigned int to = initial_to;
02616 if (to != final_to)
02617 do
02618 {
02619 result.vector[to] = 0;
02620 to += DIRECTION::direction;
02621 }
02622 while(to != final_to);
02623 result.vector[to] = 0;
02624 }
02625 }
02626 LibEccDout(dc::bitsetshift|flush_cf, "Output: " << cwprint_using(result, &bitset<N>::base2_print_on));
02627 }
02628
02629 template<unsigned int N>
02630 void
02631 bitset_base<N>::operator<<=(unsigned int shift)
02632 {
02633 unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02634 unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02635 int digit1 = bitset_base<N>::digits - digit_shift - 2;
02636 bitset_digit_t d0 = (digit1 >= -1) ? this->vector[digit1 + 1] : 0;
02637 for (int digit_to = bitset_base<N>::digits - 1; digit_to >= 0; --digit_to)
02638 {
02639 bitset_digit_t d1 = (digit1 >= 0) ? this->vector[digit1] : 0;
02640 if (bit_shift == 0)
02641 this->vector[digit_to] = d0;
02642 else
02643 this->vector[digit_to] = (d0 << bit_shift) | (d1 >> (bitset_digit_bits - bit_shift));
02644 d0 = d1;
02645 --digit1;
02646 }
02647 if (bitset_base<N>::has_excess_bits)
02648 this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
02649 }
02650
02651 template<unsigned int N>
02652 void
02653 bitset_base<N>::operator>>=(unsigned int shift)
02654 {
02655 unsigned int const digit_shift = shift >> bitset_digit_bits_log2;
02656 unsigned int const bit_shift = shift & (bitset_digit_bits - 1);
02657 unsigned int digit1 = digit_shift + 1;
02658 bitset_digit_t d0 = (digit1 <= bitset_base<N>::digits) ? this->vector[digit1 - 1] : 0;
02659 for (unsigned int digit_to = 0; digit_to < bitset_base<N>::digits; ++digit_to)
02660 {
02661 bitset_digit_t d1 = (digit1 < bitset_base<N>::digits) ? this->vector[digit1] : 0;
02662 if (bit_shift == 0)
02663 this->vector[digit_to] = d0;
02664 else
02665 this->vector[digit_to] = (d0 >> bit_shift) | (d1 << (bitset_digit_bits - bit_shift));
02666 d0 = d1;
02667 ++digit1;
02668 }
02669 }
02670
02687 template<unsigned int N>
02688 bitset<N>::bitset(std::string const& input)
02689 {
02690 this->reset();
02691 unsigned int d = 0;
02692 unsigned int u = 0;
02693
02694 for (std::string::const_reverse_iterator iter = input.rbegin(); iter != input.rend(); ++iter)
02695 {
02696 bitset_digit_t c = toupper(*iter);
02697 if (c == ' ')
02698 continue;
02699 if (c < '0')
02700 break;
02701 if (c <= '9')
02702 c -= '0';
02703 else
02704 {
02705 if (c > 'F')
02706 break;
02707 if (c >= 'A')
02708 c -= ('A' - 10);
02709 else
02710 break;
02711 }
02712 this->vector[d] |= c << u;
02713 if ((u += 4) == bitset_digit_bits)
02714 {
02715 u = 0;
02716 if (++d == bitset_base<N>::digits)
02717 break;
02718 }
02719 }
02720 if (bitset_base<N>::has_excess_bits)
02721 this->vector[bitset_base<N>::digits - 1] &= bitset_base<N>::valid_bits;
02722 }
02723
02727 template<unsigned int N>
02728 std::istream&
02729 operator>>(std::istream& is, bitset<N>& bitsetx)
02730 {
02731 std::string tmp;
02732 is >> tmp;
02733 bitsetx.bitset(tmp);
02734 return is;
02735 }
02736
02740 template<unsigned int N>
02741 std::ostream&
02742 operator<<(std::ostream& os, bitset<N> const& bits)
02743 {
02744
02745 os.fill('0');
02746 os << std::hex;
02747 for (int d = bitset<N>::digits - 1; d >= 0; --d)
02748 {
02749 os.width((d == bitset<N>::digits - 1 && bitset<N>::has_excess_bits) ?
02750 (((N % bitset_digit_bits) - 1) / 4 + 1) :
02751 (bitset_digit_bits / 4));
02752 os << bits.digit(d);
02753 if (d > 0)
02754 os << ' ';
02755 }
02756 os << std::dec;
02757 return os;
02758 }
02759
02763 template<unsigned int N>
02764 void
02765 bitset_base<N>::reset(void)
02766 {
02767 std::memset(this->vector, 0, sizeof(this->vector));
02768 }
02769
02773 template<unsigned int N>
02774 inline bool
02775 bitset_base<N>::test(size_t pos) const
02776 {
02777 #ifdef __i386__
02778 int result;
02779 __asm__ __volatile__ (
02780 "btl %2, %1\n\t"
02781 "sbbl %0, %0"
02782 : "=r" (result)
02783 : "m" ((*(bitset_digit_t volatile*)this->vector)), "Ir" (pos));
02784 return result;
02785 #else
02786 unsigned int d = pos / bitset_digit_bits;
02787 bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02788 return (this->vector[d] & mask);
02789 #endif
02790 }
02791
02795 template<unsigned int N>
02796 template<unsigned int pos>
02797 inline bool
02798 bitset_base<N>::test(void) const
02799 {
02800 static unsigned int const d = pos / bitset_digit_bits;
02801 static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02802 return (this->vector[d] & mask);
02803 }
02804
02808 template<unsigned int N>
02809 inline bool
02810 bitset_base<N>::test(bitset_index const& index) const
02811 {
02812 #ifdef __i386__
02813 return this->test(index.get_index());
02814 #else
02815 return (this->vector[index.get_digit()] & index.get_mask());
02816 #endif
02817 }
02818
02822 template<unsigned int N>
02823 inline void
02824 bitset_base<N>::set(size_t pos)
02825 {
02826 #ifdef __i386__
02827 __asm__ __volatile__ (
02828 "btsl %1, %0"
02829 : "=m" ((*(bitset_digit_t volatile*)this->vector))
02830 : "Ir" (pos));
02831
02832 #else
02833 unsigned int d = pos / bitset_digit_bits;
02834 bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02835 this->vector[d] |= mask;
02836 #endif
02837 }
02838
02842 template<unsigned int N>
02843 inline void
02844 bitset_base<N>::set(bitset_index const& index)
02845 {
02846 #ifdef __i386__
02847 this->set(index.get_index());
02848 #else
02849 this->vector[index.get_digit()] |= index.get_mask();
02850 #endif
02851 }
02852
02856 template<unsigned int N>
02857 template<unsigned int pos>
02858 inline void
02859 bitset_base<N>::set(void)
02860 {
02861 static unsigned int const d = pos / bitset_digit_bits;
02862 static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02863 this->vector[d] |= mask;
02864 }
02865
02869 template<unsigned int N>
02870 inline void
02871 bitset_base<N>::clear(size_t pos)
02872 {
02873 #ifdef __i386__
02874 __asm__ __volatile__ (
02875 "btrl %1, %0"
02876 : "=m" ((*(bitset_digit_t volatile*)this->vector))
02877 : "Ir" (pos)
02878 );
02879 #else
02880 unsigned int d = pos / bitset_digit_bits;
02881 bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02882 this->vector[d] &= ~mask;
02883 #endif
02884 }
02885
02889 template<unsigned int N>
02890 inline void
02891 bitset_base<N>::clear(bitset_index const& index)
02892 {
02893 #ifdef __i386__
02894 this->clear(index.get_index());
02895 #else
02896 this->vector[index.get_digit()] &= ~(index.get_mask());
02897 #endif
02898 }
02899
02903 template<unsigned int N>
02904 template<unsigned int pos>
02905 inline void
02906 bitset_base<N>::clear(void)
02907 {
02908 static unsigned int const d = pos / bitset_digit_bits;
02909 static bitset_digit_t const mask = ~(static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits));
02910 this->vector[d] &= mask;
02911 }
02912
02916 template<unsigned int N>
02917 inline void
02918 bitset_base<N>::flip(size_t pos)
02919 {
02920 #ifdef __i386__
02921 __asm__ __volatile__ (
02922 "btcl %1, %0"
02923 : "=m" ((*(bitset_digit_t volatile*)this->vector))
02924 : "Ir" (pos)
02925 );
02926 #else
02927 unsigned int d = pos / bitset_digit_bits;
02928 bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02929 this->vector[d] ^= mask;
02930 #endif
02931 }
02932
02936 template<unsigned int N>
02937 inline void
02938 bitset_base<N>::flip(bitset_index const& index)
02939 {
02940 #ifdef __i386__
02941 this->flip(index.get_index());
02942 #else
02943 this->vector[index.get_digit()] ^= index.get_mask();
02944 #endif
02945 }
02946
02950 template<unsigned int N>
02951 template<unsigned int pos>
02952 inline void
02953 bitset_base<N>::flip(void)
02954 {
02955 static unsigned int const d = pos / bitset_digit_bits;
02956 static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % bitset_digit_bits);
02957 this->vector[d] ^= mask;
02958 }
02959
02963 template<unsigned int N>
02964 bool
02965 bitset_base<N>::any(void) const
02966 {
02967 unsigned int to = bitset_base<N>::digits - 1;
02968 if (bitset_base<N>::digits > 1)
02969 do
02970 {
02971 if (this->vector[to] != 0)
02972 return true;
02973 --to;
02974 }
02975 while(to != 0);
02976 return (this->vector[0] != 0);
02977 }
02978
02979 static bool const oddnumberofbits[] = {
02980 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02981 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02982 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02983 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02984 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02985 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02986 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02987 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02988 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02989 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02990 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02991 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02992 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
02993 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02994 true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
02995 false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false };
02996
03000 template<unsigned int N>
03001 bool
03002 bitset_base<N>::odd(void) const
03003 {
03004 unsigned int from = bitset_base<N>::digits - 1;
03005 bitset_digit_t sum = this->vector[0];
03006 if (bitset_base<N>::digits > 1)
03007 do
03008 {
03009 sum ^= this->vector[from];
03010 --from;
03011 }
03012 while(from != 0);
03013 bitset_digit_t ssum = sum;
03014 if (sizeof(bitset_digit_t) >= 2)
03015 {
03016 ssum >>= (bitset_digit_bits / 2);
03017 sum ^= ssum;
03018 }
03019 if (sizeof(bitset_digit_t) >= 4)
03020 {
03021 ssum = sum;
03022 ssum >>= (bitset_digit_bits / 4);
03023 sum ^= ssum;
03024 }
03025 if (sizeof(bitset_digit_t) >= 8)
03026 {
03027 ssum = sum;
03028 ssum >>= (bitset_digit_bits / 8);
03029 sum ^= ssum;
03030 }
03031 if (sizeof(bitset_digit_t) == 16)
03032 {
03033 ssum = sum;
03034 ssum >>= (bitset_digit_bits / 16);
03035 sum ^= ssum;
03036 }
03037 return oddnumberofbits[sum & 0xff];
03038 }
03039
03043 structleft {
03044 public:
03045 typedef structright inverse;
03046 static int const direction = -1;
03047 static bool const __left = true;
03048 static bool const __right = false;
03049 static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03050 static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03051 };
03052
03056 structright {
03057 public:
03058 typedef structleft inverse;
03059 static int const direction = 1;
03060 static bool const __left = false;
03061 static bool const __right = true;
03062 static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
03063 static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
03064 };
03065
03074 template<unsigned int N>
03075 template<unsigned int shift, class DIRECTION>
03076 void
03077 bitset<N>::rotate(bitset<N>& result) const
03078 {
03079 LibEccDout(dc::bitsetshift|flush_cf, "Entering bitset<" << N << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03080 LibEccDout(dc::bitsetshift|flush_cf, "Rotate input : " << cwprint_using(*this, &bitset<N>::base2_print_on));
03081 shift_op<shift % N, DIRECTION, rotate_phase1>(result);
03082 LibEccDout(dc::bitsetshift|flush_cf, "After phase1 : " << cwprint_using(result, &bitset<N>::base2_print_on));
03083 shift_op<N - (shift % N), typename DIRECTION::inverse, rotate_phase2>(result);
03084 LibEccDout(dc::bitsetshift|flush_cf, "After phase2 : " << cwprint_using(result, &bitset<N>::base2_print_on));
03085 LibEccDout(dc::bitsetshift|flush_cf, "Leaving bitset<" << N << ">::rotate<" << shift << ", " << type_info_of<DIRECTION>().demangled_name() << ">");
03086 }
03087
03088 }
03089
03090 #endif // LIBECC_BITS_H