OSDN Git Service

2006-07-14 Paolo Carlini <pcarlini@suse.de>
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 14 Jul 2006 12:55:15 +0000 (12:55 +0000)
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 14 Jul 2006 12:55:15 +0000 (12:55 +0000)
* include/tr1/random.tcc (struct _To_Unsigned_Type): Add.
(subtract_with_carry<>::seed(_Gen&, false_type)): Use an
unsigned type in the loop, fix factor multiplier, take g
invocations modulo 2^32.

* include/tr1/random.tcc (subtract_with_carry<>::
seed(unsigned long)): Fix value == 0 special case.

* include/tr1/random (struct _Shift): Fix for large shifts.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@115439 138bc75d-0d04-0410-961f-82ee72b054a4

libstdc++-v3/ChangeLog
libstdc++-v3/include/tr1/random
libstdc++-v3/include/tr1/random.tcc

index 0da5ecd..b9420e0 100644 (file)
@@ -1,3 +1,15 @@
+2006-07-14  Paolo Carlini  <pcarlini@suse.de>
+
+       * include/tr1/random.tcc (struct _To_Unsigned_Type): Add.
+       (subtract_with_carry<>::seed(_Gen&, false_type)): Use an
+       unsigned type in the loop, fix factor multiplier, take g
+       invocations modulo 2^32.
+
+       * include/tr1/random.tcc (subtract_with_carry<>::
+       seed(unsigned long)): Fix value == 0 special case.
+
+       * include/tr1/random (struct _Shift): Fix for large shifts.
+
 2006-07-13  Paolo Carlini  <pcarlini@suse.de>
 
        * testsuite/performance/21_strings/string_copy_cons_and_dest.cc: New.
index f90c8d1..5810986 100644 (file)
@@ -125,7 +125,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       }
 
     template<typename _UIntType, int __w, bool = 
-            __w != std::numeric_limits<_UIntType>::digits>
+            __w < std::numeric_limits<_UIntType>::digits>
       struct _Shift
       { static const _UIntType __value = 0; };
 
index fe77abb..a3c263d 100644 (file)
@@ -102,6 +102,28 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
          2 + std::numeric_limits<_RealType>::digits * 3010/10000;
       };
 
+    template<typename _ValueT>
+      struct _To_Unsigned_Type
+      { typedef _ValueT _Type; };
+
+    template<>
+      struct _To_Unsigned_Type<short>
+      { typedef unsigned short _Type; };
+
+    template<>
+      struct _To_Unsigned_Type<int>
+      { typedef unsigned int _Type; };
+
+    template<>
+      struct _To_Unsigned_Type<long>
+      { typedef unsigned long _Type; };
+
+#ifdef _GLIBCXX_USE_LONG_LONG
+    template<>
+      struct _To_Unsigned_Type<long long>
+      { typedef unsigned long long _Type; };
+#endif
+
   } // namespace _Private
 
 
@@ -347,6 +369,9 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
     subtract_with_carry<_IntType, __m, __s, __r>::
     seed(unsigned long __value)
     {
+      if (__value == 0)
+       __value = 19780503;
+
       std::tr1::linear_congruential<unsigned long, 40014, 0, 2147483563>
        __lcg(__value);
 
@@ -357,35 +382,35 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       _M_p = 0;
     }
 
-  //
-  // This implementation differs from the tr1 spec because the tr1 spec refused
-  // to make any sense to me:  the exponent of the factor in the spec goes from
-  // 1 to (n-1), but it would only make sense to me if it went from 0 to (n-1).
-  //
-  // This algorithm is still problematic because it can overflow left right and
-  // center.
-  //
   template<typename _IntType, _IntType __m, int __s, int __r>
     template<class _Gen>
-    void
-    subtract_with_carry<_IntType, __m, __s, __r>::
-    seed(_Gen& __gen, false_type)
-    {
-      const int __n = (std::numeric_limits<_IntType>::digits + 31) / 32;
-      for (int __i = 0; __i < long_lag; ++__i)
-       {
-         _M_x[__i] = 0;
-         unsigned long __factor = 1;
-         for (int __j = 0; __j < __n; ++__j)
-           {
-             _M_x[__i] += __gen() * __factor;
-             __factor *= 0x80000000;
-           }
-         _M_x[__i] = _Private::__mod<_IntType, 1, 0, modulus>(_M_x[__i]);
-       }
-      _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0;
-      _M_p = 0;
-    }
+      void
+      subtract_with_carry<_IntType, __m, __s, __r>::
+      seed(_Gen& __gen, false_type)
+      {
+       const int __n = (std::numeric_limits<_IntType>::digits + 31) / 32;
+
+       typedef typename _Private::_Select<(sizeof(unsigned) == 4),
+         unsigned, unsigned long>::_Type _UInt32Type;
+
+       typedef typename _Private::_To_Unsigned_Type<_IntType>::_Type
+         _UIntType;
+
+       for (int __i = 0; __i < long_lag; ++__i)
+         {
+           _UIntType __tmp = 0;
+           _UIntType __factor = 1;
+           for (int __j = 0; __j < __n; ++__j)
+             {
+               __tmp += (_Private::__mod<_UInt32Type, 1, 0, 0>(__gen())
+                         * __factor);
+               __factor *= _Private::_Shift<_UIntType, 32>::__value;
+             }
+           _M_x[__i] = _Private::__mod<_UIntType, 1, 0, modulus>(__tmp);
+         }
+       _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0;
+       _M_p = 0;
+      }
 
   template<typename _IntType, _IntType __m, int __s, int __r>
     typename subtract_with_carry<_IntType, __m, __s, __r>::result_type