Commit 7849b3de by Paolo Carlini Committed by Paolo Carlini

random (bernoulli_distribution::operator()): Fix wrt generators returning integers.

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.

From-SVN: r116402
parent 4eb585a4
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> 2006-08-22 Phillip Jordan <phillip.m.jordan@gmail.com>
*include/tr1/boost_shared_ptr.h: Added locking policy to *include/tr1/boost_shared_ptr.h: Added locking policy to
......
...@@ -67,15 +67,11 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -67,15 +67,11 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
// Type selectors -- are these already implemented elsewhere? // Type selectors -- are these already implemented elsewhere?
template<bool, typename _TpTrue, typename _TpFalse> template<bool, typename _TpTrue, typename _TpFalse>
struct _Select struct _Select
{ { typedef _TpTrue _Type; };
typedef _TpTrue _Type;
};
template<typename _TpTrue, typename _TpFalse> template<typename _TpTrue, typename _TpFalse>
struct _Select<false, _TpTrue, _TpFalse> struct _Select<false, _TpTrue, _TpFalse>
{ { typedef _TpFalse _Type; };
typedef _TpFalse _Type;
};
template<typename _UIntType, int __w, bool = template<typename _UIntType, int __w, bool =
__w < std::numeric_limits<_UIntType>::digits> __w < std::numeric_limits<_UIntType>::digits>
...@@ -86,27 +82,18 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -86,27 +82,18 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
struct _Shift<_UIntType, __w, true> struct _Shift<_UIntType, __w, true>
{ static const _UIntType __value = _UIntType(1) << __w; }; { static const _UIntType __value = _UIntType(1) << __w; };
template<typename _ValueT> template<typename _Tp, _Tp __a, _Tp __c, _Tp __m, bool>
struct _To_Unsigned_Type struct _Mod;
{ typedef _ValueT _Type; };
template<>
struct _To_Unsigned_Type<short>
{ typedef unsigned short _Type; };
template<> // Dispatch based on modulus value to prevent divide-by-zero compile-time
struct _To_Unsigned_Type<int> // errors when m == 0.
{ typedef unsigned int _Type; }; 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<> template<typename _ValueT>
struct _To_Unsigned_Type<long> struct _To_Unsigned_Type;
{ typedef unsigned long _Type; };
#ifdef _GLIBCXX_USE_LONG_LONG
template<>
struct _To_Unsigned_Type<long long>
{ typedef unsigned long long _Type; };
#endif
typedef _Select<(sizeof(unsigned) == 4), typedef _Select<(sizeof(unsigned) == 4),
unsigned, unsigned long>::_Type _UInt32Type; unsigned, unsigned long>::_Type _UInt32Type;
...@@ -127,6 +114,30 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -127,6 +114,30 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
: _M_g(__g) { } : _M_g(__g) { }
result_type 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()(); operator()();
private: private:
...@@ -151,11 +162,11 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -151,11 +162,11 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
__return_value = _M_g(); __return_value = _M_g();
else if (is_integral<_Engine_result_type>::value else if (is_integral<_Engine_result_type>::value
&& !is_integral<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)); / result_type(_M_g.max() - _M_g.min() + result_type(1));
else if (!is_integral<_Engine_result_type>::value else if (!is_integral<_Engine_result_type>::value
&& !is_integral<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(_M_g.max() - _M_g.min());
return __return_value; return __return_value;
} }
...@@ -177,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -177,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
public: public:
typedef _Engine engine_type; typedef _Engine engine_type;
typedef _Adaptor<_Engine, _Dist> engine_value_type; typedef _Adaptor<_Engine, _Dist> engine_value_type;
typedef _Dist distribution_type; typedef _Dist distribution_type;
typedef typename _Dist::result_type result_type; typedef typename _Dist::result_type result_type;
...@@ -372,15 +383,20 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -372,15 +383,20 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
/** /**
* Gets the smallest possible value in the output range. * 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 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. * Gets the largest possible value in the output range.
*/ */
result_type result_type
max() const; max() const
{ return __m - 1; }
/** /**
* Gets the next random number in the sequence. * Gets the next random number in the sequence.
...@@ -1391,6 +1407,8 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1391,6 +1407,8 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
base2() const base2() const
{ return _M_b2; } { return _M_b2; }
// FIXME: Cannot be always correct. FWIW, the solution in N2032
// in practice isn't much better..
result_type result_type
min() const min() const
{ return _M_b1.min() ^ _M_b2.min(); } { return _M_b1.min() ^ _M_b2.min(); }
...@@ -1651,7 +1669,12 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1651,7 +1669,12 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
template<typename _UniformRandomNumberGenerator> template<typename _UniformRandomNumberGenerator>
result_type result_type
operator()(_UniformRandomNumberGenerator& __urng) 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$. * Gets a uniform random number in the range @f$[0, n)@f$.
...@@ -1661,7 +1684,12 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1661,7 +1684,12 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
template<typename _UniformRandomNumberGenerator> template<typename _UniformRandomNumberGenerator>
result_type result_type
operator()(_UniformRandomNumberGenerator& __urng, result_type __n) 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 * Inserts a %uniform_int random number distribution @p __x into the
...@@ -1693,6 +1721,22 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1693,6 +1721,22 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
uniform_int<_IntType1>& __x); uniform_int<_IntType1>& __x);
private: 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_min;
_IntType _M_max; _IntType _M_max;
}; };
...@@ -1753,7 +1797,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -1753,7 +1797,7 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
result_type result_type
operator()(_UniformRandomNumberGenerator& __urng) operator()(_UniformRandomNumberGenerator& __urng)
{ {
if (__urng() < _M_p) if ((__urng() - __urng.min()) < _M_p * (__urng.max() - __urng.min()))
return true; return true;
return false; return false;
} }
......
...@@ -87,12 +87,27 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -87,12 +87,27 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1)
{ return __a * __x + __c; } { return __a * __x + __c; }
}; };
// Dispatch based on modulus value to prevent divide-by-zero compile-time template<typename _ValueT>
// errors when m == 0. struct _To_Unsigned_Type
template<typename _Tp, _Tp __a, _Tp __c, _Tp __m> { typedef _ValueT _Type; };
inline _Tp
__mod(_Tp __x) template<>
{ return _Mod<_Tp, __a, __c, __m, __m == 0>::__calc(__x); } 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. // See N1822.
template<typename _RealType> template<typename _RealType>
...@@ -138,31 +153,6 @@ _GLIBCXX_BEGIN_NAMESPACE(tr1) ...@@ -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. * Gets the next generated value in sequence.
*/ */
template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m> template<class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment