From f84ca6e7cefa1c2fdcfc1cc37c6bbbaa4877154f Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Sat, 14 Apr 2012 22:33:22 +0000 Subject: [PATCH] re PR libstdc++/52699 (infinite loop generated with -O0) 2012-04-14 Paolo Carlini 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 --- libstdc++-v3/ChangeLog | 15 ++++++ libstdc++-v3/include/bits/random.tcc | 68 ++++++++++++++++-------- 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 f4d4c1fd471..97b091a52d4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,18 @@ +2012-04-14 Paolo Carlini + + 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 PR libstdc++/52839 diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index d55b51838b8..5da353f8bd4 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(_M_b.max()) - - static_cast(_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::type __urngtype; + typedef typename _UniformRandomNumberGenerator::result_type + _Gresult_type; typedef typename std::make_unsigned::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 4e6e0f49c5b..1ccf8604f5f 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