OSDN Git Service

* include/bits/random.tcc (seed_seq::generate): Cast max()
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / random.tcc
index bfc4388..5b90e5a 100644 (file)
@@ -1,6 +1,6 @@
 // random number generation (out of line) -*- C++ -*-
 
-// Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
 // software; you can redistribute it and/or modify it under the
@@ -24,7 +24,7 @@
 
 /** @file bits/random.tcc
  *  This is an internal header file, included by other library headers.
- *  You should not attempt to use it directly.
+ *  Do not attempt to use it directly. @headername{random}
  */
 
 #ifndef _RANDOM_TCC
 
 #include <numeric> // std::accumulate and std::partial_sum
 
-namespace std
+namespace std _GLIBCXX_VISIBILITY(default)
 {
   /*
    * (Further) implementation-space details.
    */
   namespace __detail
   {
+  _GLIBCXX_BEGIN_NAMESPACE_VERSION
+
     // General case for x = (ax + c) mod m -- use Schrage's algorithm to
     // avoid integer overflow.
     //
@@ -47,6 +49,8 @@ namespace std
     //
     // Preconditions:  a > 0, m > 0.
     //
+    // XXX FIXME: as-is, only works correctly for __m % __a < __m / __a. 
+    //
     template<typename _Tp, _Tp __m, _Tp __a, _Tp __c, bool>
       struct _Mod
       {
@@ -100,8 +104,11 @@ namespace std
          *__result = __unary_op(*__first);
        return __result;
       }
+
+  _GLIBCXX_END_NAMESPACE_VERSION
   } // namespace __detail
 
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<typename _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
     constexpr _UIntType
@@ -466,9 +473,9 @@ namespace std
       __os.flags(__ios_base::dec | __ios_base::fixed | __ios_base::left);
       __os.fill(__space);
 
-      for (size_t __i = 0; __i < __n - 1; ++__i)
+      for (size_t __i = 0; __i < __n; ++__i)
        __os << __x._M_x[__i] << __space;
-      __os << __x._M_x[__n - 1];
+      __os << __x._M_p;
 
       __os.flags(__flags);
       __os.fill(__fill);
@@ -493,6 +500,7 @@ namespace std
 
       for (size_t __i = 0; __i < __n; ++__i)
        __is >> __x._M_x[__i];
+      __is >> __x._M_p;
 
       __is.flags(__flags);
       return __is;
@@ -622,7 +630,7 @@ namespace std
 
       for (size_t __i = 0; __i < __r; ++__i)
        __os << __x._M_x[__i] << __space;
-      __os << __x._M_carry;
+      __os << __x._M_carry << __space << __x._M_p;
 
       __os.flags(__flags);
       __os.fill(__fill);
@@ -644,6 +652,7 @@ namespace std
       for (size_t __i = 0; __i < __r; ++__i)
        __is >> __x._M_x[__i];
       __is >> __x._M_carry;
+      __is >> __x._M_p;
 
       __is.flags(__flags);
       return __is;
@@ -721,40 +730,65 @@ namespace std
     independent_bits_engine<_RandomNumberEngine, __w, _UIntType>::
     operator()()
     {
-      const long double __r = static_cast<long double>(_M_b.max())
-                           - static_cast<long double>(_M_b.min()) + 1.0L;
-      const result_type __m = std::log(__r) / std::log(2.0L);
-      result_type __n, __n0, __y0, __y1, __s0, __s1;
+      typedef typename _RandomNumberEngine::result_type _Eresult_type;
+      const _Eresult_type __r
+       = (_M_b.max() - _M_b.min() < std::numeric_limits<_Eresult_type>::max()
+          ? _M_b.max() - _M_b.min() + 1 : 0);
+      const unsigned __edig = std::numeric_limits<_Eresult_type>::digits;
+      const unsigned __m = __r ? std::__lg(__r) : __edig;
+
+      typedef typename std::common_type<_Eresult_type, result_type>::type
+       __ctype;
+      const unsigned __cdig = std::numeric_limits<__ctype>::digits;
+
+      unsigned __n, __n0;
+      __ctype __s0, __s1, __y0, __y1;
+
       for (size_t __i = 0; __i < 2; ++__i)
        {
          __n = (__w + __m - 1) / __m + __i;
          __n0 = __n - __w % __n;
-         const result_type __w0 = __w / __n;
-         const result_type __w1 = __w0 + 1;
-         __s0 = result_type(1) << __w0;
-         __s1 = result_type(1) << __w1;
-         __y0 = __s0 * (__r / __s0);
-         __y1 = __s1 * (__r / __s1);
-         if (__r - __y0 <= __y0 / __n)
+         const unsigned __w0 = __w / __n;  // __w0 <= __m
+
+         __s0 = 0;
+         __s1 = 0;
+         if (__w0 < __cdig)
+           {
+             __s0 = __ctype(1) << __w0;
+             __s1 = __s0 << 1;
+           }
+
+         __y0 = 0;
+         __y1 = 0;
+         if (__r)
+           {
+             __y0 = __s0 * (__r / __s0);
+             if (__s1)
+               __y1 = __s1 * (__r / __s1);
+
+             if (__r - __y0 <= __y0 / __n)
+               break;
+           }
+         else
            break;
        }
 
       result_type __sum = 0;
       for (size_t __k = 0; __k < __n0; ++__k)
        {
-         result_type __u;
+         __ctype __u;
          do
            __u = _M_b() - _M_b.min();
-         while (__u >= __y0);
-         __sum = __s0 * __sum + __u % __s0;
+         while (__y0 && __u >= __y0);
+         __sum = __s0 * __sum + (__s0 ? __u % __s0 : __u);
        }
       for (size_t __k = __n0; __k < __n; ++__k)
        {
-         result_type __u;
+         __ctype __u;
          do
            __u = _M_b() - _M_b.min();
-         while (__u >= __y1);
-         __sum = __s1 * __sum + __u % __s1;
+         while (__y1 && __u >= __y1);
+         __sum = __s1 * __sum + (__s1 ? __u % __s1 : __u);
        }
       return __sum;
     }
@@ -831,12 +865,11 @@ namespace std
       operator()(_UniformRandomNumberGenerator& __urng,
                 const param_type& __param)
       {
-       typedef typename std::make_unsigned<typename
-         _UniformRandomNumberGenerator::result_type>::type __urngtype;
+       typedef typename _UniformRandomNumberGenerator::result_type
+         _Gresult_type;
        typedef typename std::make_unsigned<result_type>::type __utype;
-       typedef typename std::conditional<(sizeof(__urngtype)
-                                          > sizeof(__utype)),
-         __urngtype, __utype>::type __uctype;
+       typedef typename std::common_type<_Gresult_type, __utype>::type
+         __uctype;
 
        const __uctype __urngmin = __urng.min();
        const __uctype __urngmax = __urng.max();
@@ -1020,7 +1053,7 @@ namespace std
 
        double __cand;
        do
-         __cand = std::ceil(std::log(__aurng()) / __param._M_log_p);
+         __cand = std::floor(std::log(__aurng()) / __param._M_log_1_p);
        while (__cand >= __thr);
 
        return result_type(__cand + __naf);
@@ -1070,7 +1103,7 @@ namespace std
       return __is;
     }
 
-
+  // This is Leger's algorithm, also in Devroye, Ch. X, Example 1.5.
   template<typename _IntType>
     template<typename _UniformRandomNumberGenerator>
       typename negative_binomial_distribution<_IntType>::result_type
@@ -1095,7 +1128,7 @@ namespace std
          param_type;
        
        const double __y =
-         _M_gd(__urng, param_type(__p.k(), __p.p() / (1.0 - __p.p())));
+         _M_gd(__urng, param_type(__p.k(), (1.0 - __p.p()) / __p.p()));
 
        std::poisson_distribution<result_type> __poisson(__y);
        return __poisson(__urng);
@@ -1429,7 +1462,7 @@ namespace std
       {
        result_type __ret;
        const _IntType __t = __param.t();
-       const _IntType __p = __param.p();
+       const double __p = __param.p();
        const double __p12 = __p <= 0.5 ? __p : 1.0 - __p;
        __detail::_Adaptor<_UniformRandomNumberGenerator, double>
          __aurng(__urng);
@@ -2756,16 +2789,16 @@ namespace std
                       : (__n - 1) / 2;
       const size_t __p = (__n - __t) / 2;
       const size_t __q = __p + __t;
-      const size_t __m = std::max(__s + 1, __n);
+      const size_t __m = std::max(size_t(__s + 1), __n);
 
       for (size_t __k = 0; __k < __m; ++__k)
        {
          _Type __arg = (__begin[__k % __n]
                         ^ __begin[(__k + __p) % __n]
                         ^ __begin[(__k - 1) % __n]);
-         _Type __r1 = __arg ^ (__arg << 27);
-         __r1 = __detail::__mod<_Type, __detail::_Shift<_Type, 32>::__value,
-                                1664525u, 0u>(__r1);
+         _Type __r1 = __arg ^ (__arg >> 27);
+         __r1 = __detail::__mod<_Type,
+                   __detail::_Shift<_Type, 32>::__value>(1664525u * __r1);
          _Type __r2 = __r1;
          if (__k == 0)
            __r2 += __s;
@@ -2785,14 +2818,14 @@ namespace std
          _Type __arg = (__begin[__k % __n]
                         + __begin[(__k + __p) % __n]
                         + __begin[(__k - 1) % __n]);
-         _Type __r3 = __arg ^ (__arg << 27);
-         __r3 = __detail::__mod<_Type, __detail::_Shift<_Type, 32>::__value,
-                                1566083941u, 0u>(__r3);
+         _Type __r3 = __arg ^ (__arg >> 27);
+         __r3 = __detail::__mod<_Type,
+                  __detail::_Shift<_Type, 32>::__value>(1566083941u * __r3);
          _Type __r4 = __r3 - __k % __n;
          __r4 = __detail::__mod<_Type,
                   __detail::_Shift<_Type, 32>::__value>(__r4);
-         __begin[(__k + __p) % __n] ^= __r4;
-         __begin[(__k + __q) % __n] ^= __r3;
+         __begin[(__k + __p) % __n] ^= __r3;
+         __begin[(__k + __q) % __n] ^= __r4;
          __begin[__k % __n] = __r4;
        }
     }
@@ -2818,6 +2851,8 @@ namespace std
        }
       return __sum / __tmp;
     }
-}
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
 
 #endif