This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[v3] Improve uniform_int<>::_M_call(..., true_type)


Hi,

tested x86_64-linux, committed to mainline.

Paolo.

////////////////
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.
Index: include/tr1_impl/random
===================================================================
--- include/tr1_impl/random	(revision 129768)
+++ include/tr1_impl/random	(working copy)
@@ -1603,17 +1603,7 @@
       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: include/tr1_impl/random.tcc
===================================================================
--- include/tr1_impl/random.tcc	(revision 129768)
+++ include/tr1_impl/random.tcc	(working copy)
@@ -750,6 +750,40 @@
     }
 
 
+  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,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]