bigunsignedint.hh

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

Generated on 6 Nov 2008 with Doxygen (ver 1.5.6) [logfile].