X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=i686-linux-gnu-4.7%2Fusr%2Finclude%2Fc%2B%2B%2F4.7%2Ftr1%2Frandom.tcc;fp=i686-linux-gnu-4.7%2Fusr%2Finclude%2Fc%2B%2B%2F4.7%2Ftr1%2Frandom.tcc;h=3d8c4fe1c1095aed3100ea7ee9911136b43d627d;hb=94df942c2c7bd3457276fe5b7367623cbb8c1302;hp=0000000000000000000000000000000000000000;hpb=4dd7d9155a920895ff7b1cb6b9c9c676aa62000a;p=cross.git diff --git a/i686-linux-gnu-4.7/usr/include/c++/4.7/tr1/random.tcc b/i686-linux-gnu-4.7/usr/include/c++/4.7/tr1/random.tcc new file mode 100644 index 0000000..3d8c4fe --- /dev/null +++ b/i686-linux-gnu-4.7/usr/include/c++/4.7/tr1/random.tcc @@ -0,0 +1,1721 @@ +// random number generation (out of line) -*- C++ -*- + +// Copyright (C) 2009, 2010 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 +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + + +/** @file tr1/random.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{tr1/random} + */ + +#ifndef _GLIBCXX_TR1_RANDOM_TCC +#define _GLIBCXX_TR1_RANDOM_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +namespace tr1 +{ + /* + * (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. + // + // 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. + template + struct _Mod<_Tp, __a, __c, __m, true> + { + static _Tp + __calc(_Tp __x) + { return __a * __x + __c; } + }; + _GLIBCXX_END_NAMESPACE_VERSION + } // namespace __detail + +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + const _UIntType + linear_congruential<_UIntType, __a, __c, __m>::multiplier; + + template + const _UIntType + linear_congruential<_UIntType, __a, __c, __m>::increment; + + template + const _UIntType + linear_congruential<_UIntType, __a, __c, __m>::modulus; + + /** + * Seeds the LCR with integral value @p __x0, adjusted so that the + * ring identity is never a member of the convergence set. + */ + template + void + linear_congruential<_UIntType, __a, __c, __m>:: + seed(unsigned long __x0) + { + if ((__detail::__mod<_UIntType, 1, 0, __m>(__c) == 0) + && (__detail::__mod<_UIntType, 1, 0, __m>(__x0) == 0)) + _M_x = __detail::__mod<_UIntType, 1, 0, __m>(1); + else + _M_x = __detail::__mod<_UIntType, 1, 0, __m>(__x0); + } + + /** + * Seeds the LCR engine with a value generated by @p __g. + */ + template + template + void + linear_congruential<_UIntType, __a, __c, __m>:: + seed(_Gen& __g, false_type) + { + _UIntType __x0 = __g(); + if ((__detail::__mod<_UIntType, 1, 0, __m>(__c) == 0) + && (__detail::__mod<_UIntType, 1, 0, __m>(__x0) == 0)) + _M_x = __detail::__mod<_UIntType, 1, 0, __m>(1); + else + _M_x = __detail::__mod<_UIntType, 1, 0, __m>(__x0); + } + + /** + * Gets the next generated value in sequence. + */ + template + typename linear_congruential<_UIntType, __a, __c, __m>::result_type + linear_congruential<_UIntType, __a, __c, __m>:: + operator()() + { + _M_x = __detail::__mod<_UIntType, __a, __c, __m>(_M_x); + return _M_x; + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const linear_congruential<_UIntType, __a, __c, __m>& __lcr) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + __os.flags(__ios_base::dec | __ios_base::fixed | __ios_base::left); + __os.fill(__os.widen(' ')); + + __os << __lcr._M_x; + + __os.flags(__flags); + __os.fill(__fill); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + linear_congruential<_UIntType, __a, __c, __m>& __lcr) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::dec); + + __is >> __lcr._M_x; + + __is.flags(__flags); + return __is; + } + + + template + const int + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::word_size; + + template + const int + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::state_size; + + template + const int + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::shift_size; + + template + const int + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::mask_bits; + + template + const _UIntType + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::parameter_a; + + template + const int + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::output_u; + + template + const int + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::output_s; + + template + const _UIntType + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::output_b; + + template + const int + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::output_t; + + template + const _UIntType + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::output_c; + + template + const int + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::output_l; + + template + void + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>:: + seed(unsigned long __value) + { + _M_x[0] = __detail::__mod<_UIntType, 1, 0, + __detail::_Shift<_UIntType, __w>::__value>(__value); + + for (int __i = 1; __i < state_size; ++__i) + { + _UIntType __x = _M_x[__i - 1]; + __x ^= __x >> (__w - 2); + __x *= 1812433253ul; + __x += __i; + _M_x[__i] = __detail::__mod<_UIntType, 1, 0, + __detail::_Shift<_UIntType, __w>::__value>(__x); + } + _M_p = state_size; + } + + template + template + void + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>:: + seed(_Gen& __gen, false_type) + { + for (int __i = 0; __i < state_size; ++__i) + _M_x[__i] = __detail::__mod<_UIntType, 1, 0, + __detail::_Shift<_UIntType, __w>::__value>(__gen()); + _M_p = state_size; + } + + template + typename + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>::result_type + mersenne_twister<_UIntType, __w, __n, __m, __r, __a, __u, __s, + __b, __t, __c, __l>:: + operator()() + { + // Reload the vector - cost is O(n) amortized over n calls. + if (_M_p >= state_size) + { + const _UIntType __upper_mask = (~_UIntType()) << __r; + const _UIntType __lower_mask = ~__upper_mask; + + for (int __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 (int __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; + } + + // Calculate o(x(i)). + result_type __z = _M_x[_M_p++]; + __z ^= (__z >> __u); + __z ^= (__z << __s) & __b; + __z ^= (__z << __t) & __c; + __z ^= (__z >> __l); + + return __z; + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const mersenne_twister<_UIntType, __w, __n, __m, + __r, __a, __u, __s, __b, __t, __c, __l>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::dec | __ios_base::fixed | __ios_base::left); + __os.fill(__space); + + for (int __i = 0; __i < __n - 1; ++__i) + __os << __x._M_x[__i] << __space; + __os << __x._M_x[__n - 1]; + + __os.flags(__flags); + __os.fill(__fill); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + mersenne_twister<_UIntType, __w, __n, __m, + __r, __a, __u, __s, __b, __t, __c, __l>& __x) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::dec | __ios_base::skipws); + + for (int __i = 0; __i < __n; ++__i) + __is >> __x._M_x[__i]; + + __is.flags(__flags); + return __is; + } + + + template + const _IntType + subtract_with_carry<_IntType, __m, __s, __r>::modulus; + + template + const int + subtract_with_carry<_IntType, __m, __s, __r>::long_lag; + + template + const int + subtract_with_carry<_IntType, __m, __s, __r>::short_lag; + + template + void + subtract_with_carry<_IntType, __m, __s, __r>:: + seed(unsigned long __value) + { + if (__value == 0) + __value = 19780503; + + std::tr1::linear_congruential + __lcg(__value); + + for (int __i = 0; __i < long_lag; ++__i) + _M_x[__i] = __detail::__mod<_UIntType, 1, 0, modulus>(__lcg()); + + _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0; + _M_p = 0; + } + + template + template + void + subtract_with_carry<_IntType, __m, __s, __r>:: + seed(_Gen& __gen, false_type) + { + const int __n = (std::numeric_limits<_UIntType>::digits + 31) / 32; + + for (int __i = 0; __i < long_lag; ++__i) + { + _UIntType __tmp = 0; + _UIntType __factor = 1; + for (int __j = 0; __j < __n; ++__j) + { + __tmp += __detail::__mod<__detail::_UInt32Type, 1, 0, 0> + (__gen()) * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + _M_x[__i] = __detail::__mod<_UIntType, 1, 0, modulus>(__tmp); + } + _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0; + _M_p = 0; + } + + template + typename subtract_with_carry<_IntType, __m, __s, __r>::result_type + subtract_with_carry<_IntType, __m, __s, __r>:: + operator()() + { + // Derive short lag index from current index. + int __ps = _M_p - short_lag; + if (__ps < 0) + __ps += long_lag; + + // Calculate new x(i) without overflow or division. + // NB: Thanks to the requirements for _IntType, _M_x[_M_p] + _M_carry + // cannot overflow. + _UIntType __xi; + if (_M_x[__ps] >= _M_x[_M_p] + _M_carry) + { + __xi = _M_x[__ps] - _M_x[_M_p] - _M_carry; + _M_carry = 0; + } + else + { + __xi = modulus - _M_x[_M_p] - _M_carry + _M_x[__ps]; + _M_carry = 1; + } + _M_x[_M_p] = __xi; + + // Adjust current index to loop around in ring buffer. + if (++_M_p >= long_lag) + _M_p = 0; + + return __xi; + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const subtract_with_carry<_IntType, __m, __s, __r>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::dec | __ios_base::fixed | __ios_base::left); + __os.fill(__space); + + for (int __i = 0; __i < __r; ++__i) + __os << __x._M_x[__i] << __space; + __os << __x._M_carry; + + __os.flags(__flags); + __os.fill(__fill); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + subtract_with_carry<_IntType, __m, __s, __r>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::dec | __ios_base::skipws); + + for (int __i = 0; __i < __r; ++__i) + __is >> __x._M_x[__i]; + __is >> __x._M_carry; + + __is.flags(__flags); + return __is; + } + + + template + const int + subtract_with_carry_01<_RealType, __w, __s, __r>::word_size; + + template + const int + subtract_with_carry_01<_RealType, __w, __s, __r>::long_lag; + + template + const int + subtract_with_carry_01<_RealType, __w, __s, __r>::short_lag; + + template + void + subtract_with_carry_01<_RealType, __w, __s, __r>:: + _M_initialize_npows() + { + for (int __j = 0; __j < __n; ++__j) +#if _GLIBCXX_USE_C99_MATH_TR1 + _M_npows[__j] = std::tr1::ldexp(_RealType(1), -__w + __j * 32); +#else + _M_npows[__j] = std::pow(_RealType(2), -__w + __j * 32); +#endif + } + + template + void + subtract_with_carry_01<_RealType, __w, __s, __r>:: + seed(unsigned long __value) + { + if (__value == 0) + __value = 19780503; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 512. Seeding subtract_with_carry_01 from a single unsigned long. + std::tr1::linear_congruential + __lcg(__value); + + this->seed(__lcg); + } + + template + template + void + subtract_with_carry_01<_RealType, __w, __s, __r>:: + seed(_Gen& __gen, false_type) + { + for (int __i = 0; __i < long_lag; ++__i) + { + for (int __j = 0; __j < __n - 1; ++__j) + _M_x[__i][__j] = __detail::__mod<_UInt32Type, 1, 0, 0>(__gen()); + _M_x[__i][__n - 1] = __detail::__mod<_UInt32Type, 1, 0, + __detail::_Shift<_UInt32Type, __w % 32>::__value>(__gen()); + } + + _M_carry = 1; + for (int __j = 0; __j < __n; ++__j) + if (_M_x[long_lag - 1][__j] != 0) + { + _M_carry = 0; + break; + } + + _M_p = 0; + } + + template + typename subtract_with_carry_01<_RealType, __w, __s, __r>::result_type + subtract_with_carry_01<_RealType, __w, __s, __r>:: + operator()() + { + // Derive short lag index from current index. + int __ps = _M_p - short_lag; + if (__ps < 0) + __ps += long_lag; + + _UInt32Type __new_carry; + for (int __j = 0; __j < __n - 1; ++__j) + { + if (_M_x[__ps][__j] > _M_x[_M_p][__j] + || (_M_x[__ps][__j] == _M_x[_M_p][__j] && _M_carry == 0)) + __new_carry = 0; + else + __new_carry = 1; + + _M_x[_M_p][__j] = _M_x[__ps][__j] - _M_x[_M_p][__j] - _M_carry; + _M_carry = __new_carry; + } + + if (_M_x[__ps][__n - 1] > _M_x[_M_p][__n - 1] + || (_M_x[__ps][__n - 1] == _M_x[_M_p][__n - 1] && _M_carry == 0)) + __new_carry = 0; + else + __new_carry = 1; + + _M_x[_M_p][__n - 1] = __detail::__mod<_UInt32Type, 1, 0, + __detail::_Shift<_UInt32Type, __w % 32>::__value> + (_M_x[__ps][__n - 1] - _M_x[_M_p][__n - 1] - _M_carry); + _M_carry = __new_carry; + + result_type __ret = 0.0; + for (int __j = 0; __j < __n; ++__j) + __ret += _M_x[_M_p][__j] * _M_npows[__j]; + + // Adjust current index to loop around in ring buffer. + if (++_M_p >= long_lag) + _M_p = 0; + + return __ret; + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const subtract_with_carry_01<_RealType, __w, __s, __r>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::dec | __ios_base::fixed | __ios_base::left); + __os.fill(__space); + + for (int __i = 0; __i < __r; ++__i) + for (int __j = 0; __j < __x.__n; ++__j) + __os << __x._M_x[__i][__j] << __space; + __os << __x._M_carry; + + __os.flags(__flags); + __os.fill(__fill); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + subtract_with_carry_01<_RealType, __w, __s, __r>& __x) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::dec | __ios_base::skipws); + + for (int __i = 0; __i < __r; ++__i) + for (int __j = 0; __j < __x.__n; ++__j) + __is >> __x._M_x[__i][__j]; + __is >> __x._M_carry; + + __is.flags(__flags); + return __is; + } + + template + const int + discard_block<_UniformRandomNumberGenerator, __p, __r>::block_size; + + template + const int + discard_block<_UniformRandomNumberGenerator, __p, __r>::used_block; + + template + typename discard_block<_UniformRandomNumberGenerator, + __p, __r>::result_type + discard_block<_UniformRandomNumberGenerator, __p, __r>:: + operator()() + { + if (_M_n >= used_block) + { + while (_M_n < block_size) + { + _M_b(); + ++_M_n; + } + _M_n = 0; + } + ++_M_n; + return _M_b(); + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const discard_block<_UniformRandomNumberGenerator, + __p, __r>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::dec | __ios_base::fixed + | __ios_base::left); + __os.fill(__space); + + __os << __x._M_b << __space << __x._M_n; + + __os.flags(__flags); + __os.fill(__fill); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + discard_block<_UniformRandomNumberGenerator, __p, __r>& __x) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::dec | __ios_base::skipws); + + __is >> __x._M_b >> __x._M_n; + + __is.flags(__flags); + return __is; + } + + + template + const int + xor_combine<_UniformRandomNumberGenerator1, __s1, + _UniformRandomNumberGenerator2, __s2>::shift1; + + template + const int + xor_combine<_UniformRandomNumberGenerator1, __s1, + _UniformRandomNumberGenerator2, __s2>::shift2; + + template + void + xor_combine<_UniformRandomNumberGenerator1, __s1, + _UniformRandomNumberGenerator2, __s2>:: + _M_initialize_max() + { + const int __w = std::numeric_limits::digits; + + const result_type __m1 = + std::min(result_type(_M_b1.max() - _M_b1.min()), + __detail::_Shift::__value - 1); + + const result_type __m2 = + std::min(result_type(_M_b2.max() - _M_b2.min()), + __detail::_Shift::__value - 1); + + // NB: In TR1 s1 is not required to be >= s2. + if (__s1 < __s2) + _M_max = _M_initialize_max_aux(__m2, __m1, __s2 - __s1) << __s1; + else + _M_max = _M_initialize_max_aux(__m1, __m2, __s1 - __s2) << __s2; + } + + template + typename xor_combine<_UniformRandomNumberGenerator1, __s1, + _UniformRandomNumberGenerator2, __s2>::result_type + xor_combine<_UniformRandomNumberGenerator1, __s1, + _UniformRandomNumberGenerator2, __s2>:: + _M_initialize_max_aux(result_type __a, result_type __b, int __d) + { + const result_type __two2d = result_type(1) << __d; + const result_type __c = __a * __two2d; + + if (__a == 0 || __b < __two2d) + return __c + __b; + + const result_type __t = std::max(__c, __b); + const result_type __u = std::min(__c, __b); + + result_type __ub = __u; + result_type __p; + for (__p = 0; __ub != 1; __ub >>= 1) + ++__p; + + const result_type __two2p = result_type(1) << __p; + const result_type __k = __t / __two2p; + + if (__k & 1) + return (__k + 1) * __two2p - 1; + + if (__c >= __b) + return (__k + 1) * __two2p + _M_initialize_max_aux((__t % __two2p) + / __two2d, + __u % __two2p, __d); + else + return (__k + 1) * __two2p + _M_initialize_max_aux((__u % __two2p) + / __two2d, + __t % __two2p, __d); + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const xor_combine<_UniformRandomNumberGenerator1, __s1, + _UniformRandomNumberGenerator2, __s2>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::dec | __ios_base::fixed | __ios_base::left); + __os.fill(__space); + + __os << __x.base1() << __space << __x.base2(); + + __os.flags(__flags); + __os.fill(__fill); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + xor_combine<_UniformRandomNumberGenerator1, __s1, + _UniformRandomNumberGenerator2, __s2>& __x) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::skipws); + + __is >> __x._M_b1 >> __x._M_b2; + + __is.flags(__flags); + return __is; + } + + + template + template + typename uniform_int<_IntType>::result_type + uniform_int<_IntType>:: + _M_call(_UniformRandomNumberGenerator& __urng, + result_type __min, result_type __max, true_type) + { + // XXX Must be fixed to work well for *arbitrary* __urng.max(), + // __urng.min(), __max, __min. Currently works fine only in the + // most common case __urng.max() - __urng.min() >= __max - __min, + // with __urng.max() > __urng.min() >= 0. + typedef typename __gnu_cxx::__add_unsigned::__type __urntype; + typedef typename __gnu_cxx::__add_unsigned::__type + __utype; + typedef typename __gnu_cxx::__conditional_type<(sizeof(__urntype) + > sizeof(__utype)), + __urntype, __utype>::__type __uctype; + + result_type __ret; + + const __urntype __urnmin = __urng.min(); + const __urntype __urnmax = __urng.max(); + const __urntype __urnrange = __urnmax - __urnmin; + const __uctype __urange = __max - __min; + const __uctype __udenom = (__urnrange <= __urange + ? 1 : __urnrange / (__urange + 1)); + do + __ret = (__urntype(__urng()) - __urnmin) / __udenom; + while (__ret > __max - __min); + + return __ret + __min; + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const uniform_int<_IntType>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__space); + + __os << __x.min() << __space << __x.max(); + + __os.flags(__flags); + __os.fill(__fill); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + uniform_int<_IntType>& __x) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::dec | __ios_base::skipws); + + __is >> __x._M_min >> __x._M_max; + + __is.flags(__flags); + return __is; + } + + + 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; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const std::streamsize __precision = __os.precision(); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__os.widen(' ')); + __os.precision(__gnu_cxx::__numeric_traits::__max_digits10); + + __os << __x.p(); + + __os.flags(__flags); + __os.fill(__fill); + __os.precision(__precision); + return __os; + } + + + template + template + typename geometric_distribution<_IntType, _RealType>::result_type + geometric_distribution<_IntType, _RealType>:: + operator()(_UniformRandomNumberGenerator& __urng) + { + // About the epsilon thing see this thread: + // http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00971.html + const _RealType __naf = + (1 - std::numeric_limits<_RealType>::epsilon()) / 2; + // The largest _RealType convertible to _IntType. + const _RealType __thr = + std::numeric_limits<_IntType>::max() + __naf; + + _RealType __cand; + do + __cand = std::ceil(std::log(__urng()) / _M_log_p); + while (__cand >= __thr); + + return result_type(__cand + __naf); + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const geometric_distribution<_IntType, _RealType>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const std::streamsize __precision = __os.precision(); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__os.widen(' ')); + __os.precision(__gnu_cxx::__numeric_traits<_RealType>::__max_digits10); + + __os << __x.p(); + + __os.flags(__flags); + __os.fill(__fill); + __os.precision(__precision); + return __os; + } + + + template + void + poisson_distribution<_IntType, _RealType>:: + _M_initialize() + { +#if _GLIBCXX_USE_C99_MATH_TR1 + if (_M_mean >= 12) + { + const _RealType __m = std::floor(_M_mean); + _M_lm_thr = std::log(_M_mean); + _M_lfm = std::tr1::lgamma(__m + 1); + _M_sm = std::sqrt(__m); + + const _RealType __pi_4 = 0.7853981633974483096156608458198757L; + const _RealType __dx = std::sqrt(2 * __m * std::log(32 * __m + / __pi_4)); + _M_d = std::tr1::round(std::max(_RealType(6), + std::min(__m, __dx))); + const _RealType __cx = 2 * __m + _M_d; + _M_scx = std::sqrt(__cx / 2); + _M_1cx = 1 / __cx; + + _M_c2b = std::sqrt(__pi_4 * __cx) * std::exp(_M_1cx); + _M_cb = 2 * __cx * std::exp(-_M_d * _M_1cx * (1 + _M_d / 2)) / _M_d; + } + else +#endif + _M_lm_thr = std::exp(-_M_mean); + } + + /** + * A rejection algorithm when mean >= 12 and a simple method based + * upon the multiplication of uniform random variates otherwise. + * NB: The former is available only if _GLIBCXX_USE_C99_MATH_TR1 + * is defined. + * + * Reference: + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. X, Sects. 3.3 & 3.4 (+ Errata!). + */ + template + template + typename poisson_distribution<_IntType, _RealType>::result_type + poisson_distribution<_IntType, _RealType>:: + operator()(_UniformRandomNumberGenerator& __urng) + { +#if _GLIBCXX_USE_C99_MATH_TR1 + if (_M_mean >= 12) + { + _RealType __x; + + // See comments above... + const _RealType __naf = + (1 - std::numeric_limits<_RealType>::epsilon()) / 2; + const _RealType __thr = + std::numeric_limits<_IntType>::max() + __naf; + + const _RealType __m = std::floor(_M_mean); + // sqrt(pi / 2) + const _RealType __spi_2 = 1.2533141373155002512078826424055226L; + const _RealType __c1 = _M_sm * __spi_2; + const _RealType __c2 = _M_c2b + __c1; + const _RealType __c3 = __c2 + 1; + const _RealType __c4 = __c3 + 1; + // e^(1 / 78) + const _RealType __e178 = 1.0129030479320018583185514777512983L; + const _RealType __c5 = __c4 + __e178; + const _RealType __c = _M_cb + __c5; + const _RealType __2cx = 2 * (2 * __m + _M_d); + + bool __reject = true; + do + { + const _RealType __u = __c * __urng(); + const _RealType __e = -std::log(__urng()); + + _RealType __w = 0.0; + + if (__u <= __c1) + { + const _RealType __n = _M_nd(__urng); + const _RealType __y = -std::abs(__n) * _M_sm - 1; + __x = std::floor(__y); + __w = -__n * __n / 2; + if (__x < -__m) + continue; + } + else if (__u <= __c2) + { + const _RealType __n = _M_nd(__urng); + const _RealType __y = 1 + std::abs(__n) * _M_scx; + __x = std::ceil(__y); + __w = __y * (2 - __y) * _M_1cx; + if (__x > _M_d) + continue; + } + else if (__u <= __c3) + // NB: This case not in the book, nor in the Errata, + // but should be ok... + __x = -1; + else if (__u <= __c4) + __x = 0; + else if (__u <= __c5) + __x = 1; + else + { + const _RealType __v = -std::log(__urng()); + const _RealType __y = _M_d + __v * __2cx / _M_d; + __x = std::ceil(__y); + __w = -_M_d * _M_1cx * (1 + __y / 2); + } + + __reject = (__w - __e - __x * _M_lm_thr + > _M_lfm - std::tr1::lgamma(__x + __m + 1)); + + __reject |= __x + __m >= __thr; + + } while (__reject); + + return result_type(__x + __m + __naf); + } + else +#endif + { + _IntType __x = 0; + _RealType __prod = 1.0; + + do + { + __prod *= __urng(); + __x += 1; + } + while (__prod > _M_lm_thr); + + return __x - 1; + } + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const poisson_distribution<_IntType, _RealType>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const std::streamsize __precision = __os.precision(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__space); + __os.precision(__gnu_cxx::__numeric_traits<_RealType>::__max_digits10); + + __os << __x.mean() << __space << __x._M_nd; + + __os.flags(__flags); + __os.fill(__fill); + __os.precision(__precision); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + poisson_distribution<_IntType, _RealType>& __x) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::skipws); + + __is >> __x._M_mean >> __x._M_nd; + __x._M_initialize(); + + __is.flags(__flags); + return __is; + } + + + template + void + binomial_distribution<_IntType, _RealType>:: + _M_initialize() + { + const _RealType __p12 = _M_p <= 0.5 ? _M_p : 1.0 - _M_p; + + _M_easy = true; + +#if _GLIBCXX_USE_C99_MATH_TR1 + if (_M_t * __p12 >= 8) + { + _M_easy = false; + const _RealType __np = std::floor(_M_t * __p12); + const _RealType __pa = __np / _M_t; + const _RealType __1p = 1 - __pa; + + const _RealType __pi_4 = 0.7853981633974483096156608458198757L; + const _RealType __d1x = + std::sqrt(__np * __1p * std::log(32 * __np + / (81 * __pi_4 * __1p))); + _M_d1 = std::tr1::round(std::max(_RealType(1), __d1x)); + const _RealType __d2x = + std::sqrt(__np * __1p * std::log(32 * _M_t * __1p + / (__pi_4 * __pa))); + _M_d2 = std::tr1::round(std::max(_RealType(1), __d2x)); + + // sqrt(pi / 2) + const _RealType __spi_2 = 1.2533141373155002512078826424055226L; + _M_s1 = std::sqrt(__np * __1p) * (1 + _M_d1 / (4 * __np)); + _M_s2 = std::sqrt(__np * __1p) * (1 + _M_d2 / (4 * _M_t * __1p)); + _M_c = 2 * _M_d1 / __np; + _M_a1 = std::exp(_M_c) * _M_s1 * __spi_2; + const _RealType __a12 = _M_a1 + _M_s2 * __spi_2; + const _RealType __s1s = _M_s1 * _M_s1; + _M_a123 = __a12 + (std::exp(_M_d1 / (_M_t * __1p)) + * 2 * __s1s / _M_d1 + * std::exp(-_M_d1 * _M_d1 / (2 * __s1s))); + const _RealType __s2s = _M_s2 * _M_s2; + _M_s = (_M_a123 + 2 * __s2s / _M_d2 + * std::exp(-_M_d2 * _M_d2 / (2 * __s2s))); + _M_lf = (std::tr1::lgamma(__np + 1) + + std::tr1::lgamma(_M_t - __np + 1)); + _M_lp1p = std::log(__pa / __1p); + + _M_q = -std::log(1 - (__p12 - __pa) / __1p); + } + else +#endif + _M_q = -std::log(1 - __p12); + } + + template + template + typename binomial_distribution<_IntType, _RealType>::result_type + binomial_distribution<_IntType, _RealType>:: + _M_waiting(_UniformRandomNumberGenerator& __urng, _IntType __t) + { + _IntType __x = 0; + _RealType __sum = 0; + + do + { + const _RealType __e = -std::log(__urng()); + __sum += __e / (__t - __x); + __x += 1; + } + while (__sum <= _M_q); + + return __x - 1; + } + + /** + * A rejection algorithm when t * p >= 8 and a simple waiting time + * method - the second in the referenced book - otherwise. + * NB: The former is available only if _GLIBCXX_USE_C99_MATH_TR1 + * is defined. + * + * Reference: + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. X, Sect. 4 (+ Errata!). + */ + template + template + typename binomial_distribution<_IntType, _RealType>::result_type + binomial_distribution<_IntType, _RealType>:: + operator()(_UniformRandomNumberGenerator& __urng) + { + result_type __ret; + const _RealType __p12 = _M_p <= 0.5 ? _M_p : 1.0 - _M_p; + +#if _GLIBCXX_USE_C99_MATH_TR1 + if (!_M_easy) + { + _RealType __x; + + // See comments above... + const _RealType __naf = + (1 - std::numeric_limits<_RealType>::epsilon()) / 2; + const _RealType __thr = + std::numeric_limits<_IntType>::max() + __naf; + + const _RealType __np = std::floor(_M_t * __p12); + const _RealType __pa = __np / _M_t; + + // sqrt(pi / 2) + const _RealType __spi_2 = 1.2533141373155002512078826424055226L; + const _RealType __a1 = _M_a1; + const _RealType __a12 = __a1 + _M_s2 * __spi_2; + const _RealType __a123 = _M_a123; + const _RealType __s1s = _M_s1 * _M_s1; + const _RealType __s2s = _M_s2 * _M_s2; + + bool __reject; + do + { + const _RealType __u = _M_s * __urng(); + + _RealType __v; + + if (__u <= __a1) + { + const _RealType __n = _M_nd(__urng); + const _RealType __y = _M_s1 * std::abs(__n); + __reject = __y >= _M_d1; + if (!__reject) + { + const _RealType __e = -std::log(__urng()); + __x = std::floor(__y); + __v = -__e - __n * __n / 2 + _M_c; + } + } + else if (__u <= __a12) + { + const _RealType __n = _M_nd(__urng); + const _RealType __y = _M_s2 * std::abs(__n); + __reject = __y >= _M_d2; + if (!__reject) + { + const _RealType __e = -std::log(__urng()); + __x = std::floor(-__y); + __v = -__e - __n * __n / 2; + } + } + else if (__u <= __a123) + { + const _RealType __e1 = -std::log(__urng()); + const _RealType __e2 = -std::log(__urng()); + + const _RealType __y = _M_d1 + 2 * __s1s * __e1 / _M_d1; + __x = std::floor(__y); + __v = (-__e2 + _M_d1 * (1 / (_M_t - __np) + -__y / (2 * __s1s))); + __reject = false; + } + else + { + const _RealType __e1 = -std::log(__urng()); + const _RealType __e2 = -std::log(__urng()); + + const _RealType __y = _M_d2 + 2 * __s2s * __e1 / _M_d2; + __x = std::floor(-__y); + __v = -__e2 - _M_d2 * __y / (2 * __s2s); + __reject = false; + } + + __reject = __reject || __x < -__np || __x > _M_t - __np; + if (!__reject) + { + const _RealType __lfx = + std::tr1::lgamma(__np + __x + 1) + + std::tr1::lgamma(_M_t - (__np + __x) + 1); + __reject = __v > _M_lf - __lfx + __x * _M_lp1p; + } + + __reject |= __x + __np >= __thr; + } + while (__reject); + + __x += __np + __naf; + + const _IntType __z = _M_waiting(__urng, _M_t - _IntType(__x)); + __ret = _IntType(__x) + __z; + } + else +#endif + __ret = _M_waiting(__urng, _M_t); + + if (__p12 != _M_p) + __ret = _M_t - __ret; + return __ret; + } + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const binomial_distribution<_IntType, _RealType>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const std::streamsize __precision = __os.precision(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__space); + __os.precision(__gnu_cxx::__numeric_traits<_RealType>::__max_digits10); + + __os << __x.t() << __space << __x.p() + << __space << __x._M_nd; + + __os.flags(__flags); + __os.fill(__fill); + __os.precision(__precision); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + binomial_distribution<_IntType, _RealType>& __x) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::dec | __ios_base::skipws); + + __is >> __x._M_t >> __x._M_p >> __x._M_nd; + __x._M_initialize(); + + __is.flags(__flags); + return __is; + } + + + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>& __os, + const uniform_real<_RealType>& __x) + { + typedef std::basic_ostream<_CharT, _Traits> __ostream_type; + typedef typename __ostream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const std::streamsize __precision = __os.precision(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__space); + __os.precision(__gnu_cxx::__numeric_traits<_RealType>::__max_digits10); + + __os << __x.min() << __space << __x.max(); + + __os.flags(__flags); + __os.fill(__fill); + __os.precision(__precision); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>& __is, + uniform_real<_RealType>& __x) + { + typedef std::basic_istream<_CharT, _Traits> __istream_type; + typedef typename __istream_type::ios_base __ios_base; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::skipws); + + __is >> __x._M_min >> __x._M_max; + + __is.flags(__flags); + return __is; + } + + + 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; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const std::streamsize __precision = __os.precision(); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__os.widen(' ')); + __os.precision(__gnu_cxx::__numeric_traits<_RealType>::__max_digits10); + + __os << __x.lambda(); + + __os.flags(__flags); + __os.fill(__fill); + __os.precision(__precision); + return __os; + } + + + /** + * Polar method due to Marsaglia. + * + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. V, Sect. 4.4. + */ + template + template + typename normal_distribution<_RealType>::result_type + normal_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng) + { + result_type __ret; + + if (_M_saved_available) + { + _M_saved_available = false; + __ret = _M_saved; + } + else + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __urng() - 1.0; + __y = result_type(2.0) * __urng() - 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; + __ret = __y * __mult; + } + + __ret = __ret * _M_sigma + _M_mean; + return __ret; + } + + template + std::basic_ostream<_CharT, _Traits>& + 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; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const std::streamsize __precision = __os.precision(); + const _CharT __space = __os.widen(' '); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__space); + __os.precision(__gnu_cxx::__numeric_traits<_RealType>::__max_digits10); + + __os << __x._M_saved_available << __space + << __x.mean() << __space + << __x.sigma(); + if (__x._M_saved_available) + __os << __space << __x._M_saved; + + __os.flags(__flags); + __os.fill(__fill); + __os.precision(__precision); + return __os; + } + + template + std::basic_istream<_CharT, _Traits>& + 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; + + const typename __ios_base::fmtflags __flags = __is.flags(); + __is.flags(__ios_base::dec | __ios_base::skipws); + + __is >> __x._M_saved_available >> __x._M_mean + >> __x._M_sigma; + if (__x._M_saved_available) + __is >> __x._M_saved; + + __is.flags(__flags); + return __is; + } + + + template + void + gamma_distribution<_RealType>:: + _M_initialize() + { + if (_M_alpha >= 1) + _M_l_d = std::sqrt(2 * _M_alpha - 1); + else + _M_l_d = (std::pow(_M_alpha, _M_alpha / (1 - _M_alpha)) + * (1 - _M_alpha)); + } + + /** + * Cheng's rejection algorithm GB for alpha >= 1 and a modification + * of Vaduva's rejection from Weibull algorithm due to Devroye for + * alpha < 1. + * + * References: + * Cheng, R. C. The Generation of Gamma Random Variables with Non-integral + * Shape Parameter. Applied Statistics, 26, 71-75, 1977. + * + * Vaduva, I. Computer Generation of Gamma Gandom Variables by Rejection + * and Composition Procedures. Math. Operationsforschung and Statistik, + * Series in Statistics, 8, 545-576, 1977. + * + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. IX, Sect. 3.4 (+ Errata!). + */ + template + template + typename gamma_distribution<_RealType>::result_type + gamma_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng) + { + result_type __x; + + bool __reject; + if (_M_alpha >= 1) + { + // alpha - log(4) + const result_type __b = _M_alpha + - result_type(1.3862943611198906188344642429163531L); + const result_type __c = _M_alpha + _M_l_d; + const result_type __1l = 1 / _M_l_d; + + // 1 + log(9 / 2) + const result_type __k = 2.5040773967762740733732583523868748L; + + do + { + const result_type __u = __urng(); + const result_type __v = __urng(); + + const result_type __y = __1l * std::log(__v / (1 - __v)); + __x = _M_alpha * std::exp(__y); + + const result_type __z = __u * __v * __v; + const result_type __r = __b + __c * __y - __x; + + __reject = __r < result_type(4.5) * __z - __k; + if (__reject) + __reject = __r < std::log(__z); + } + while (__reject); + } + else + { + const result_type __c = 1 / _M_alpha; + + do + { + const result_type __z = -std::log(__urng()); + const result_type __e = -std::log(__urng()); + + __x = std::pow(__z, __c); + + __reject = __z + __e < _M_l_d + __x; + } + while (__reject); + } + + return __x; + } + + 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; + + const typename __ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + const std::streamsize __precision = __os.precision(); + __os.flags(__ios_base::scientific | __ios_base::left); + __os.fill(__os.widen(' ')); + __os.precision(__gnu_cxx::__numeric_traits<_RealType>::__max_digits10); + + __os << __x.alpha(); + + __os.flags(__flags); + __os.fill(__fill); + __os.precision(__precision); + return __os; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} +} + +#endif