sl@0: /* boost random/gamma_distribution.hpp header file sl@0: * sl@0: * Copyright Jens Maurer 2002 sl@0: * Distributed under the Boost Software License, Version 1.0. (See sl@0: * accompanying file LICENSE_1_0.txt or copy at sl@0: * http://www.boost.org/LICENSE_1_0.txt) sl@0: * sl@0: * See http://www.boost.org for most recent version including documentation. sl@0: * sl@0: * $Id: gamma_distribution.hpp,v 1.9 2004/07/27 03:43:32 dgregor Exp $ sl@0: * sl@0: */ sl@0: sl@0: #ifndef BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP sl@0: #define BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: namespace boost { sl@0: sl@0: // Knuth sl@0: template sl@0: class gamma_distribution sl@0: { sl@0: public: sl@0: typedef RealType input_type; sl@0: typedef RealType result_type; sl@0: sl@0: #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS sl@0: BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); sl@0: #endif sl@0: sl@0: explicit gamma_distribution(const result_type& alpha = result_type(1)) sl@0: : _exp(result_type(1)), _alpha(alpha) sl@0: { sl@0: assert(alpha > result_type(0)); sl@0: init(); sl@0: } sl@0: sl@0: // compiler-generated copy ctor and assignment operator are fine sl@0: sl@0: RealType alpha() const { return _alpha; } sl@0: sl@0: void reset() { _exp.reset(); } sl@0: sl@0: template sl@0: result_type operator()(Engine& eng) sl@0: { sl@0: #ifndef BOOST_NO_STDC_NAMESPACE sl@0: // allow for Koenig lookup sl@0: using std::tan; using std::sqrt; using std::exp; using std::log; sl@0: using std::pow; sl@0: #endif sl@0: if(_alpha == result_type(1)) { sl@0: return _exp(eng); sl@0: } else if(_alpha > result_type(1)) { sl@0: // Can we have a boost::mathconst please? sl@0: const result_type pi = result_type(3.14159265358979323846); sl@0: for(;;) { sl@0: result_type y = tan(pi * eng()); sl@0: result_type x = sqrt(result_type(2)*_alpha-result_type(1))*y sl@0: + _alpha-result_type(1); sl@0: if(x <= result_type(0)) sl@0: continue; sl@0: if(eng() > sl@0: (result_type(1)+y*y) * exp((_alpha-result_type(1)) sl@0: *log(x/(_alpha-result_type(1))) sl@0: - sqrt(result_type(2)*_alpha sl@0: -result_type(1))*y)) sl@0: continue; sl@0: return x; sl@0: } sl@0: } else /* alpha < 1.0 */ { sl@0: for(;;) { sl@0: result_type u = eng(); sl@0: result_type y = _exp(eng); sl@0: result_type x, q; sl@0: if(u < _p) { sl@0: x = exp(-y/_alpha); sl@0: q = _p*exp(-x); sl@0: } else { sl@0: x = result_type(1)+y; sl@0: q = _p + (result_type(1)-_p) * pow(x, _alpha-result_type(1)); sl@0: } sl@0: if(u >= q) sl@0: continue; sl@0: return x; sl@0: } sl@0: } sl@0: } sl@0: sl@0: #if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) sl@0: template sl@0: friend std::basic_ostream& sl@0: operator<<(std::basic_ostream& os, const gamma_distribution& gd) sl@0: { sl@0: os << gd._alpha; sl@0: return os; sl@0: } sl@0: sl@0: template sl@0: friend std::basic_istream& sl@0: operator>>(std::basic_istream& is, gamma_distribution& gd) sl@0: { sl@0: is >> std::ws >> gd._alpha; sl@0: gd.init(); sl@0: return is; sl@0: } sl@0: #endif sl@0: sl@0: private: sl@0: void init() sl@0: { sl@0: #ifndef BOOST_NO_STDC_NAMESPACE sl@0: // allow for Koenig lookup sl@0: using std::exp; sl@0: #endif sl@0: _p = exp(result_type(1)) / (_alpha + exp(result_type(1))); sl@0: } sl@0: sl@0: exponential_distribution _exp; sl@0: result_type _alpha; sl@0: // some data precomputed from the parameters sl@0: result_type _p; sl@0: }; sl@0: sl@0: } // namespace boost sl@0: sl@0: #endif // BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP