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