2006-08-25 Paolo Carlini <pcarlini@suse.de>
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Aug 2006 16:02:23 +0000 (16:02 +0000)
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Aug 2006 16:02:23 +0000 (16:02 +0000)
        * include/tr1/random (bernoulli_distribution::operator()): Fix
        wrt generators returning integers.
(uniform_int<>::_M_call): Add.
(uniform_int<>::operator()): Use it.

* include/tr1/random (_Adaptor<>::min, _Adaptor<>::max): Add.
(_Adaptor<>::operator()): Allow for nonzero _M_g.min().

* include/tr1/random.tcc (linear_congruential<>::min, max):
Move inline...
(__mod): Move ...
* include/tr1/random: ... here.
(struct _Mod): Declare.

* include/tr1/random (struct _To_Unsigned_Type): Only declare,
move...
* include/tr1/random.tcc: ... here.

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

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

index 7a8d904..5dfa9f1 100644 (file)
@@ -1,3 +1,23 @@
+2006-08-25  Paolo Carlini  <pcarlini@suse.de>
+
+       * include/tr1/random (bernoulli_distribution::operator()): Fix
+        wrt generators returning integers.
+       (uniform_int<>::_M_call): Add.
+       (uniform_int<>::operator()): Use it.
+
+       * include/tr1/random (_Adaptor<>::min, _Adaptor<>::max): Add.
+       (_Adaptor<>::operator()): Allow for nonzero _M_g.min().
+
+       * include/tr1/random.tcc (linear_congruential<>::min, max):
+       Move inline...
+       (__mod): Move ...
+       * include/tr1/random: ... here.
+       (struct _Mod): Declare.
+
+       * include/tr1/random (struct _To_Unsigned_Type): Only declare,
+       move...
+       * include/tr1/random.tcc: ... here.
+
 2006-08-22  Phillip Jordan  <phillip.m.jordan@gmail.com>
 
        *include/tr1/boost_shared_ptr.h: Added locking policy to
index 41e010a..b90d323 100644 (file)
@@ -67,15 +67,11 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
     // Type selectors -- are these already implemented elsewhere?
     template<bool, typename _TpTrue, typename _TpFalse>
       struct _Select
-      {
-       typedef _TpTrue _Type;
-      };
+      { typedef _TpTrue _Type; };
 
     template<typename _TpTrue, typename _TpFalse>
       struct _Select<false, _TpTrue, _TpFalse>
-      {
-       typedef _TpFalse _Type;
-      };
+      { typedef _TpFalse _Type; };
 
     template<typename _UIntType, int __w, bool = 
             __w < std::numeric_limits<_UIntType>::digits>
@@ -86,27 +82,18 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       struct _Shift<_UIntType, __w, true>
       { static const _UIntType __value = _UIntType(1) << __w; };
 
-    template<typename _ValueT>
-      struct _To_Unsigned_Type
-      { typedef _ValueT _Type; };
-
-    template<>
-      struct _To_Unsigned_Type<short>
-      { typedef unsigned short _Type; };
+    template<typename _Tp, _Tp __a, _Tp __c, _Tp __m, bool>
+      struct _Mod;
 
-    template<>
-      struct _To_Unsigned_Type<int>
-      { typedef unsigned int _Type; };
+    // Dispatch based on modulus value to prevent divide-by-zero compile-time
+    // errors when m == 0.
+    template<typename _Tp, _Tp __a, _Tp __c, _Tp __m>
+      inline _Tp
+      __mod(_Tp __x)
+      { return _Mod<_Tp, __a, __c, __m, __m == 0>::__calc(__x); }
 
-    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
+    template<typename _ValueT>
+      struct _To_Unsigned_Type;
 
     typedef _Select<(sizeof(unsigned) == 4),
                    unsigned, unsigned long>::_Type _UInt32Type;
@@ -127,6 +114,30 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
        : _M_g(__g) { }
 
        result_type
+       min() const
+       {
+         result_type __return_value = 0;
+         if (is_integral<_Engine_result_type>::value
+             && is_integral<result_type>::value)
+           __return_value = _M_g.min();
+         else if (!is_integral<result_type>::value)
+           __return_value = result_type(0);
+         return __return_value;
+       }
+
+       result_type
+       max() const
+       {
+         result_type __return_value = 0;
+         if (is_integral<_Engine_result_type>::value
+             && is_integral<result_type>::value)
+           __return_value = _M_g.max();
+         else if (!is_integral<result_type>::value)
+           __return_value = result_type(1);
+         return __return_value;
+       }
+
+       result_type
        operator()();
 
       private:
@@ -151,11 +162,11 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
          __return_value = _M_g();
        else if (is_integral<_Engine_result_type>::value
                 && !is_integral<result_type>::value)
-         __return_value = result_type(_M_g())
+         __return_value = result_type(_M_g() - _M_g.min())
            / result_type(_M_g.max() - _M_g.min() + result_type(1));
        else if (!is_integral<_Engine_result_type>::value
                 && !is_integral<result_type>::value)
-         __return_value = result_type(_M_g())
+         __return_value = result_type(_M_g() - _M_g.min())
            / result_type(_M_g.max() - _M_g.min());
        return __return_value;
       }
