diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b07378d10c1b..4173c75951e1 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,7 +1,33 @@ +2009-06-11 Paolo Carlini + + * include/bits/random.tcc + (negative_binomial_distribution<>::operator() + (_UniformRandomNumberGenerator&, const param_type&): Tweak to use a + class member gamma_distribution. + (negative_binomial_distribution<>::operator() + (_UniformRandomNumberGenerator&)): Implement out of line here. + (operator<<(basic_ostream<>&, negative_binomial_distribution<>), + operator>>(basic_ostream<>&, negative_binomial_distribution<>): Adjust. + (student_t_distribution<>::operator() + (_UniformRandomNumberGenerator&, const param_type&): Move inline, + simplify. + (operator<<(basic_ostream<>&, student_t_distribution<>), + operator>>(basic_ostream<>&, student_t_distribution<>): Adjust. + (chi_squared_distribution<>::operator() + (_UniformRandomNumberGenerator&, const param_type&): Move inline, + tweak to use a class member gamma_distribution. + (operator<<(basic_ostream<>&, chi_squared_distribution<>), + operator>>(basic_ostream<>&, chi_squared_distribution<>): Adjust. + (fisher_f_distribution<>::operator() (_UniformRandomNumberGenerator&, + const param_type&): Move inline, tweak to use class member + gamma_distributions. + (operator<<(basic_ostream<>&, fisher_f_distribution<>), + operator>>(basic_ostream<>&, fisher_f_distribution<>): Adjust. + * include/bits/random.h: Adjust, minor tweaks. + 2009-06-10 Tom Tromey - * python/libstdcxx/v6/printers.py (lookup_function): Remove extra - ';'. + * python/libstdcxx/v6/printers.py (lookup_function): Remove extra ';'. (build_libstdcxx_dictionary): Accept shortened form of basic_string names. (StdStringPrinter.to_string): Remove reference to WideEncoding. diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 8a21ae55da7d..e8edbf05dd44 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -2078,7 +2078,7 @@ namespace std private: param_type _M_param; - normal_distribution _M_nd; + std::normal_distribution _M_nd; }; /** @@ -2111,15 +2111,16 @@ namespace std operator>>(std::basic_istream<_CharT, _Traits>&, std::lognormal_distribution<_RealType>&); - + /** - * @brief A chi_squared_distribution random number distribution. + * @brief A gamma continuous distribution for random numbers. * - * The formula for the normal probability mass function is - * @f$ p(x|n) = \frac{x^{(n/2) - 1}e^{-x/2}}{\Gamma(n/2) 2^{n/2}} @f$ + * The formula for the gamma probability density function is + * @f$ p(x|\alpha,\beta) = \frac{1}{\beta\Gamma(\alpha)} + * (x/\beta)^{\alpha - 1} e^{-x/\beta} @f$. */ template - class chi_squared_distribution + class gamma_distribution { public: /** The type of the range of the distribution. */ @@ -2127,29 +2128,50 @@ namespace std /** Parameter type. */ struct param_type { - typedef chi_squared_distribution<_RealType> distribution_type; + typedef gamma_distribution<_RealType> distribution_type; + friend class gamma_distribution<_RealType>; explicit - param_type(_RealType __n = _RealType(1)) - : _M_n(__n) - { } + param_type(_RealType __alpha_val = _RealType(1), + _RealType __beta_val = _RealType(1)) + : _M_alpha(__alpha_val), _M_beta(__beta_val) + { + _GLIBCXX_DEBUG_ASSERT(_M_alpha > _RealType(0)); + _M_initialize(); + } _RealType - n() const - { return _M_n; } + alpha() const + { return _M_alpha; } + + _RealType + beta() const + { return _M_beta; } private: - _RealType _M_n; + void + _M_initialize(); + + _RealType _M_alpha; + _RealType _M_beta; + + _RealType _M_malpha, _M_a2; }; + public: + /** + * @brief Constructs a gamma distribution with parameters + * @f$ \alpha @f$ and @f$ \beta @f$. + */ explicit - chi_squared_distribution(_RealType __n = _RealType(1)) - : _M_param(__n) + gamma_distribution(_RealType __alpha_val = _RealType(1), + _RealType __beta_val = _RealType(1)) + : _M_param(__alpha_val, __beta_val), _M_nd() { } explicit - chi_squared_distribution(const param_type& __p) - : _M_param(__p) + gamma_distribution(const param_type& __p) + : _M_param(__p), _M_nd() { } /** @@ -2157,14 +2179,21 @@ namespace std */ void reset() - { } + { _M_nd.reset(); } /** - * + * @brief Returns the @f$ \alpha @f$ of the distribution. */ _RealType - n() const - { return _M_param.n(); } + alpha() const + { return _M_param.alpha(); } + + /** + * @brief Returns the @f$ \beta @f$ of the distribution. + */ + _RealType + beta() const + { return _M_param.beta(); } /** * @brief Returns the parameter set of the distribution. @@ -2207,6 +2236,142 @@ namespace std private: param_type _M_param; + + std::normal_distribution _M_nd; + }; + + /** + * @brief Inserts a %gamma_distribution random number distribution + * @p __x into the output stream @p __os. + * + * @param __os An output stream. + * @param __x A %gamma_distribution random number distribution. + * + * @returns The output stream with the state of @p __x inserted or in + * an error state. + */ + template + std::basic_ostream<_CharT, _Traits>& + operator<<(std::basic_ostream<_CharT, _Traits>&, + const std::gamma_distribution<_RealType>&); + + /** + * @brief Extracts a %gamma_distribution random number distribution + * @p __x from the input stream @p __is. + * + * @param __is An input stream. + * @param __x A %gamma_distribution random number generator engine. + * + * @returns The input stream with @p __x extracted or in an error state. + */ + template + std::basic_istream<_CharT, _Traits>& + operator>>(std::basic_istream<_CharT, _Traits>&, + std::gamma_distribution<_RealType>&); + + + /** + * @brief A chi_squared_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f$ p(x|n) = \frac{x^{(n/2) - 1}e^{-x/2}}{\Gamma(n/2) 2^{n/2}} @f$ + */ + template + class chi_squared_distribution + { + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + /** Parameter type. */ + struct param_type + { + typedef chi_squared_distribution<_RealType> distribution_type; + + explicit + param_type(_RealType __n = _RealType(1)) + : _M_n(__n) + { } + + _RealType + n() const + { return _M_n; } + + private: + _RealType _M_n; + }; + + explicit + chi_squared_distribution(_RealType __n = _RealType(1)) + : _M_param(__n), _M_gd(__n / 2) + { } + + explicit + chi_squared_distribution(const param_type& __p) + : _M_param(__p), _M_gd(__p.n() / 2) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_gd.reset(); } + + /** + * + */ + _RealType + n() const + { return _M_param.n(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return 2 * _M_gd(__urng); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + return 2 * _M_gd(__urng, param_type(__p.n() / 2)); + } + + private: + param_type _M_param; + + std::gamma_distribution _M_gd; }; /** @@ -2420,12 +2585,12 @@ namespace std explicit fisher_f_distribution(_RealType __m = _RealType(1), _RealType __n = _RealType(1)) - : _M_param(__m, __n) + : _M_param(__m, __n), _M_gd_x(__m / 2), _M_gd_y(__n / 2) { } explicit fisher_f_distribution(const param_type& __p) - : _M_param(__p) + : _M_param(__p), _M_gd_x(__p.m() / 2), _M_gd_y(__p.n() / 2) { } /** @@ -2433,7 +2598,10 @@ namespace std */ void reset() - { } + { + _M_gd_x.reset(); + _M_gd_y.reset(); + } /** * @@ -2478,15 +2646,23 @@ namespace std template result_type operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, this->param()); } + { return (_M_gd_x(__urng) * n()) / (_M_gd_y(__urng) * m()); } template result_type operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + return ((_M_gd_x(__urng, param_type(__p.m() / 2)) * n()) + / (_M_gd_y(__urng, param_type(__p.n() / 2)) * m())); + } private: param_type _M_param; + + std::gamma_distribution _M_gd_x, _M_gd_y; }; /** @@ -2553,12 +2729,12 @@ namespace std explicit student_t_distribution(_RealType __n = _RealType(1)) - : _M_param(__n), _M_nd() + : _M_param(__n), _M_nd(), _M_gd(__n / 2, 2) { } explicit student_t_distribution(const param_type& __p) - : _M_param(__p), _M_nd() + : _M_param(__p), _M_nd(), _M_gd(__p.n() / 2, 2) { } /** @@ -2566,7 +2742,10 @@ namespace std */ void reset() - { _M_nd.reset(); } + { + _M_nd.reset(); + _M_gd.reset(); + } /** * @@ -2606,18 +2785,26 @@ namespace std template result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, this->param()); } + operator()(_UniformRandomNumberGenerator& __urng) + { return _M_nd(__urng) * std::sqrt(n() / _M_gd(__urng)); } template result_type operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + + const result_type __g = _M_gd(__urng, param_type(__p.n() / 2, 2)); + return _M_nd(__urng) * std::sqrt(__p.n() / __g); + } private: param_type _M_param; - normal_distribution _M_nd; + std::normal_distribution _M_nd; + std::gamma_distribution _M_gd; }; /** @@ -2977,7 +3164,7 @@ namespace std param_type _M_param; // NB: Unused when _GLIBCXX_USE_C99_MATH_TR1 is undefined. - normal_distribution _M_nd; + std::normal_distribution _M_nd; }; @@ -3166,12 +3353,12 @@ namespace std explicit negative_binomial_distribution(_IntType __k = 1, double __p = 0.5) - : _M_param(__k, __p) + : _M_param(__k, __p), _M_gd(__k, __p / (1.0 - __p)) { } explicit negative_binomial_distribution(const param_type& __p) - : _M_param(__p) + : _M_param(__p), _M_gd(__p.k(), __p.p() / (1.0 - __p.p())) { } /** @@ -3179,7 +3366,7 @@ namespace std */ void reset() - { } + { _M_gd.reset(); } /** * @brief Return the @f$ k @f$ parameter of the distribution. @@ -3226,8 +3413,7 @@ namespace std template result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, this->param()); } + operator()(_UniformRandomNumberGenerator& __urng); template result_type @@ -3236,6 +3422,8 @@ namespace std private: param_type _M_param; + + std::gamma_distribution _M_gd; }; /** @@ -3421,7 +3609,7 @@ namespace std param_type _M_param; // NB: Unused when _GLIBCXX_USE_C99_MATH_TR1 is undefined. - normal_distribution _M_nd; + std::normal_distribution _M_nd; }; /** @@ -3574,164 +3762,6 @@ namespace std std::exponential_distribution<_RealType>&); - /** - * @brief A gamma continuous distribution for random numbers. - * - * The formula for the gamma probability density function is - * @f$ p(x|\alpha,\beta) = \frac{1}{\beta\Gamma(\alpha)} - * (x/\beta)^{\alpha - 1} e^{-x/\beta} @f$. - */ - template - class gamma_distribution - { - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - /** Parameter type. */ - struct param_type - { - typedef gamma_distribution<_RealType> distribution_type; - friend class gamma_distribution<_RealType>; - - explicit - param_type(_RealType __alpha_val = _RealType(1), - _RealType __beta_val = _RealType(1)) - : _M_alpha(__alpha_val), _M_beta(__beta_val) - { - _GLIBCXX_DEBUG_ASSERT(_M_alpha > _RealType(0)); - _M_initialize(); - } - - _RealType - alpha() const - { return _M_alpha; } - - _RealType - beta() const - { return _M_beta; } - - private: - void - _M_initialize(); - - _RealType _M_alpha; - _RealType _M_beta; - - _RealType _M_malpha, _M_a2; - }; - - public: - /** - * @brief Constructs a gamma distribution with parameters - * @f$ \alpha @f$ and @f$ \beta @f$. - */ - explicit - gamma_distribution(_RealType __alpha_val = _RealType(1), - _RealType __beta_val = _RealType(1)) - : _M_param(__alpha_val, __beta_val), _M_nd() - { } - - explicit - gamma_distribution(const param_type& __p) - : _M_param(__p), _M_nd() - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { _M_nd.reset(); } - - /** - * @brief Returns the @f$ \alpha @f$ of the distribution. - */ - _RealType - alpha() const - { return _M_param.alpha(); } - - /** - * @brief Returns the @f$ \beta @f$ of the distribution. - */ - _RealType - beta() const - { return _M_param.beta(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, this->param()); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - private: - param_type _M_param; - - normal_distribution _M_nd; - }; - - /** - * @brief Inserts a %gamma_distribution random number distribution - * @p __x into the output stream @p __os. - * - * @param __os An output stream. - * @param __x A %gamma_distribution random number distribution. - * - * @returns The output stream with the state of @p __x inserted or in - * an error state. - */ - template - std::basic_ostream<_CharT, _Traits>& - operator<<(std::basic_ostream<_CharT, _Traits>&, - const std::gamma_distribution<_RealType>&); - - /** - * @brief Extracts a %gamma_distribution random number distribution - * @p __x from the input stream @p __is. - * - * @param __is An input stream. - * @param __x A %gamma_distribution random number generator engine. - * - * @returns The input stream with @p __x extracted or in an error state. - */ - template - std::basic_istream<_CharT, _Traits>& - operator>>(std::basic_istream<_CharT, _Traits>&, - std::gamma_distribution<_RealType>&); - - /** * @brief A weibull_distribution random number distribution. * diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index b933f6d3dfcf..eb2ce4a4500a 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -854,6 +854,20 @@ namespace std return __is; } + + template + template + typename negative_binomial_distribution<_IntType>::result_type + negative_binomial_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng) + { + const double __y = _M_gd(__urng); + + // XXX Is the constructor too slow? + std::poisson_distribution __poisson(__y); + return __poisson(__urng); + } + template template typename negative_binomial_distribution<_IntType>::result_type @@ -861,11 +875,13 @@ namespace std operator()(_UniformRandomNumberGenerator& __urng, const param_type& __p) { - gamma_distribution<> __gamma(__p.k(), 1.0); - double __x = __gamma(__urng); + typedef typename std::gamma_distribution::param_type + param_type; + + const double __y = + _M_gd(__urng, param_type(__p.k(), __p.p() / (1.0 - __p.p()))); - poisson_distribution __poisson(__x * __p.p() - / (1.0 - __p.p())); + std::poisson_distribution __poisson(__y); return __poisson(__urng); } @@ -885,7 +901,8 @@ namespace std __os.fill(__os.widen(' ')); __os.precision(std::numeric_limits::digits10 + 1); - __os << __x.k() << __space << __x.p(); + __os << __x.k() << __space << __x.p() + << __space << __x._M_gd; __os.flags(__flags); __os.fill(__fill); @@ -906,7 +923,7 @@ namespace std _IntType __k; double __p; - __is >> __k >> __p; + __is >> __k >> __p >> __x._M_gd; __x.param(typename negative_binomial_distribution<_IntType>:: param_type(__k, __p)); @@ -1538,17 +1555,6 @@ namespace std } - template - template - typename chi_squared_distribution<_RealType>::result_type - chi_squared_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - gamma_distribution<_RealType> __gamma(__p.n() / 2, 1.0); - return 2 * __gamma(__urng); - } - template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, @@ -1565,7 +1571,7 @@ namespace std __os.fill(__space); __os.precision(std::numeric_limits<_RealType>::digits10 + 1); - __os << __x.n(); + __os << __x.n() << __space << __x._M_gd; __os.flags(__flags); __os.fill(__fill); @@ -1585,7 +1591,7 @@ namespace std __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __n; - __is >> __n; + __is >> __n >> __x._M_gd; __x.param(typename chi_squared_distribution<_RealType>:: param_type(__n)); @@ -1657,23 +1663,6 @@ namespace std } - template - template - typename fisher_f_distribution<_RealType>::result_type - fisher_f_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - gamma_distribution<_RealType> __gamma; - _RealType __ym = __gamma(__urng, - typename gamma_distribution<_RealType>::param_type(__p.m() / 2, 2)); - - _RealType __yn = __gamma(__urng, - typename gamma_distribution<_RealType>::param_type(__p.n() / 2, 2)); - - return (__ym * __p.n()) / (__yn * __p.m()); - } - template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, @@ -1690,7 +1679,8 @@ namespace std __os.fill(__space); __os.precision(std::numeric_limits<_RealType>::digits10 + 1); - __os << __x.m() << __space << __x.n(); + __os << __x.m() << __space << __x.n() + << __space << __x._M_gd_x << __space << __x._M_gd_y; __os.flags(__flags); __os.fill(__fill); @@ -1710,7 +1700,7 @@ namespace std __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __m, __n; - __is >> __m >> __n; + __is >> __m >> __n >> __x._M_gd_x >> __x._M_gd_y; __x.param(typename fisher_f_distribution<_RealType>:: param_type(__m, __n)); @@ -1719,43 +1709,6 @@ namespace std } - template - template - typename student_t_distribution<_RealType>::result_type - student_t_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - if (__param.n() <= 2.0) - { - _RealType __y1 = _M_nd(__urng); - chi_squared_distribution<_RealType> __chisq(__param.n()); - _RealType __y2 = __chisq(__urng); - - return __y1 / std::sqrt(__y2 / __param.n()); - } - else - { - _RealType __y1, __y2, __z; - exponential_distribution<_RealType> - __exponential(1.0 / (__param.n() / 2.0 - 1.0)); - - do - { - __y1 = _M_nd(__urng); - __y2 = __exponential(__urng); - - __z = __y1 * __y1 / (__param.n() - 2.0); - } - while (1.0 - __z < 0.0 || std::exp(-__y2 - __z) > (1.0 - __z)); - - // Note that there is a typo in Knuth's formula, the line below - // is taken from the original paper of Marsaglia, Mathematics of - // Computation, 34 (1980), p 234-256 - return __y1 / std::sqrt((1.0 - 2.0 / __param.n()) * (1.0 - __z)); - } - } - template std::basic_ostream<_CharT, _Traits>& operator<<(std::basic_ostream<_CharT, _Traits>& __os, @@ -1772,7 +1725,7 @@ namespace std __os.fill(__space); __os.precision(std::numeric_limits<_RealType>::digits10 + 1); - __os << __x.n() << __space << __x._M_nd; + __os << __x.n() << __space << __x._M_nd << __space << __x._M_gd; __os.flags(__flags); __os.fill(__fill); @@ -1792,7 +1745,7 @@ namespace std __is.flags(__ios_base::dec | __ios_base::skipws); _RealType __n; - __is >> __n >> __x._M_nd; + __is >> __n >> __x._M_nd >> __x._M_gd; __x.param(typename student_t_distribution<_RealType>::param_type(__n)); __is.flags(__flags);