diff options
author | Paolo Carlini <pcarlini@suse.de> | 2006-08-25 16:02:23 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2006-08-25 16:02:23 +0000 |
commit | 7849b3de894a9e76cff084f4cd58c28c722b8713 (patch) | |
tree | 2706929ee99b7642eb8d567ba87f98f03c731103 /libstdc++-v3/include | |
parent | 4eb585a4731413faa3ed0f224674ff31c7ab7a76 (diff) | |
download | gcc-7849b3de894a9e76cff084f4cd58c28c722b8713.zip gcc-7849b3de894a9e76cff084f4cd58c28c722b8713.tar.gz gcc-7849b3de894a9e76cff084f4cd58c28c722b8713.tar.bz2 |
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
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/tr1/random | 110 | ||||
-rw-r--r-- | libstdc++-v3/include/tr1/random.tcc | 52 |
2 files changed, 98 insertions, 64 deletions
diff --git a/libstdc++-v3/include/tr1/random b/libstdc++-v3/include/tr1/random index 41e010a..b90d323 100644 --- a/libstdc++-v3/include/tr1/random +++ b/libstdc++-v3/include/tr1/random @@ -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; } diff --git a/libstdc++-v3/include/tr1/random.tcc b/libstdc++-v3/include/tr1/random.tcc index cbeb57d..b95a5f8 100644 --- a/libstdc++-v3/include/tr1/random.tcc +++ b/libstdc++-v3/include/tr1/random.tcc @@ -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> |