bigunsignedint.hh

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

Generated on Thu Apr 2 10:39:53 2009 for dune-common by  doxygen 1.5.6