]> git.donarmstrong.com Git - rsem.git/blob - boost/random/gamma_distribution.hpp
RSEM Source Codes
[rsem.git] / boost / random / gamma_distribution.hpp
1 /* boost random/gamma_distribution.hpp header file
2  *
3  * Copyright Jens Maurer 2002
4  * Distributed under the Boost Software License, Version 1.0. (See
5  * accompanying file LICENSE_1_0.txt or copy at
6  * http://www.boost.org/LICENSE_1_0.txt)
7  *
8  * See http://www.boost.org for most recent version including documentation.
9  *
10  * $Id: gamma_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $
11  *
12  */
13
14 #ifndef BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP
15 #define BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP
16
17 #include <boost/config/no_tr1/cmath.hpp>
18 #include <cassert>
19 #include <boost/limits.hpp>
20 #include <boost/static_assert.hpp>
21 #include <boost/random/detail/config.hpp>
22 #include <boost/random/exponential_distribution.hpp>
23
24 namespace boost {
25
26 // The algorithm is taken from Knuth
27
28 /**
29  * The gamma distribution is a continuous distribution with a single
30  * parameter alpha.
31  *
32  * It has \f$p(x) = x^{\alpha-1}\frac{e^{-x}}{\Gamma(\alpha)}\f$.
33  */
34 template<class RealType = double>
35 class gamma_distribution
36 {
37 public:
38   typedef RealType input_type;
39   typedef RealType result_type;
40
41 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
42   BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
43 #endif
44
45   explicit gamma_distribution(const result_type& alpha_arg = result_type(1))
46     : _exp(result_type(1)), _alpha(alpha_arg)
47   {
48     assert(_alpha > result_type(0));
49     init();
50   }
51
52   // compiler-generated copy ctor and assignment operator are fine
53
54   RealType alpha() const { return _alpha; }
55
56   void reset() { _exp.reset(); }
57
58   template<class Engine>
59   result_type operator()(Engine& eng)
60   {
61 #ifndef BOOST_NO_STDC_NAMESPACE
62     // allow for Koenig lookup
63     using std::tan; using std::sqrt; using std::exp; using std::log;
64     using std::pow;
65 #endif
66     if(_alpha == result_type(1)) {
67       return _exp(eng);
68     } else if(_alpha > result_type(1)) {
69       // Can we have a boost::mathconst please?
70       const result_type pi = result_type(3.14159265358979323846);
71       for(;;) {
72         result_type y = tan(pi * eng());
73         result_type x = sqrt(result_type(2)*_alpha-result_type(1))*y
74           + _alpha-result_type(1);
75         if(x <= result_type(0))
76           continue;
77         if(eng() >
78            (result_type(1)+y*y) * exp((_alpha-result_type(1))
79                                         *log(x/(_alpha-result_type(1)))
80                                         - sqrt(result_type(2)*_alpha
81                                                -result_type(1))*y))
82           continue;
83         return x;
84       }
85     } else /* alpha < 1.0 */ {
86       for(;;) {
87         result_type u = eng();
88         result_type y = _exp(eng);
89         result_type x, q;
90         if(u < _p) {
91           x = exp(-y/_alpha);
92           q = _p*exp(-x);
93         } else {
94           x = result_type(1)+y;
95           q = _p + (result_type(1)-_p) * pow(x, _alpha-result_type(1));
96         }
97         if(u >= q)
98           continue;
99         return x;
100       }
101     }
102   }
103
104 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
105   template<class CharT, class Traits>
106   friend std::basic_ostream<CharT,Traits>&
107   operator<<(std::basic_ostream<CharT,Traits>& os, const gamma_distribution& gd)
108   {
109     os << gd._alpha;
110     return os;
111   }
112
113   template<class CharT, class Traits>
114   friend std::basic_istream<CharT,Traits>&
115   operator>>(std::basic_istream<CharT,Traits>& is, gamma_distribution& gd)
116   {
117     is >> std::ws >> gd._alpha;
118     gd.init();
119     return is;
120   }
121 #endif
122
123 private:
124   /// \cond hide_private_members
125   void init()
126   {
127 #ifndef BOOST_NO_STDC_NAMESPACE
128     // allow for Koenig lookup
129     using std::exp;
130 #endif
131     _p = exp(result_type(1)) / (_alpha + exp(result_type(1)));
132   }
133   /// \endcond
134
135   exponential_distribution<RealType> _exp;
136   result_type _alpha;
137   // some data precomputed from the parameters
138   result_type _p;
139 };
140
141 } // namespace boost
142
143 #endif // BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP