random (xor_combine<>::_M_initialize_max_aux): New.
authorPaolo Carlini <pcarlini@suse.de>
Mon, 2 Oct 2006 00:12:50 +0000 (00:12 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Mon, 2 Oct 2006 00:12:50 +0000 (00:12 +0000)
2006-10-01  Paolo Carlini  <pcarlini@suse.de>

* include/tr1/random (xor_combine<>::_M_initialize_max_aux): New.
(xor_combine<>::operator()()): Tweak per N2079.
* include/tr1/random.tcc (xor_combine<>::_M_initialize_max_aux):
Define.
(xor_combine<>::_M_initialize_max): Use it.
* testsuite/tr1/5_numerical_facilities/random/xor_combine/
cons/default.cc: Adjust.
* docs/html/ext/tr1.html: Adjust.

From-SVN: r117353

libstdc++-v3/ChangeLog
libstdc++-v3/docs/html/ext/tr1.html
libstdc++-v3/include/tr1/random
libstdc++-v3/include/tr1/random.tcc
libstdc++-v3/testsuite/tr1/5_numerical_facilities/random/xor_combine/cons/default.cc

index 99eff89a130fcee917952366ee9707b27779dcb1..8115f0de8a4422e82fa0aca40e9ec5b8b9fdf757 100644 (file)
@@ -1,3 +1,14 @@
+2006-10-01  Paolo Carlini  <pcarlini@suse.de>
+
+       * include/tr1/random (xor_combine<>::_M_initialize_max_aux): New.
+       (xor_combine<>::operator()()): Tweak per N2079.
+       * include/tr1/random.tcc (xor_combine<>::_M_initialize_max_aux):
+       Define.
+       (xor_combine<>::_M_initialize_max): Use it.
+       * testsuite/tr1/5_numerical_facilities/random/xor_combine/
+       cons/default.cc: Adjust.
+       * docs/html/ext/tr1.html: Adjust.
+
 2006-10-01  Paolo Carlini  <pcarlini@suse.de>
 
        * include/ext/type_traits.h: Avoid _T, badname for some targets;
index 78f130dbafa555b5598318bdbf07a8be712f95b8..d8ae3971540c27aa1fe1f86d3fcaf21fbcd98825 100644 (file)
@@ -706,7 +706,7 @@ release.
       <td>done</td>
       <td></td>
       <td></td>
-      <td>Buggy min() and max()</td>
+      <td>operator()() per N2079</td>
     </tr>
     <tr>
       <td>5.1.5</td>
@@ -2307,7 +2307,7 @@ permitted in any medium, provided this notice is preserved.
 <table width="100%" border="0">
 <tr>
   <td>
-    <!-- IGNORE DIFF -->Last modified 2006-08-25
+    <!-- IGNORE DIFF -->Last modified 2006-10-01
   </td>
   <td align="right" valign="bottom">
     <a href="http://validator.w3.org/check/referer">
index 05286ee17ddf1af939312d5e2106ec9c3531b17e..543378ea9e9e1735e2ed06c03428c750a27a52a6 100644 (file)
@@ -1262,7 +1262,8 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
 
     public:
       /** The type of the generated random value. */
-      typedef typename __gnu_cxx::__conditional_type<(sizeof(_Result_type1) > sizeof(_Result_type2)),
+      typedef typename __gnu_cxx::__conditional_type<(sizeof(_Result_type1)
+                                                     > sizeof(_Result_type2)),
        _Result_type1, _Result_type2>::__type result_type;
 
       // parameter values
@@ -1310,7 +1311,6 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       base2() const
       { return _M_b2; }
 
-      // XXX Per N2032, but aren't always right...
       result_type
       min() const
       { return 0; }
@@ -1322,9 +1322,13 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       /**
        * Gets the next random number in the sequence.
        */
+      // NB: Not exactly the TR1 formula, per N2079 instead.
       result_type
       operator()()
-      { return ((_M_b1() << shift1) ^ (_M_b2() << shift2)); }
+      {
+       return ((result_type(_M_b1() - _M_b1.min()) << shift1)
+               ^ (result_type(_M_b2() - _M_b2.min()) << shift2));
+      }
 
       /**
        * Compares two %xor_combine random number generator objects of
@@ -1397,6 +1401,9 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
       void
       _M_initialize_max();
 
+      result_type
+      _M_initialize_max_aux(result_type, result_type, int);
+
       base1_type  _M_b1;
       base2_type  _M_b2;
       result_type _M_max;
index fd052feb274908a78eec6cb183fb08f2ad931594..46d73dad56e3360d5c60d6e77572e6bd1a263959 100644 (file)
@@ -619,30 +619,59 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
                _UniformRandomNumberGenerator2, __s2>::
     _M_initialize_max()
     {
-      const int __lshift = std::abs(__s1 - __s2);
+      const int __w = std::numeric_limits<result_type>::digits;
 
-      result_type __m1 = _M_b1.max() - _M_b1.min();
-      result_type __m2 = _M_b2.max() - _M_b2.min();
+      const result_type __m1 =
+       std::min(result_type(_M_b1.max() - _M_b1.min()),
+                _Shift<result_type, __w - __s1>::__value - 1);
 
-      // NB: in TR1 s1 is not required to be >= s2.
-      if (__s1 >= __s2)
-       __m1 <<= __lshift;
+      const result_type __m2 =
+       std::min(result_type(_M_b2.max() - _M_b2.min()),
+                _Shift<result_type, __w - __s2>::__value - 1);
+
+      // NB: In TR1 s1 is not required to be >= s2.
+      if (__s1 < __s2)
+       _M_max = _M_initialize_max_aux(__m2, __m1, __s2 - __s1) << __s1;
       else
-       __m2 <<= __lshift;
+       _M_max = _M_initialize_max_aux(__m1, __m2, __s1 - __s2) << __s2;
+    }
+
+  template<class _UniformRandomNumberGenerator1, int __s1,
+          class _UniformRandomNumberGenerator2, int __s2>
+    typename xor_combine<_UniformRandomNumberGenerator1, __s1,
+                        _UniformRandomNumberGenerator2, __s2>::result_type
+    xor_combine<_UniformRandomNumberGenerator1, __s1,
+               _UniformRandomNumberGenerator2, __s2>::
+    _M_initialize_max_aux(result_type __a, result_type __b, int __d)
+    {
+      const result_type __two2d = result_type(1) << __d;
+      const result_type __c = __a * __two2d;
 
-      result_type __a = __m1 & __m2;
-      const result_type __b = __m1 | __m2;      
+      if (__a == 0 || __b < __two2d)
+       return __c + __b;
 
-      result_type __c = 0;
-      if (__a)
-       {
-         result_type __k;
-         for (__k = 0; __a != 1; __a >>= 1)
-           ++__k;
-         __c = (result_type(1) << __k) - 1;
-       }
+      const result_type __t = std::max(__c, __b);
+      const result_type __u = std::min(__c, __b);
+
+      result_type __ub = __u;
+      result_type __p;
+      for (__p = 0; __ub != 1; __ub >>= 1)
+       ++__p;
 
-      _M_max = (__c | __b) << __lshift; 
+      const result_type __two2p = result_type(1) << __p;
+      const result_type __k = __t / __two2p;
+
+      if (__k & 1)
+       return (__k + 1) * __two2p - 1;
+
+      if (__c >= __b)
+       return (__k + 1) * __two2p + _M_initialize_max_aux((__t % __two2p)
+                                                          / __two2d,
+                                                          __u % __two2p, __d);
+      else
+       return (__k + 1) * __two2p + _M_initialize_max_aux((__u % __two2p)
+                                                          / __two2d,
+                                                          __t % __two2p, __d);
     }
 
   template<class _UniformRandomNumberGenerator1, int __s1,
@@ -852,7 +881,8 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
                      continue;
                  }
                else if (__u <= __c3)
-                 // XXX This case not in the book, nor in the Errata...
+                 // NB: This case not in the book, nor in the Errata,
+                 // but should be ok...
                  __x = -1;
                else if (__u <= __c4)
                  __x = 0;
index 5ac01b8dd81ff118dd950606fd7f6e0d374dd24b..83ff51b5b97d3343db616931e3d0069d3b5f5e86 100644 (file)
@@ -36,7 +36,7 @@ test01()
     minstd_rand0, 2
     > x;
 
-  VERIFY( x() == 32642 );
+  VERIFY( x() == 32644 );
 }
 
 int main()