diff options
author | Paolo Carlini <paolo.carlini@oracle.com> | 2012-04-14 22:33:22 +0000 |
---|---|---|
committer | Paolo Carlini <paolo@gcc.gnu.org> | 2012-04-14 22:33:22 +0000 |
commit | f84ca6e7cefa1c2fdcfc1cc37c6bbbaa4877154f (patch) | |
tree | 8b420cece30584d28c1e8bb54f8329b5dfb328c3 /libstdc++-v3 | |
parent | 608dccd7ab68e19bcd61caad1161be7d8db10056 (diff) | |
download | gcc-f84ca6e7cefa1c2fdcfc1cc37c6bbbaa4877154f.zip gcc-f84ca6e7cefa1c2fdcfc1cc37c6bbbaa4877154f.tar.gz gcc-f84ca6e7cefa1c2fdcfc1cc37c6bbbaa4877154f.tar.bz2 |
re PR libstdc++/52699 (infinite loop generated with -O0)
2012-04-14 Paolo Carlini <paolo.carlini@oracle.com>
PR libstdc++/52699
* include/bits/random.tcc (independent_bits_engine<>::operator()())
Avoid various overflows; use common_type on result_type and
_RandomNumberEngine::result_type; avoid floating point computations;
other smaller tweaks.
* include/bits/random.tcc (uniform_int_distribution<>::operator())
Use common_type; assume _UniformRandomNumberGenerator::result_type
unsigned; tidy.
* include/bits/stl_algobase.h (__lg(unsigned), __lg(unsigned long),
__lg(unsigned long long)): Add.
From-SVN: r186456
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 15 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/random.tcc | 68 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_algobase.h | 12 |
3 files changed, 73 insertions, 22 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index f4d4c1f..97b091a 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,18 @@ +2012-04-14 Paolo Carlini <paolo.carlini@oracle.com> + + PR libstdc++/52699 + * include/bits/random.tcc (independent_bits_engine<>::operator()()) + Avoid various overflows; use common_type on result_type and + _RandomNumberEngine::result_type; avoid floating point computations; + other smaller tweaks. + + * include/bits/random.tcc (uniform_int_distribution<>::operator()) + Use common_type; assume _UniformRandomNumberGenerator::result_type + unsigned; tidy. + + * include/bits/stl_algobase.h (__lg(unsigned), __lg(unsigned long), + __lg(unsigned long long)): Add. + 2012-04-14 Alan Modra <amodra@gmail.com> PR libstdc++/52839 diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index d55b518..5da353f 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -730,40 +730,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION independent_bits_engine<_RandomNumberEngine, __w, _UIntType>:: operator()() { - const long double __r = static_cast<long double>(_M_b.max()) - - static_cast<long double>(_M_b.min()) + 1.0L; - const result_type __m = std::log(__r) / std::log(2.0L); - result_type __n, __n0, __y0, __y1, __s0, __s1; + typedef typename _RandomNumberEngine::result_type _Eresult_type; + const _Eresult_type __r + = (_M_b.max() - _M_b.min() < std::numeric_limits<_Eresult_type>::max() + ? _M_b.max() - _M_b.min() + 1 : 0); + const unsigned __edig = std::numeric_limits<_Eresult_type>::digits; + const unsigned __m = __r ? std::__lg(__r) : __edig; + + typedef typename std::common_type<_Eresult_type, result_type>::type + __ctype; + const unsigned __cdig = std::numeric_limits<__ctype>::digits; + + unsigned __n, __n0; + __ctype __s0, __s1, __y0, __y1; + for (size_t __i = 0; __i < 2; ++__i) { __n = (__w + __m - 1) / __m + __i; __n0 = __n - __w % __n; - const result_type __w0 = __w / __n; - const result_type __w1 = __w0 + 1; - __s0 = result_type(1) << __w0; - __s1 = result_type(1) << __w1; - __y0 = __s0 * (__r / __s0); - __y1 = __s1 * (__r / __s1); - if (__r - __y0 <= __y0 / __n) + const unsigned __w0 = __w / __n; // __w0 <= __m + + __s0 = 0; + __s1 = 0; + if (__w0 < __cdig) + { + __s0 = __ctype(1) << __w0; + __s1 = __s0 << 1; + } + + __y0 = 0; + __y1 = 0; + if (__r) + { + __y0 = __s0 * (__r / __s0); + if (__s1) + __y1 = __s1 * (__r / __s1); + + if (__r - __y0 <= __y0 / __n) + break; + } + else break; } result_type __sum = 0; for (size_t __k = 0; __k < __n0; ++__k) { - result_type __u; + __ctype __u; do __u = _M_b() - _M_b.min(); - while (__u >= __y0); - __sum = __s0 * __sum + __u % __s0; + while (__y0 && __u >= __y0); + __sum = __s0 * __sum + (__s0 ? __u % __s0 : __u); } for (size_t __k = __n0; __k < __n; ++__k) { - result_type __u; + __ctype __u; do __u = _M_b() - _M_b.min(); - while (__u >= __y1); - __sum = __s1 * __sum + __u % __s1; + while (__y1 && __u >= __y1); + __sum = __s1 * __sum + (__s1 ? __u % __s1 : __u); } return __sum; } @@ -840,12 +865,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator()(_UniformRandomNumberGenerator& __urng, const param_type& __param) { - typedef typename std::make_unsigned<typename - _UniformRandomNumberGenerator::result_type>::type __urngtype; + typedef typename _UniformRandomNumberGenerator::result_type + _Gresult_type; typedef typename std::make_unsigned<result_type>::type __utype; - typedef typename std::conditional<(sizeof(__urngtype) - > sizeof(__utype)), - __urngtype, __utype>::type __uctype; + typedef typename std::common_type<_Gresult_type, __utype>::type + __uctype; const __uctype __urngmin = __urng.min(); const __uctype __urngmax = __urng.max(); diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index 4e6e0f4..1ccf860 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -989,14 +989,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __lg(int __n) { return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } + inline unsigned + __lg(unsigned __n) + { return sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } + inline long __lg(long __n) { return sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } + inline unsigned long + __lg(unsigned long __n) + { return sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } + inline long long __lg(long long __n) { return sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } + inline unsigned long long + __lg(unsigned long long __n) + { return sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } + _GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_ALGO |