Chris@16
|
1 // boost\math\distributions\bernoulli.hpp
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright John Maddock 2006.
|
Chris@16
|
4 // Copyright Paul A. Bristow 2007.
|
Chris@16
|
5
|
Chris@16
|
6 // Use, modification and distribution are subject to the
|
Chris@16
|
7 // Boost Software License, Version 1.0.
|
Chris@16
|
8 // (See accompanying file LICENSE_1_0.txt
|
Chris@16
|
9 // or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
10
|
Chris@16
|
11 // http://en.wikipedia.org/wiki/bernoulli_distribution
|
Chris@16
|
12 // http://mathworld.wolfram.com/BernoulliDistribution.html
|
Chris@16
|
13
|
Chris@16
|
14 // bernoulli distribution is the discrete probability distribution of
|
Chris@16
|
15 // the number (k) of successes, in a single Bernoulli trials.
|
Chris@16
|
16 // It is a version of the binomial distribution when n = 1.
|
Chris@16
|
17
|
Chris@16
|
18 // But note that the bernoulli distribution
|
Chris@16
|
19 // (like others including the poisson, binomial & negative binomial)
|
Chris@16
|
20 // is strictly defined as a discrete function: only integral values of k are envisaged.
|
Chris@16
|
21 // However because of the method of calculation using a continuous gamma function,
|
Chris@16
|
22 // it is convenient to treat it as if a continous function,
|
Chris@16
|
23 // and permit non-integral values of k.
|
Chris@16
|
24 // To enforce the strict mathematical model, users should use floor or ceil functions
|
Chris@16
|
25 // on k outside this function to ensure that k is integral.
|
Chris@16
|
26
|
Chris@16
|
27 #ifndef BOOST_MATH_SPECIAL_BERNOULLI_HPP
|
Chris@16
|
28 #define BOOST_MATH_SPECIAL_BERNOULLI_HPP
|
Chris@16
|
29
|
Chris@16
|
30 #include <boost/math/distributions/fwd.hpp>
|
Chris@16
|
31 #include <boost/math/tools/config.hpp>
|
Chris@16
|
32 #include <boost/math/distributions/complement.hpp> // complements
|
Chris@16
|
33 #include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
|
Chris@16
|
34 #include <boost/math/special_functions/fpclassify.hpp> // isnan.
|
Chris@16
|
35
|
Chris@16
|
36 #include <utility>
|
Chris@16
|
37
|
Chris@16
|
38 namespace boost
|
Chris@16
|
39 {
|
Chris@16
|
40 namespace math
|
Chris@16
|
41 {
|
Chris@16
|
42 namespace bernoulli_detail
|
Chris@16
|
43 {
|
Chris@16
|
44 // Common error checking routines for bernoulli distribution functions:
|
Chris@16
|
45 template <class RealType, class Policy>
|
Chris@16
|
46 inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& /* pol */)
|
Chris@16
|
47 {
|
Chris@16
|
48 if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
|
Chris@16
|
49 {
|
Chris@16
|
50 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
51 function,
|
Chris@16
|
52 "Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, Policy());
|
Chris@16
|
53 return false;
|
Chris@16
|
54 }
|
Chris@16
|
55 return true;
|
Chris@16
|
56 }
|
Chris@16
|
57 template <class RealType, class Policy>
|
Chris@16
|
58 inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */, const mpl::true_&)
|
Chris@16
|
59 {
|
Chris@16
|
60 return check_success_fraction(function, p, result, Policy());
|
Chris@16
|
61 }
|
Chris@16
|
62 template <class RealType, class Policy>
|
Chris@16
|
63 inline bool check_dist(const char* , const RealType& , RealType* , const Policy& /* pol */, const mpl::false_&)
|
Chris@16
|
64 {
|
Chris@16
|
65 return true;
|
Chris@16
|
66 }
|
Chris@16
|
67 template <class RealType, class Policy>
|
Chris@16
|
68 inline bool check_dist(const char* function, const RealType& p, RealType* result, const Policy& /* pol */)
|
Chris@16
|
69 {
|
Chris@16
|
70 return check_dist(function, p, result, Policy(), typename policies::constructor_error_check<Policy>::type());
|
Chris@16
|
71 }
|
Chris@16
|
72
|
Chris@16
|
73 template <class RealType, class Policy>
|
Chris@16
|
74 inline bool check_dist_and_k(const char* function, const RealType& p, RealType k, RealType* result, const Policy& pol)
|
Chris@16
|
75 {
|
Chris@16
|
76 if(check_dist(function, p, result, Policy(), typename policies::method_error_check<Policy>::type()) == false)
|
Chris@16
|
77 {
|
Chris@16
|
78 return false;
|
Chris@16
|
79 }
|
Chris@16
|
80 if(!(boost::math::isfinite)(k) || !((k == 0) || (k == 1)))
|
Chris@16
|
81 {
|
Chris@16
|
82 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
83 function,
|
Chris@16
|
84 "Number of successes argument is %1%, but must be 0 or 1 !", k, pol);
|
Chris@16
|
85 return false;
|
Chris@16
|
86 }
|
Chris@16
|
87 return true;
|
Chris@16
|
88 }
|
Chris@16
|
89 template <class RealType, class Policy>
|
Chris@16
|
90 inline bool check_dist_and_prob(const char* function, RealType p, RealType prob, RealType* result, const Policy& /* pol */)
|
Chris@16
|
91 {
|
Chris@16
|
92 if(check_dist(function, p, result, Policy(), typename policies::method_error_check<Policy>::type()) && detail::check_probability(function, prob, result, Policy()) == false)
|
Chris@16
|
93 {
|
Chris@16
|
94 return false;
|
Chris@16
|
95 }
|
Chris@16
|
96 return true;
|
Chris@16
|
97 }
|
Chris@16
|
98 } // namespace bernoulli_detail
|
Chris@16
|
99
|
Chris@16
|
100
|
Chris@16
|
101 template <class RealType = double, class Policy = policies::policy<> >
|
Chris@16
|
102 class bernoulli_distribution
|
Chris@16
|
103 {
|
Chris@16
|
104 public:
|
Chris@16
|
105 typedef RealType value_type;
|
Chris@16
|
106 typedef Policy policy_type;
|
Chris@16
|
107
|
Chris@16
|
108 bernoulli_distribution(RealType p = 0.5) : m_p(p)
|
Chris@16
|
109 { // Default probability = half suits 'fair' coin tossing
|
Chris@16
|
110 // where probability of heads == probability of tails.
|
Chris@16
|
111 RealType result; // of checks.
|
Chris@16
|
112 bernoulli_detail::check_dist(
|
Chris@16
|
113 "boost::math::bernoulli_distribution<%1%>::bernoulli_distribution",
|
Chris@16
|
114 m_p,
|
Chris@16
|
115 &result, Policy());
|
Chris@16
|
116 } // bernoulli_distribution constructor.
|
Chris@16
|
117
|
Chris@16
|
118 RealType success_fraction() const
|
Chris@16
|
119 { // Probability.
|
Chris@16
|
120 return m_p;
|
Chris@16
|
121 }
|
Chris@16
|
122
|
Chris@16
|
123 private:
|
Chris@16
|
124 RealType m_p; // success_fraction
|
Chris@16
|
125 }; // template <class RealType> class bernoulli_distribution
|
Chris@16
|
126
|
Chris@16
|
127 typedef bernoulli_distribution<double> bernoulli;
|
Chris@16
|
128
|
Chris@16
|
129 template <class RealType, class Policy>
|
Chris@16
|
130 inline const std::pair<RealType, RealType> range(const bernoulli_distribution<RealType, Policy>& /* dist */)
|
Chris@16
|
131 { // Range of permissible values for random variable k = {0, 1}.
|
Chris@16
|
132 using boost::math::tools::max_value;
|
Chris@16
|
133 return std::pair<RealType, RealType>(static_cast<RealType>(0), static_cast<RealType>(1));
|
Chris@16
|
134 }
|
Chris@16
|
135
|
Chris@16
|
136 template <class RealType, class Policy>
|
Chris@16
|
137 inline const std::pair<RealType, RealType> support(const bernoulli_distribution<RealType, Policy>& /* dist */)
|
Chris@16
|
138 { // Range of supported values for random variable k = {0, 1}.
|
Chris@16
|
139 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
|
Chris@16
|
140 return std::pair<RealType, RealType>(static_cast<RealType>(0), static_cast<RealType>(1));
|
Chris@16
|
141 }
|
Chris@16
|
142
|
Chris@16
|
143 template <class RealType, class Policy>
|
Chris@16
|
144 inline RealType mean(const bernoulli_distribution<RealType, Policy>& dist)
|
Chris@16
|
145 { // Mean of bernoulli distribution = p (n = 1).
|
Chris@16
|
146 return dist.success_fraction();
|
Chris@16
|
147 } // mean
|
Chris@16
|
148
|
Chris@16
|
149 // Rely on dereived_accessors quantile(half)
|
Chris@16
|
150 //template <class RealType>
|
Chris@16
|
151 //inline RealType median(const bernoulli_distribution<RealType, Policy>& dist)
|
Chris@16
|
152 //{ // Median of bernoulli distribution is not defined.
|
Chris@16
|
153 // return tools::domain_error<RealType>(BOOST_CURRENT_FUNCTION, "Median is not implemented, result is %1%!", std::numeric_limits<RealType>::quiet_NaN());
|
Chris@16
|
154 //} // median
|
Chris@16
|
155
|
Chris@16
|
156 template <class RealType, class Policy>
|
Chris@16
|
157 inline RealType variance(const bernoulli_distribution<RealType, Policy>& dist)
|
Chris@16
|
158 { // Variance of bernoulli distribution =p * q.
|
Chris@16
|
159 return dist.success_fraction() * (1 - dist.success_fraction());
|
Chris@16
|
160 } // variance
|
Chris@16
|
161
|
Chris@16
|
162 template <class RealType, class Policy>
|
Chris@16
|
163 RealType pdf(const bernoulli_distribution<RealType, Policy>& dist, const RealType& k)
|
Chris@16
|
164 { // Probability Density/Mass Function.
|
Chris@16
|
165 BOOST_FPU_EXCEPTION_GUARD
|
Chris@16
|
166 // Error check:
|
Chris@16
|
167 RealType result = 0; // of checks.
|
Chris@16
|
168 if(false == bernoulli_detail::check_dist_and_k(
|
Chris@16
|
169 "boost::math::pdf(bernoulli_distribution<%1%>, %1%)",
|
Chris@16
|
170 dist.success_fraction(), // 0 to 1
|
Chris@16
|
171 k, // 0 or 1
|
Chris@16
|
172 &result, Policy()))
|
Chris@16
|
173 {
|
Chris@16
|
174 return result;
|
Chris@16
|
175 }
|
Chris@16
|
176 // Assume k is integral.
|
Chris@16
|
177 if (k == 0)
|
Chris@16
|
178 {
|
Chris@16
|
179 return 1 - dist.success_fraction(); // 1 - p
|
Chris@16
|
180 }
|
Chris@16
|
181 else // k == 1
|
Chris@16
|
182 {
|
Chris@16
|
183 return dist.success_fraction(); // p
|
Chris@16
|
184 }
|
Chris@16
|
185 } // pdf
|
Chris@16
|
186
|
Chris@16
|
187 template <class RealType, class Policy>
|
Chris@16
|
188 inline RealType cdf(const bernoulli_distribution<RealType, Policy>& dist, const RealType& k)
|
Chris@16
|
189 { // Cumulative Distribution Function Bernoulli.
|
Chris@16
|
190 RealType p = dist.success_fraction();
|
Chris@16
|
191 // Error check:
|
Chris@16
|
192 RealType result = 0;
|
Chris@16
|
193 if(false == bernoulli_detail::check_dist_and_k(
|
Chris@16
|
194 "boost::math::cdf(bernoulli_distribution<%1%>, %1%)",
|
Chris@16
|
195 p,
|
Chris@16
|
196 k,
|
Chris@16
|
197 &result, Policy()))
|
Chris@16
|
198 {
|
Chris@16
|
199 return result;
|
Chris@16
|
200 }
|
Chris@16
|
201 if (k == 0)
|
Chris@16
|
202 {
|
Chris@16
|
203 return 1 - p;
|
Chris@16
|
204 }
|
Chris@16
|
205 else
|
Chris@16
|
206 { // k == 1
|
Chris@16
|
207 return 1;
|
Chris@16
|
208 }
|
Chris@16
|
209 } // bernoulli cdf
|
Chris@16
|
210
|
Chris@16
|
211 template <class RealType, class Policy>
|
Chris@16
|
212 inline RealType cdf(const complemented2_type<bernoulli_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
213 { // Complemented Cumulative Distribution Function bernoulli.
|
Chris@16
|
214 RealType const& k = c.param;
|
Chris@16
|
215 bernoulli_distribution<RealType, Policy> const& dist = c.dist;
|
Chris@16
|
216 RealType p = dist.success_fraction();
|
Chris@16
|
217 // Error checks:
|
Chris@16
|
218 RealType result = 0;
|
Chris@16
|
219 if(false == bernoulli_detail::check_dist_and_k(
|
Chris@16
|
220 "boost::math::cdf(bernoulli_distribution<%1%>, %1%)",
|
Chris@16
|
221 p,
|
Chris@16
|
222 k,
|
Chris@16
|
223 &result, Policy()))
|
Chris@16
|
224 {
|
Chris@16
|
225 return result;
|
Chris@16
|
226 }
|
Chris@16
|
227 if (k == 0)
|
Chris@16
|
228 {
|
Chris@16
|
229 return p;
|
Chris@16
|
230 }
|
Chris@16
|
231 else
|
Chris@16
|
232 { // k == 1
|
Chris@16
|
233 return 0;
|
Chris@16
|
234 }
|
Chris@16
|
235 } // bernoulli cdf complement
|
Chris@16
|
236
|
Chris@16
|
237 template <class RealType, class Policy>
|
Chris@16
|
238 inline RealType quantile(const bernoulli_distribution<RealType, Policy>& dist, const RealType& p)
|
Chris@16
|
239 { // Quantile or Percent Point Bernoulli function.
|
Chris@16
|
240 // Return the number of expected successes k either 0 or 1.
|
Chris@16
|
241 // for a given probability p.
|
Chris@16
|
242
|
Chris@16
|
243 RealType result = 0; // of error checks:
|
Chris@16
|
244 if(false == bernoulli_detail::check_dist_and_prob(
|
Chris@16
|
245 "boost::math::quantile(bernoulli_distribution<%1%>, %1%)",
|
Chris@16
|
246 dist.success_fraction(),
|
Chris@16
|
247 p,
|
Chris@16
|
248 &result, Policy()))
|
Chris@16
|
249 {
|
Chris@16
|
250 return result;
|
Chris@16
|
251 }
|
Chris@16
|
252 if (p <= (1 - dist.success_fraction()))
|
Chris@16
|
253 { // p <= pdf(dist, 0) == cdf(dist, 0)
|
Chris@16
|
254 return 0;
|
Chris@16
|
255 }
|
Chris@16
|
256 else
|
Chris@16
|
257 {
|
Chris@16
|
258 return 1;
|
Chris@16
|
259 }
|
Chris@16
|
260 } // quantile
|
Chris@16
|
261
|
Chris@16
|
262 template <class RealType, class Policy>
|
Chris@16
|
263 inline RealType quantile(const complemented2_type<bernoulli_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
264 { // Quantile or Percent Point bernoulli function.
|
Chris@16
|
265 // Return the number of expected successes k for a given
|
Chris@16
|
266 // complement of the probability q.
|
Chris@16
|
267 //
|
Chris@16
|
268 // Error checks:
|
Chris@16
|
269 RealType q = c.param;
|
Chris@16
|
270 const bernoulli_distribution<RealType, Policy>& dist = c.dist;
|
Chris@16
|
271 RealType result = 0;
|
Chris@16
|
272 if(false == bernoulli_detail::check_dist_and_prob(
|
Chris@16
|
273 "boost::math::quantile(bernoulli_distribution<%1%>, %1%)",
|
Chris@16
|
274 dist.success_fraction(),
|
Chris@16
|
275 q,
|
Chris@16
|
276 &result, Policy()))
|
Chris@16
|
277 {
|
Chris@16
|
278 return result;
|
Chris@16
|
279 }
|
Chris@16
|
280
|
Chris@16
|
281 if (q <= 1 - dist.success_fraction())
|
Chris@16
|
282 { // // q <= cdf(complement(dist, 0)) == pdf(dist, 0)
|
Chris@16
|
283 return 1;
|
Chris@16
|
284 }
|
Chris@16
|
285 else
|
Chris@16
|
286 {
|
Chris@16
|
287 return 0;
|
Chris@16
|
288 }
|
Chris@16
|
289 } // quantile complemented.
|
Chris@16
|
290
|
Chris@16
|
291 template <class RealType, class Policy>
|
Chris@16
|
292 inline RealType mode(const bernoulli_distribution<RealType, Policy>& dist)
|
Chris@16
|
293 {
|
Chris@16
|
294 return static_cast<RealType>((dist.success_fraction() <= 0.5) ? 0 : 1); // p = 0.5 can be 0 or 1
|
Chris@16
|
295 }
|
Chris@16
|
296
|
Chris@16
|
297 template <class RealType, class Policy>
|
Chris@16
|
298 inline RealType skewness(const bernoulli_distribution<RealType, Policy>& dist)
|
Chris@16
|
299 {
|
Chris@16
|
300 BOOST_MATH_STD_USING; // Aid ADL for sqrt.
|
Chris@16
|
301 RealType p = dist.success_fraction();
|
Chris@16
|
302 return (1 - 2 * p) / sqrt(p * (1 - p));
|
Chris@16
|
303 }
|
Chris@16
|
304
|
Chris@16
|
305 template <class RealType, class Policy>
|
Chris@16
|
306 inline RealType kurtosis_excess(const bernoulli_distribution<RealType, Policy>& dist)
|
Chris@16
|
307 {
|
Chris@16
|
308 RealType p = dist.success_fraction();
|
Chris@16
|
309 // Note Wolfram says this is kurtosis in text, but gamma2 is the kurtosis excess,
|
Chris@16
|
310 // and Wikipedia also says this is the kurtosis excess formula.
|
Chris@16
|
311 // return (6 * p * p - 6 * p + 1) / (p * (1 - p));
|
Chris@16
|
312 // But Wolfram kurtosis article gives this simpler formula for kurtosis excess:
|
Chris@16
|
313 return 1 / (1 - p) + 1/p -6;
|
Chris@16
|
314 }
|
Chris@16
|
315
|
Chris@16
|
316 template <class RealType, class Policy>
|
Chris@16
|
317 inline RealType kurtosis(const bernoulli_distribution<RealType, Policy>& dist)
|
Chris@16
|
318 {
|
Chris@16
|
319 RealType p = dist.success_fraction();
|
Chris@16
|
320 return 1 / (1 - p) + 1/p -6 + 3;
|
Chris@16
|
321 // Simpler than:
|
Chris@16
|
322 // return (6 * p * p - 6 * p + 1) / (p * (1 - p)) + 3;
|
Chris@16
|
323 }
|
Chris@16
|
324
|
Chris@16
|
325 } // namespace math
|
Chris@16
|
326 } // namespace boost
|
Chris@16
|
327
|
Chris@16
|
328 // This include must be at the end, *after* the accessors
|
Chris@16
|
329 // for this distribution have been defined, in order to
|
Chris@16
|
330 // keep compilers that support two-phase lookup happy.
|
Chris@16
|
331 #include <boost/math/distributions/detail/derived_accessors.hpp>
|
Chris@16
|
332
|
Chris@16
|
333 #endif // BOOST_MATH_SPECIAL_BERNOULLI_HPP
|
Chris@16
|
334
|
Chris@16
|
335
|
Chris@16
|
336
|