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 #ifdef HAVE_MPI
00030 template<class K>
00031 struct MPITraits;
00032 #endif
00033
00041 template<int k>
00042 class bigunsignedint {
00043 public:
00044
00045
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
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
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
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
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
00159 template<int k>
00160 inline unsigned int bigunsignedint<k>::touint () const
00161 {
00162 return (digit[1]<<bits)+digit[0];
00163 }
00164
00165
00166 template<int k>
00167 inline void bigunsignedint<k>::print (std::ostream& s) const
00168 {
00169 bool leading=false;
00170
00171
00172 for (int i=n-1; i>=0; i--)
00173 for (int d=hexdigits-1; d>=0; d--)
00174 {
00175
00176 int current = (digit[i]>>(d*4))&0xF;
00177 if (current!=0)
00178 {
00179
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
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++)
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
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
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
00348 int j=shift/bits;
00349 for (int i=n-1-j; i>=0; i--)
00350 result.digit[i+j] = digit[i];
00351
00352
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
00373 int j=shift/bits;
00374 for (unsigned int i=0; i<n-j; i++)
00375 result.digit[i] = digit[i+j];
00376
00377
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