bigunsignedint.hh

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

Generated on 9 Apr 2008 with Doxygen (ver 1.5.2) [logfile].