@@ -177,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
 
     public:
       typedef _Engine                                engine_type;
-      typedef _Adaptor<_Engine, _Dist>     engine_value_type;
+      typedef _Adaptor<_Engine, _Dist>               engine_value_type;
       typedef _Dist                                  distribution_type;
       typedef typename _Dist::result_type            result_type;
 
@@ -372,15 +383,20 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
 
       /**
        * Gets the smallest possible value in the output range.
+       *
+       * The minumum depends on the @p __c parameter: if it is zero, the
+       * minimum generated must be > 0, otherwise 0 is allowed.
        */
       result_type
-      min() const;
+      min() const
+      { return (__mod<_UIntType, 1, 0, __m>(__c) == 0) ? 1 : 0; }
 
       /**
        * Gets the largest possible value in the output range.
        */
       result_type
-      max() const;
+      max() const
+      { return __m - 1; }
 
       /**
        * Gets the next random number in the sequence.
@@ -1391,6 +1407,8 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       base2() const
       { return _M_b2; }
 
+      // FIXME: Cannot be always correct.  FWIW, the solution in N2032
+      // in practice isn't much better..
       result_type
       min() const
       { return _M_b1.min() ^ _M_b2.min(); }
@@ -1651,7 +1669,12 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       template<typename _UniformRandomNumberGenerator>
         result_type
         operator()(_UniformRandomNumberGenerator& __urng)
-        { return (__urng() % (_M_max - _M_min + 1)) + _M_min; }
+        {
+         typedef typename _UniformRandomNumberGenerator::result_type
+           _UResult_type;
+         return _M_call(__urng, _M_min, _M_max,
+                        typename is_integral<_UResult_type>::type());
+       }
 
       /**
        * Gets a uniform random number in the range @f$[0, n)@f$.
@@ -1661,7 +1684,12 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       template<typename _UniformRandomNumberGenerator>
         result_type
         operator()(_UniformRandomNumberGenerator& __urng, result_type __n)
-        { return __urng() % __n; }
+        {
+         typedef typename _UniformRandomNumberGenerator::result_type
+           _UResult_type;
+         return _M_call(__urng, 0, __n - 1,
+                        typename is_integral<_UResult_type>::type());
+       }
 
       /**
        * Inserts a %uniform_int random number distribution @p __x into the
@@ -1693,6 +1721,22 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
                   uniform_int<_IntType1>& __x);
 
     private:
+      template<typename _UniformRandomNumberGenerator>
+        result_type
+        _M_call(_UniformRandomNumberGenerator& __urng,
+               result_type __min, result_type __max, true_type)
+        { return result_type(__urng() % (__max - __min + 1)) + __min; }
+
+      template<typename _UniformRandomNumberGenerator>
+        result_type
+        _M_call(_UniformRandomNumberGenerator& __urng,
+               result_type __min, result_type __max, false_type)
+        {
+         return result_type((__urng() - __urng.min())
+                            / (__urng.max() - __urng.min())
+                            * (__max - __min + 1)) + __min;
+       }
+
       _IntType _M_min;
       _IntType _M_max;
     };
@@ -1753,7 +1797,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       result_type
       operator()(_UniformRandomNumberGenerator& __urng)
       {
-       if (__urng() < _M_p)
+       if ((__urng() - __urng.min()) < _M_p * (__urng.max() - __urng.min()))
          return true;
        return false;
       }
index cbeb57d..b95a5f8 100644 (file)
@@ -87,12 +87,27 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
        { return __a * __x + __c; }
       };
 
-    // Dispatch based on modulus value to prevent divide-by-zero compile-time
-    // errors when m == 0.
-    template<typename _Tp, _Tp __a, _Tp __c, _Tp __m>
-      inline _Tp
-      __mod(_Tp __x)
-      { return _Mod<_Tp, __a, __c, __m, __m == 0>::__calc(__x); }
+    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
 
     // See N1822.
     template<typename _RealType>
@@ -138,31 +153,6 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       }
 
   /**
-   * Returns a value that is less than or equal to all values potentially
-   * returned by operator(). The return value of this function does not
-   * change during the lifetime of the object..
-   *
-   * The minumum depends on the @p __c parameter: if it is zero, the
-   * minimum generated must be > 0, otherwise 0 is allowed.
-   */
-  template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
-    typename linear_congruential<_UIntType, __a, __c, __m>::result_type
-    linear_congruential<_UIntType, __a, __c, __m>::
-    min() const
-    { return (__mod<_UIntType, 1, 0, __m>(__c) == 0) ? 1 : 0; }
-
-  /**
-   * Gets the maximum possible value of the generated range.
-   *
-   * For a linear congruential generator, the maximum is always @p __m - 1.
-   */
-  template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
-    typename linear_congruential<_UIntType, __a, __c, __m>::result_type
-    linear_congruential<_UIntType, __a, __c, __m>::
-    max() const
-    { return (__m == 0) ? std::numeric_limits<_UIntType>::max() : (__m - 1); }
-
-  /**
    * Gets the next generated value in sequence.
    */
   template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>