X-Git-Url: https://git.donarmstrong.com/?p=rsem.git;a=blobdiff_plain;f=boost%2Frandom%2Fgamma_distribution.hpp;fp=boost%2Frandom%2Fgamma_distribution.hpp;h=20f5c3b4ff906cb8cb5ab594835cc60ea40be61b;hp=384954baca2994c4afcb7a183dbce988489d06a8;hb=2d71eb92104693ca9baa5a2e1c23eeca776d8fd3;hpb=da57529b92adbb7ae74a89861cb39fb35ac7c62d diff --git a/boost/random/gamma_distribution.hpp b/boost/random/gamma_distribution.hpp index 384954b..20f5c3b 100644 --- a/boost/random/gamma_distribution.hpp +++ b/boost/random/gamma_distribution.hpp @@ -1,13 +1,14 @@ /* boost random/gamma_distribution.hpp header file * * Copyright Jens Maurer 2002 + * Copyright Steven Watanabe 2010 * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * * See http://www.boost.org for most recent version including documentation. * - * $Id: gamma_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * $Id: gamma_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ * */ @@ -15,129 +16,277 @@ #define BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP #include -#include +#include +#include +#include #include #include #include #include namespace boost { +namespace random { // The algorithm is taken from Knuth /** - * The gamma distribution is a continuous distribution with a single - * parameter alpha. + * The gamma distribution is a continuous distribution with two + * parameters alpha and beta. It produces values > 0. * - * It has \f$p(x) = x^{\alpha-1}\frac{e^{-x}}{\Gamma(\alpha)}\f$. + * It has + * \f$\displaystyle p(x) = x^{\alpha-1}\frac{e^{-x/\beta}}{\beta^\alpha\Gamma(\alpha)}\f$. */ template class gamma_distribution { public: - typedef RealType input_type; - typedef RealType result_type; + typedef RealType input_type; + typedef RealType result_type; + + class param_type + { + public: + typedef gamma_distribution distribution_type; + + /** + * Constructs a @c param_type object from the "alpha" and "beta" + * parameters. + * + * Requires: alpha > 0 && beta > 0 + */ + param_type(const RealType& alpha_arg = RealType(1.0), + const RealType& beta_arg = RealType(1.0)) + : _alpha(alpha_arg), _beta(beta_arg) + { + } + + /** Returns the "alpha" parameter of the distribution. */ + RealType alpha() const { return _alpha; } + /** Returns the "beta" parameter of the distribution. */ + RealType beta() const { return _beta; } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + /** Writes the parameters to a @c std::ostream. */ + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, + const param_type& parm) + { + os << parm._alpha << ' ' << parm._beta; + return os; + } + + /** Reads the parameters from a @c std::istream. */ + template + friend std::basic_istream& + operator>>(std::basic_istream& is, param_type& parm) + { + is >> parm._alpha >> std::ws >> parm._beta; + return is; + } +#endif + + /** Returns true if the two sets of parameters are the same. */ + friend bool operator==(const param_type& lhs, const param_type& rhs) + { + return lhs._alpha == rhs._alpha && lhs._beta == rhs._beta; + } + /** Returns true if the two sets fo parameters are different. */ + friend bool operator!=(const param_type& lhs, const param_type& rhs) + { + return !(lhs == rhs); + } + private: + RealType _alpha; + RealType _beta; + }; #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); #endif - explicit gamma_distribution(const result_type& alpha_arg = result_type(1)) - : _exp(result_type(1)), _alpha(alpha_arg) - { - assert(_alpha > result_type(0)); - init(); - } + /** + * Creates a new gamma_distribution with parameters "alpha" and "beta". + * + * Requires: alpha > 0 && beta > 0 + */ + explicit gamma_distribution(const result_type& alpha_arg = result_type(1.0), + const result_type& beta_arg = result_type(1.0)) + : _exp(result_type(1)), _alpha(alpha_arg), _beta(beta_arg) + { + BOOST_ASSERT(_alpha > result_type(0)); + BOOST_ASSERT(_beta > result_type(0)); + init(); + } + + /** Constructs a @c gamma_distribution from its parameters. */ + explicit gamma_distribution(const param_type& parm) + : _exp(result_type(1)), _alpha(parm.alpha()), _beta(parm.beta()) + { + init(); + } - // compiler-generated copy ctor and assignment operator are fine + // compiler-generated copy ctor and assignment operator are fine - RealType alpha() const { return _alpha; } + /** Returns the "alpha" paramter of the distribution. */ + RealType alpha() const { return _alpha; } + /** Returns the "beta" parameter of the distribution. */ + RealType beta() const { return _beta; } + /** Returns the smallest value that the distribution can produce. */ + RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } + /* Returns the largest value that the distribution can produce. */ + RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const + { return (std::numeric_limits::infinity)(); } - void reset() { _exp.reset(); } + /** Returns the parameters of the distribution. */ + param_type param() const { return param_type(_alpha, _beta); } + /** Sets the parameters of the distribution. */ + void param(const param_type& parm) + { + _alpha = parm.alpha(); + _beta = parm.beta(); + init(); + } + + /** + * Effects: Subsequent uses of the distribution do not depend + * on values produced by any engine prior to invoking reset. + */ + void reset() { _exp.reset(); } - template - result_type operator()(Engine& eng) - { + /** + * Returns a random variate distributed according to + * the gamma distribution. + */ + template + result_type operator()(Engine& eng) + { #ifndef BOOST_NO_STDC_NAMESPACE - // allow for Koenig lookup - using std::tan; using std::sqrt; using std::exp; using std::log; - using std::pow; + // allow for Koenig lookup + using std::tan; using std::sqrt; using std::exp; using std::log; + using std::pow; #endif - if(_alpha == result_type(1)) { - return _exp(eng); - } else if(_alpha > result_type(1)) { - // Can we have a boost::mathconst please? - const result_type pi = result_type(3.14159265358979323846); - for(;;) { - result_type y = tan(pi * eng()); - result_type x = sqrt(result_type(2)*_alpha-result_type(1))*y - + _alpha-result_type(1); - if(x <= result_type(0)) - continue; - if(eng() > - (result_type(1)+y*y) * exp((_alpha-result_type(1)) - *log(x/(_alpha-result_type(1))) - - sqrt(result_type(2)*_alpha - -result_type(1))*y)) - continue; - return x; - } - } else /* alpha < 1.0 */ { - for(;;) { - result_type u = eng(); - result_type y = _exp(eng); - result_type x, q; - if(u < _p) { - x = exp(-y/_alpha); - q = _p*exp(-x); - } else { - x = result_type(1)+y; - q = _p + (result_type(1)-_p) * pow(x, _alpha-result_type(1)); + if(_alpha == result_type(1)) { + return _exp(eng) * _beta; + } else if(_alpha > result_type(1)) { + // Can we have a boost::mathconst please? + const result_type pi = result_type(3.14159265358979323846); + for(;;) { + result_type y = tan(pi * uniform_01()(eng)); + result_type x = sqrt(result_type(2)*_alpha-result_type(1))*y + + _alpha-result_type(1); + if(x <= result_type(0)) + continue; + if(uniform_01()(eng) > + (result_type(1)+y*y) * exp((_alpha-result_type(1)) + *log(x/(_alpha-result_type(1))) + - sqrt(result_type(2)*_alpha + -result_type(1))*y)) + continue; + return x * _beta; + } + } else /* alpha < 1.0 */ { + for(;;) { + result_type u = uniform_01()(eng); + result_type y = _exp(eng); + result_type x, q; + if(u < _p) { + x = exp(-y/_alpha); + q = _p*exp(-x); + } else { + x = result_type(1)+y; + q = _p + (result_type(1)-_p) * pow(x,_alpha-result_type(1)); + } + if(u >= q) + continue; + return x * _beta; + } } - if(u >= q) - continue; - return x; - } } - } + + template + RealType operator()(URNG& urng, const param_type& parm) const + { + return gamma_distribution(parm)(urng); + } #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS - template - friend std::basic_ostream& - operator<<(std::basic_ostream& os, const gamma_distribution& gd) - { - os << gd._alpha; - return os; - } - - template - friend std::basic_istream& - operator>>(std::basic_istream& is, gamma_distribution& gd) - { - is >> std::ws >> gd._alpha; - gd.init(); - return is; - } + /** Writes a @c gamma_distribution to a @c std::ostream. */ + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, + const gamma_distribution& gd) + { + os << gd.param(); + return os; + } + + /** Reads a @c gamma_distribution from a @c std::istream. */ + template + friend std::basic_istream& + operator>>(std::basic_istream& is, gamma_distribution& gd) + { + gd.read(is); + return is; + } #endif + /** + * Returns true if the two distributions will produce identical + * sequences of random variates given equal generators. + */ + friend bool operator==(const gamma_distribution& lhs, + const gamma_distribution& rhs) + { + return lhs._alpha == rhs._alpha + && lhs._beta == rhs._beta + && lhs._exp == rhs._exp; + } + + /** + * Returns true if the two distributions can produce different + * sequences of random variates, given equal generators. + */ + friend bool operator!=(const gamma_distribution& lhs, + const gamma_distribution& rhs) + { + return !(lhs == rhs); + } + private: - /// \cond hide_private_members - void init() - { + /// \cond hide_private_members + + template + void read(std::basic_istream& is) + { + param_type parm; + if(is >> parm) { + param(parm); + } + } + + void init() + { #ifndef BOOST_NO_STDC_NAMESPACE - // allow for Koenig lookup - using std::exp; + // allow for Koenig lookup + using std::exp; #endif - _p = exp(result_type(1)) / (_alpha + exp(result_type(1))); - } - /// \endcond - - exponential_distribution _exp; - result_type _alpha; - // some data precomputed from the parameters - result_type _p; + _p = exp(result_type(1)) / (_alpha + exp(result_type(1))); + } + /// \endcond + + exponential_distribution _exp; + result_type _alpha; + result_type _beta; + // some data precomputed from the parameters + result_type _p; }; + +} // namespace random + +using random::gamma_distribution; + } // namespace boost #endif // BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP