Dune Core Modules (2.3.1)

bigunsignedint.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 // $Id$
4 
5 #ifndef DUNE_BIGUNSIGNEDINT_HH
6 #define DUNE_BIGUNSIGNEDINT_HH
7 
8 #include <iostream>
9 #include <limits>
10 #include <cstdlib>
12 #include <dune/common/hash.hh>
13 
20 namespace Dune
21 {
27 #if HAVE_MPI
28  template<class K>
29  struct MPITraits;
30 #endif
31 
41  template<int k>
43  public:
44 
45  // unsigned short is 16 bits wide, n is the number of digits needed
46  enum { bits=std::numeric_limits<unsigned short>::digits, n=k/bits+(k%bits!=0),
47  hexdigits=4, bitmask=0xFFFF, compbitmask=0xFFFF0000,
48  overflowmask=0x1 };
49 
51  bigunsignedint ();
52 
54  bigunsignedint (int x);
55 
57  bigunsignedint (std::size_t x);
58 
60  void print (std::ostream& s) const ;
61 
64 
67 
70 
73 
78 
83 
84 
87 
90 
93 
96 
97 
99  bigunsignedint<k> operator<< (int i) const;
100 
102  bigunsignedint<k> operator>> (int i) const;
103 
104 
106  bool operator< (const bigunsignedint<k>& x) const;
107 
109  bool operator<= (const bigunsignedint<k>& x) const;
110 
112  bool operator> (const bigunsignedint<k>& x) const;
113 
115  bool operator>= (const bigunsignedint<k>& x) const;
116 
118  bool operator== (const bigunsignedint<k>& x) const;
119 
121  bool operator!= (const bigunsignedint<k>& x) const;
122 
123 
125  // operator unsigned int () const;
126  unsigned int touint() const;
132  double todouble() const;
133 
134  friend class bigunsignedint<k/2>;
135  friend struct std::numeric_limits< bigunsignedint<k> >;
136 
137 #if HAVE_DUNE_HASH
138 
139  inline friend std::size_t hash_value(const bigunsignedint& arg)
140  {
141  return hash_range(arg.digit,arg.digit + arg.n);
142  }
143 
144 #endif // HAVE_DUNE_HASH
145 
146  private:
147  unsigned short digit[n];
148 #if HAVE_MPI
149  friend struct MPITraits<bigunsignedint<k> >;
150 #endif
151  inline void assign(std::size_t x);
152 
153 
154  } ;
155 
156  // Constructors
157  template<int k>
159  {
160  assign(0u);
161  }
162 
163  template<int k>
165  {
166  std::size_t x = std::abs(y);
167  assign(x);
168  }
169 
170  template<int k>
172  {
173  assign(x);
174  }
175  template<int k>
176  void bigunsignedint<k>::assign(std::size_t x)
177  {
178  int no=std::min(static_cast<int>(n),
179  static_cast<int>(std::numeric_limits<std::size_t>::digits/bits));
180 
181  for(int i=0; i<no; ++i) {
182  digit[i] = (x&bitmask);
183  x=x>>bits;
184  }
185  for (unsigned int i=no; i<n; i++) digit[i]=0;
186  }
187 
188  // export
189  template<int k>
190  inline unsigned int bigunsignedint<k>::touint () const
191  {
192  return (digit[1]<<bits)+digit[0];
193  }
194 
195  template<int k>
196  inline double bigunsignedint<k>::todouble() const
197  {
198  int firstInZeroRange=n;
199  for(int i=n-1; i>=0; --i)
200  if(digit[i]!=0)
201  break;
202  else
203  --firstInZeroRange;
204  int representableDigits=std::numeric_limits<double>::digits/bits;
205  int lastInRepresentableRange=0;
206  if(representableDigits<firstInZeroRange)
207  lastInRepresentableRange=firstInZeroRange-representableDigits;
208  double val=0;
209  for(int i=firstInZeroRange-1; i>=lastInRepresentableRange; --i)
210  val =val*(1<<bits)+digit[i];
211  return val*(1<<(bits*lastInRepresentableRange));
212  }
213  // print
214  template<int k>
215  inline void bigunsignedint<k>::print (std::ostream& s) const
216  {
217  bool leading=false;
218 
219  // print from left to right
220  for (int i=n-1; i>=0; i--)
221  for (int d=hexdigits-1; d>=0; d--)
222  {
223  // extract one hex digit
224  int current = (digit[i]>>(d*4))&0xF;
225  if (current!=0)
226  {
227  // s.setf(std::ios::noshowbase);
228  s << std::hex << current;
229  leading = false;
230  }
231  else if (!leading) s << std::hex << current;
232  }
233  if (leading) s << "0";
234  s << std::dec;
235  }
236 
237  template <int k>
238  inline std::ostream& operator<< (std::ostream& s, const bigunsignedint<k>& x)
239  {
240  x.print(s);
241  return s;
242  }
243 
244 
245  // Operators
246  template <int k>
248  {
249  bigunsignedint<k> result;
250  int overflow=0;
251 
252  for (unsigned int i=0; i<n; i++)
253  {
254  int sum = ((int)digit[i]) + ((int)x.digit[i]) + overflow;
255  result.digit[i] = sum&bitmask;
256  overflow = (sum>>bits)&overflowmask;
257  }
258  return result;
259  }
260 
261  template <int k>
263  {
264  bigunsignedint<k> result;
265  int overflow=0;
266 
267  for (unsigned int i=0; i<n; i++)
268  {
269  int diff = ((int)digit[i]) - (((int)x.digit[i]) + overflow);
270  if (diff>=0)
271  result.digit[i] = (unsigned short) diff;
272  else
273  {
274  result.digit[i] = (unsigned short) (diff+bitmask);
275  overflow = 1;
276  }
277  }
278  return result;
279  }
280 
281  template <int k>
283  {
284  bigunsignedint<2*k> finalproduct(0);
285 
286  for (unsigned int m=0; m<n; m++) // digit in right factor
287  {
288  bigunsignedint<2*k> singleproduct(0);
289  unsigned int overflow(0);
290  for (unsigned int i=0; i<n; i++)
291  {
292  unsigned int digitproduct = ((unsigned int)digit[i])*((unsigned int)x.digit[m])+overflow;
293  singleproduct.digit[i+m] = (unsigned short) (digitproduct&bitmask);
294  overflow = (digitproduct>>bits)&bitmask;
295  }
296  finalproduct = finalproduct+singleproduct;
297  }
298 
299  bigunsignedint<k> result;
300  for (unsigned int i=0; i<n; i++) result.digit[i] = finalproduct.digit[i];
301  return result;
302  }
303 
304  template <int k>
306  {
307  int overflow=1;
308 
309  for (unsigned int i=0; i<n; i++)
310  {
311  int sum = ((int)digit[i]) + overflow;
312  digit[i] = sum&bitmask;
313  overflow = (sum>>bits)&overflowmask;
314  }
315  return *this;
316  }
317 
318  template <int k>
320  {
321  if(x==0)
322  DUNE_THROW(Dune::MathError, "division by zero!");
323 
324  // better slow than nothing
325  bigunsignedint<k> temp(*this);
326  bigunsignedint<k> result(0);
327 
328  while (temp>=x)
329  {
330  ++result;
331  temp = temp-x;
332  }
333 
334  return result;
335  }
336 
337  template <int k>
339  {
340  // better slow than nothing
341  bigunsignedint<k> temp(*this);
342  bigunsignedint<k> result(0);
343 
344  while (temp>=x)
345  {
346  ++result;
347  temp = temp-x;
348  }
349 
350  return temp;
351  }
352 
353 
354  template <int k>
356  {
357  bigunsignedint<k> result;
358  for (unsigned int i=0; i<n; i++)
359  result.digit[i] = digit[i]&x.digit[i];
360  return result;
361  }
362 
363  template <int k>
365  {
366  bigunsignedint<k> result;
367  for (unsigned int i=0; i<n; i++)
368  result.digit[i] = digit[i]^x.digit[i];
369  return result;
370  }
371 
372  template <int k>
374  {
375  bigunsignedint<k> result;
376  for (unsigned int i=0; i<n; i++)
377  result.digit[i] = digit[i]|x.digit[i];
378  return result;
379  }
380 
381  template <int k>
383  {
384  bigunsignedint<k> result;
385  for (unsigned int i=0; i<n; i++)
386  result.digit[i] = ~digit[i];
387  return result;
388  }
389 
390  template <int k>
391  inline bigunsignedint<k> bigunsignedint<k>::operator<< (int shift) const
392  {
393  bigunsignedint<k> result(0);
394 
395  // multiples of bits
396  int j=shift/bits;
397  for (int i=n-1-j; i>=0; i--)
398  result.digit[i+j] = digit[i];
399 
400  // remainder
401  j=shift%bits;
402  for (int i=n-1; i>=0; i--)
403  {
404  unsigned int temp = result.digit[i];
405  temp = temp<<j;
406  result.digit[i] = (unsigned short) (temp&bitmask);
407  temp = temp>>bits;
408  if (i+1<(int)n)
409  result.digit[i+1] = result.digit[i+1]|temp;
410  }
411 
412  return result;
413  }
414 
415  template <int k>
417  {
418  bigunsignedint<k> result(0);
419 
420  // multiples of bits
421  int j=shift/bits;
422  for (unsigned int i=0; i<n-j; i++)
423  result.digit[i] = digit[i+j];
424 
425  // remainder
426  j=shift%bits;
427  for (unsigned int i=0; i<n; i++)
428  {
429  unsigned int temp = result.digit[i];
430  temp = temp<<(bits-j);
431  result.digit[i] = (unsigned short) ((temp&compbitmask)>>bits);
432  if (i>0)
433  result.digit[i-1] = result.digit[i-1] | (temp&bitmask);
434  }
435 
436  return result;
437  }
438 
439  template <int k>
441  {
442  for (unsigned int i=0; i<n; i++)
443  if (digit[i]!=x.digit[i]) return true;
444  return false;
445  }
446 
447  template <int k>
449  {
450  return !((*this)!=x);
451  }
452 
453  template <int k>
455  {
456  for (int i=n-1; i>=0; i--)
457  if (digit[i]<x.digit[i]) return true;
458  else if (digit[i]>x.digit[i]) return false;
459  return false;
460  }
461 
462  template <int k>
464  {
465  for (int i=n-1; i>=0; i--)
466  if (digit[i]<x.digit[i]) return true;
467  else if (digit[i]>x.digit[i]) return false;
468  return true;
469  }
470 
471  template <int k>
473  {
474  return !((*this)<=x);
475  }
476 
477  template <int k>
479  {
480  return !((*this)<x);
481  }
482 
483 
484  template <int k>
485  inline bigunsignedint<k> operator+ (const bigunsignedint<k>& x, std::size_t y)
486  {
487  bigunsignedint<k> temp(y);
488  return x+temp;
489  }
490 
491  template <int k>
492  inline bigunsignedint<k> operator- (const bigunsignedint<k>& x, std::size_t y)
493  {
494  bigunsignedint<k> temp(y);
495  return x-temp;
496  }
497 
498  template <int k>
499  inline bigunsignedint<k> operator* (const bigunsignedint<k>& x, std::size_t y)
500  {
501  bigunsignedint<k> temp(y);
502  return x*temp;
503  }
504 
505  template <int k>
506  inline bigunsignedint<k> operator/ (const bigunsignedint<k>& x, std::size_t y)
507  {
508  bigunsignedint<k> temp(y);
509  return x/temp;
510  }
511 
512  template <int k>
513  inline bigunsignedint<k> operator% (const bigunsignedint<k>& x, std::size_t y)
514  {
515  bigunsignedint<k> temp(y);
516  return x%temp;
517  }
518 
519  template <int k>
520  inline bigunsignedint<k> operator+ (std::size_t x, const bigunsignedint<k>& y)
521  {
522  bigunsignedint<k> temp(x);
523  return temp+y;
524  }
525 
526  template <int k>
527  inline bigunsignedint<k> operator- (std::size_t x, const bigunsignedint<k>& y)
528  {
529  bigunsignedint<k> temp(x);
530  return temp-y;
531  }
532 
533  template <int k>
534  inline bigunsignedint<k> operator* (std::size_t x, const bigunsignedint<k>& y)
535  {
536  bigunsignedint<k> temp(x);
537  return temp*y;
538  }
539 
540  template <int k>
541  inline bigunsignedint<k> operator/ (std::size_t x, const bigunsignedint<k>& y)
542  {
543  bigunsignedint<k> temp(x);
544  return temp/y;
545  }
546 
547  template <int k>
548  inline bigunsignedint<k> operator% (std::size_t x, const bigunsignedint<k>& y)
549  {
550  bigunsignedint<k> temp(x);
551  return temp%y;
552  }
553 
554 
556 }
557 
558 namespace std
559 {
560  template<int k>
561  struct numeric_limits<Dune::bigunsignedint<k> >
562  {
563  public:
564  static const bool is_specialized = true;
565 
566  static Dune::bigunsignedint<k> min()
567  {
568  return static_cast<Dune::bigunsignedint<k> >(0);
569  }
570 
571  static Dune::bigunsignedint<k> max()
572  {
574  for(std::size_t i=0; i < Dune::bigunsignedint<k>::n; ++i)
575  max_.digit[i]=std::numeric_limits<unsigned short>::max();
576  return max_;
577  }
578 
579 
580  static const int digits = Dune::bigunsignedint<k>::bits *
582  static const bool is_signed = false;
583  static const bool is_integer = true;
584  static const bool is_exact = true;
585  static const int radix = 2;
586 
587  static Dune::bigunsignedint<k> epsilon()
588  {
589  return static_cast<Dune::bigunsignedint<k> >(0);
590  }
591 
592  static Dune::bigunsignedint<k> round_error()
593  {
594  return static_cast<Dune::bigunsignedint<k> >(0);
595  }
596 
597  static const int min_exponent = 0;
598  static const int min_exponent10 = 0;
599  static const int max_exponent = 0;
600  static const int max_exponent10 = 0;
601 
602  static const bool has_infinity = false;
603  static const bool has_quiet_NaN = false;
604  static const bool has_signaling_NaN = false;
605 
606  static const float_denorm_style has_denorm = denorm_absent;
607  static const bool has_denorm_loss = false;
608 
609  static Dune::bigunsignedint<k> infinity() throw()
610  {
611  return static_cast<Dune::bigunsignedint<k> >(0);
612  }
613 
614  static Dune::bigunsignedint<k> quiet_NaN() throw()
615  {
616  return static_cast<Dune::bigunsignedint<k> >(0);
617  }
618 
619  static Dune::bigunsignedint<k> signaling_NaN() throw()
620  {
621  return static_cast<Dune::bigunsignedint<k> >(0);
622  }
623 
624  static Dune::bigunsignedint<k> denorm_min() throw()
625  {
626  return static_cast<Dune::bigunsignedint<k> >(0);
627  }
628 
629  static const bool is_iec559 = false;
630  static const bool is_bounded = true;
631  static const bool is_modulo = true;
632 
633  static const bool traps = false;
634  static const bool tinyness_before = false;
635  static const float_round_style round_style = round_toward_zero;
636 
637  };
638 
639 }
640 
642 
643 #endif
Default exception class for mathematical errors.
Definition: exceptions.hh:267
Portable very large unsigned integers.
Definition: bigunsignedint.hh:42
A few common exception classes.
bigunsignedint< k > operator|(const bigunsignedint< k > &x) const
bitwise or
Definition: bigunsignedint.hh:373
bigunsignedint< k > operator<<(int i) const
left shift1/
Definition: bigunsignedint.hh:391
unsigned int touint() const
export to other types
Definition: bigunsignedint.hh:190
bool operator<=(const bigunsignedint< k > &x) const
less than or equal
Definition: bigunsignedint.hh:463
bigunsignedint< k > operator^(const bigunsignedint< k > &x) const
bitwise exor
Definition: bigunsignedint.hh:364
void print(std::ostream &s) const
Print number in hex notation.
Definition: bigunsignedint.hh:215
bigunsignedint< k > operator*(const bigunsignedint< k > &x) const
multiply
Definition: bigunsignedint.hh:282
bool operator<(const bigunsignedint< k > &x) const
less than
Definition: bigunsignedint.hh:454
std::ostream & operator<<(std::ostream &s, const array< T, N > &e)
Output operator for array.
Definition: array.hh:159
bool operator==(const bigunsignedint< k > &x) const
equal
Definition: bigunsignedint.hh:448
bool operator!=(const bigunsignedint< k > &x) const
not equal
Definition: bigunsignedint.hh:440
bigunsignedint< k > operator%(const bigunsignedint< k > &x) const
Definition: bigunsignedint.hh:338
bigunsignedint()
Construct uninitialized.
Definition: bigunsignedint.hh:158
bool operator>=(const bigunsignedint< k > &x) const
greater or equal
Definition: bigunsignedint.hh:478
bigunsignedint< k > operator>>(int i) const
right shift
Definition: bigunsignedint.hh:416
bigunsignedint< k > operator~() const
bitwise komplement
Definition: bigunsignedint.hh:382
bigunsignedint< k > operator-(const bigunsignedint< k > &x) const
subtract
Definition: bigunsignedint.hh:262
bigunsignedint< k > & operator++()
prefix increment
Definition: bigunsignedint.hh:305
double todouble() const
Convert to a double.
Definition: bigunsignedint.hh:196
bigunsignedint< k > operator&(const bigunsignedint< k > &x) const
bitwise and
Definition: bigunsignedint.hh:355
bigunsignedint< k > operator/(const bigunsignedint< k > &x) const
Definition: bigunsignedint.hh:319
bigunsignedint< k > operator+(const bigunsignedint< k > &x) const
add
Definition: bigunsignedint.hh:247
bool operator>(const bigunsignedint< k > &x) const
greater than
Definition: bigunsignedint.hh:472
#define DUNE_THROW(E, m)
Definition: exceptions.hh:244
Support for calculating hash values of objects.
#define DUNE_DEFINE_HASH(template_args, type)
Defines the required struct specialization to make type hashable via Dune::hash.
Definition: hash.hh:126
#define DUNE_HASH_TYPE(...)
Wrapper macro for the type to be hashed in DUNE_DEFINE_HASH.
Definition: hash.hh:143
#define DUNE_HASH_TEMPLATE_ARGS(...)
Wrapper macro for the template arguments in DUNE_DEFINE_HASH.
Definition: hash.hh:135
Dune namespace.
Definition: alignment.hh:14
std::size_t hash_range(It first, It last)
Hashes all elements in the range [first,last) and returns the combined hash.
Definition: hash.hh:449
A traits class describing the mapping of types onto MPI_Datatypes.
Definition: mpitraits.hh:37
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)