annotate DEPENDENCIES/generic/include/boost/math/distributions/poisson.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
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