Chris@16
|
1 // boost\math\distributions\poisson.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 // Poisson distribution is a discrete probability distribution.
|
Chris@16
|
12 // It expresses the probability of a number (k) of
|
Chris@16
|
13 // events, occurrences, failures or arrivals occurring in a fixed time,
|
Chris@16
|
14 // assuming these events occur with a known average or mean rate (lambda)
|
Chris@16
|
15 // and are independent of the time since the last event.
|
Chris@16
|
16 // The distribution was discovered by Simeon-Denis Poisson (1781-1840).
|
Chris@16
|
17
|
Chris@16
|
18 // Parameter lambda is the mean number of events in the given time interval.
|
Chris@16
|
19 // The random variate k is the number of events, occurrences or arrivals.
|
Chris@16
|
20 // k argument may be integral, signed, or unsigned, or floating point.
|
Chris@16
|
21 // If necessary, it has already been promoted from an integral type.
|
Chris@16
|
22
|
Chris@16
|
23 // Note that the Poisson distribution
|
Chris@16
|
24 // (like others including the binomial, negative binomial & Bernoulli)
|
Chris@16
|
25 // is strictly defined as a discrete function:
|
Chris@16
|
26 // only integral values of k are envisaged.
|
Chris@16
|
27 // However because the method of calculation uses a continuous gamma function,
|
Chris@16
|
28 // it is convenient to treat it as if a continous function,
|
Chris@16
|
29 // and permit non-integral values of k.
|
Chris@16
|
30 // To enforce the strict mathematical model, users should use floor or ceil functions
|
Chris@16
|
31 // on k outside this function to ensure that k is integral.
|
Chris@16
|
32
|
Chris@16
|
33 // See http://en.wikipedia.org/wiki/Poisson_distribution
|
Chris@16
|
34 // http://documents.wolfram.com/v5/Add-onsLinks/StandardPackages/Statistics/DiscreteDistributions.html
|
Chris@16
|
35
|
Chris@16
|
36 #ifndef BOOST_MATH_SPECIAL_POISSON_HPP
|
Chris@16
|
37 #define BOOST_MATH_SPECIAL_POISSON_HPP
|
Chris@16
|
38
|
Chris@16
|
39 #include <boost/math/distributions/fwd.hpp>
|
Chris@16
|
40 #include <boost/math/special_functions/gamma.hpp> // for incomplete gamma. gamma_q
|
Chris@16
|
41 #include <boost/math/special_functions/trunc.hpp> // for incomplete gamma. gamma_q
|
Chris@16
|
42 #include <boost/math/distributions/complement.hpp> // complements
|
Chris@16
|
43 #include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
|
Chris@16
|
44 #include <boost/math/special_functions/fpclassify.hpp> // isnan.
|
Chris@16
|
45 #include <boost/math/special_functions/factorials.hpp> // factorials.
|
Chris@16
|
46 #include <boost/math/tools/roots.hpp> // for root finding.
|
Chris@16
|
47 #include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
|
Chris@16
|
48
|
Chris@16
|
49 #include <utility>
|
Chris@16
|
50
|
Chris@16
|
51 namespace boost
|
Chris@16
|
52 {
|
Chris@16
|
53 namespace math
|
Chris@16
|
54 {
|
Chris@16
|
55 namespace poisson_detail
|
Chris@16
|
56 {
|
Chris@16
|
57 // Common error checking routines for Poisson distribution functions.
|
Chris@16
|
58 // These are convoluted, & apparently redundant, to try to ensure that
|
Chris@16
|
59 // checks are always performed, even if exceptions are not enabled.
|
Chris@16
|
60
|
Chris@16
|
61 template <class RealType, class Policy>
|
Chris@16
|
62 inline bool check_mean(const char* function, const RealType& mean, RealType* result, const Policy& pol)
|
Chris@16
|
63 {
|
Chris@16
|
64 if(!(boost::math::isfinite)(mean) || (mean < 0))
|
Chris@16
|
65 {
|
Chris@16
|
66 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
67 function,
|
Chris@16
|
68 "Mean argument is %1%, but must be >= 0 !", mean, pol);
|
Chris@16
|
69 return false;
|
Chris@16
|
70 }
|
Chris@16
|
71 return true;
|
Chris@16
|
72 } // bool check_mean
|
Chris@16
|
73
|
Chris@16
|
74 template <class RealType, class Policy>
|
Chris@16
|
75 inline bool check_mean_NZ(const char* function, const RealType& mean, RealType* result, const Policy& pol)
|
Chris@16
|
76 { // mean == 0 is considered an error.
|
Chris@16
|
77 if( !(boost::math::isfinite)(mean) || (mean <= 0))
|
Chris@16
|
78 {
|
Chris@16
|
79 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
80 function,
|
Chris@16
|
81 "Mean argument is %1%, but must be > 0 !", mean, pol);
|
Chris@16
|
82 return false;
|
Chris@16
|
83 }
|
Chris@16
|
84 return true;
|
Chris@16
|
85 } // bool check_mean_NZ
|
Chris@16
|
86
|
Chris@16
|
87 template <class RealType, class Policy>
|
Chris@16
|
88 inline bool check_dist(const char* function, const RealType& mean, RealType* result, const Policy& pol)
|
Chris@16
|
89 { // Only one check, so this is redundant really but should be optimized away.
|
Chris@16
|
90 return check_mean_NZ(function, mean, result, pol);
|
Chris@16
|
91 } // bool check_dist
|
Chris@16
|
92
|
Chris@16
|
93 template <class RealType, class Policy>
|
Chris@16
|
94 inline bool check_k(const char* function, const RealType& k, RealType* result, const Policy& pol)
|
Chris@16
|
95 {
|
Chris@16
|
96 if((k < 0) || !(boost::math::isfinite)(k))
|
Chris@16
|
97 {
|
Chris@16
|
98 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
99 function,
|
Chris@16
|
100 "Number of events k argument is %1%, but must be >= 0 !", k, pol);
|
Chris@16
|
101 return false;
|
Chris@16
|
102 }
|
Chris@16
|
103 return true;
|
Chris@16
|
104 } // bool check_k
|
Chris@16
|
105
|
Chris@16
|
106 template <class RealType, class Policy>
|
Chris@16
|
107 inline bool check_dist_and_k(const char* function, RealType mean, RealType k, RealType* result, const Policy& pol)
|
Chris@16
|
108 {
|
Chris@16
|
109 if((check_dist(function, mean, result, pol) == false) ||
|
Chris@16
|
110 (check_k(function, k, result, pol) == false))
|
Chris@16
|
111 {
|
Chris@16
|
112 return false;
|
Chris@16
|
113 }
|
Chris@16
|
114 return true;
|
Chris@16
|
115 } // bool check_dist_and_k
|
Chris@16
|
116
|
Chris@16
|
117 template <class RealType, class Policy>
|
Chris@16
|
118 inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol)
|
Chris@16
|
119 { // Check 0 <= p <= 1
|
Chris@16
|
120 if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
|
Chris@16
|
121 {
|
Chris@16
|
122 *result = policies::raise_domain_error<RealType>(
|
Chris@16
|
123 function,
|
Chris@16
|
124 "Probability argument is %1%, but must be >= 0 and <= 1 !", p, pol);
|
Chris@16
|
125 return false;
|
Chris@16
|
126 }
|
Chris@16
|
127 return true;
|
Chris@16
|
128 } // bool check_prob
|
Chris@16
|
129
|
Chris@16
|
130 template <class RealType, class Policy>
|
Chris@16
|
131 inline bool check_dist_and_prob(const char* function, RealType mean, RealType p, RealType* result, const Policy& pol)
|
Chris@16
|
132 {
|
Chris@16
|
133 if((check_dist(function, mean, result, pol) == false) ||
|
Chris@16
|
134 (check_prob(function, p, result, pol) == false))
|
Chris@16
|
135 {
|
Chris@16
|
136 return false;
|
Chris@16
|
137 }
|
Chris@16
|
138 return true;
|
Chris@16
|
139 } // bool check_dist_and_prob
|
Chris@16
|
140
|
Chris@16
|
141 } // namespace poisson_detail
|
Chris@16
|
142
|
Chris@16
|
143 template <class RealType = double, class Policy = policies::policy<> >
|
Chris@16
|
144 class poisson_distribution
|
Chris@16
|
145 {
|
Chris@16
|
146 public:
|
Chris@16
|
147 typedef RealType value_type;
|
Chris@16
|
148 typedef Policy policy_type;
|
Chris@16
|
149
|
Chris@16
|
150 poisson_distribution(RealType l_mean = 1) : m_l(l_mean) // mean (lambda).
|
Chris@16
|
151 { // Expected mean number of events that occur during the given interval.
|
Chris@16
|
152 RealType r;
|
Chris@16
|
153 poisson_detail::check_dist(
|
Chris@16
|
154 "boost::math::poisson_distribution<%1%>::poisson_distribution",
|
Chris@16
|
155 m_l,
|
Chris@16
|
156 &r, Policy());
|
Chris@16
|
157 } // poisson_distribution constructor.
|
Chris@16
|
158
|
Chris@16
|
159 RealType mean() const
|
Chris@16
|
160 { // Private data getter function.
|
Chris@16
|
161 return m_l;
|
Chris@16
|
162 }
|
Chris@16
|
163 private:
|
Chris@16
|
164 // Data member, initialized by constructor.
|
Chris@16
|
165 RealType m_l; // mean number of occurrences.
|
Chris@16
|
166 }; // template <class RealType, class Policy> class poisson_distribution
|
Chris@16
|
167
|
Chris@16
|
168 typedef poisson_distribution<double> poisson; // Reserved name of type double.
|
Chris@16
|
169
|
Chris@16
|
170 // Non-member functions to give properties of the distribution.
|
Chris@16
|
171
|
Chris@16
|
172 template <class RealType, class Policy>
|
Chris@16
|
173 inline const std::pair<RealType, RealType> range(const poisson_distribution<RealType, Policy>& /* dist */)
|
Chris@16
|
174 { // Range of permissible values for random variable k.
|
Chris@16
|
175 using boost::math::tools::max_value;
|
Chris@16
|
176 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // Max integer?
|
Chris@16
|
177 }
|
Chris@16
|
178
|
Chris@16
|
179 template <class RealType, class Policy>
|
Chris@16
|
180 inline const std::pair<RealType, RealType> support(const poisson_distribution<RealType, Policy>& /* dist */)
|
Chris@16
|
181 { // Range of supported values for random variable k.
|
Chris@16
|
182 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
|
Chris@16
|
183 using boost::math::tools::max_value;
|
Chris@16
|
184 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187 template <class RealType, class Policy>
|
Chris@16
|
188 inline RealType mean(const poisson_distribution<RealType, Policy>& dist)
|
Chris@16
|
189 { // Mean of poisson distribution = lambda.
|
Chris@16
|
190 return dist.mean();
|
Chris@16
|
191 } // mean
|
Chris@16
|
192
|
Chris@16
|
193 template <class RealType, class Policy>
|
Chris@16
|
194 inline RealType mode(const poisson_distribution<RealType, Policy>& dist)
|
Chris@16
|
195 { // mode.
|
Chris@16
|
196 BOOST_MATH_STD_USING // ADL of std functions.
|
Chris@16
|
197 return floor(dist.mean());
|
Chris@16
|
198 }
|
Chris@16
|
199
|
Chris@16
|
200 //template <class RealType, class Policy>
|
Chris@16
|
201 //inline RealType median(const poisson_distribution<RealType, Policy>& dist)
|
Chris@16
|
202 //{ // median = approximately lambda + 1/3 - 0.2/lambda
|
Chris@16
|
203 // RealType l = dist.mean();
|
Chris@16
|
204 // return dist.mean() + static_cast<RealType>(0.3333333333333333333333333333333333333333333333)
|
Chris@16
|
205 // - static_cast<RealType>(0.2) / l;
|
Chris@16
|
206 //} // BUT this formula appears to be out-by-one compared to quantile(half)
|
Chris@16
|
207 // Query posted on Wikipedia.
|
Chris@16
|
208 // Now implemented via quantile(half) in derived accessors.
|
Chris@16
|
209
|
Chris@16
|
210 template <class RealType, class Policy>
|
Chris@16
|
211 inline RealType variance(const poisson_distribution<RealType, Policy>& dist)
|
Chris@16
|
212 { // variance.
|
Chris@16
|
213 return dist.mean();
|
Chris@16
|
214 }
|
Chris@16
|
215
|
Chris@16
|
216 // RealType standard_deviation(const poisson_distribution<RealType, Policy>& dist)
|
Chris@16
|
217 // standard_deviation provided by derived accessors.
|
Chris@16
|
218
|
Chris@16
|
219 template <class RealType, class Policy>
|
Chris@16
|
220 inline RealType skewness(const poisson_distribution<RealType, Policy>& dist)
|
Chris@16
|
221 { // skewness = sqrt(l).
|
Chris@16
|
222 BOOST_MATH_STD_USING // ADL of std functions.
|
Chris@16
|
223 return 1 / sqrt(dist.mean());
|
Chris@16
|
224 }
|
Chris@16
|
225
|
Chris@16
|
226 template <class RealType, class Policy>
|
Chris@16
|
227 inline RealType kurtosis_excess(const poisson_distribution<RealType, Policy>& dist)
|
Chris@16
|
228 { // skewness = sqrt(l).
|
Chris@16
|
229 return 1 / dist.mean(); // kurtosis_excess 1/mean from Wiki & MathWorld eq 31.
|
Chris@16
|
230 // http://mathworld.wolfram.com/Kurtosis.html explains that the kurtosis excess
|
Chris@16
|
231 // is more convenient because the kurtosis excess of a normal distribution is zero
|
Chris@16
|
232 // whereas the true kurtosis is 3.
|
Chris@16
|
233 } // RealType kurtosis_excess
|
Chris@16
|
234
|
Chris@16
|
235 template <class RealType, class Policy>
|
Chris@16
|
236 inline RealType kurtosis(const poisson_distribution<RealType, Policy>& dist)
|
Chris@16
|
237 { // kurtosis is 4th moment about the mean = u4 / sd ^ 4
|
Chris@16
|
238 // http://en.wikipedia.org/wiki/Curtosis
|
Chris@16
|
239 // kurtosis can range from -2 (flat top) to +infinity (sharp peak & heavy tails).
|
Chris@16
|
240 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm
|
Chris@16
|
241 return 3 + 1 / dist.mean(); // NIST.
|
Chris@16
|
242 // http://mathworld.wolfram.com/Kurtosis.html explains that the kurtosis excess
|
Chris@16
|
243 // is more convenient because the kurtosis excess of a normal distribution is zero
|
Chris@16
|
244 // whereas the true kurtosis is 3.
|
Chris@16
|
245 } // RealType kurtosis
|
Chris@16
|
246
|
Chris@16
|
247 template <class RealType, class Policy>
|
Chris@16
|
248 RealType pdf(const poisson_distribution<RealType, Policy>& dist, const RealType& k)
|
Chris@16
|
249 { // Probability Density/Mass Function.
|
Chris@16
|
250 // Probability that there are EXACTLY k occurrences (or arrivals).
|
Chris@16
|
251 BOOST_FPU_EXCEPTION_GUARD
|
Chris@16
|
252
|
Chris@16
|
253 BOOST_MATH_STD_USING // for ADL of std functions.
|
Chris@16
|
254
|
Chris@16
|
255 RealType mean = dist.mean();
|
Chris@16
|
256 // Error check:
|
Chris@16
|
257 RealType result = 0;
|
Chris@16
|
258 if(false == poisson_detail::check_dist_and_k(
|
Chris@16
|
259 "boost::math::pdf(const poisson_distribution<%1%>&, %1%)",
|
Chris@16
|
260 mean,
|
Chris@16
|
261 k,
|
Chris@16
|
262 &result, Policy()))
|
Chris@16
|
263 {
|
Chris@16
|
264 return result;
|
Chris@16
|
265 }
|
Chris@16
|
266
|
Chris@16
|
267 // Special case of mean zero, regardless of the number of events k.
|
Chris@16
|
268 if (mean == 0)
|
Chris@16
|
269 { // Probability for any k is zero.
|
Chris@16
|
270 return 0;
|
Chris@16
|
271 }
|
Chris@16
|
272 if (k == 0)
|
Chris@16
|
273 { // mean ^ k = 1, and k! = 1, so can simplify.
|
Chris@16
|
274 return exp(-mean);
|
Chris@16
|
275 }
|
Chris@16
|
276 return boost::math::gamma_p_derivative(k+1, mean, Policy());
|
Chris@16
|
277 } // pdf
|
Chris@16
|
278
|
Chris@16
|
279 template <class RealType, class Policy>
|
Chris@16
|
280 RealType cdf(const poisson_distribution<RealType, Policy>& dist, const RealType& k)
|
Chris@16
|
281 { // Cumulative Distribution Function Poisson.
|
Chris@16
|
282 // The random variate k is the number of occurrences(or arrivals)
|
Chris@16
|
283 // k argument may be integral, signed, or unsigned, or floating point.
|
Chris@16
|
284 // If necessary, it has already been promoted from an integral type.
|
Chris@16
|
285 // Returns the sum of the terms 0 through k of the Poisson Probability Density or Mass (pdf).
|
Chris@16
|
286
|
Chris@16
|
287 // But note that the Poisson distribution
|
Chris@16
|
288 // (like others including the binomial, negative binomial & Bernoulli)
|
Chris@16
|
289 // is strictly defined as a discrete function: only integral values of k are envisaged.
|
Chris@16
|
290 // However because of the method of calculation using a continuous gamma function,
|
Chris@16
|
291 // it is convenient to treat it as if it is a continous function
|
Chris@16
|
292 // and permit non-integral values of k.
|
Chris@16
|
293 // To enforce the strict mathematical model, users should use floor or ceil functions
|
Chris@16
|
294 // outside this function to ensure that k is integral.
|
Chris@16
|
295
|
Chris@16
|
296 // The terms are not summed directly (at least for larger k)
|
Chris@16
|
297 // instead the incomplete gamma integral is employed,
|
Chris@16
|
298
|
Chris@16
|
299 BOOST_MATH_STD_USING // for ADL of std function exp.
|
Chris@16
|
300
|
Chris@16
|
301 RealType mean = dist.mean();
|
Chris@16
|
302 // Error checks:
|
Chris@16
|
303 RealType result = 0;
|
Chris@16
|
304 if(false == poisson_detail::check_dist_and_k(
|
Chris@16
|
305 "boost::math::cdf(const poisson_distribution<%1%>&, %1%)",
|
Chris@16
|
306 mean,
|
Chris@16
|
307 k,
|
Chris@16
|
308 &result, Policy()))
|
Chris@16
|
309 {
|
Chris@16
|
310 return result;
|
Chris@16
|
311 }
|
Chris@16
|
312 // Special cases:
|
Chris@16
|
313 if (mean == 0)
|
Chris@16
|
314 { // Probability for any k is zero.
|
Chris@16
|
315 return 0;
|
Chris@16
|
316 }
|
Chris@16
|
317 if (k == 0)
|
Chris@16
|
318 { // return pdf(dist, static_cast<RealType>(0));
|
Chris@16
|
319 // but mean (and k) have already been checked,
|
Chris@16
|
320 // so this avoids unnecessary repeated checks.
|
Chris@16
|
321 return exp(-mean);
|
Chris@16
|
322 }
|
Chris@16
|
323 // For small integral k could use a finite sum -
|
Chris@16
|
324 // it's cheaper than the gamma function.
|
Chris@16
|
325 // BUT this is now done efficiently by gamma_q function.
|
Chris@16
|
326 // Calculate poisson cdf using the gamma_q function.
|
Chris@16
|
327 return gamma_q(k+1, mean, Policy());
|
Chris@16
|
328 } // binomial cdf
|
Chris@16
|
329
|
Chris@16
|
330 template <class RealType, class Policy>
|
Chris@16
|
331 RealType cdf(const complemented2_type<poisson_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
332 { // Complemented Cumulative Distribution Function Poisson
|
Chris@16
|
333 // The random variate k is the number of events, occurrences or arrivals.
|
Chris@16
|
334 // k argument may be integral, signed, or unsigned, or floating point.
|
Chris@16
|
335 // If necessary, it has already been promoted from an integral type.
|
Chris@16
|
336 // But note that the Poisson distribution
|
Chris@16
|
337 // (like others including the binomial, negative binomial & Bernoulli)
|
Chris@16
|
338 // is strictly defined as a discrete function: only integral values of k are envisaged.
|
Chris@16
|
339 // However because of the method of calculation using a continuous gamma function,
|
Chris@16
|
340 // it is convenient to treat it as is it is a continous function
|
Chris@16
|
341 // and permit non-integral values of k.
|
Chris@16
|
342 // To enforce the strict mathematical model, users should use floor or ceil functions
|
Chris@16
|
343 // outside this function to ensure that k is integral.
|
Chris@16
|
344
|
Chris@16
|
345 // Returns the sum of the terms k+1 through inf of the Poisson Probability Density/Mass (pdf).
|
Chris@16
|
346 // The terms are not summed directly (at least for larger k)
|
Chris@16
|
347 // instead the incomplete gamma integral is employed,
|
Chris@16
|
348
|
Chris@16
|
349 RealType const& k = c.param;
|
Chris@16
|
350 poisson_distribution<RealType, Policy> const& dist = c.dist;
|
Chris@16
|
351
|
Chris@16
|
352 RealType mean = dist.mean();
|
Chris@16
|
353
|
Chris@16
|
354 // Error checks:
|
Chris@16
|
355 RealType result = 0;
|
Chris@16
|
356 if(false == poisson_detail::check_dist_and_k(
|
Chris@16
|
357 "boost::math::cdf(const poisson_distribution<%1%>&, %1%)",
|
Chris@16
|
358 mean,
|
Chris@16
|
359 k,
|
Chris@16
|
360 &result, Policy()))
|
Chris@16
|
361 {
|
Chris@16
|
362 return result;
|
Chris@16
|
363 }
|
Chris@16
|
364 // Special case of mean, regardless of the number of events k.
|
Chris@16
|
365 if (mean == 0)
|
Chris@16
|
366 { // Probability for any k is unity, complement of zero.
|
Chris@16
|
367 return 1;
|
Chris@16
|
368 }
|
Chris@16
|
369 if (k == 0)
|
Chris@16
|
370 { // Avoid repeated checks on k and mean in gamma_p.
|
Chris@16
|
371 return -boost::math::expm1(-mean, Policy());
|
Chris@16
|
372 }
|
Chris@16
|
373 // Unlike un-complemented cdf (sum from 0 to k),
|
Chris@16
|
374 // can't use finite sum from k+1 to infinity for small integral k,
|
Chris@16
|
375 // anyway it is now done efficiently by gamma_p.
|
Chris@16
|
376 return gamma_p(k + 1, mean, Policy()); // Calculate Poisson cdf using the gamma_p function.
|
Chris@16
|
377 // CCDF = gamma_p(k+1, lambda)
|
Chris@16
|
378 } // poisson ccdf
|
Chris@16
|
379
|
Chris@16
|
380 template <class RealType, class Policy>
|
Chris@16
|
381 inline RealType quantile(const poisson_distribution<RealType, Policy>& dist, const RealType& p)
|
Chris@16
|
382 { // Quantile (or Percent Point) Poisson function.
|
Chris@16
|
383 // Return the number of expected events k for a given probability p.
|
Chris@16
|
384 static const char* function = "boost::math::quantile(const poisson_distribution<%1%>&, %1%)";
|
Chris@16
|
385 RealType result = 0; // of Argument checks:
|
Chris@16
|
386 if(false == poisson_detail::check_prob(
|
Chris@16
|
387 function,
|
Chris@16
|
388 p,
|
Chris@16
|
389 &result, Policy()))
|
Chris@16
|
390 {
|
Chris@16
|
391 return result;
|
Chris@16
|
392 }
|
Chris@16
|
393 // Special case:
|
Chris@16
|
394 if (dist.mean() == 0)
|
Chris@16
|
395 { // if mean = 0 then p = 0, so k can be anything?
|
Chris@16
|
396 if (false == poisson_detail::check_mean_NZ(
|
Chris@16
|
397 function,
|
Chris@16
|
398 dist.mean(),
|
Chris@16
|
399 &result, Policy()))
|
Chris@16
|
400 {
|
Chris@16
|
401 return result;
|
Chris@16
|
402 }
|
Chris@16
|
403 }
|
Chris@16
|
404 if(p == 0)
|
Chris@16
|
405 {
|
Chris@16
|
406 return 0; // Exact result regardless of discrete-quantile Policy
|
Chris@16
|
407 }
|
Chris@16
|
408 if(p == 1)
|
Chris@16
|
409 {
|
Chris@16
|
410 return policies::raise_overflow_error<RealType>(function, 0, Policy());
|
Chris@16
|
411 }
|
Chris@16
|
412 typedef typename Policy::discrete_quantile_type discrete_type;
|
Chris@16
|
413 boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
Chris@16
|
414 RealType guess, factor = 8;
|
Chris@16
|
415 RealType z = dist.mean();
|
Chris@16
|
416 if(z < 1)
|
Chris@16
|
417 guess = z;
|
Chris@16
|
418 else
|
Chris@16
|
419 guess = boost::math::detail::inverse_poisson_cornish_fisher(z, p, RealType(1-p), Policy());
|
Chris@16
|
420 if(z > 5)
|
Chris@16
|
421 {
|
Chris@16
|
422 if(z > 1000)
|
Chris@16
|
423 factor = 1.01f;
|
Chris@16
|
424 else if(z > 50)
|
Chris@16
|
425 factor = 1.1f;
|
Chris@16
|
426 else if(guess > 10)
|
Chris@16
|
427 factor = 1.25f;
|
Chris@16
|
428 else
|
Chris@16
|
429 factor = 2;
|
Chris@16
|
430 if(guess < 1.1)
|
Chris@16
|
431 factor = 8;
|
Chris@16
|
432 }
|
Chris@16
|
433
|
Chris@16
|
434 return detail::inverse_discrete_quantile(
|
Chris@16
|
435 dist,
|
Chris@16
|
436 p,
|
Chris@16
|
437 false,
|
Chris@16
|
438 guess,
|
Chris@16
|
439 factor,
|
Chris@16
|
440 RealType(1),
|
Chris@16
|
441 discrete_type(),
|
Chris@16
|
442 max_iter);
|
Chris@16
|
443 } // quantile
|
Chris@16
|
444
|
Chris@16
|
445 template <class RealType, class Policy>
|
Chris@16
|
446 inline RealType quantile(const complemented2_type<poisson_distribution<RealType, Policy>, RealType>& c)
|
Chris@16
|
447 { // Quantile (or Percent Point) of Poisson function.
|
Chris@16
|
448 // Return the number of expected events k for a given
|
Chris@16
|
449 // complement of the probability q.
|
Chris@16
|
450 //
|
Chris@16
|
451 // Error checks:
|
Chris@16
|
452 static const char* function = "boost::math::quantile(complement(const poisson_distribution<%1%>&, %1%))";
|
Chris@16
|
453 RealType q = c.param;
|
Chris@16
|
454 const poisson_distribution<RealType, Policy>& dist = c.dist;
|
Chris@16
|
455 RealType result = 0; // of argument checks.
|
Chris@16
|
456 if(false == poisson_detail::check_prob(
|
Chris@16
|
457 function,
|
Chris@16
|
458 q,
|
Chris@16
|
459 &result, Policy()))
|
Chris@16
|
460 {
|
Chris@16
|
461 return result;
|
Chris@16
|
462 }
|
Chris@16
|
463 // Special case:
|
Chris@16
|
464 if (dist.mean() == 0)
|
Chris@16
|
465 { // if mean = 0 then p = 0, so k can be anything?
|
Chris@16
|
466 if (false == poisson_detail::check_mean_NZ(
|
Chris@16
|
467 function,
|
Chris@16
|
468 dist.mean(),
|
Chris@16
|
469 &result, Policy()))
|
Chris@16
|
470 {
|
Chris@16
|
471 return result;
|
Chris@16
|
472 }
|
Chris@16
|
473 }
|
Chris@16
|
474 if(q == 0)
|
Chris@16
|
475 {
|
Chris@16
|
476 return policies::raise_overflow_error<RealType>(function, 0, Policy());
|
Chris@16
|
477 }
|
Chris@16
|
478 if(q == 1)
|
Chris@16
|
479 {
|
Chris@16
|
480 return 0; // Exact result regardless of discrete-quantile Policy
|
Chris@16
|
481 }
|
Chris@16
|
482 typedef typename Policy::discrete_quantile_type discrete_type;
|
Chris@16
|
483 boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
|
Chris@16
|
484 RealType guess, factor = 8;
|
Chris@16
|
485 RealType z = dist.mean();
|
Chris@16
|
486 if(z < 1)
|
Chris@16
|
487 guess = z;
|
Chris@16
|
488 else
|
Chris@16
|
489 guess = boost::math::detail::inverse_poisson_cornish_fisher(z, RealType(1-q), q, Policy());
|
Chris@16
|
490 if(z > 5)
|
Chris@16
|
491 {
|
Chris@16
|
492 if(z > 1000)
|
Chris@16
|
493 factor = 1.01f;
|
Chris@16
|
494 else if(z > 50)
|
Chris@16
|
495 factor = 1.1f;
|
Chris@16
|
496 else if(guess > 10)
|
Chris@16
|
497 factor = 1.25f;
|
Chris@16
|
498 else
|
Chris@16
|
499 factor = 2;
|
Chris@16
|
500 if(guess < 1.1)
|
Chris@16
|
501 factor = 8;
|
Chris@16
|
502 }
|
Chris@16
|
503
|
Chris@16
|
504 return detail::inverse_discrete_quantile(
|
Chris@16
|
505 dist,
|
Chris@16
|
506 q,
|
Chris@16
|
507 true,
|
Chris@16
|
508 guess,
|
Chris@16
|
509 factor,
|
Chris@16
|
510 RealType(1),
|
Chris@16
|
511 discrete_type(),
|
Chris@16
|
512 max_iter);
|
Chris@16
|
513 } // quantile complement.
|
Chris@16
|
514
|
Chris@16
|
515 } // namespace math
|
Chris@16
|
516 } // namespace boost
|
Chris@16
|
517
|
Chris@16
|
518 // This include must be at the end, *after* the accessors
|
Chris@16
|
519 // for this distribution have been defined, in order to
|
Chris@16
|
520 // keep compilers that support two-phase lookup happy.
|
Chris@16
|
521 #include <boost/math/distributions/detail/derived_accessors.hpp>
|
Chris@16
|
522 #include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
|
Chris@16
|
523
|
Chris@16
|
524 #endif // BOOST_MATH_SPECIAL_POISSON_HPP
|
Chris@16
|
525
|
Chris@16
|
526
|
Chris@16
|
527
|