X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=libstdc%2B%2B-v3%2Finclude%2Fbits%2Frandom.tcc;h=f092b5cd4cbcd29c360c6c10c0284a63b94e9fb3;hb=83ffe9cde7fe0b4deb0d1b54175fd9b19c38179c;hp=0bbc9fd400d45798f49b642185b322341a6b9cb1;hpb=113b21bdaf45d2b80d1585b4b2c9cb20395667be;p=thirdparty%2Fgcc.git diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index 0bbc9fd400d4..f092b5cd4cbc 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -1,6 +1,6 @@ // random number generation (out of line) -*- C++ -*- -// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. +// Copyright (C) 2009-2023 Free Software Foundation, Inc. // // This file is part of the GNU ISO C++ Library. This library is free // software; you can redistribute it and/or modify it under the @@ -34,80 +34,64 @@ namespace std _GLIBCXX_VISIBILITY(default) { - /* - * (Further) implementation-space details. - */ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// @cond undocumented + // (Further) implementation-space details. namespace __detail { - _GLIBCXX_BEGIN_NAMESPACE_VERSION - - // General case for x = (ax + c) mod m -- use Schrage's algorithm to - // avoid integer overflow. - // - // Because a and c are compile-time integral constants the compiler - // kindly elides any unreachable paths. + // General case for x = (ax + c) mod m -- use Schrage's algorithm + // to avoid integer overflow. // // Preconditions: a > 0, m > 0. // - template - struct _Mod - { - static _Tp - __calc(_Tp __x) - { - if (__a == 1) - __x %= __m; - else - { - static const _Tp __q = __m / __a; - static const _Tp __r = __m % __a; - - _Tp __t1 = __a * (__x % __q); - _Tp __t2 = __r * (__x / __q); - if (__t1 >= __t2) - __x = __t1 - __t2; - else - __x = __m - __t2 + __t1; - } - - if (__c != 0) - { - const _Tp __d = __m - __x; - if (__d > __c) - __x += __c; - else - __x = __c - __d; - } - return __x; - } - }; - - // Special case for m == 0 -- use unsigned integer overflow as modulo - // operator. + // Note: only works correctly for __m % __a < __m / __a. template - struct _Mod<_Tp, __m, __a, __c, true> + _Tp + _Mod<_Tp, __m, __a, __c, false, true>:: + __calc(_Tp __x) { - static _Tp - __calc(_Tp __x) - { return __a * __x + __c; } - }; + if (__a == 1) + __x %= __m; + else + { + static const _Tp __q = __m / __a; + static const _Tp __r = __m % __a; + + _Tp __t1 = __a * (__x % __q); + _Tp __t2 = __r * (__x / __q); + if (__t1 >= __t2) + __x = __t1 - __t2; + else + __x = __m - __t2 + __t1; + } + + if (__c != 0) + { + const _Tp __d = __m - __x; + if (__d > __c) + __x += __c; + else + __x = __c - __d; + } + return __x; + } template + typename _Tp> _OutputIterator - __transform(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _UnaryOperation __unary_op) + __normalize(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, const _Tp& __factor) { for (; __first != __last; ++__first, ++__result) - *__result = __unary_op(*__first); + *__result = *__first / __factor; return __result; } - _GLIBCXX_END_NAMESPACE_VERSION } // namespace __detail + /// @endcond -_GLIBCXX_BEGIN_NAMESPACE_VERSION - +#if ! __cpp_inline_variables template constexpr _UIntType linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier; @@ -123,6 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template constexpr _UIntType linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed; +#endif /** * Seeds the LCR with integral value @p __s, adjusted so that the @@ -145,9 +130,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ template template - typename std::enable_if::value>::type + auto linear_congruential_engine<_UIntType, __a, __c, __m>:: seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> { const _UIntType __k0 = __m == 0 ? std::numeric_limits<_UIntType>::digits : std::__lg(__m); @@ -171,8 +157,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const linear_congruential_engine<_UIntType, __a, __c, __m>& __lcr) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -192,8 +177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_UIntType, __a, __c, __m>& __lcr) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec); @@ -204,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __is; } - +#if ! __cpp_inline_variables template::default_seed; +#endif template template - typename std::enable_if::value>::type + auto mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>:: seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> { const _UIntType __upper_mask = (~_UIntType()) << __r; const size_t __k = (__w + 31) / 32; @@ -399,8 +385,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } if (__zero) _M_x[0] = __detail::_Shift<_UIntType, __w - 1>::__value; + _M_p = state_size; } + template + void + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + _M_gen_rand(void) + { + const _UIntType __upper_mask = (~_UIntType()) << __r; + const _UIntType __lower_mask = ~__upper_mask; + + for (size_t __k = 0; __k < (__n - __m); ++__k) + { + _UIntType __y = ((_M_x[__k] & __upper_mask) + | (_M_x[__k + 1] & __lower_mask)); + _M_x[__k] = (_M_x[__k + __m] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + } + + for (size_t __k = (__n - __m); __k < (__n - 1); ++__k) + { + _UIntType __y = ((_M_x[__k] & __upper_mask) + | (_M_x[__k + 1] & __lower_mask)); + _M_x[__k] = (_M_x[__k + (__m - __n)] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + } + + _UIntType __y = ((_M_x[__n - 1] & __upper_mask) + | (_M_x[0] & __lower_mask)); + _M_x[__n - 1] = (_M_x[__m - 1] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + _M_p = 0; + } + + template + void + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + discard(unsigned long long __z) + { + while (__z > state_size - _M_p) + { + __z -= state_size - _M_p; + _M_gen_rand(); + } + _M_p += __z; + } + template= state_size) - { - const _UIntType __upper_mask = (~_UIntType()) << __r; - const _UIntType __lower_mask = ~__upper_mask; - - for (size_t __k = 0; __k < (__n - __m); ++__k) - { - _UIntType __y = ((_M_x[__k] & __upper_mask) - | (_M_x[__k + 1] & __lower_mask)); - _M_x[__k] = (_M_x[__k + __m] ^ (__y >> 1) - ^ ((__y & 0x01) ? __a : 0)); - } - - for (size_t __k = (__n - __m); __k < (__n - 1); ++__k) - { - _UIntType __y = ((_M_x[__k] & __upper_mask) - | (_M_x[__k + 1] & __lower_mask)); - _M_x[__k] = (_M_x[__k + (__m - __n)] ^ (__y >> 1) - ^ ((__y & 0x01) ? __a : 0)); - } - - _UIntType __y = ((_M_x[__n - 1] & __upper_mask) - | (_M_x[0] & __lower_mask)); - _M_x[__n - 1] = (_M_x[__m - 1] ^ (__y >> 1) - ^ ((__y & 0x01) ? __a : 0)); - _M_p = 0; - } + _M_gen_rand(); // Calculate o(x(i)). result_type __z = _M_x[_M_p++]; @@ -462,8 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -471,9 +486,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __os.flags(__ios_base::dec | __ios_base::fixed | __ios_base::left); __os.fill(__space); - for (size_t __i = 0; __i < __n - 1; ++__i) + for (size_t __i = 0; __i < __n; ++__i) __os << __x._M_x[__i] << __space; - __os << __x._M_x[__n - 1]; + __os << __x._M_p; __os.flags(__flags); __os.fill(__fill); @@ -490,20 +505,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); for (size_t __i = 0; __i < __n; ++__i) __is >> __x._M_x[__i]; + __is >> __x._M_p; __is.flags(__flags); return __is; } - +#if ! __cpp_inline_variables template constexpr size_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::word_size; @@ -517,15 +532,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION subtract_with_carry_engine<_UIntType, __w, __s, __r>::long_lag; template - constexpr _UIntType + constexpr uint_least32_t subtract_with_carry_engine<_UIntType, __w, __s, __r>::default_seed; +#endif template void subtract_with_carry_engine<_UIntType, __w, __s, __r>:: seed(result_type __value) { - std::linear_congruential_engine + std::linear_congruential_engine __lcg(__value == 0u ? default_seed : __value); const size_t __n = (__w + 31) / 32; @@ -550,9 +566,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template template - typename std::enable_if::value>::type + auto subtract_with_carry_engine<_UIntType, __w, __s, __r>:: seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> { const size_t __k = (__w + 31) / 32; uint_least32_t __arr[__r * __k]; @@ -616,8 +633,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const subtract_with_carry_engine<_UIntType, __w, __s, __r>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -627,7 +643,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION for (size_t __i = 0; __i < __r; ++__i) __os << __x._M_x[__i] << __space; - __os << __x._M_carry; + __os << __x._M_carry << __space << __x._M_p; __os.flags(__flags); __os.fill(__fill); @@ -640,8 +656,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, subtract_with_carry_engine<_UIntType, __w, __s, __r>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); @@ -649,12 +664,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION for (size_t __i = 0; __i < __r; ++__i) __is >> __x._M_x[__i]; __is >> __x._M_carry; + __is >> __x._M_p; __is.flags(__flags); return __is; } - +#if ! __cpp_inline_variables template constexpr size_t discard_block_engine<_RandomNumberEngine, __p, __r>::block_size; @@ -662,6 +678,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template constexpr size_t discard_block_engine<_RandomNumberEngine, __p, __r>::used_block; +#endif template typename discard_block_engine<_RandomNumberEngine, @@ -685,8 +702,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const discard_block_engine<_RandomNumberEngine, __p, __r>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -707,8 +723,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, discard_block_engine<_RandomNumberEngine, __p, __r>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); @@ -726,56 +741,116 @@ _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; } - +#if ! __cpp_inline_variables template constexpr size_t shuffle_order_engine<_RandomNumberEngine, __k>::table_size; +#endif + + namespace __detail + { + // Determine whether an integer is representable as double. + template + constexpr bool + __representable_as_double(_Tp __x) noexcept + { + static_assert(numeric_limits<_Tp>::is_integer, ""); + static_assert(!numeric_limits<_Tp>::is_signed, ""); + // All integers <= 2^53 are representable. + return (__x <= (1ull << __DBL_MANT_DIG__)) + // Between 2^53 and 2^54 only even numbers are representable. + || (!(__x & 1) && __detail::__representable_as_double(__x >> 1)); + } + + // Determine whether x+1 is representable as double. + template + constexpr bool + __p1_representable_as_double(_Tp __x) noexcept + { + static_assert(numeric_limits<_Tp>::is_integer, ""); + static_assert(!numeric_limits<_Tp>::is_signed, ""); + return numeric_limits<_Tp>::digits < __DBL_MANT_DIG__ + || (bool(__x + 1u) // return false if x+1 wraps around to zero + && __detail::__representable_as_double(__x + 1u)); + } + } template typename shuffle_order_engine<_RandomNumberEngine, __k>::result_type shuffle_order_engine<_RandomNumberEngine, __k>:: operator()() { - size_t __j = __k * ((_M_y - _M_b.min()) - / (_M_b.max() - _M_b.min() + 1.0L)); + constexpr result_type __range = max() - min(); + size_t __j = __k; + const result_type __y = _M_y - min(); + // Avoid using slower long double arithmetic if possible. + if _GLIBCXX17_CONSTEXPR (__detail::__p1_representable_as_double(__range)) + __j *= __y / (__range + 1.0); + else + __j *= __y / (__range + 1.0L); _M_y = _M_v[__j]; _M_v[__j] = _M_b(); @@ -788,8 +863,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator<<(std::basic_ostream<_CharT, _Traits>& __os, const shuffle_order_engine<_RandomNumberEngine, __k>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -813,8 +887,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, shuffle_order_engine<_RandomNumberEngine, __k>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); @@ -829,79 +902,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } - template - template - typename uniform_int_distribution<_IntType>::result_type - uniform_int_distribution<_IntType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - typedef typename std::make_unsigned::type __urngtype; - typedef typename std::make_unsigned::type __utype; - typedef typename std::conditional<(sizeof(__urngtype) - > sizeof(__utype)), - __urngtype, __utype>::type __uctype; - - const __uctype __urngmin = __urng.min(); - const __uctype __urngmax = __urng.max(); - const __uctype __urngrange = __urngmax - __urngmin; - const __uctype __urange - = __uctype(__param.b()) - __uctype(__param.a()); - - __uctype __ret; - - if (__urngrange > __urange) - { - // downscaling - const __uctype __uerange = __urange + 1; // __urange can be zero - const __uctype __scaling = __urngrange / __uerange; - const __uctype __past = __uerange * __scaling; - do - __ret = __uctype(__urng()) - __urngmin; - while (__ret >= __past); - __ret /= __scaling; - } - else if (__urngrange < __urange) - { - // upscaling - /* - Note that every value in [0, urange] - can be written uniquely as - - (urngrange + 1) * high + low - - where - - high in [0, urange / (urngrange + 1)] - - and - - low in [0, urngrange]. - */ - __uctype __tmp; // wraparound control - do - { - const __uctype __uerngrange = __urngrange + 1; - __tmp = (__uerngrange * operator() - (__urng, param_type(0, __urange / __uerngrange))); - __ret = __tmp + (__uctype(__urng()) - __urngmin); - } - while (__ret > __urange || __ret < __tmp); - } - else - __ret = __uctype(__urng()) - __urngmin; - - return __ret + __param.a(); - } - template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const uniform_int_distribution<_IntType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -921,29 +927,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, uniform_int_distribution<_IntType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename uniform_int_distribution<_IntType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _IntType __a, __b; - __is >> __a >> __b; - __x.param(typename uniform_int_distribution<_IntType>:: - param_type(__a, __b)); + if (__is >> __a >> __b) + __x.param(param_type(__a, __b)); __is.flags(__flags); return __is; } + template + template + void + uniform_real_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + auto __range = __p.b() - __p.a(); + while (__f != __t) + *__f++ = __aurng() * __range + __p.a(); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const uniform_real_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -966,29 +988,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, uniform_real_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename uniform_real_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::skipws); _RealType __a, __b; - __is >> __a >> __b; - __x.param(typename uniform_real_distribution<_RealType>:: - param_type(__a, __b)); + if (__is >> __a >> __b) + __x.param(param_type(__a, __b)); __is.flags(__flags); return __is; } + template + void + std::bernoulli_distribution:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + auto __limit = __p.p() * (__aurng.max() - __aurng.min()); + + while (__f != __t) + *__f++ = (__aurng() - __aurng.min()) < __limit; + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const bernoulli_distribution& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1025,20 +1063,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION double __cand; do - __cand = std::floor(std::log(__aurng()) / __param._M_log_1_p); + __cand = std::floor(std::log(1.0 - __aurng()) / __param._M_log_1_p); while (__cand >= __thr); return result_type(__cand + __naf); } + template + template + void + geometric_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // About the epsilon thing see this thread: + // http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00971.html + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + // The largest _RealType convertible to _IntType. + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + while (__f != __t) + { + double __cand; + do + __cand = std::floor(std::log(1.0 - __aurng()) + / __param._M_log_1_p); + while (__cand >= __thr); + + *__f++ = __cand + __naf; + } + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const geometric_distribution<_IntType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1061,21 +1130,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, geometric_distribution<_IntType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type = typename geometric_distribution<_IntType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::skipws); double __p; - __is >> __p; - __x.param(typename geometric_distribution<_IntType>::param_type(__p)); + if (__is >> __p) + __x.param(param_type(__p)); __is.flags(__flags); return __is; } - // This is Leger's algorithm. + // This is Leger's algorithm, also in Devroye, Ch. X, Example 1.5. template template typename negative_binomial_distribution<_IntType>::result_type @@ -1085,8 +1154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const double __y = _M_gd(__urng); // XXX Is the constructor too slow? - std::poisson_distribution __poisson(__y * (1.0 - p()) - / p()); + std::poisson_distribution __poisson(__y); return __poisson(__urng); } @@ -1097,23 +1165,63 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator()(_UniformRandomNumberGenerator& __urng, const param_type& __p) { - typedef typename std::gamma_distribution::param_type + typedef typename std::gamma_distribution::param_type param_type; - const double __y = _M_gd(__urng, param_type(__p.k(), 1.0)); + const double __y = + _M_gd(__urng, param_type(__p.k(), (1.0 - __p.p()) / __p.p())); - std::poisson_distribution __poisson(__y * (1.0 - __p.p()) - / __p.p() ); + std::poisson_distribution __poisson(__y); return __poisson(__urng); } + template + template + void + negative_binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + { + const double __y = _M_gd(__urng); + + // XXX Is the constructor too slow? + std::poisson_distribution __poisson(__y); + *__f++ = __poisson(__urng); + } + } + + template + template + void + negative_binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typename std::gamma_distribution::param_type + __p2(__p.k(), (1.0 - __p.p()) / __p.p()); + + while (__f != __t) + { + const double __y = _M_gd(__urng, __p2); + + std::poisson_distribution __poisson(__y); + *__f++ = __poisson(__urng); + } + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const negative_binomial_distribution<_IntType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1137,17 +1245,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, negative_binomial_distribution<_IntType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename negative_binomial_distribution<_IntType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::skipws); _IntType __k; double __p; - __is >> __k >> __p >> __x._M_gd; - __x.param(typename negative_binomial_distribution<_IntType>:: - param_type(__k, __p)); + if (__is >> __k >> __p >> __x._M_gd) + __x.param(param_type(__k, __p)); __is.flags(__flags); return __is; @@ -1170,7 +1278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const double __pi_4 = 0.7853981633974483096156608458198757L; const double __dx = std::sqrt(2 * __m * std::log(32 * __m / __pi_4)); - _M_d = std::round(std::max(6.0, std::min(__m, __dx))); + _M_d = std::round(std::max(6.0, std::min(__m, __dx))); const double __cx = 2 * __m + _M_d; _M_scx = std::sqrt(__cx / 2); _M_1cx = 1 / __cx; @@ -1221,6 +1329,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const double __c2 = __param._M_c2b + __c1; const double __c3 = __c2 + 1; const double __c4 = __c3 + 1; + // 1 / 78 + const double __178 = 0.0128205128205128205128205128205128L; // e^(1 / 78) const double __e178 = 1.0129030479320018583185514777512983L; const double __c5 = __c4 + __e178; @@ -1231,7 +1341,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION do { const double __u = __c * __aurng(); - const double __e = -std::log(__aurng()); + const double __e = -std::log(1.0 - __aurng()); double __w = 0.0; @@ -1260,10 +1370,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else if (__u <= __c4) __x = 0; else if (__u <= __c5) - __x = 1; + { + __x = 1; + // Only in the Errata, see libstdc++/83237. + __w = __178; + } else { - const double __v = -std::log(__aurng()); + const double __v = -std::log(1.0 - __aurng()); const double __y = __param._M_d + __v * __2cx / __param._M_d; __x = std::ceil(__y); @@ -1296,14 +1410,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } + template + template + void + poisson_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const poisson_distribution<_IntType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1327,15 +1455,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, poisson_distribution<_IntType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type = typename poisson_distribution<_IntType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::skipws); double __mean; - __is >> __mean >> __x._M_nd; - __x.param(typename poisson_distribution<_IntType>::param_type(__mean)); + if (__is >> __mean >> __x._M_nd) + __x.param(param_type(__mean)); __is.flags(__flags); return __is; @@ -1363,11 +1491,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const double __d1x = std::sqrt(__np * __1p * std::log(32 * __np / (81 * __pi_4 * __1p))); - _M_d1 = std::round(std::max(1.0, __d1x)); + _M_d1 = std::round(std::max(1.0, __d1x)); const double __d2x = std::sqrt(__np * __1p * std::log(32 * _M_t * __1p / (__pi_4 * __pa))); - _M_d2 = std::round(std::max(1.0, __d2x)); + _M_d2 = std::round(std::max(1.0, __d2x)); // sqrt(pi / 2) const double __spi_2 = 1.2533141373155002512078826424055226L; @@ -1398,7 +1526,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template typename binomial_distribution<_IntType>::result_type binomial_distribution<_IntType>:: - _M_waiting(_UniformRandomNumberGenerator& __urng, _IntType __t) + _M_waiting(_UniformRandomNumberGenerator& __urng, + _IntType __t, double __q) { _IntType __x = 0; double __sum = 0.0; @@ -1407,11 +1536,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION do { - const double __e = -std::log(__aurng()); + if (__t == __x) + return __x; + const double __e = -std::log(1.0 - __aurng()); __sum += __e / (__t - __x); __x += 1; } - while (__sum <= _M_param._M_q); + while (__sum <= __q); return __x - 1; } @@ -1475,7 +1606,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __reject = __y >= __param._M_d1; if (!__reject) { - const double __e = -std::log(__aurng()); + const double __e = -std::log(1.0 - __aurng()); __x = std::floor(__y); __v = -__e - __n * __n / 2 + __param._M_c; } @@ -1487,15 +1618,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __reject = __y >= __param._M_d2; if (!__reject) { - const double __e = -std::log(__aurng()); + const double __e = -std::log(1.0 - __aurng()); __x = std::floor(-__y); __v = -__e - __n * __n / 2; } } else if (__u <= __a123) { - const double __e1 = -std::log(__aurng()); - const double __e2 = -std::log(__aurng()); + const double __e1 = -std::log(1.0 - __aurng()); + const double __e2 = -std::log(1.0 - __aurng()); const double __y = __param._M_d1 + 2 * __s1s * __e1 / __param._M_d1; @@ -1506,8 +1637,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else { - const double __e1 = -std::log(__aurng()); - const double __e2 = -std::log(__aurng()); + const double __e1 = -std::log(1.0 - __aurng()); + const double __e2 = -std::log(1.0 - __aurng()); const double __y = __param._M_d2 + 2 * __s2s * __e1 / __param._M_d2; @@ -1532,26 +1663,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __x += __np + __naf; - const _IntType __z = _M_waiting(__urng, __t - _IntType(__x)); + const _IntType __z = _M_waiting(__urng, __t - _IntType(__x), + __param._M_q); __ret = _IntType(__x) + __z; } else #endif - __ret = _M_waiting(__urng, __t); + __ret = _M_waiting(__urng, __t, __param._M_q); if (__p12 != __p) __ret = __t - __ret; return __ret; } + template + template + void + binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const binomial_distribution<_IntType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1576,30 +1722,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, binomial_distribution<_IntType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type = typename binomial_distribution<_IntType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _IntType __t; double __p; - __is >> __t >> __p >> __x._M_nd; - __x.param(typename binomial_distribution<_IntType>:: - param_type(__t, __p)); + if (__is >> __t >> __p >> __x._M_nd) + __x.param(param_type(__t, __p)); __is.flags(__flags); return __is; } + template + template + void + std::exponential_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + while (__f != __t) + *__f++ = -std::log(result_type(1) - __aurng()) / __p.lambda(); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const exponential_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1621,16 +1781,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, exponential_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename exponential_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __lambda; - __is >> __lambda; - __x.param(typename exponential_distribution<_RealType>:: - param_type(__lambda)); + if (__is >> __lambda) + __x.param(param_type(__lambda)); __is.flags(__flags); return __is; @@ -1680,6 +1840,66 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __ret; } + template + template + void + normal_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + + if (__f == __t) + return; + + if (_M_saved_available) + { + _M_saved_available = false; + *__f++ = _M_saved * __param.stddev() + __param.mean(); + + if (__f == __t) + return; + } + + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + while (__f + 1 < __t) + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + *__f++ = __y * __mult * __param.stddev() + __param.mean(); + *__f++ = __x * __mult * __param.stddev() + __param.mean(); + } + + if (__f != __t) + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + _M_saved = __x * __mult; + _M_saved_available = true; + *__f = __y * __mult * __param.stddev() + __param.mean(); + } + } + template bool operator==(const std::normal_distribution<_RealType>& __d1, @@ -1687,15 +1907,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__d1._M_param == __d2._M_param && __d1._M_saved_available == __d2._M_saved_available) - { - if (__d1._M_saved_available - && __d1._M_saved == __d2._M_saved) - return true; - else if(!__d1._M_saved_available) - return true; - else - return false; - } + return __d1._M_saved_available ? __d1._M_saved == __d2._M_saved : true; else return false; } @@ -1705,8 +1917,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator<<(std::basic_ostream<_CharT, _Traits>& __os, const normal_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1732,32 +1943,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, normal_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type = typename normal_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); double __mean, __stddev; - __is >> __mean >> __stddev - >> __x._M_saved_available; - if (__x._M_saved_available) - __is >> __x._M_saved; - __x.param(typename normal_distribution<_RealType>:: - param_type(__mean, __stddev)); + bool __saved_avail; + if (__is >> __mean >> __stddev >> __saved_avail) + { + if (!__saved_avail || (__is >> __x._M_saved)) + { + __x._M_saved_available = __saved_avail; + __x.param(param_type(__mean, __stddev)); + } + } __is.flags(__flags); return __is; } + template + template + void + lognormal_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = std::exp(__p.s() * _M_nd(__urng) + __p.m()); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const lognormal_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1781,29 +2008,55 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, lognormal_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename lognormal_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __m, __s; - __is >> __m >> __s >> __x._M_nd; - __x.param(typename lognormal_distribution<_RealType>:: - param_type(__m, __s)); + if (__is >> __m >> __s >> __x._M_nd) + __x.param(param_type(__m, __s)); __is.flags(__flags); return __is; } + template + template + void + std::chi_squared_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = 2 * _M_gd(__urng); + } + + template + template + void + std::chi_squared_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const typename + std::gamma_distribution::param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = 2 * _M_gd(__urng, __p); + } template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const chi_squared_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1826,16 +2079,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, chi_squared_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename chi_squared_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __n; - __is >> __n >> __x._M_gd; - __x.param(typename chi_squared_distribution<_RealType>:: - param_type(__n)); + if (__is >> __n >> __x._M_gd) + __x.param(param_type(__n)); __is.flags(__flags); return __is; @@ -1860,13 +2113,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __p.a() + __p.b() * std::tan(__pi * __u); } + template + template + void + cauchy_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + const _RealType __pi = 3.1415926535897932384626433832795029L; + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + while (__f != __t) + { + _RealType __u; + do + __u = __aurng(); + while (__u == 0.5); + + *__f++ = __p.a() + __p.b() * std::tan(__pi * __u); + } + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const cauchy_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1889,29 +2165,59 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, cauchy_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type = typename cauchy_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __a, __b; - __is >> __a >> __b; - __x.param(typename cauchy_distribution<_RealType>:: - param_type(__a, __b)); + if (__is >> __a >> __b) + __x.param(param_type(__a, __b)); __is.flags(__flags); return __is; } + template + template + void + std::fisher_f_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = ((_M_gd_x(__urng) * n()) / (_M_gd_y(__urng) * m())); + } + + template + template + void + std::fisher_f_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typedef typename std::gamma_distribution::param_type + param_type; + param_type __p1(__p.m() / 2); + param_type __p2(__p.n() / 2); + while (__f != __t) + *__f++ = ((_M_gd_x(__urng, __p1) * n()) + / (_M_gd_y(__urng, __p2) * m())); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const fisher_f_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1935,29 +2241,57 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, fisher_f_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename fisher_f_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __m, __n; - __is >> __m >> __n >> __x._M_gd_x >> __x._M_gd_y; - __x.param(typename fisher_f_distribution<_RealType>:: - param_type(__m, __n)); + if (__is >> __m >> __n >> __x._M_gd_x >> __x._M_gd_y) + __x.param(param_type(__m, __n)); __is.flags(__flags); return __is; } + template + template + void + std::student_t_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = _M_nd(__urng) * std::sqrt(n() / _M_gd(__urng)); + } + + template + template + void + std::student_t_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typename std::gamma_distribution::param_type + __p2(__p.n() / 2, 2); + while (__f != __t) + *__f++ = _M_nd(__urng) * std::sqrt(__p.n() / _M_gd(__urng, __p2)); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const student_t_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -1980,15 +2314,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, student_t_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename student_t_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __n; - __is >> __n >> __x._M_nd >> __x._M_gd; - __x.param(typename student_t_distribution<_RealType>::param_type(__n)); + if (__is >> __n >> __x._M_nd >> __x._M_gd) + __x.param(param_type(__n)); __is.flags(__flags); return __is; @@ -2037,7 +2372,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __v = __v * __v * __v; __u = __aurng(); } - while (__u > result_type(1.0) - 0.331 * __n * __n * __n * __n + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n && (std::log(__u) > (0.5 * __n * __n + __a1 * (1.0 - __v + std::log(__v))))); @@ -2054,13 +2389,78 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } + template + template + void + gamma_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + result_type __u, __v, __n; + const result_type __a1 = (__param._M_malpha + - _RealType(1.0) / _RealType(3.0)); + + if (__param.alpha() == __param._M_malpha) + while (__f != __t) + { + do + { + do + { + __n = _M_nd(__urng); + __v = result_type(1.0) + __param._M_a2 * __n; + } + while (__v <= 0.0); + + __v = __v * __v * __v; + __u = __aurng(); + } + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n + && (std::log(__u) > (0.5 * __n * __n + __a1 + * (1.0 - __v + std::log(__v))))); + + *__f++ = __a1 * __v * __param.beta(); + } + else + while (__f != __t) + { + do + { + do + { + __n = _M_nd(__urng); + __v = result_type(1.0) + __param._M_a2 * __n; + } + while (__v <= 0.0); + + __v = __v * __v * __v; + __u = __aurng(); + } + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n + && (std::log(__u) > (0.5 * __n * __n + __a1 + * (1.0 - __v + std::log(__v))))); + + do + __u = __aurng(); + while (__u == 0.0); + + *__f++ = (std::pow(__u, result_type(1.0) / __param.alpha()) + * __a1 * __v * __param.beta()); + } + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const gamma_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -2084,16 +2484,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, gamma_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type = typename gamma_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __alpha_val, __beta_val; - __is >> __alpha_val >> __beta_val >> __x._M_nd; - __x.param(typename gamma_distribution<_RealType>:: - param_type(__alpha_val, __beta_val)); + if (__is >> __alpha_val >> __beta_val >> __x._M_nd) + __x.param(param_type(__alpha_val, __beta_val)); __is.flags(__flags); return __is; @@ -2109,17 +2508,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> __aurng(__urng); - return __p.b() * std::pow(-std::log(__aurng()), + return __p.b() * std::pow(-std::log(result_type(1) - __aurng()), result_type(1) / __p.a()); } + template + template + void + weibull_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + auto __inv_a = result_type(1) / __p.a(); + + while (__f != __t) + *__f++ = __p.b() * std::pow(-std::log(result_type(1) - __aurng()), + __inv_a); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const weibull_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -2142,16 +2559,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, weibull_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type = typename weibull_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __a, __b; - __is >> __a >> __b; - __x.param(typename weibull_distribution<_RealType>:: - param_type(__a, __b)); + if (__is >> __a >> __b) + __x.param(param_type(__a, __b)); __is.flags(__flags); return __is; @@ -2167,7 +2583,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> __aurng(__urng); - return __p.a() - __p.b() * std::log(-std::log(__aurng())); + return __p.a() - __p.b() * std::log(-std::log(result_type(1) + - __aurng())); + } + + template + template + void + extreme_value_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + while (__f != __t) + *__f++ = __p.a() - __p.b() * std::log(-std::log(result_type(1) + - __aurng())); } template @@ -2175,8 +2610,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator<<(std::basic_ostream<_CharT, _Traits>& __os, const extreme_value_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -2199,16 +2633,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, extreme_value_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using param_type + = typename extreme_value_distribution<_RealType>::param_type; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __a, __b; - __is >> __a >> __b; - __x.param(typename extreme_value_distribution<_RealType>:: - param_type(__a, __b)); + if (__is >> __a >> __b) + __x.param(param_type(__a, __b)); __is.flags(__flags); return __is; @@ -2228,9 +2662,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const double __sum = std::accumulate(_M_prob.begin(), _M_prob.end(), 0.0); + __glibcxx_assert(__sum > 0); // Now normalize the probabilites. - __detail::__transform(_M_prob.begin(), _M_prob.end(), _M_prob.begin(), - std::bind2nd(std::divides(), __sum)); + __detail::__normalize(_M_prob.begin(), _M_prob.end(), _M_prob.begin(), + __sum); // Accumulate partial sums. _M_cp.reserve(_M_prob.size()); std::partial_sum(_M_prob.begin(), _M_prob.end(), @@ -2275,13 +2710,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __pos - __param._M_cp.begin(); } + template + template + void + discrete_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + + if (__param._M_cp.empty()) + { + while (__f != __t) + *__f++ = result_type(0); + return; + } + + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + while (__f != __t) + { + const double __p = __aurng(); + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + + *__f++ = __pos - __param._M_cp.begin(); + } + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const discrete_distribution<_IntType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -2302,32 +2767,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __os; } +namespace __detail +{ + template + basic_istream<_CharT, _Traits>& + __extract_params(basic_istream<_CharT, _Traits>& __is, + vector<_ValT>& __vals, size_t __n) + { + __vals.reserve(__n); + while (__n--) + { + _ValT __val; + if (__is >> __val) + __vals.push_back(__val); + else + break; + } + return __is; + } +} // namespace __detail + template std::basic_istream<_CharT, _Traits>& operator>>(std::basic_istream<_CharT, _Traits>& __is, discrete_distribution<_IntType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); size_t __n; - __is >> __n; - - std::vector __prob_vec; - __prob_vec.reserve(__n); - for (; __n != 0; --__n) + if (__is >> __n) { - double __prob; - __is >> __prob; - __prob_vec.push_back(__prob); + std::vector __prob_vec; + if (__detail::__extract_params(__is, __prob_vec, __n)) + __x.param({__prob_vec.begin(), __prob_vec.end()}); } - __x.param(typename discrete_distribution<_IntType>:: - param_type(__prob_vec.begin(), __prob_vec.end())); - __is.flags(__flags); return __is; } @@ -2350,9 +2827,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const double __sum = std::accumulate(_M_den.begin(), _M_den.end(), 0.0); + __glibcxx_assert(__sum > 0); - __detail::__transform(_M_den.begin(), _M_den.end(), _M_den.begin(), - std::bind2nd(std::divides(), __sum)); + __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(), + __sum); _M_cp.reserve(_M_den.size()); std::partial_sum(_M_den.begin(), _M_den.end(), @@ -2450,13 +2928,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __param._M_int[__i] + (__p - __pref) / __param._M_den[__i]; } + template + template + void + piecewise_constant_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + if (__param._M_cp.empty()) + { + while (__f != __t) + *__f++ = __aurng(); + return; + } + + while (__f != __t) + { + const double __p = __aurng(); + + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + const size_t __i = __pos - __param._M_cp.begin(); + + const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; + + *__f++ = (__param._M_int[__i] + + (__p - __pref) / __param._M_den[__i]); + } + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const piecewise_constant_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -2487,36 +2999,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, piecewise_constant_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); size_t __n; - __is >> __n; - - std::vector<_RealType> __int_vec; - __int_vec.reserve(__n + 1); - for (size_t __i = 0; __i <= __n; ++__i) - { - _RealType __int; - __is >> __int; - __int_vec.push_back(__int); - } - - std::vector __den_vec; - __den_vec.reserve(__n); - for (size_t __i = 0; __i < __n; ++__i) + if (__is >> __n) { - double __den; - __is >> __den; - __den_vec.push_back(__den); + std::vector<_RealType> __int_vec; + if (__detail::__extract_params(__is, __int_vec, __n + 1)) + { + std::vector __den_vec; + if (__detail::__extract_params(__is, __den_vec, __n)) + { + __x.param({ __int_vec.begin(), __int_vec.end(), + __den_vec.begin() }); + } + } } - __x.param(typename piecewise_constant_distribution<_RealType>:: - param_type(__int_vec.begin(), __int_vec.end(), __den_vec.begin())); - __is.flags(__flags); return __is; } @@ -2548,16 +3050,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_cp.push_back(__sum); _M_m.push_back((_M_den[__k + 1] - _M_den[__k]) / __delta); } + __glibcxx_assert(__sum > 0); // Now normalize the densities... - __detail::__transform(_M_den.begin(), _M_den.end(), _M_den.begin(), - std::bind2nd(std::divides(), __sum)); + __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(), + __sum); // ... and partial sums... - __detail::__transform(_M_cp.begin(), _M_cp.end(), _M_cp.begin(), - std::bind2nd(std::divides(), __sum)); + __detail::__normalize(_M_cp.begin(), _M_cp.end(), _M_cp.begin(), __sum); // ... and slopes. - __detail::__transform(_M_m.begin(), _M_m.end(), _M_m.begin(), - std::bind2nd(std::divides(), __sum)); + __detail::__normalize(_M_m.begin(), _M_m.end(), _M_m.begin(), __sum); + // Make sure the last cumulative probablility is one. _M_cp[_M_cp.size() - 1] = 1.0; } @@ -2652,13 +3154,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __x; } + template + template + void + piecewise_linear_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, const piecewise_linear_distribution<_RealType>& __x) { - typedef std::basic_ostream<_CharT, _Traits> __ostream_type; - typedef typename __ostream_type::ios_base __ios_base; + using __ios_base = typename basic_ostream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __os.flags(); const _CharT __fill = __os.fill(); @@ -2689,44 +3205,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator>>(std::basic_istream<_CharT, _Traits>& __is, piecewise_linear_distribution<_RealType>& __x) { - typedef std::basic_istream<_CharT, _Traits> __istream_type; - typedef typename __istream_type::ios_base __ios_base; + using __ios_base = typename basic_istream<_CharT, _Traits>::ios_base; const typename __ios_base::fmtflags __flags = __is.flags(); __is.flags(__ios_base::dec | __ios_base::skipws); size_t __n; - __is >> __n; - - std::vector<_RealType> __int_vec; - __int_vec.reserve(__n + 1); - for (size_t __i = 0; __i <= __n; ++__i) - { - _RealType __int; - __is >> __int; - __int_vec.push_back(__int); - } - - std::vector __den_vec; - __den_vec.reserve(__n + 1); - for (size_t __i = 0; __i <= __n; ++__i) + if (__is >> __n) { - double __den; - __is >> __den; - __den_vec.push_back(__den); + vector<_RealType> __int_vec; + if (__detail::__extract_params(__is, __int_vec, __n + 1)) + { + vector __den_vec; + if (__detail::__extract_params(__is, __den_vec, __n + 1)) + { + __x.param({ __int_vec.begin(), __int_vec.end(), + __den_vec.begin() }); + } + } } - - __x.param(typename piecewise_linear_distribution<_RealType>:: - param_type(__int_vec.begin(), __int_vec.end(), __den_vec.begin())); - __is.flags(__flags); return __is; } - template + template seed_seq::seed_seq(std::initializer_list<_IntType> __il) { + _M_v.reserve(__il.size()); for (auto __iter = __il.begin(); __iter != __il.end(); ++__iter) _M_v.push_back(__detail::__mod::__value>(*__iter)); @@ -2735,6 +3241,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template seed_seq::seed_seq(_InputIterator __begin, _InputIterator __end) { + if _GLIBCXX17_CONSTEXPR (__is_random_access_iter<_InputIterator>::value) + _M_v.reserve(std::distance(__begin, __end)); + for (_InputIterator __iter = __begin; __iter != __end; ++__iter) _M_v.push_back(__detail::__mod::__value>(*__iter)); @@ -2762,44 +3271,72 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : (__n - 1) / 2; const size_t __p = (__n - __t) / 2; const size_t __q = __p + __t; - const size_t __m = std::max(__s + 1, __n); + const size_t __m = std::max(size_t(__s + 1), __n); + +#ifndef __UINT32_TYPE__ + struct _Up + { + _Up(uint_least32_t v) : _M_v(v & 0xffffffffu) { } + + operator uint_least32_t() const { return _M_v; } + + uint_least32_t _M_v; + }; + using uint32_t = _Up; +#endif - for (size_t __k = 0; __k < __m; ++__k) + // k == 0, every element in [begin,end) equals 0x8b8b8b8bu { - _Type __arg = (__begin[__k % __n] - ^ __begin[(__k + __p) % __n] - ^ __begin[(__k - 1) % __n]); - _Type __r1 = __arg ^ (__arg << 27); - __r1 = __detail::__mod<_Type, __detail::_Shift<_Type, 32>::__value, - 1664525u, 0u>(__r1); - _Type __r2 = __r1; - if (__k == 0) - __r2 += __s; - else if (__k <= __s) - __r2 += __k % __n + _M_v[__k - 1]; - else - __r2 += __k % __n; - __r2 = __detail::__mod<_Type, - __detail::_Shift<_Type, 32>::__value>(__r2); - __begin[(__k + __p) % __n] += __r1; - __begin[(__k + __q) % __n] += __r2; - __begin[__k % __n] = __r2; + uint32_t __r1 = 1371501266u; + uint32_t __r2 = __r1 + __s; + __begin[__p] += __r1; + __begin[__q] = (uint32_t)__begin[__q] + __r2; + __begin[0] = __r2; + } + + for (size_t __k = 1; __k <= __s; ++__k) + { + const size_t __kn = __k % __n; + const size_t __kpn = (__k + __p) % __n; + const size_t __kqn = (__k + __q) % __n; + uint32_t __arg = (__begin[__kn] + ^ __begin[__kpn] + ^ __begin[(__k - 1) % __n]); + uint32_t __r1 = 1664525u * (__arg ^ (__arg >> 27)); + uint32_t __r2 = __r1 + (uint32_t)__kn + _M_v[__k - 1]; + __begin[__kpn] = (uint32_t)__begin[__kpn] + __r1; + __begin[__kqn] = (uint32_t)__begin[__kqn] + __r2; + __begin[__kn] = __r2; + } + + for (size_t __k = __s + 1; __k < __m; ++__k) + { + const size_t __kn = __k % __n; + const size_t __kpn = (__k + __p) % __n; + const size_t __kqn = (__k + __q) % __n; + uint32_t __arg = (__begin[__kn] + ^ __begin[__kpn] + ^ __begin[(__k - 1) % __n]); + uint32_t __r1 = 1664525u * (__arg ^ (__arg >> 27)); + uint32_t __r2 = __r1 + (uint32_t)__kn; + __begin[__kpn] = (uint32_t)__begin[__kpn] + __r1; + __begin[__kqn] = (uint32_t)__begin[__kqn] + __r2; + __begin[__kn] = __r2; } for (size_t __k = __m; __k < __m + __n; ++__k) { - _Type __arg = (__begin[__k % __n] - + __begin[(__k + __p) % __n] - + __begin[(__k - 1) % __n]); - _Type __r3 = __arg ^ (__arg << 27); - __r3 = __detail::__mod<_Type, __detail::_Shift<_Type, 32>::__value, - 1566083941u, 0u>(__r3); - _Type __r4 = __r3 - __k % __n; - __r4 = __detail::__mod<_Type, - __detail::_Shift<_Type, 32>::__value>(__r4); - __begin[(__k + __p) % __n] ^= __r4; - __begin[(__k + __q) % __n] ^= __r3; - __begin[__k % __n] = __r4; + const size_t __kn = __k % __n; + const size_t __kpn = (__k + __p) % __n; + const size_t __kqn = (__k + __q) % __n; + uint32_t __arg = (__begin[__kn] + + __begin[__kpn] + + __begin[(__k - 1) % __n]); + uint32_t __r3 = 1566083941u * (__arg ^ (__arg >> 27)); + uint32_t __r4 = __r3 - __kn; + __begin[__kpn] ^= __r3; + __begin[__kqn] ^= __r4; + __begin[__kn] = __r4; } } @@ -2808,21 +3345,36 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _RealType generate_canonical(_UniformRandomNumberGenerator& __urng) { + static_assert(std::is_floating_point<_RealType>::value, + "template argument must be a floating point type"); + const size_t __b = std::min(static_cast(std::numeric_limits<_RealType>::digits), __bits); const long double __r = static_cast(__urng.max()) - static_cast(__urng.min()) + 1.0L; const size_t __log2r = std::log(__r) / std::log(2.0L); - size_t __k = std::max(1UL, (__b + __log2r - 1UL) / __log2r); + const size_t __m = std::max(1UL, + (__b + __log2r - 1UL) / __log2r); + _RealType __ret; _RealType __sum = _RealType(0); _RealType __tmp = _RealType(1); - for (; __k != 0; --__k) + for (size_t __k = __m; __k != 0; --__k) { __sum += _RealType(__urng() - __urng.min()) * __tmp; __tmp *= __r; } - return __sum / __tmp; + __ret = __sum / __tmp; + if (__builtin_expect(__ret >= _RealType(1), 0)) + { +#if _GLIBCXX_USE_C99_MATH_TR1 + __ret = std::nextafter(_RealType(1), _RealType(0)); +#else + __ret = _RealType(1) + - std::numeric_limits<_RealType>::epsilon() / _RealType(2); +#endif + } + return __ret; } _GLIBCXX_END_NAMESPACE_VERSION