1 | /* boost random/negative_binomial_distribution.hpp header file |
2 | * |
3 | * Copyright Steven Watanabe 2010 |
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$ |
11 | */ |
12 | |
13 | #ifndef BOOST_RANDOM_NEGATIVE_BINOMIAL_DISTRIBUTION_HPP_INCLUDED |
14 | #define BOOST_RANDOM_NEGATIVE_BINOMIAL_DISTRIBUTION_HPP_INCLUDED |
15 | |
16 | #include <iosfwd> |
17 | |
18 | #include <boost/limits.hpp> |
19 | #include <boost/random/detail/config.hpp> |
20 | #include <boost/random/gamma_distribution.hpp> |
21 | #include <boost/random/poisson_distribution.hpp> |
22 | |
23 | namespace boost { |
24 | namespace random { |
25 | |
26 | /** |
27 | * The negative binomial distribution is an integer valued |
28 | * distribution with two parameters, @c k and @c p. The |
29 | * distribution produces non-negative values. |
30 | * |
31 | * The distribution function is |
32 | * \f$\displaystyle P(i) = {k+i-1\choose i}p^k(1-p)^i\f$. |
33 | * |
34 | * This implementation uses a gamma-poisson mixture. |
35 | */ |
36 | template<class IntType = int, class RealType = double> |
37 | class negative_binomial_distribution { |
38 | public: |
39 | typedef IntType result_type; |
40 | typedef RealType input_type; |
41 | |
42 | class param_type { |
43 | public: |
44 | typedef negative_binomial_distribution distribution_type; |
45 | /** |
46 | * Construct a param_type object. @c k and @c p |
47 | * are the parameters of the distribution. |
48 | * |
49 | * Requires: k >=0 && 0 <= p <= 1 |
50 | */ |
51 | explicit param_type(IntType k_arg = 1, RealType p_arg = RealType (0.5)) |
52 | : _k(k_arg), _p(p_arg) |
53 | {} |
54 | /** Returns the @c k parameter of the distribution. */ |
55 | IntType k() const { return _k; } |
56 | /** Returns the @c p parameter of the distribution. */ |
57 | RealType p() const { return _p; } |
58 | #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS |
59 | /** Writes the parameters of the distribution to a @c std::ostream. */ |
60 | template<class CharT, class Traits> |
61 | friend std::basic_ostream<CharT,Traits>& |
62 | operator<<(std::basic_ostream<CharT,Traits>& os, |
63 | const param_type& parm) |
64 | { |
65 | os << parm._p << " " << parm._k; |
66 | return os; |
67 | } |
68 | |
69 | /** Reads the parameters of the distribution from a @c std::istream. */ |
70 | template<class CharT, class Traits> |
71 | friend std::basic_istream<CharT,Traits>& |
72 | operator>>(std::basic_istream<CharT,Traits>& is, param_type& parm) |
73 | { |
74 | is >> parm._p >> std::ws >> parm._k; |
75 | return is; |
76 | } |
77 | #endif |
78 | /** Returns true if the parameters have the same values. */ |
79 | friend bool operator==(const param_type& lhs, const param_type& rhs) |
80 | { |
81 | return lhs._k == rhs._k && lhs._p == rhs._p; |
82 | } |
83 | /** Returns true if the parameters have different values. */ |
84 | friend bool operator!=(const param_type& lhs, const param_type& rhs) |
85 | { |
86 | return !(lhs == rhs); |
87 | } |
88 | private: |
89 | IntType _k; |
90 | RealType _p; |
91 | }; |
92 | |
93 | /** |
94 | * Construct a @c negative_binomial_distribution object. @c k and @c p |
95 | * are the parameters of the distribution. |
96 | * |
97 | * Requires: k >=0 && 0 <= p <= 1 |
98 | */ |
99 | explicit negative_binomial_distribution(IntType k_arg = 1, |
100 | RealType p_arg = RealType(0.5)) |
101 | : _k(k_arg), _p(p_arg) |
102 | {} |
103 | |
104 | /** |
105 | * Construct an @c negative_binomial_distribution object from the |
106 | * parameters. |
107 | */ |
108 | explicit negative_binomial_distribution(const param_type& parm) |
109 | : _k(parm.k()), _p(parm.p()) |
110 | {} |
111 | |
112 | /** |
113 | * Returns a random variate distributed according to the |
114 | * negative binomial distribution. |
115 | */ |
116 | template<class URNG> |
117 | IntType operator()(URNG& urng) const |
118 | { |
119 | gamma_distribution<RealType> gamma(_k, (1-_p)/_p); |
120 | poisson_distribution<IntType, RealType> poisson(gamma(urng)); |
121 | return poisson(urng); |
122 | } |
123 | |
124 | /** |
125 | * Returns a random variate distributed according to the negative |
126 | * binomial distribution with parameters specified by @c param. |
127 | */ |
128 | template<class URNG> |
129 | IntType operator()(URNG& urng, const param_type& parm) const |
130 | { |
131 | return negative_binomial_distribution(parm)(urng); |
132 | } |
133 | |
134 | /** Returns the @c k parameter of the distribution. */ |
135 | IntType k() const { return _k; } |
136 | /** Returns the @c p parameter of the distribution. */ |
137 | RealType p() const { return _p; } |
138 | |
139 | /** Returns the smallest value that the distribution can produce. */ |
140 | IntType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; } |
141 | /** Returns the largest value that the distribution can produce. */ |
142 | IntType max BOOST_PREVENT_MACRO_SUBSTITUTION() const |
143 | { return (std::numeric_limits<IntType>::max)(); } |
144 | |
145 | /** Returns the parameters of the distribution. */ |
146 | param_type param() const { return param_type(_k, _p); } |
147 | /** Sets parameters of the distribution. */ |
148 | void param(const param_type& parm) |
149 | { |
150 | _k = parm.k(); |
151 | _p = parm.p(); |
152 | } |
153 | |
154 | /** |
155 | * Effects: Subsequent uses of the distribution do not depend |
156 | * on values produced by any engine prior to invoking reset. |
157 | */ |
158 | void reset() { } |
159 | |
160 | #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS |
161 | /** Writes the parameters of the distribution to a @c std::ostream. */ |
162 | template<class CharT, class Traits> |
163 | friend std::basic_ostream<CharT,Traits>& |
164 | operator<<(std::basic_ostream<CharT,Traits>& os, |
165 | const negative_binomial_distribution& bd) |
166 | { |
167 | os << bd.param(); |
168 | return os; |
169 | } |
170 | |
171 | /** Reads the parameters of the distribution from a @c std::istream. */ |
172 | template<class CharT, class Traits> |
173 | friend std::basic_istream<CharT,Traits>& |
174 | operator>>(std::basic_istream<CharT,Traits>& is, |
175 | negative_binomial_distribution& bd) |
176 | { |
177 | bd.read(is); |
178 | return is; |
179 | } |
180 | #endif |
181 | |
182 | /** Returns true if the two distributions will produce the same |
183 | sequence of values, given equal generators. */ |
184 | friend bool operator==(const negative_binomial_distribution& lhs, |
185 | const negative_binomial_distribution& rhs) |
186 | { |
187 | return lhs._k == rhs._k && lhs._p == rhs._p; |
188 | } |
189 | /** Returns true if the two distributions could produce different |
190 | sequences of values, given equal generators. */ |
191 | friend bool operator!=(const negative_binomial_distribution& lhs, |
192 | const negative_binomial_distribution& rhs) |
193 | { |
194 | return !(lhs == rhs); |
195 | } |
196 | |
197 | private: |
198 | |
199 | /// @cond \show_private |
200 | |
201 | template<class CharT, class Traits> |
202 | void read(std::basic_istream<CharT, Traits>& is) { |
203 | param_type parm; |
204 | if(is >> parm) { |
205 | param(parm); |
206 | } |
207 | } |
208 | |
209 | // parameters |
210 | IntType _k; |
211 | RealType _p; |
212 | |
213 | /// @endcond |
214 | }; |
215 | |
216 | } |
217 | |
218 | } |
219 | |
220 | #endif |
221 | |