diff options
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/include/bits/uniform_int_dist.h | 52 |
1 files changed, 33 insertions, 19 deletions
diff --git a/libstdc++-v3/include/bits/uniform_int_dist.h b/libstdc++-v3/include/bits/uniform_int_dist.h index cf6ba35c675..524593bb984 100644 --- a/libstdc++-v3/include/bits/uniform_int_dist.h +++ b/libstdc++-v3/include/bits/uniform_int_dist.h @@ -58,7 +58,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { /* Determine whether number is a power of 2. */ template<typename _Tp> - inline bool + constexpr bool _Power_of_2(_Tp __x) { return ((__x - 1) & __x) == 0; @@ -242,9 +242,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static _Up _S_nd(_Urbg& __g, _Up __range) { - using __gnu_cxx::__int_traits; - static_assert(!__int_traits<_Up>::__is_signed, "U must be unsigned"); - static_assert(!__int_traits<_Wp>::__is_signed, "W must be unsigned"); + using _Up_traits = __gnu_cxx::__int_traits<_Up>; + using _Wp_traits = __gnu_cxx::__int_traits<_Wp>; + static_assert(!_Up_traits::__is_signed, "U must be unsigned"); + static_assert(!_Wp_traits::__is_signed, "W must be unsigned"); + static_assert(_Wp_traits::__digits == (2 * _Up_traits::__digits), + "W must be twice as wide as U"); // reference: Fast Random Integer Generation in an Interval // ACM Transactions on Modeling and Computer Simulation 29 (1), 2019 @@ -260,7 +263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __low = _Up(__product); } } - return __product >> __gnu_cxx::__int_traits<_Up>::__digits; + return __product >> _Up_traits::__digits; } }; @@ -275,9 +278,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename make_unsigned<result_type>::type __utype; typedef typename common_type<_Gresult_type, __utype>::type __uctype; - const __uctype __urngmin = __urng.min(); - const __uctype __urngmax = __urng.max(); - const __uctype __urngrange = __urngmax - __urngmin; + static_assert( __urng.min() < __urng.max(), + "Uniform random bit generator must define min() < max()"); + + constexpr __uctype __urngmin = __urng.min(); + constexpr __uctype __urngmax = __urng.max(); + constexpr __uctype __urngrange = __urngmax - __urngmin; const __uctype __urange = __uctype(__param.b()) - __uctype(__param.a()); @@ -288,21 +294,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const __uctype __uerange = __urange + 1; // __urange can be zero - using __gnu_cxx::__int_traits; +#if defined __UINT64_TYPE__ && defined __UINT32_TYPE__ #if __SIZEOF_INT128__ - if (__int_traits<__uctype>::__digits == 64 - && __urngrange == __int_traits<__uctype>::__max) + if _GLIBCXX17_CONSTEXPR (__urngrange == __UINT64_MAX__) { - __ret = _S_nd<unsigned __int128>(__urng, __uerange); + // __urng produces values that use exactly 64-bits, + // so use 128-bit integers to downscale to desired range. + __UINT64_TYPE__ __u64erange = __uerange; + __ret = _S_nd<unsigned __int128>(__urng, __u64erange); } else #endif - if (__int_traits<__uctype>::__digits == 32 - && __urngrange == __int_traits<__uctype>::__max) + if _GLIBCXX17_CONSTEXPR (__urngrange == __UINT32_MAX__) { - __ret = _S_nd<__UINT64_TYPE__>(__urng, __uerange); + // __urng produces values that use exactly 32-bits, + // so use 64-bit integers to downscale to desired range. + __UINT32_TYPE__ __u32erange = __uerange; + __ret = _S_nd<__UINT64_TYPE__>(__urng, __u32erange); } else +#endif { // fallback case (2 divisions) const __uctype __scaling = __urngrange / __uerange; @@ -361,9 +372,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename make_unsigned<result_type>::type __utype; typedef typename common_type<_Gresult_type, __utype>::type __uctype; - const __uctype __urngmin = __urng.min(); - const __uctype __urngmax = __urng.max(); - const __uctype __urngrange = __urngmax - __urngmin; + static_assert( __urng.min() < __urng.max(), + "Uniform random bit generator must define min() < max()"); + + constexpr __uctype __urngmin = __urng.min(); + constexpr __uctype __urngmax = __urng.max(); + constexpr __uctype __urngrange = __urngmax - __urngmin; const __uctype __urange = __uctype(__param.b()) - __uctype(__param.a()); @@ -417,7 +431,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { do { - const __uctype __uerngrange = __urngrange + 1; + constexpr __uctype __uerngrange = __urngrange + 1; __tmp = (__uerngrange * operator() (__urng, param_type(0, __urange / __uerngrange))); __ret = __tmp + (__uctype(__urng()) - __urngmin); |