Main Page   Reference Manual   Compound List   File List  

libecc/bitset.h

Go to the documentation of this file.
00001 //
00006 //
00007 // This file is part of the libecc package.
00008 // Copyright (C) 2002, by
00009 //
00010 // Carlo Wood, Run on IRC <carlo@alinoe.com>
00011 // RSA-1024 0x624ACAD5 1997-01-26                    Sign & Encrypt
00012 // Fingerprint16 = 32 EC A7 B6 AC DB 65 A6  F6 F6 55 DD 1C DC FF 61
00013 //
00014 // This program is free software; you can redistribute it and/or
00015 // modify it under the terms of the GNU General Public License
00016 // as published by the Free Software Foundation; either version 2
00017 // of the License, or (at your option) any later version.
00018 // 
00019 // This program is distributed in the hope that it will be useful,
00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 // GNU General Public License for more details.
00023 // 
00024 // You should have received a copy of the GNU General Public License
00025 // along with this program; if not, write to the Free Software
00026 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
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 
00042 namespace libecc {
00043 
00044 // Forward declaration.
00045 template<unsigned int n, bool inverted>
00046   class bitset_invertible;
00047 
00056 typedef unsigned int bitset_digit_t;
00057 
00067 template<unsigned int n>
00068   struct bitset_base {
00069     public:
00073       static unsigned int const number_of_bits = n;
00074 
00076       static unsigned int const digit_bits = sizeof(bitset_digit_t) * 8;
00077 
00079       static unsigned int const digits = (n - 1) / digit_bits + 1;
00080 
00081       // ! The number of valid bits in the most significant digit.
00082       static unsigned int const number_of_valid_bits = digit_bits - (digits * digit_bits - n);
00083 
00085       static bitset_digit_t const valid_bits =
00086           ((static_cast<bitset_digit_t>(1) << (number_of_valid_bits - 1)) << 1) - 1;
00087 
00089       static bool const has_excess_bits = ((digits * digit_bits) != n);
00090 
00091     protected:
00098       bitset_digit_t vector[digits];
00099 
00100       template<unsigned int n1, bool i1, unsigned int n2, bool i2>
00101         friend bool operator==(bitset_invertible<n1, i1> const&, bitset_invertible<n2, i2> const&);
00102   };
00103 
00104 #ifndef HIDE_FROM_DOXYGEN
00105 namespace Operator {
00106 
00107 // Functors.
00108 
00109 // Functor for '='.
00110 struct bitsetAssign {
00111   static bool const sets_excess_bits = true;
00112   static bool const with_zero_sets_zero = true;
00113   static bool const with_ones_sets_ones = true;
00114   static bool const with_ones_inverts = false;
00115   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out = in; }
00116 };
00117 
00118 // Functor for '&='.
00119 struct bitsetANDAssign {
00120   static bool const sets_excess_bits = false;
00121   static bool const with_zero_sets_zero = true;
00122   static bool const with_ones_sets_ones = false;
00123   static bool const with_ones_inverts = false;
00124   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out &= in; }
00125 };
00126 
00127 // Functor for '|='.
00128 struct bitsetORAssign {
00129   static bool const sets_excess_bits = true;
00130   static bool const with_zero_sets_zero = false;
00131   static bool const with_ones_sets_ones = true;
00132   static bool const with_ones_inverts = false;
00133   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out |= in; }
00134 };
00135 
00136 // Functor for '^='.
00137 struct bitsetXORAssign {
00138   static bool const sets_excess_bits = true;
00139   static bool const with_zero_sets_zero = false;
00140   static bool const with_ones_sets_ones = false;
00141   static bool const with_ones_inverts = true;
00142   static inline void exec(bitset_digit_t& out, bitset_digit_t in) { out ^= in; }
00143 };
00144 
00145 // Functor for '&'.
00146 struct bitsetAND {
00147   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 & digit2; }
00148 };
00149 
00150 // Functor for '|'.
00151 struct bitsetOR {
00152   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 | digit2; }
00153 };
00154 
00155 // Functor for '^'.
00156 struct bitsetXOR {
00157   static inline bitset_digit_t exec(bitset_digit_t digit1, bitset_digit_t digit2) { return digit1 ^ digit2; }
00158 };
00159 
00160 template<unsigned int n, bool inverted1, bool inverted2, typename OP>
00161   struct expression
00162   {
00163     bitset_invertible<n, inverted1> const& first;
00164     bitset_invertible<n, inverted2> const& second;
00165     OP op;
00166     expression(bitset_invertible<n, inverted1> const& arg1, bitset_invertible<n, inverted2> const& arg2) : first(arg1), second(arg2) { }
00167   };
00168 
00169 } // namespace Operator
00170 #endif // HIDE_FROM_DOXYGEN
00171 
00189 template<unsigned int n, bool inverted>
00190   class bitset_invertible : public bitset_base<n> {
00191     public:
00192       // Constructors
00193       bitset_invertible(void);
00194       template<typename Expression>
00195         explicit bitset_invertible<n, inverted>(Expression const&);
00196 
00197     protected:
00198       template<typename OP, unsigned int x, bool invertedx>
00199         void assign(bitset_invertible<x, invertedx> const&, OP);
00200       template<typename OP1, unsigned int x, bool inverted1, bool inverted2, typename OP2>
00201         void assign(Operator::expression<x, inverted1, inverted2, OP2> const&, OP1);
00202 
00203     private:
00204       template<unsigned int m, bool i>
00205         friend class bitset_invertible;
00206       bitset_digit_t digit(unsigned int d) const { return inverted ? ~(vector[d]) : vector[d]; }
00207   };
00208 
00209 // Default constructor.
00210 template<unsigned int n, bool inverted>
00211   inline
00212   bitset_invertible<n, inverted>::bitset_invertible(void)
00213   {
00214     if (has_excess_bits)
00215       vector[digits - 1] = 0;                   // Reset the excess bits!
00216   }
00217 
00218 // Copy constructor.
00219 template<unsigned int n, bool inverted>
00220   template<typename Expression>
00221     inline
00222     bitset_invertible<n, inverted>::bitset_invertible(Expression const& expr)
00223     {
00224       this->assign(expr, Operator::bitsetAssign());
00225     }
00226 
00227 //
00228 // Assignment function.
00229 // This function handles:
00230 //
00231 // a = b;
00232 // a = ~b;
00233 // a &= b;
00234 // a &= ~b;
00235 // a |= b;
00236 // a |= ~b;
00237 // a ^= b;
00238 // a ^= ~b;
00239 //
00240 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
00241 //
00242 template<unsigned int n, bool inverted>
00243   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted_argument>
00244     inline void
00245     bitset_invertible<n, inverted>::assign(bitset_invertible<x, inverted_argument> const& bits, ASSIGNMENT_OPERATOR)
00246     {
00247       // Handle excess digits.
00248       if (digits > bitset_base<x>::digits)
00249       {
00250         if (!inverted_argument)
00251         {
00252           // Fill excess digits with 0's when needed.
00253           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
00254           {
00255             unsigned int count = digits - bitset_base<x>::digits;
00256             do { vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
00257           }
00258         }
00259         else
00260         {
00261           // Fill excess digits with 1's when needed.
00262           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
00263           {
00264             vector[digits - 1] = valid_bits;
00265             unsigned int count = digits - bitset_base<x>::digits;
00266             while(--count) { vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
00267           }
00268           // Or invert them.
00269           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
00270           {
00271             vector[digits - 1] ^= valid_bits;
00272             unsigned int count = digits - bitset_base<x>::digits;
00273             while(--count) { vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
00274           }
00275         }
00276       }
00277 
00278       // Handle other digits.
00279       unsigned int d;
00280       if (digits < bitset_base<x>::digits)
00281         d = digits - 1;
00282       else
00283         d = bitset_base<x>::digits - 1;
00284       ASSIGNMENT_OPERATOR::exec(vector[d], bits.digit(d));
00285       while(d) { --d; ASSIGNMENT_OPERATOR::exec(vector[d], bits.digit(d)); }
00286 
00287       // Reset excess bits if needed.
00288       if (((!inverted_argument && x > n) ||
00289             (inverted_argument && digits <= bitset_base<x>::digits)) &&
00290           has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
00291         vector[digits - 1] &= valid_bits;
00292     }
00293 
00294 //
00295 // Assignment function for expressions.
00296 // This function handles:
00297 //
00298 // a = b & c;
00299 // a = b & ~c;
00300 // a = ~b & c;
00301 // a = ~b & ~b;
00302 // a = b | c;
00303 // a = b | ~c;
00304 // a = ~b | c;
00305 // a = ~b | ~b;
00306 // a = b ^ c;
00307 // a = b ^ ~c;
00308 // a = ~b ^ c;
00309 // a = ~b ^ ~b;
00310 // a &= b & c;
00311 // a &= b & ~c;
00312 // a &= ~b & c;
00313 // a &= ~b & ~b;
00314 // a &= b | c;
00315 // a &= b | ~c;
00316 // a &= ~b | c;
00317 // a &= ~b | ~b;
00318 // a &= b ^ c;
00319 // a &= b ^ ~c;
00320 // a &= ~b ^ c;
00321 // a &= ~b ^ ~b;
00322 // a |= b & c;
00323 // a |= b & ~c;
00324 // a |= ~b & c;
00325 // a |= ~b & ~b;
00326 // a |= b | c;
00327 // a |= b | ~c;
00328 // a |= ~b | c;
00329 // a |= ~b | ~b;
00330 // a |= b ^ c;
00331 // a |= b ^ ~c;
00332 // a |= ~b ^ c;
00333 // a |= ~b ^ ~b;
00334 // a ^= b & c;
00335 // a ^= b & ~c;
00336 // a ^= ~b & c;
00337 // a ^= ~b & ~b;
00338 // a ^= b | c;
00339 // a ^= b | ~c;
00340 // a ^= ~b | c;
00341 // a ^= ~b | ~b;
00342 // a ^= b ^ c;
00343 // a ^= b ^ ~c;
00344 // a ^= ~b ^ c;
00345 // a ^= ~b ^ ~b;
00346 //
00347 // ASSIGNMENT_OPERATOR is one of bitsetAssign, bitsetANDAssign, bitsetORAssign or bitsetXORAssign.
00348 // OPERATOR is one of bitsetAND, bitsetOR or bitsetXOR.
00349 //
00350 template<unsigned int n, bool inverted>
00351   template<typename ASSIGNMENT_OPERATOR, unsigned int x, bool inverted1, bool inverted2, typename OPERATOR>
00352     inline void
00353     bitset_invertible<n, inverted>::assign(Operator::expression<x, inverted1, inverted2, OPERATOR> const& expr, ASSIGNMENT_OPERATOR)
00354     {
00355       static bool const argument_has_leading_ones = OPERATOR::exec(inverted1, inverted2);
00356 
00357       // Handle excess digits.
00358       if (digits > bitset_base<x>::digits)
00359       {
00360         if (!argument_has_leading_ones)
00361         {
00362           // Fill excess digits with 0's when needed.
00363           if (ASSIGNMENT_OPERATOR::with_zero_sets_zero)
00364           {
00365             unsigned int count = digits - bitset_base<x>::digits;
00366             do { vector[count + bitset_base<x>::digits - 1] = 0; } while (--count);
00367           }
00368         }
00369         else
00370         {
00371           // Fill excess digits with 1's when needed.
00372           if (ASSIGNMENT_OPERATOR::with_ones_sets_ones)
00373           {
00374             vector[digits - 1] = valid_bits;
00375             unsigned int count = digits - bitset_base<x>::digits;
00376             while(--count) { vector[count + bitset_base<x>::digits - 1] = ~static_cast<bitset_digit_t>(0); }
00377           }
00378           if (ASSIGNMENT_OPERATOR::with_ones_inverts)
00379           {
00380             vector[digits - 1] ^= valid_bits;
00381             unsigned int count = digits - bitset_base<x>::digits;
00382             while(--count) { vector[count + bitset_base<x>::digits - 1] ^= ~static_cast<bitset_digit_t>(0); }
00383           }
00384         }
00385       }
00386 
00387       // Handle other digits.
00388       unsigned int d;
00389       if (digits < bitset_base<x>::digits)
00390         d = digits - 1;
00391       else
00392         d = bitset_base<x>::digits - 1;
00393       ASSIGNMENT_OPERATOR::exec(vector[d], OPERATOR::exec(expr.first.digit(d), expr.second.digit(d)));
00394       while(d) { --d; ASSIGNMENT_OPERATOR::exec(vector[d], OPERATOR::exec(expr.first.digit(d), expr.second.digit(d))); }
00395 
00396       // Reset excess bits if needed.
00397       if (((!argument_has_leading_ones && x > n) ||
00398             (argument_has_leading_ones && digits <= bitset_base<x>::digits)) &&
00399           has_excess_bits && ASSIGNMENT_OPERATOR::sets_excess_bits)
00400         vector[digits - 1] &= valid_bits;
00401     }
00402 
00429 template<unsigned int n, bool inverted>
00430   inline bitset_invertible<n, !inverted> const&
00431   operator~(bitset_invertible<n, inverted> const& bits)
00432   {
00433     return *reinterpret_cast<bitset_invertible<n, !inverted> const*>(&bits);
00434   }
00435 
00442 template<unsigned int n>
00443   class bitset : public bitset_invertible<n, false> {
00444     public:
00445       // Constructors.
00446       bitset(void);
00447       bitset(std::string const&);
00448       // This definition must be here, inside the template class declaration because
00449       // otherwise the compiler (2.95 - 3.1) barfs.
00455       bitset(bitset_digit_t const (&v)[bitset_base<n>::digits])
00456       {
00457 #if ECC_DEBUG
00458         LIBCWD_ASSERT( (v[digits - 1] & ~valid_bits) == 0 );
00459 #endif
00460         memcpy(vector, v, sizeof(vector));
00461       }
00462 
00463       // Copy constructors.
00464       template<unsigned int m, bool inverted>
00465         bitset(bitset_invertible<m, inverted> const&);
00466       template<unsigned int m, bool i1, bool i2, typename OP>
00467         bitset(Operator::expression<m, i1, i2, OP> const& expr);
00468 
00469       // Assignment operator.
00470       template<typename Expression>
00471         bitset& operator=(Expression const&);
00472 
00473       // Perform AND, OR, XOR operations
00474       template<typename Expression>
00475         bitset& operator&=(Expression const&);
00476       template<typename Expression>
00477         bitset& operator|=(Expression const&);
00478       template<typename Expression>
00479         bitset& operator^=(Expression const&);
00480 
00481     public:
00482       // Shift bitset left or right and perform operation with result.
00483       template<unsigned int shift, class DIRECTION, class OPERATION>
00484         void shift_op(bitset& result) const;
00485 
00486       // Rotate left or right
00487       template<unsigned int shift, class DIRECTION>                     // Return a copy rotated `shift' bits in `DIRECTION'.
00488         void rotate(bitset& result) const;
00489 
00490       // Single bit operations
00491       bool test(size_t n) const;                                        // Return true if bit `n' is set.
00492       bool odd(void) const;                                             // Return true if the vector has an odd number of bits set.
00493       void set(size_t n);                                               // Set bit `n'.
00494       void clear(size_t n);                                             // Clear bit `n'.
00495       void flip(size_t n);                                              // Toggle bit `n'.
00496 
00497       // Single bit operations at a constant position
00498       template<unsigned int pos>
00499         bool test(void) const;                                          // Return true if bit `pos' is set.
00500       template<unsigned int pos>
00501         void set(void);                                                 // Set bit `pos'.
00502       template<unsigned int pos>
00503         void clear(void);                                               // Clear bit `pos'.
00504       template<unsigned int pos>
00505         void flip(void);                                                // Toggle bit `pos'.
00506       template<unsigned int pos>
00507         void digitset(unsigned int d, bool value);                      // Set bit `pos' of digit `d' to `value'.
00508 
00509       // Other functions
00510       bitset& reset(void);
00511       void setall(void);
00512       bool any(void) const;
00513 
00514       // Digit representation
00515       bitset_digit_t digit(unsigned int d) const { return vector[d]; }
00516       bitset_digit_t& digit(unsigned int d) { return vector[d]; }
00517       bitset_digit_t const* digits_ptr(void) const { return vector; }
00518       uint32_t digit32(unsigned int d32) const
00519       {
00520         if (sizeof(bitset_digit_t) == 4)
00521           return vector[d32];
00522         else
00523         {
00524           unsigned int d = d32 / (sizeof(bitset_digit_t) / 4);
00525           unsigned int r = d32 % (sizeof(bitset_digit_t) / 4);
00526           return (vector[d] >> (r * 32)) & 0xffffffff;
00527         }
00528       }
00529   };
00530 
00534 template<unsigned int n>
00535   inline
00536   bitset<n>::bitset(void)
00537   {
00538   }
00539 
00543 template<unsigned int n>
00544   void
00545   bitset<n>::setall(void)
00546   {
00547     vector[digits - 1] = valid_bits;
00548     if (digits > 1)
00549     {
00550       int d = digits - 2;
00551       do { vector[d] = ~static_cast<bitset_digit_t>(0); } while(--d >= 0);
00552     }
00553   }
00554 
00579 template<unsigned int n>
00580   template<typename Expression>
00581     inline bitset<n>& bitset<n>::operator=(Expression const& expr)
00582     {
00583       this->assign(expr, Operator::bitsetAssign());
00584       return *this;
00585     }
00586 
00603 template<unsigned int n>
00604   template<unsigned int m, bool inverted>
00605     inline bitset<n>::bitset(bitset_invertible<m, inverted> const& bits) : bitset_invertible<n, false>(bits)
00606     {
00607     }
00608 
00614 template<unsigned int n>
00615   template<unsigned int m, bool i1, bool i2, typename OP>
00616     inline bitset<n>::bitset(Operator::expression<m, i1, i2, OP> const& expr) : bitset_invertible<n, false>(expr)
00617     {
00618     }
00619 
00631 template<unsigned int n1, bool inverted1, unsigned int n2, bool inverted2>
00632   bool operator==(bitset_invertible<n1, inverted1> const& bits1, bitset_invertible<n2, inverted2> const& bits2)
00633   {
00634     unsigned int d;
00635     if (bitset_invertible<n1, inverted1>::digits > bitset_invertible<n2, inverted2>::digits)
00636     {
00637       d = bitset_base<n1>::digits - 1;
00638       do
00639       {
00640         if (bits1.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
00641           return false;
00642       }
00643       while (--d != bitset_base<n2>::digits - 1);
00644     }
00645     if (bitset_base<n2>::digits > bitset_base<n1>::digits)
00646     {
00647       d = bitset_base<n2>::digits - 1;
00648       do
00649       {
00650         if (bits2.vector[d] != (inverted1 == inverted2 ? 0 : ~static_cast<bitset_digit_t>(0)))
00651           return false;
00652       }
00653       while (--d != bitset_base<n1>::digits - 1);
00654     }
00655     if (bitset_base<n1>::digits > 1 && bitset_base<n2>::digits > 1)
00656     {
00657       if (bitset_base<n1>::digits == bitset_base<n2>::digits)
00658         d = bitset_base<n1>::digits - 1;
00659       do
00660       {
00661         if (inverted1 == inverted2)
00662         {
00663           if (bits1.vector[d] != bits2.vector[d])
00664             return false;
00665         }
00666         else
00667         {
00668           if (bits1.vector[d] != ~(bits2.vector[d]))
00669             return false;
00670         }
00671       }
00672       while(--d != 0);
00673     }
00674     if (inverted1 != inverted2)
00675       return (bits1.vector[0] == ~(bits2.vector[0]));
00676     return (bits1.vector[0] == bits2.vector[0]);
00677   }
00678 
00684 template<typename Expression1, typename Expression2>
00685   inline bool
00686   operator!=(Expression1 const& expr1, Expression2 const& expr2)
00687   {
00688     return !(expr1 == expr2);
00689   }
00690 
00695 template<unsigned int n>
00696   template<typename Expression>
00697     inline bitset<n>&
00698     bitset<n>::operator&=(Expression const& expr)
00699     {
00700       this->assign(expr, Operator::bitsetANDAssign());
00701       return *this;
00702     }
00703 
00708 template<unsigned int n>
00709   template<typename Expression>
00710     inline bitset<n>&
00711     bitset<n>::operator|=(Expression const& expr)
00712     {
00713       this->assign(expr, Operator::bitsetORAssign());
00714       return *this;
00715     }
00716 
00721 template<unsigned int n>
00722   template<typename Expression>
00723     inline bitset<n>&
00724     bitset<n>::operator^=(Expression const& expr)
00725     {
00726       this->assign(expr, Operator::bitsetXORAssign());
00727       return *this;
00728     }
00729 
00734 template<unsigned int m, bool inverted1, bool inverted2>
00735   Operator::expression<m, inverted1, inverted2, Operator::bitsetAND>
00736   operator&(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
00737     {
00738       return Operator::expression<m, inverted1, inverted2, Operator::bitsetAND>(arg1, arg2);
00739     }
00740 
00745 template<unsigned int m, bool inverted1, bool inverted2>
00746   Operator::expression<m, inverted1, inverted2, Operator::bitsetOR>
00747   operator|(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
00748     {
00749       return Operator::expression<m, inverted1, inverted2, Operator::bitsetOR>(arg1, arg2);
00750     }
00751 
00756 template<unsigned int m, bool inverted1, bool inverted2>
00757   Operator::expression<m, inverted1, inverted2, Operator::bitsetXOR>
00758   operator^(bitset_invertible<m, inverted1> const& arg1, bitset_invertible<m, inverted2> const& arg2)
00759     {
00760       return Operator::expression<m, inverted1, inverted2, Operator::bitsetXOR>(arg1, arg2);
00761     }
00762 
00773 template<unsigned int n>
00774   template<unsigned int shift, class DIRECTION, class OPERATION>
00775     void
00776     bitset<n>::shift_op(bitset& result) const
00777     {
00778       static unsigned int const digit_shift = shift / digit_bits;
00779       static unsigned int const bit_shift = shift % digit_bits;
00780 
00781       static unsigned int const zeroed_digits =
00782         DIRECTION::__left ? ((shift < n) ? digit_shift : digits)
00783                           : ((digit_bits - number_of_valid_bits + shift) / digit_bits);
00784 
00785       if (zeroed_digits < digits)
00786       {
00787         static unsigned int const complement_shift = (bit_shift == 0) ? 0 : digit_bits - bit_shift;
00788         static unsigned int const initial_to = DIRECTION::__right ? 0 : digits - 1;
00789         static unsigned int const initial_from = initial_to + DIRECTION::direction * digit_shift;
00790         static unsigned int const final_from = DIRECTION::__left ? 0 : digits - 1;
00791 
00792         register bitset_digit_t digit = vector[initial_from];
00793         if (initial_from != final_from)
00794         {
00795           register bitset_digit_t next_digit;
00796           unsigned int to = initial_to;
00797           unsigned int from = initial_from + DIRECTION::direction;
00798           if (from != final_from)
00799             do
00800             {
00801               next_digit = vector[from];
00802               if (bit_shift != 0)
00803               {
00804                 DIRECTION::shift(digit, bit_shift);
00805                 digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
00806               }
00807               OPERATION::op(result.vector[to], digit);
00808               digit = next_digit;
00809               to += DIRECTION::direction;
00810               from += DIRECTION::direction;
00811             }
00812             while (from != final_from);
00813           if (DIRECTION::__left || bit_shift < number_of_valid_bits || bit_shift != 0)
00814             next_digit = vector[final_from];
00815           if (bit_shift != 0)
00816           {
00817             DIRECTION::shift(digit, bit_shift);
00818             digit |= DIRECTION::reverse_shift_copy(next_digit, complement_shift);
00819           }
00820           if (DIRECTION::__left || bit_shift < number_of_valid_bits)
00821           {
00822             OPERATION::op(result.vector[final_from - DIRECTION::direction * (digit_shift + 1)], digit);
00823             digit = DIRECTION::shift_copy(next_digit, bit_shift);
00824           }
00825         }
00826         else
00827           DIRECTION::shift(digit, bit_shift);
00828         static bool const have_mixed_digit = shift != 0 && (DIRECTION::__left ? shift : (n - shift)) % digit_bits != 0;
00829         static unsigned int const last_digit = (DIRECTION::__left ? shift : (n - 1 - shift)) / digit_bits;
00830         if (have_mixed_digit)
00831           OPERATION::mixed_op(result.vector[last_digit], digit);
00832         else
00833           OPERATION::op(result.vector[last_digit], digit);
00834         if (DIRECTION::__left && has_excess_bits)
00835           result.vector[digits - 1] &= valid_bits;
00836       }
00837       if (OPERATION::__clear && zeroed_digits > 0)
00838       {
00839         static unsigned int const final_to = DIRECTION::__left ? 0 : digits - 1;
00840         static unsigned int const initial_to = final_to - DIRECTION::direction * (zeroed_digits - 1);
00841         unsigned int to = initial_to;
00842         if (to != final_to)
00843           do
00844           {
00845             result.vector[to] = 0;
00846             to += DIRECTION::direction;
00847           }
00848           while(to != final_to);
00849         result.vector[to] = 0;
00850       }
00851     }
00852 
00869 template<unsigned int n>
00870   bitset<n>::bitset(std::string const& input)
00871   {
00872     reset();                                            // Reset internal digits to zero.
00873     unsigned int d = 0;                                 // Current index of internal digit.
00874     unsigned int u = 0;                                 // Current bit-shift of input digit relative to internal digit.
00875 
00876     for (std::string::const_reverse_iterator iter = input.rbegin(); iter != input.rend(); ++iter)       // Read right to left.
00877     {
00878       bitset_digit_t c = toupper(*iter);                // Get next hexadecimal input character.
00879       if (c == ' ')                                     // Skip spaces.
00880         continue;
00881       if (c < '0')                                      // Terminate reading when not a hexadecimal character.
00882         break;
00883       if (c <= '9')
00884         c -= '0';                                       // Set c to the value that the input character represents.
00885       else
00886       {
00887         if (c > 'F')
00888           break;
00889         if (c >= 'A')
00890           c -= ('A' - 10);
00891         else
00892           break;
00893       }
00894       vector[d] |= c << u;                              // Set internal bits.
00895       if ((u += 4) == digit_bits)                       // Update bit/digit 'pointers'.
00896       {
00897         u = 0;
00898         if (++d == digits)                              // Terminate reading when bitset is full.
00899           break;
00900       }
00901     }
00902     if (has_excess_bits)
00903       vector[digits - 1] &= valid_bits;                 // Reset possibly set excess bits.
00904   }
00905 
00909 template<unsigned int n>
00910   std::istream&
00911   operator>>(std::istream& is, bitset<n>& bitsetx)
00912   {
00913     std::string tmp;
00914     is >> tmp;
00915     bitsetx.bitset(tmp);
00916     return is;
00917   }
00918 
00922 template<unsigned int n>
00923   std::ostream&
00924   operator<<(std::ostream& os, bitset<n> const& bits)
00925   {
00926 #if 0
00927     // Binary representation
00928     for (int d = bitset<n>::digits - 1; d >= 0; --d)
00929       for (bitset_digit_t mask = (~static_cast<bitset_digit_t>(0) >> 1) + 1; mask != 0; mask >>= 1)
00930         if (d != bitset<n>::digits - 1 || (mask & bitset<n>::valid_bits))
00931           if (bits.digit(d) & mask)
00932             os << '1';
00933           else
00934             os << '0';
00935 #else
00936     // Hexadecimal representation
00937     os.fill('0');
00938     os << std::hex;
00939     for (int d = bitset<n>::digits - 1; d >= 0; --d)
00940     {
00941       os.width((d == bitset<n>::digits - 1 && bitset<n>::has_excess_bits) ?
00942           (((n % bitset<n>::digit_bits) - 1) / 4 + 1) :
00943           (bitset<n>::digit_bits / 4));
00944       os << bits.digit(d);
00945       if (d > 0)
00946         os << ' ';
00947     }
00948 #endif
00949     return os;
00950   }
00951 
00955 template<unsigned int n>
00956   bitset<n>&
00957   bitset<n>::reset(void)
00958   {
00959     bitset_digit_t* const least_significant_digit = &vector[0];
00960     if (digits > 1)
00961     {
00962       bitset_digit_t* digit_pointer = &vector[digits];
00963       int count = digits - 1;
00964       do { *--digit_pointer = 0; } while(--count);
00965     }
00966     *least_significant_digit = 0;
00967     return *this;
00968   }
00969 
00973 template<unsigned int n>
00974   bool
00975   bitset<n>::test(size_t pos) const
00976   {
00977     unsigned int d = pos / digit_bits;
00978     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
00979     return (vector[d] & mask);
00980   }
00981 
00985 template<unsigned int n>
00986   template<unsigned int pos>
00987     bool
00988     bitset<n>::test(void) const
00989     {
00990       static unsigned int const d = pos / digit_bits;
00991       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
00992       return (vector[d] & mask);
00993     }
00994 
00998 template<unsigned int n>
00999   void
01000   bitset<n>::set(size_t pos)
01001   {
01002     unsigned int d = pos / digit_bits;
01003     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
01004     vector[d] |= mask;
01005   }
01006 
01010 template<unsigned int n>
01011   template<unsigned int pos>
01012     void
01013     bitset<n>::set(void)
01014     {
01015       static unsigned int const d = pos / digit_bits;
01016       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
01017       vector[d] |= mask;
01018     }
01019 
01023 template<unsigned int n>
01024   template<unsigned int pos>
01025     void
01026     bitset<n>::digitset(unsigned int d, bool value)
01027     {
01028       bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
01029       if (value)
01030         vector[d] |= mask;
01031       else
01032         vector[d] &= ~mask;
01033     }
01034 
01038 template<unsigned int n>
01039   void
01040   bitset<n>::clear(size_t pos)
01041   {
01042     unsigned int d = pos / digit_bits;
01043     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
01044     vector[d] &= ~mask;
01045   }
01046 
01050 template<unsigned int n>
01051   template<unsigned int pos>
01052     void
01053     bitset<n>::clear(void)
01054     {
01055       static unsigned int const d = pos / digit_bits;
01056       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
01057       vector[d] &= ~mask;
01058     }
01059 
01063 template<unsigned int n>
01064   void
01065   bitset<n>::flip(size_t pos)
01066   {
01067     unsigned int d = pos / digit_bits;
01068     bitset_digit_t mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
01069     vector[d] ^= mask;
01070   }
01071 
01075 template<unsigned int n>
01076   template<unsigned int pos>
01077     void
01078     bitset<n>::flip(void)
01079     {
01080       static unsigned int const d = pos / digit_bits;
01081       static bitset_digit_t const mask = static_cast<bitset_digit_t>(1) << (pos % digit_bits);
01082       vector[d] ^= mask;
01083     }
01084 
01088 template<unsigned int n>
01089   bool
01090   bitset<n>::any(void) const
01091   {
01092     unsigned int to = digits - 1;
01093     if (digits > 1)
01094       do
01095       {
01096         if (vector[to] != 0)
01097           return true;
01098         --to;
01099       }
01100       while(to != 0);
01101     return (vector[0] != 0);
01102   }
01103 
01104 static bool const oddnumberofbits[] = {
01105   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
01106   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
01107   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
01108   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
01109   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
01110   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
01111   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
01112   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
01113   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
01114   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
01115   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
01116   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
01117   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false,
01118   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
01119   true, false, false, true, false, true, true, false, false, true, true, false, true, false, false, true,
01120   false, true, true, false, true, false, false, true, true, false, false, true, false, true, true, false };
01121 
01125 template<unsigned int n>
01126   bool
01127   bitset<n>::odd(void) const
01128   {
01129     unsigned int from = digits - 1;
01130     bitset_digit_t sum = vector[0];
01131     if (digits > 1)
01132       do
01133       {
01134         sum ^= vector[from];
01135         --from;
01136       }
01137       while(from != 0);
01138     bitset_digit_t ssum = sum;
01139     if (sizeof(bitset_digit_t) >= 2)
01140     {
01141       ssum >>= (digit_bits / 2);
01142       sum ^= ssum;
01143     }
01144     if (sizeof(bitset_digit_t) >= 4)
01145     {
01146       ssum = sum;
01147       ssum >>= (digit_bits / 4);
01148       sum ^= ssum;
01149     }
01150     if (sizeof(bitset_digit_t) >= 8)
01151     {
01152       ssum = sum;
01153       ssum >>= (digit_bits / 8);
01154       sum ^= ssum;
01155     }
01156     if (sizeof(bitset_digit_t) == 16)
01157     {
01158       ssum = sum;
01159       ssum >>= (digit_bits / 16);
01160       sum ^= ssum;
01161     }
01162     return oddnumberofbits[sum & 0xff];
01163   }
01164 
01168 struct left {
01169 public:
01170   typedef struct right inverse;
01171   static int const direction = -1;
01172   static bool const __left = true;
01173   static bool const __right = false;
01174   static inline void shift(bitset_digit_t& digit, unsigned int shift) { digit <<= shift; }
01175   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
01176   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
01177 };
01178 
01182 struct right {
01183 public:
01184   typedef struct left inverse;
01185   static int const direction = 1;
01186   static bool const __left = false;
01187   static bool const __right = true;
01188   static inline void shift(bitset_digit_t& digit, unsigned int shift) { digit >>= shift; }
01189   static inline bitset_digit_t shift_copy(bitset_digit_t digit, unsigned int shift) { return digit >> shift; }
01190   static inline bitset_digit_t reverse_shift_copy(bitset_digit_t digit, unsigned int shift) { return digit << shift; }
01191 };
01192 
01196 struct assign {
01197 public:
01198   static bool const __clear = true;
01199   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
01200   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
01201 };
01202 
01206 struct exor {
01207 public:
01208   static bool const __clear = false;
01209   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
01210   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 ^= digit2; }
01211 };
01212 
01213 #ifndef HIDE_FROM_DOXYGEN
01214 struct rotate_phase1 {
01215 public:
01216   static bool const __clear = false;
01217   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
01218   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
01219 };
01220 
01221 struct rotate_phase2 {
01222 public:
01223   static bool const __clear = false;
01224   static inline void op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 = digit2; }
01225   static inline void mixed_op(bitset_digit_t& digit1, bitset_digit_t digit2) { digit1 |= digit2; }
01226 };
01227 #endif
01228 
01237 template<unsigned int n>
01238   template<unsigned int shift, class DIRECTION>
01239     void
01240     bitset<n>::rotate(bitset<n>& result) const
01241     {
01242       shift_op<shift % n, DIRECTION, rotate_phase1>(result);
01243       shift_op<n - (shift % n), typename DIRECTION::inverse, rotate_phase2>(result);
01244     }
01245 
01246 } // namespace libecc
01247 
01248 #endif // LIBECC_BITS_H
Copyright © 2002 Carlo Wood.  All rights reserved.