00001
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
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
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
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
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
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
00158 template<int k>
00159 inline unsigned int bigunsignedint<k>::touint () const
00160 {
00161 return (digit[1]<<bits)+digit[0];
00162 }
00163
00164
00165 template<int k>
00166 inline void bigunsignedint<k>::print (std::ostream& s) const
00167 {
00168 bool leading=false;
00169
00170
00171 for (int i=n-1; i>=0; i--)
00172 for (int d=hexdigits-1; d>=0; d--)
00173 {
00174
00175 int current = (digit[i]>>(d*4))&0xF;
00176 if (current!=0)
00177 {
00178
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
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++)
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
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
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
00347 int j=shift/bits;
00348 for (int i=n-1-j; i>=0; i--)
00349 result.digit[i+j] = digit[i];
00350
00351
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
00372 int j=shift/bits;
00373 for (unsigned int i=0; i<n-j; i++)
00374 result.digit[i] = digit[i+j];
00375
00376
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