re PR libstdc++/33815 (tr1::uniform_int isn't uniform)
authorPaolo Carlini <paolo@gcc.gnu.org>
Tue, 30 Oct 2007 13:05:26 +0000 (13:05 +0000)
committerPaolo Carlini <paolo@gcc.gnu.org>
Tue, 30 Oct 2007 13:05:26 +0000 (13:05 +0000)
2007-10-19  Paolo Carlini  <pcarlini@suse.de>

PR libstdc++/33815
* include/tr1_impl/random
(uniform_int<>::_M_call(_UniformRandomNumberGenerator&, result_type,
result_type, true_type)): Avoid the modulo (which uses the low-order
bits).

From-SVN: r129769

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

index 847b69e71d8a68f9449b074276e3e26141e69d3f..2b783daf8bb7321e8a43634672351dbb1da6275a 100644 (file)
@@ -1,21 +1,31 @@
+2007-10-30  Paolo Carlini  <pcarlini@suse.de>
+
+       * include/tr1_impl/random (uniform_int<>::
+       _M_call(_UniformRandomNumberGenerator&, result_type, result_type,
+       true_type)): Only declare.
+       * include/tr1_impl/random.tcc (uniform_int<>::
+       _M_call(_UniformRandomNumberGenerator&, result_type, result_type,
+       true_type)): Re-do, unbiased for the currently supported ranges;
+       add comment.
+
 2007-10-30  Benjamin Kosnik  <bkoz@redhat.com>
 
-       *docs/html/ext/pb_ds/multimap_text_insert_timing_test_small.html:
+       * docs/html/ext/pb_ds/multimap_text_insert_timing_test_small.html:
        Correct filename.       
-       *docs/html/ext/pb_ds/multimap_text_find_timing_test_large.html: Same.
-       *docs/html/ext/pb_ds/
+       * docs/html/ext/pb_ds/multimap_text_find_timing_test_large.html: Same.
+       * docs/html/ext/pb_ds/
        multimap_text_insert_mem_usage_test_small.html: Same.
-       *docs/html/ext/pb_ds/multimap_text_insert_timing_test_large.html: Same.
-       *docs/html/ext/pb_ds/
+       * docs/html/ext/pb_ds/multimap_text_insert_timing_test_large.html: Same.
+       * docs/html/ext/pb_ds/
        multimap_text_insert_mem_usage_test_large.html: Same.
-       *docs/html/ext/pb_ds/multimap_text_find_timing_test_small.html: Same.
+       * docs/html/ext/pb_ds/multimap_text_find_timing_test_small.html: Same.
 
 2007-10-30  Benjamin Kosnik  <bkoz@redhat.com>
        
-       *include/Makefile.am (PCHFLAGS): Remove -Wno-deprecated.
-       *include/Makefile.in: Regenerate.
-       
-       *include/std/memory: Remove extraneous include. 
+       * include/Makefile.am (PCHFLAGS): Remove -Wno-deprecated.
+       * include/Makefile.in: Regenerate.
+
+       * include/std/memory: Remove extraneous include.        
 
 2007-10-29  Benjamin Kosnik  <bkoz@redhat.com>
  
index 7b9b951f74a1c7c6a36cf8152b7e8cba69096e3f..4ce7d8b4c47bc375c3a39e2684dfb062e6e1fcff 100644 (file)
@@ -1603,17 +1603,7 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
       template<typename _UniformRandomNumberGenerator>
         result_type
         _M_call(_UniformRandomNumberGenerator& __urng,
-               result_type __min, result_type __max, true_type)
-        {
-         // XXX Must be fixed to also work when __urng.max() - __urng.min()
-         // is smaller than __max - __min.
-         typedef typename __gnu_cxx::__add_unsigned<typename
-           _UniformRandomNumberGenerator::result_type>::__type __utype;
-         return result_type((__max - __min + 1.0L)
-                            * (__utype(__urng()) - __utype(__urng.min()))
-                            / (__utype(__urng.max())
-                               - __utype(__urng.min()) + 1.0L)) + __min;
-       }
+               result_type __min, result_type __max, true_type);
 
       template<typename _UniformRandomNumberGenerator>
         result_type
index e57d609ef5e83cf0ae39d815eb955a62537b40f4..2b0f6957b14da99b6ef49cbb6f6bae9d9a7e16fb 100644 (file)
@@ -750,6 +750,40 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
     }
 
 
+  template<typename _IntType>
+    template<typename _UniformRandomNumberGenerator>
+      typename uniform_int<_IntType>::result_type
+      uniform_int<_IntType>::
+      _M_call(_UniformRandomNumberGenerator& __urng,
+             result_type __min, result_type __max, true_type)
+      {
+       // XXX Must be fixed to work well for *arbitrary* __urng.max(),
+       // __urng.min(), __max, __min.  Currently works fine only in the
+       // most common case __urng.max() - __urng.min() >= __max - __min,
+       // with __urng.max() > __urng.min() >= 0.
+       typedef typename __gnu_cxx::__add_unsigned<typename
+         _UniformRandomNumberGenerator::result_type>::__type __urntype;
+       typedef typename __gnu_cxx::__add_unsigned<result_type>::__type
+                                                             __utype;
+       typedef typename __gnu_cxx::__conditional_type<(sizeof(__urntype)
+                                                       > sizeof(__utype)),
+         __urntype, __utype>::__type                         __uctype;
+
+       result_type __ret;
+
+       const __urntype __urnmin = __urng.min();
+       const __urntype __urnmax = __urng.max();
+       const __urntype __urnrange = __urnmax - __urnmin;
+       const __uctype __urange = __max - __min;
+       const __uctype __udenom = (__urnrange <= __urange
+                                  ? 1 : __urnrange / (__urange + 1));
+       do
+         __ret = (__urntype(__urng()) -  __urnmin) / __udenom;
+       while (__ret > __max - __min);
+
+       return __ret + __min;
+      }
+
   template<typename _IntType, typename _CharT, typename _Traits>
     std::basic_ostream<_CharT, _Traits>&
     operator<<(std::basic_ostream<_CharT, _Traits>& __os,