From c1f1e35236548aca9ab71ac191d8ac4d80631f66 Mon Sep 17 00:00:00 2001
From: Markus Blatt <mblatt@dune-project.org>
Date: Fri, 18 Sep 2009 13:44:46 +0000
Subject: [PATCH] Do not assume the sizes of integral types. Just ask
 numeric_limits. Otherwise on some 64bit platforms we run into trouble.

[[Imported from SVN: r5576]]
---
 common/bigunsignedint.hh          | 52 ++++++++++++++++++-------------
 common/test/bigunsignedinttest.cc | 22 +++++++++++++
 2 files changed, 52 insertions(+), 22 deletions(-)

diff --git a/common/bigunsignedint.hh b/common/bigunsignedint.hh
index cf2cc74d5..6f56fb236 100644
--- a/common/bigunsignedint.hh
+++ b/common/bigunsignedint.hh
@@ -47,7 +47,8 @@ namespace Dune
   public:
 
     // unsigned short is 16 bits wide, n is the number of digits needed
-    enum { n=k/16+(k%16!=0), bits=16, hexdigits=4, bitmask=0xFFFF, compbitmask=0xFFFF0000,
+    enum { bits=std::numeric_limits<unsigned short>::digits, n=k/bits+(k%bits!=0),
+           hexdigits=4, bitmask=0xFFFF, compbitmask=0xFFFF0000,
            overflowmask=0x1 };
 
     //! Construct uninitialized
@@ -57,7 +58,7 @@ namespace Dune
     bigunsignedint (int x);
 
     //! Construct from unsigned int
-    bigunsignedint (unsigned int x);
+    bigunsignedint (std::size_t x);
 
     //! Print number in hex notation
     void print (std::ostream& s) const ;
@@ -132,6 +133,8 @@ namespace Dune
 #if HAVE_MPI
     friend class MPITraits<bigunsignedint<k> >;
 #endif
+    inline void assign(std::size_t x);
+
 
   } ;
 
@@ -143,20 +146,25 @@ namespace Dune
   template<int k>
   bigunsignedint<k>::bigunsignedint (int y)
   {
-    unsigned int x = std::abs(y);
-    // assume unsigned int is 32 bits
-    digit[0] = (x&bitmask);
-    if (n>1) digit[1] = (x>>bits)&bitmask;
-    for (unsigned int i=2; i<n; i++) digit[i]=0;
+    std::size_t x = std::abs(y);
+    assign(y);
   }
 
   template<int k>
-  bigunsignedint<k>::bigunsignedint (unsigned int x)
+  bigunsignedint<k>::bigunsignedint (std::size_t x)
+  {
+    assign(x);
+  }
+  template<int k>
+  void bigunsignedint<k>::assign(std::size_t x)
   {
-    // assume unsigned int is 32 bits
-    digit[0] = (x&bitmask);
-    if (n>1) digit[1] = (x>>bits)&bitmask;
-    for (unsigned int i=2; i<n; i++) digit[i]=0;
+    int no=std::numeric_limits<std::size_t>::digits/bits;
+
+    for(int i=0; i<no; ++i) {
+      digit[i] = (x&bitmask);
+      x=x>>bits;
+    }
+    for (unsigned int i=no; i<n; i++) digit[i]=0;
   }
 
   // export
@@ -438,70 +446,70 @@ namespace Dune
 
 
   template <int k>
-  inline bigunsignedint<k> operator+ (const bigunsignedint<k>& x, unsigned int y)
+  inline bigunsignedint<k> operator+ (const bigunsignedint<k>& x, std::size_t y)
   {
     bigunsignedint<k> temp(y);
     return x+temp;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator- (const bigunsignedint<k>& x, unsigned int y)
+  inline bigunsignedint<k> operator- (const bigunsignedint<k>& x, std::size_t y)
   {
     bigunsignedint<k> temp(y);
     return x-temp;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator* (const bigunsignedint<k>& x, unsigned int y)
+  inline bigunsignedint<k> operator* (const bigunsignedint<k>& x, std::size_t y)
   {
     bigunsignedint<k> temp(y);
     return x*temp;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator/ (const bigunsignedint<k>& x, unsigned int y)
+  inline bigunsignedint<k> operator/ (const bigunsignedint<k>& x, std::size_t y)
   {
     bigunsignedint<k> temp(y);
     return x/temp;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator% (const bigunsignedint<k>& x, unsigned int y)
+  inline bigunsignedint<k> operator% (const bigunsignedint<k>& x, std::size_t y)
   {
     bigunsignedint<k> temp(y);
     return x%temp;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator+ (unsigned int x, const bigunsignedint<k>& y)
+  inline bigunsignedint<k> operator+ (std::size_t x, const bigunsignedint<k>& y)
   {
     bigunsignedint<k> temp(x);
     return temp+y;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator- (unsigned int x, const bigunsignedint<k>& y)
+  inline bigunsignedint<k> operator- (std::size_t x, const bigunsignedint<k>& y)
   {
     bigunsignedint<k> temp(x);
     return temp-y;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator* (unsigned int x, const bigunsignedint<k>& y)
+  inline bigunsignedint<k> operator* (std::size_t x, const bigunsignedint<k>& y)
   {
     bigunsignedint<k> temp(x);
     return temp*y;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator/ (unsigned int x, const bigunsignedint<k>& y)
+  inline bigunsignedint<k> operator/ (std::size_t x, const bigunsignedint<k>& y)
   {
     bigunsignedint<k> temp(x);
     return temp/y;
   }
 
   template <int k>
-  inline bigunsignedint<k> operator% (unsigned int x, const bigunsignedint<k>& y)
+  inline bigunsignedint<k> operator% (std::size_t x, const bigunsignedint<k>& y)
   {
     bigunsignedint<k> temp(x);
     return temp%y;
diff --git a/common/test/bigunsignedinttest.cc b/common/test/bigunsignedinttest.cc
index 607da28c9..2586185cb 100644
--- a/common/test/bigunsignedinttest.cc
+++ b/common/test/bigunsignedinttest.cc
@@ -47,8 +47,25 @@ int main()
 
   Dune::bigunsignedint<100> a, b, c;
   a=100;
+  int ret=0;
+  if(a.touint()!=100)
+  {
+    std::cerr<<"wrong conversion"<<std::endl;
+    ++ret;
+  }
+
   b=3;
+  if(b.touint()!=3)
+  {
+    std::cerr<<"wrong conversion"<<std::endl;
+    ++ret;
+  }
   c=a/b;
+  if(c.touint()!=100/3)
+  {
+    std::cerr<<"wrong conversion"<<std::endl;
+    ++ret;
+  }
   std::cout<<a<<"/"<<b<<"="<<c<<std::endl;
 
   try{
@@ -57,8 +74,13 @@ int main()
     b=0;
     c=a/1;
     std::cout<<a1<<"/"<<b1<<"="<<c1<<std::endl;
+    return ret;
+
   }
   catch(Dune::MathError e) {
     std::cout<<e<<std::endl;
+    return 1;
   }
+
+
 }
-- 
GitLab