diff options
author | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-04-29 23:36:09 +0000 |
---|---|---|
committer | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-04-29 23:36:09 +0000 |
commit | 1a5394ea56c7d8d0857892d32f08e99c9e9cedca (patch) | |
tree | 9adf35dcdbd754a14ae986576a07b43387e41d70 /libstdc++-v3/include/bits/random.h | |
parent | 3b630ea10b6aaef9f85d08259caf8def31de1902 (diff) | |
download | gcc-1a5394ea56c7d8d0857892d32f08e99c9e9cedca.tar.gz |
2012-04-29 Marc Glisse <marc.glisse@inria.fr>
Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/51795
* include/bits/stl_algobase.h (__lg<>(_Size)): Remove.
(__lg(int), __lg(unsigned), __lg(long), __lg(unsigned long),
__lg(long long), __lg(unsigned long long)): Define constexpr.
* include/bits/random.h (_Mod<>): Overcome Schrage's algorithm
limitations.
(__mod): Adjust.
(linear_congruential): Remove FIXME static_assert.
* include/bits/random.tcc (_Mod<>): Adjust.
* testsuite/26_numerics/random/linear_congruential_engine/operators/
51795.cc: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186948 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3/include/bits/random.h')
-rw-r--r-- | libstdc++-v3/include/bits/random.h | 78 |
1 files changed, 68 insertions, 10 deletions
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 8f6bf4f7bd5..4361296bca0 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -76,15 +76,78 @@ _GLIBCXX_END_NAMESPACE_VERSION struct _Shift<_UIntType, __w, true> { static const _UIntType __value = _UIntType(1) << __w; }; - template<typename _Tp, _Tp __m, _Tp __a, _Tp __c, bool> - struct _Mod; + template<int __s, + int __which = ((__s <= __CHAR_BIT__ * sizeof (int)) + + (__s <= __CHAR_BIT__ * sizeof (long)) + + (__s <= __CHAR_BIT__ * sizeof (long long)) + /* assume long long no bigger than __int128 */ + + (__s <= 128))> + struct _Select_uint_least_t + { + static_assert(__which < 0, /* needs to be dependent */ + "sorry, would be too much trouble for a slow result"); + }; + + template<int __s> + struct _Select_uint_least_t<__s, 4> + { typedef unsigned int type; }; + + template<int __s> + struct _Select_uint_least_t<__s, 3> + { typedef unsigned long type; }; + + template<int __s> + struct _Select_uint_least_t<__s, 2> + { typedef unsigned long long type; }; + +#ifdef _GLIBCXX_USE_INT128 + template<int __s> + struct _Select_uint_least_t<__s, 1> + { typedef unsigned __int128 type; }; +#endif + + // Assume a != 0, a < m, c < m, x < m. + template<typename _Tp, _Tp __m, _Tp __a, _Tp __c, + bool __big_enough = (!(__m & (__m - 1)) + || (_Tp(-1) - __c) / __a >= __m - 1), + bool __schrage_ok = __m % __a < __m / __a> + struct _Mod + { + typedef typename _Select_uint_least_t<std::__lg(__a) + + std::__lg(__m) + 2>::type _Tp2; + static _Tp + __calc(_Tp __x) + { return static_cast<_Tp>((_Tp2(__a) * __x + __c) % __m); } + }; + + // Schrage. + template<typename _Tp, _Tp __m, _Tp __a, _Tp __c> + struct _Mod<_Tp, __m, __a, __c, false, true> + { + static _Tp + __calc(_Tp __x); + }; + + // Special cases: + // - for m == 2^n or m == 0, unsigned integer overflow is safe. + // - a * (m - 1) + c fits in _Tp, there is no overflow. + template<typename _Tp, _Tp __m, _Tp __a, _Tp __c, bool __s> + struct _Mod<_Tp, __m, __a, __c, true, __s> + { + static _Tp + __calc(_Tp __x) + { + _Tp __res = __a * __x + __c; + if (__m) + __res %= __m; + return __res; + } + }; - // Dispatch based on modulus value to prevent divide-by-zero compile-time - // errors when m == 0. template<typename _Tp, _Tp __m, _Tp __a = 1, _Tp __c = 0> inline _Tp __mod(_Tp __x) - { return _Mod<_Tp, __m, __a, __c, __m == 0>::__calc(__x); } + { return _Mod<_Tp, __m, __a, __c>::__calc(__x); } /* * An adaptor class for converting the output of any Generator into @@ -174,11 +237,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(__m == 0u || (__a < __m && __c < __m), "template argument substituting __m out of bounds"); - // XXX FIXME: - // _Mod::__calc should handle correctly __m % __a >= __m / __a too. - static_assert(__m % __a < __m / __a, - "sorry, not implemented yet: try a smaller 'a' constant"); - public: /** The type of the generated random value. */ typedef _UIntType result_type; |