bigunsignedint.hh
Go to the documentation of this file.00001
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
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
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
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
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
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
00161 template<int k>
00162 inline unsigned int bigunsignedint<k>::touint () const
00163 {
00164 return (digit[1]<<bits)+digit[0];
00165 }
00166
00167
00168 template<int k>
00169 inline void bigunsignedint<k>::print (std::ostream& s) const
00170 {
00171 bool leading=false;
00172
00173
00174 for (int i=n-1; i>=0; i--)
00175 for (int d=hexdigits-1; d>=0; d--)
00176 {
00177
00178 int current = (digit[i]>>(d*4))&0xF;
00179 if (current!=0)
00180 {
00181
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
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++)
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
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
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
00350 int j=shift/bits;
00351 for (int i=n-1-j; i>=0; i--)
00352 result.digit[i+j] = digit[i];
00353
00354
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
00375 int j=shift/bits;
00376 for (unsigned int i=0; i<n-j; i++)
00377 result.digit[i] = digit[i+j];
00378
00379
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