bigunsignedint.hh

Go to the documentation of this file.
00001 // $Id: bigunsignedint.hh 5738 2009-12-04 13:30:49Z mblatt $
00002 
00003 #ifndef DUNE_BIGUNSIGNEDINT_HH
00004 #define DUNE_BIGUNSIGNEDINT_HH
00005 
00006 #include<iostream>
00007 #include<limits>
00008 #include<cstdlib>
00009 #include<dune/common/exceptions.hh>
00010 
00017 namespace std
00018 {
00019   template<class T> struct numeric_limits;
00020 }
00021 
00022 namespace Dune
00023 {
00029 #if HAVE_MPI
00030   template<class K>
00031   struct MPITraits;
00032 #endif
00033 
00043   template<int k>
00044   class bigunsignedint {
00045   public:
00046 
00047         // unsigned short is 16 bits wide, n is the number of digits needed
00048     enum { bits=std::numeric_limits<unsigned short>::digits, n=k/bits+(k%bits!=0), 
00049            hexdigits=4, bitmask=0xFFFF, compbitmask=0xFFFF0000, 
00050            overflowmask=0x1 };
00051 
00053         bigunsignedint ();
00054 
00056     bigunsignedint (int x);
00057 
00059     bigunsignedint (std::size_t x);
00060 
00062         void print (std::ostream& s) const ;
00063 
00065         bigunsignedint<k> operator+ (const bigunsignedint<k>& x) const;
00066 
00068         bigunsignedint<k> operator- (const bigunsignedint<k>& x) const;
00069 
00071         bigunsignedint<k> operator* (const bigunsignedint<k>& x) const;
00072 
00074         bigunsignedint<k>& operator++ ();
00075 
00077         bigunsignedint<k> operator/ (const bigunsignedint<k>& x) const;
00078 
00080         bigunsignedint<k> operator% (const bigunsignedint<k>& x) const;
00081 
00082 
00084         bigunsignedint<k> operator& (const bigunsignedint<k>& x) const;
00085 
00087         bigunsignedint<k> operator^ (const bigunsignedint<k>& x) const;
00088 
00090         bigunsignedint<k> operator| (const bigunsignedint<k>& x) const;
00091 
00093         bigunsignedint<k> operator~ () const;
00094 
00095 
00097         bigunsignedint<k> operator<< (int i) const;
00098 
00100         bigunsignedint<k> operator>> (int i) const;
00101 
00102 
00104         bool operator< (const bigunsignedint<k>& x) const;
00105 
00107         bool operator<= (const bigunsignedint<k>& x) const;
00108 
00110         bool operator> (const bigunsignedint<k>& x) const;
00111 
00113         bool operator>= (const bigunsignedint<k>& x) const;
00114 
00116         bool operator== (const bigunsignedint<k>& x) const;
00117 
00119         bool operator!= (const bigunsignedint<k>& x) const;
00120 
00121 
00123 //      operator unsigned int () const;
00124     unsigned int touint() const;
00130     double todouble() const;
00131 
00132         friend class bigunsignedint<k/2>;
00133     friend class std::numeric_limits<bigunsignedint<k> >;
00134     
00135   private:
00136         unsigned short digit[n];
00137 #if HAVE_MPI
00138     friend class MPITraits<bigunsignedint<k> >;
00139 #endif
00140     inline void assign(std::size_t x);
00141     
00142     
00143   } ;
00144 
00145   // Constructors
00146   template<int k>
00147   bigunsignedint<k>::bigunsignedint ()
00148   { 
00149     assign(0u);
00150   }
00151 
00152   template<int k>
00153   bigunsignedint<k>::bigunsignedint (int y)
00154   {
00155     std::size_t x = std::abs(y);
00156     assign(x);
00157   }
00158 
00159   template<int k>
00160   bigunsignedint<k>::bigunsignedint (std::size_t x)
00161   {
00162     assign(x);
00163   }
00164   template<int k>
00165   void bigunsignedint<k>::assign(std::size_t x)
00166   {
00167     int no=std::min(static_cast<int>(n),
00168                     static_cast<int>(std::numeric_limits<std::size_t>::digits/bits));
00169     
00170     for(int i=0; i<no; ++i){
00171         digit[i] = (x&bitmask);
00172         x=x>>bits;
00173     }
00174     for (unsigned int i=no; i<n; i++) digit[i]=0;
00175   }
00176 
00177   // export
00178   template<int k>
00179   inline unsigned int bigunsignedint<k>::touint () const
00180   {
00181         return (digit[1]<<bits)+digit[0];
00182   }
00183 
00184   template<int k>
00185   inline double bigunsignedint<k>::todouble() const
00186   {
00187     int firstInZeroRange=n;
00188     for(int i=n-1; i>=0; --i)
00189       if(digit[i]!=0)
00190         break;
00191       else
00192         --firstInZeroRange;
00193     int representableDigits=std::numeric_limits<double>::digits/bits;
00194     int lastInRepresentableRange=0;
00195     if(representableDigits<firstInZeroRange)
00196       lastInRepresentableRange=firstInZeroRange-representableDigits;
00197     double val=0;
00198     for(int i=firstInZeroRange-1; i>=lastInRepresentableRange; --i)
00199       val =val*(1<<bits)+digit[i];
00200     return val*(1<<(bits*lastInRepresentableRange));
00201   }
00202   // print
00203   template<int k>
00204   inline void bigunsignedint<k>::print (std::ostream& s) const
00205   {    
00206         bool leading=false;
00207 
00208         // print from left to right
00209         for (int i=n-1; i>=0; i--)
00210           for (int d=hexdigits-1; d>=0; d--)
00211                 {
00212                   // extract one hex digit
00213                   int current = (digit[i]>>(d*4))&0xF;
00214                   if (current!=0)
00215                         {
00216                           //                      s.setf(std::ios::noshowbase);
00217                           s << std::hex << current;
00218                           leading = false;
00219                         }
00220                   else if (!leading) s << std::hex << current;
00221                 }
00222         if (leading) s << "0";
00223         s << std::dec;
00224   }
00225 
00226   template <int k>
00227   inline std::ostream& operator<< (std::ostream& s, const bigunsignedint<k>& x)
00228   {
00229         x.print(s);
00230         return s;
00231   }
00232 
00233 
00234   // Operators
00235   template <int k>
00236   inline bigunsignedint<k> bigunsignedint<k>::operator+ (const bigunsignedint<k>& x) const
00237   {
00238         bigunsignedint<k> result;
00239         int overflow=0;
00240 
00241         for (unsigned int i=0; i<n; i++)
00242           {
00243                 int sum = ((int)digit[i]) + ((int)x.digit[i]) + overflow;
00244                 result.digit[i] = sum&bitmask;
00245                 overflow = (sum>>bits)&overflowmask;
00246           }
00247         return result;
00248   }
00249 
00250   template <int k>
00251   inline bigunsignedint<k> bigunsignedint<k>::operator- (const bigunsignedint<k>& x) const
00252   {
00253         bigunsignedint<k> result;
00254         int overflow=0;
00255 
00256         for (unsigned int i=0; i<n; i++)
00257           {
00258                 int diff = ((int)digit[i]) - (((int)x.digit[i]) + overflow);
00259                 if (diff>=0)
00260                   result.digit[i] = (unsigned short) diff;
00261                 else
00262                   {
00263                         result.digit[i] = (unsigned short) (diff+bitmask);
00264                         overflow = 1;
00265                   }
00266           }
00267         return result;
00268   }
00269 
00270   template <int k>
00271   inline bigunsignedint<k> bigunsignedint<k>::operator* (const bigunsignedint<k>& x) const
00272   {
00273         bigunsignedint<2*k> finalproduct(0);
00274 
00275         for (unsigned int m=0; m<n; m++) // digit in right factor
00276           {
00277                 bigunsignedint<2*k> singleproduct(0);
00278                 unsigned int overflow(0);
00279                 for (unsigned int i=0; i<n; i++) 
00280                   {
00281                         unsigned int digitproduct = ((unsigned int)digit[i])*((unsigned int)x.digit[m])+overflow;
00282                         singleproduct.digit[i+m] = (unsigned short) (digitproduct&bitmask);
00283                         overflow = (digitproduct>>bits)&bitmask;
00284                   }
00285                 finalproduct = finalproduct+singleproduct;
00286           }
00287 
00288         bigunsignedint<k> result;
00289         for (unsigned int i=0; i<n; i++) result.digit[i] = finalproduct.digit[i];
00290         return result;
00291   }
00292 
00293   template <int k>
00294   inline  bigunsignedint<k>& bigunsignedint<k>::operator++ ()
00295   {
00296         int overflow=1;
00297 
00298         for (unsigned int i=0; i<n; i++)
00299           {
00300                 int sum = ((int)digit[i]) + overflow;
00301                 digit[i] = sum&bitmask;
00302                 overflow = (sum>>bits)&overflowmask;
00303           }
00304         return *this;
00305   }
00306 
00307   template <int k>
00308   inline bigunsignedint<k> bigunsignedint<k>::operator/ (const bigunsignedint<k>& x) const
00309   {
00310     if(x==0)
00311       DUNE_THROW(Dune::MathError, "division by zero!");
00312 
00313         // better slow than nothing
00314         bigunsignedint<k> temp(*this);
00315         bigunsignedint<k> result(0);
00316 
00317         while (temp>=x)
00318           {
00319                 ++result;
00320                 temp = temp-x;
00321           }
00322 
00323         return result;
00324   }
00325 
00326   template <int k>
00327   inline bigunsignedint<k> bigunsignedint<k>::operator% (const bigunsignedint<k>& x) const
00328   {
00329         // better slow than nothing
00330         bigunsignedint<k> temp(*this);
00331         bigunsignedint<k> result(0);
00332 
00333         while (temp>=x)
00334           {
00335                 ++result;
00336                 temp = temp-x;
00337           }
00338 
00339         return temp;
00340   }
00341 
00342 
00343   template <int k>
00344   inline bigunsignedint<k> bigunsignedint<k>::operator& (const bigunsignedint<k>& x) const
00345   {
00346         bigunsignedint<k> result;
00347         for (unsigned int i=0; i<n; i++)
00348           result.digit[i] = digit[i]&x.digit[i];
00349         return result;
00350   }
00351 
00352   template <int k>
00353   inline bigunsignedint<k> bigunsignedint<k>::operator^ (const bigunsignedint<k>& x) const
00354   {
00355         bigunsignedint<k> result;
00356         for (unsigned int i=0; i<n; i++)
00357           result.digit[i] = digit[i]^x.digit[i];
00358         return result;
00359   }
00360 
00361   template <int k>
00362   inline bigunsignedint<k> bigunsignedint<k>::operator| (const bigunsignedint<k>& x) const
00363   {
00364         bigunsignedint<k> result;
00365         for (unsigned int i=0; i<n; i++)
00366           result.digit[i] = digit[i]|x.digit[i];
00367         return result;
00368   }
00369 
00370   template <int k>
00371   inline bigunsignedint<k> bigunsignedint<k>::operator~ () const
00372   {
00373         bigunsignedint<k> result;
00374         for (unsigned int i=0; i<n; i++)
00375           result.digit[i] = ~digit[i];
00376         return result;
00377   }
00378 
00379   template <int k>
00380   inline bigunsignedint<k> bigunsignedint<k>::operator<< (int shift) const
00381   {
00382         bigunsignedint<k> result(0);
00383 
00384         // multiples of bits
00385         int j=shift/bits;
00386         for (int i=n-1-j; i>=0; i--)
00387           result.digit[i+j] = digit[i];
00388 
00389         // remainder
00390         j=shift%bits;
00391         for (int i=n-1; i>=0; i--)
00392           {
00393                 unsigned int temp = result.digit[i];
00394                 temp = temp<<j;
00395                 result.digit[i] = (unsigned short) (temp&bitmask);
00396                 temp = temp>>bits;
00397                 if (i+1<(int)n)
00398                   result.digit[i+1] = result.digit[i+1]|temp;
00399           }     
00400 
00401         return result;
00402   }
00403 
00404   template <int k>
00405   inline bigunsignedint<k> bigunsignedint<k>::operator>> (int shift) const
00406   {
00407         bigunsignedint<k> result(0);
00408 
00409         // multiples of bits
00410         int j=shift/bits;
00411         for (unsigned int i=0; i<n-j; i++)
00412           result.digit[i] = digit[i+j];
00413 
00414         // remainder
00415         j=shift%bits;
00416         for (unsigned int i=0; i<n; i++)
00417           {
00418                 unsigned int temp = result.digit[i];
00419                 temp = temp<<(bits-j);
00420                 result.digit[i] = (unsigned short) ((temp&compbitmask)>>bits);
00421                 if (i>0)
00422                   result.digit[i-1] = result.digit[i-1] | (temp&bitmask);
00423           }
00424 
00425         return result;
00426   }
00427 
00428   template <int k>
00429   inline bool bigunsignedint<k>::operator!= (const bigunsignedint<k>& x) const
00430   {
00431         for (unsigned int i=0; i<n; i++)
00432           if (digit[i]!=x.digit[i]) return true;
00433         return false;
00434   }
00435 
00436   template <int k>
00437   inline bool bigunsignedint<k>::operator== (const bigunsignedint<k>& x) const
00438   {
00439         return !((*this)!=x);
00440   }
00441 
00442   template <int k>
00443   inline bool bigunsignedint<k>::operator< (const bigunsignedint<k>& x) const
00444   {
00445         for (int i=n-1; i>=0; i--) 
00446           if (digit[i]<x.digit[i]) return true;
00447           else if (digit[i]>x.digit[i]) return false;
00448         return false;
00449   }
00450 
00451   template <int k>
00452   inline bool bigunsignedint<k>::operator<= (const bigunsignedint<k>& x) const
00453   {
00454         for (int i=n-1; i>=0; i--) 
00455           if (digit[i]<x.digit[i]) return true;
00456           else if (digit[i]>x.digit[i]) return false;
00457         return true;
00458   }
00459 
00460   template <int k>
00461   inline bool bigunsignedint<k>::operator> (const bigunsignedint<k>& x) const
00462   {
00463         return !((*this)<=x);   
00464   }
00465 
00466   template <int k>
00467   inline bool bigunsignedint<k>::operator>= (const bigunsignedint<k>& x) const
00468   {
00469         return !((*this)<x);    
00470   }
00471 
00472 
00473   template <int k>
00474   inline bigunsignedint<k> operator+ (const bigunsignedint<k>& x, std::size_t y)
00475   {
00476         bigunsignedint<k> temp(y);
00477         return x+temp;
00478   }
00479 
00480   template <int k>
00481   inline bigunsignedint<k> operator- (const bigunsignedint<k>& x, std::size_t y)
00482   {
00483         bigunsignedint<k> temp(y);
00484         return x-temp;
00485   }
00486 
00487   template <int k>
00488   inline bigunsignedint<k> operator* (const bigunsignedint<k>& x, std::size_t y)
00489   {
00490         bigunsignedint<k> temp(y);
00491         return x*temp;
00492   }
00493 
00494   template <int k>
00495   inline bigunsignedint<k> operator/ (const bigunsignedint<k>& x, std::size_t y)
00496   {
00497         bigunsignedint<k> temp(y);
00498         return x/temp;
00499   }
00500 
00501   template <int k>
00502   inline bigunsignedint<k> operator% (const bigunsignedint<k>& x, std::size_t y)
00503   {
00504         bigunsignedint<k> temp(y);
00505         return x%temp;
00506   }
00507 
00508   template <int k>
00509   inline bigunsignedint<k> operator+ (std::size_t x, const bigunsignedint<k>& y)
00510   {
00511         bigunsignedint<k> temp(x);
00512         return temp+y;
00513   }
00514 
00515   template <int k>
00516   inline bigunsignedint<k> operator- (std::size_t x, const bigunsignedint<k>& y)
00517   {
00518         bigunsignedint<k> temp(x);
00519         return temp-y;
00520   }
00521 
00522   template <int k>
00523   inline bigunsignedint<k> operator* (std::size_t x, const bigunsignedint<k>& y)
00524   {
00525         bigunsignedint<k> temp(x);
00526         return temp*y;
00527   }
00528 
00529   template <int k>
00530   inline bigunsignedint<k> operator/ (std::size_t x, const bigunsignedint<k>& y)
00531   {
00532         bigunsignedint<k> temp(x);
00533         return temp/y;
00534   }
00535 
00536   template <int k>
00537   inline bigunsignedint<k> operator% (std::size_t x, const bigunsignedint<k>& y)
00538   {
00539         bigunsignedint<k> temp(x);
00540         return temp%y;
00541   }
00542 
00543 
00545 }
00546 
00547 namespace std
00548 {
00549   template<class T> struct numeric_limits;
00550   
00551   template<int k>
00552   struct numeric_limits<Dune::bigunsignedint<k> >
00553   {
00554     static const bool is_specialized = true;
00555     
00556     static Dune::bigunsignedint<k> min()
00557     {
00558       return static_cast<Dune::bigunsignedint<k> >(0);
00559     }
00560 
00561     static Dune::bigunsignedint<k> max()
00562     {
00563       Dune::bigunsignedint<k> max_;
00564       for(std::size_t i=0; i < Dune::bigunsignedint<k>::n; ++i)
00565         max_.digit[i]=std::numeric_limits<unsigned short>::max();
00566       return max_;
00567     }
00568     
00569     
00570     static const int digits = Dune::bigunsignedint<k>::bits *
00571     Dune::bigunsignedint<k>::n;
00572     static const bool is_signed = false;
00573     static const bool is_integer = true;
00574     static const bool is_exact = true;
00575     static const int radix = 2;
00576     
00577     static Dune::bigunsignedint<k> epsilon()
00578     {
00579       return static_cast<Dune::bigunsignedint<k> >(0);
00580     }
00581 
00582     static Dune::bigunsignedint<k> round_error()
00583     {
00584       return static_cast<Dune::bigunsignedint<k> >(0);
00585     }
00586     
00587     static const int min_exponent = 0;
00588     static const int min_exponent10 = 0;
00589     static const int max_exponent = 0;
00590     static const int max_exponent10 = 0;
00591     
00592     static const bool has_infinity = false;
00593     static const bool has_quiet_NaN = false;
00594     static const bool has_signaling_NaN = false; 
00595     
00596     static const float_denorm_style has_denorm = denorm_absent;
00597     static const bool has_denorm_loss = false;
00598 
00599     static Dune::bigunsignedint<k> infinity() throw()
00600     { 
00601       return static_cast<Dune::bigunsignedint<k> >(0); 
00602     }
00603 
00604     static Dune::bigunsignedint<k> quiet_NaN() throw()
00605     { 
00606       return static_cast<Dune::bigunsignedint<k> >(0); 
00607     }
00608 
00609     static Dune::bigunsignedint<k> signaling_NaN() throw()
00610     { 
00611       return static_cast<Dune::bigunsignedint<k> >(0); 
00612     }
00613 
00614     static Dune::bigunsignedint<k> denorm_min() throw()
00615     { 
00616       return static_cast<Dune::bigunsignedint<k> >(0); 
00617     }
00618 
00619     static const bool is_iec559 = false;
00620     static const bool is_bounded = true;
00621     static const bool is_modulo = true;
00622 
00623     static const bool traps = false;
00624     static const bool tinyness_before = false;
00625     static const float_round_style round_style = round_toward_zero;
00626 
00627   };
00628   
00629 }
00630 
00631 #endif
Generated on Mon Apr 26 10:45:21 2010 for dune-common by  doxygen 1.6.3