{
/* 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;
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
__low = _Up(__product);
}
}
- return __product >> __gnu_cxx::__int_traits<_Up>::__digits;
+ return __product >> _Up_traits::__digits;
}
};
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());
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;
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());
{
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);