File indexing completed on 2025-01-18 09:39:44
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifndef BOOST_MATH_SPECIAL_POISSON_HPP
0037 #define BOOST_MATH_SPECIAL_POISSON_HPP
0038
0039 #include <boost/math/distributions/fwd.hpp>
0040 #include <boost/math/special_functions/gamma.hpp> // for incomplete gamma. gamma_q
0041 #include <boost/math/special_functions/trunc.hpp> // for incomplete gamma. gamma_q
0042 #include <boost/math/distributions/complement.hpp> // complements
0043 #include <boost/math/distributions/detail/common_error_handling.hpp> // error checks
0044 #include <boost/math/special_functions/fpclassify.hpp> // isnan.
0045 #include <boost/math/special_functions/factorials.hpp> // factorials.
0046 #include <boost/math/tools/roots.hpp> // for root finding.
0047 #include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
0048
0049 #include <utility>
0050 #include <limits>
0051
0052 namespace boost
0053 {
0054 namespace math
0055 {
0056 namespace poisson_detail
0057 {
0058
0059
0060
0061
0062 template <class RealType, class Policy>
0063 inline bool check_mean(const char* function, const RealType& mean, RealType* result, const Policy& pol)
0064 {
0065 if(!(boost::math::isfinite)(mean) || (mean < 0))
0066 {
0067 *result = policies::raise_domain_error<RealType>(
0068 function,
0069 "Mean argument is %1%, but must be >= 0 !", mean, pol);
0070 return false;
0071 }
0072 return true;
0073 }
0074
0075 template <class RealType, class Policy>
0076 inline bool check_mean_NZ(const char* function, const RealType& mean, RealType* result, const Policy& pol)
0077 {
0078 if( !(boost::math::isfinite)(mean) || (mean <= 0))
0079 {
0080 *result = policies::raise_domain_error<RealType>(
0081 function,
0082 "Mean argument is %1%, but must be > 0 !", mean, pol);
0083 return false;
0084 }
0085 return true;
0086 }
0087
0088 template <class RealType, class Policy>
0089 inline bool check_dist(const char* function, const RealType& mean, RealType* result, const Policy& pol)
0090 {
0091 return check_mean_NZ(function, mean, result, pol);
0092 }
0093
0094 template <class RealType, class Policy>
0095 inline bool check_k(const char* function, const RealType& k, RealType* result, const Policy& pol)
0096 {
0097 if((k < 0) || !(boost::math::isfinite)(k))
0098 {
0099 *result = policies::raise_domain_error<RealType>(
0100 function,
0101 "Number of events k argument is %1%, but must be >= 0 !", k, pol);
0102 return false;
0103 }
0104 return true;
0105 }
0106
0107 template <class RealType, class Policy>
0108 inline bool check_dist_and_k(const char* function, RealType mean, RealType k, RealType* result, const Policy& pol)
0109 {
0110 if((check_dist(function, mean, result, pol) == false) ||
0111 (check_k(function, k, result, pol) == false))
0112 {
0113 return false;
0114 }
0115 return true;
0116 }
0117
0118 template <class RealType, class Policy>
0119 inline bool check_prob(const char* function, const RealType& p, RealType* result, const Policy& pol)
0120 {
0121 if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
0122 {
0123 *result = policies::raise_domain_error<RealType>(
0124 function,
0125 "Probability argument is %1%, but must be >= 0 and <= 1 !", p, pol);
0126 return false;
0127 }
0128 return true;
0129 }
0130
0131 template <class RealType, class Policy>
0132 inline bool check_dist_and_prob(const char* function, RealType mean, RealType p, RealType* result, const Policy& pol)
0133 {
0134 if((check_dist(function, mean, result, pol) == false) ||
0135 (check_prob(function, p, result, pol) == false))
0136 {
0137 return false;
0138 }
0139 return true;
0140 }
0141
0142 }
0143
0144 template <class RealType = double, class Policy = policies::policy<> >
0145 class poisson_distribution
0146 {
0147 public:
0148 using value_type = RealType;
0149 using policy_type = Policy;
0150
0151 explicit poisson_distribution(RealType l_mean = 1) : m_l(l_mean)
0152 {
0153 RealType r;
0154 poisson_detail::check_dist(
0155 "boost::math::poisson_distribution<%1%>::poisson_distribution",
0156 m_l,
0157 &r, Policy());
0158 }
0159
0160 RealType mean() const
0161 {
0162 return m_l;
0163 }
0164 private:
0165
0166 RealType m_l;
0167 };
0168
0169 using poisson = poisson_distribution<double>;
0170
0171 #ifdef __cpp_deduction_guides
0172 template <class RealType>
0173 poisson_distribution(RealType)->poisson_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0174 #endif
0175
0176
0177
0178 template <class RealType, class Policy>
0179 inline std::pair<RealType, RealType> range(const poisson_distribution<RealType, Policy>& )
0180 {
0181 using boost::math::tools::max_value;
0182 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0183 }
0184
0185 template <class RealType, class Policy>
0186 inline std::pair<RealType, RealType> support(const poisson_distribution<RealType, Policy>& )
0187 {
0188
0189 using boost::math::tools::max_value;
0190 return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0191 }
0192
0193 template <class RealType, class Policy>
0194 inline RealType mean(const poisson_distribution<RealType, Policy>& dist)
0195 {
0196 return dist.mean();
0197 }
0198
0199 template <class RealType, class Policy>
0200 inline RealType mode(const poisson_distribution<RealType, Policy>& dist)
0201 {
0202 BOOST_MATH_STD_USING
0203 return floor(dist.mean());
0204 }
0205
0206
0207
0208 template <class RealType, class Policy>
0209 inline RealType variance(const poisson_distribution<RealType, Policy>& dist)
0210 {
0211 return dist.mean();
0212 }
0213
0214
0215
0216 template <class RealType, class Policy>
0217 inline RealType skewness(const poisson_distribution<RealType, Policy>& dist)
0218 {
0219 BOOST_MATH_STD_USING
0220 return 1 / sqrt(dist.mean());
0221 }
0222
0223 template <class RealType, class Policy>
0224 inline RealType kurtosis_excess(const poisson_distribution<RealType, Policy>& dist)
0225 {
0226 return 1 / dist.mean();
0227
0228
0229
0230 }
0231
0232 template <class RealType, class Policy>
0233 inline RealType kurtosis(const poisson_distribution<RealType, Policy>& dist)
0234 {
0235
0236
0237
0238 return 3 + 1 / dist.mean();
0239
0240
0241
0242 }
0243
0244 template <class RealType, class Policy>
0245 RealType pdf(const poisson_distribution<RealType, Policy>& dist, const RealType& k)
0246 {
0247
0248 BOOST_FPU_EXCEPTION_GUARD
0249
0250 BOOST_MATH_STD_USING
0251
0252 RealType mean = dist.mean();
0253
0254 RealType result = 0;
0255 if(false == poisson_detail::check_dist_and_k(
0256 "boost::math::pdf(const poisson_distribution<%1%>&, %1%)",
0257 mean,
0258 k,
0259 &result, Policy()))
0260 {
0261 return result;
0262 }
0263
0264
0265 if (mean == 0)
0266 {
0267 return 0;
0268 }
0269 if (k == 0)
0270 {
0271 return exp(-mean);
0272 }
0273 return boost::math::gamma_p_derivative(k+1, mean, Policy());
0274 }
0275
0276 template <class RealType, class Policy>
0277 RealType logpdf(const poisson_distribution<RealType, Policy>& dist, const RealType& k)
0278 {
0279 BOOST_FPU_EXCEPTION_GUARD
0280
0281 BOOST_MATH_STD_USING
0282 using boost::math::lgamma;
0283
0284 RealType mean = dist.mean();
0285
0286 RealType result = -std::numeric_limits<RealType>::infinity();
0287 if(false == poisson_detail::check_dist_and_k(
0288 "boost::math::pdf(const poisson_distribution<%1%>&, %1%)",
0289 mean,
0290 k,
0291 &result, Policy()))
0292 {
0293 return result;
0294 }
0295
0296
0297 if (mean == 0)
0298 {
0299 return std::numeric_limits<RealType>::quiet_NaN();
0300 }
0301
0302
0303 if(k > 0 && mean > 0)
0304 {
0305 return -lgamma(k+1) + k*log(mean) - mean;
0306 }
0307
0308 result = log(pdf(dist, k));
0309 return result;
0310 }
0311
0312 template <class RealType, class Policy>
0313 RealType cdf(const poisson_distribution<RealType, Policy>& dist, const RealType& k)
0314 {
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332 BOOST_MATH_STD_USING
0333
0334 RealType mean = dist.mean();
0335
0336 RealType result = 0;
0337 if(false == poisson_detail::check_dist_and_k(
0338 "boost::math::cdf(const poisson_distribution<%1%>&, %1%)",
0339 mean,
0340 k,
0341 &result, Policy()))
0342 {
0343 return result;
0344 }
0345
0346 if (mean == 0)
0347 {
0348 return 0;
0349 }
0350 if (k == 0)
0351 {
0352
0353
0354 return exp(-mean);
0355 }
0356
0357
0358
0359
0360 return gamma_q(k+1, mean, Policy());
0361 }
0362
0363 template <class RealType, class Policy>
0364 RealType cdf(const complemented2_type<poisson_distribution<RealType, Policy>, RealType>& c)
0365 {
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382 RealType const& k = c.param;
0383 poisson_distribution<RealType, Policy> const& dist = c.dist;
0384
0385 RealType mean = dist.mean();
0386
0387
0388 RealType result = 0;
0389 if(false == poisson_detail::check_dist_and_k(
0390 "boost::math::cdf(const poisson_distribution<%1%>&, %1%)",
0391 mean,
0392 k,
0393 &result, Policy()))
0394 {
0395 return result;
0396 }
0397
0398 if (mean == 0)
0399 {
0400 return 1;
0401 }
0402 if (k == 0)
0403 {
0404 return -boost::math::expm1(-mean, Policy());
0405 }
0406
0407
0408
0409 return gamma_p(k + 1, mean, Policy());
0410
0411 }
0412
0413 template <class RealType, class Policy>
0414 inline RealType quantile(const poisson_distribution<RealType, Policy>& dist, const RealType& p)
0415 {
0416
0417 static const char* function = "boost::math::quantile(const poisson_distribution<%1%>&, %1%)";
0418 RealType result = 0;
0419 if(false == poisson_detail::check_prob(
0420 function,
0421 p,
0422 &result, Policy()))
0423 {
0424 return result;
0425 }
0426
0427 if (dist.mean() == 0)
0428 {
0429 if (false == poisson_detail::check_mean_NZ(
0430 function,
0431 dist.mean(),
0432 &result, Policy()))
0433 {
0434 return result;
0435 }
0436 }
0437 if(p == 0)
0438 {
0439 return 0;
0440 }
0441 if(p == 1)
0442 {
0443 return policies::raise_overflow_error<RealType>(function, 0, Policy());
0444 }
0445 using discrete_type = typename Policy::discrete_quantile_type;
0446 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0447 RealType guess;
0448 RealType factor = 8;
0449 RealType z = dist.mean();
0450 if(z < 1)
0451 guess = z;
0452 else
0453 guess = boost::math::detail::inverse_poisson_cornish_fisher(z, p, RealType(1-p), Policy());
0454 if(z > 5)
0455 {
0456 if(z > 1000)
0457 factor = 1.01f;
0458 else if(z > 50)
0459 factor = 1.1f;
0460 else if(guess > 10)
0461 factor = 1.25f;
0462 else
0463 factor = 2;
0464 if(guess < 1.1)
0465 factor = 8;
0466 }
0467
0468 return detail::inverse_discrete_quantile(
0469 dist,
0470 p,
0471 false,
0472 guess,
0473 factor,
0474 RealType(1),
0475 discrete_type(),
0476 max_iter);
0477 }
0478
0479 template <class RealType, class Policy>
0480 inline RealType quantile(const complemented2_type<poisson_distribution<RealType, Policy>, RealType>& c)
0481 {
0482
0483
0484
0485
0486 static const char* function = "boost::math::quantile(complement(const poisson_distribution<%1%>&, %1%))";
0487 RealType q = c.param;
0488 const poisson_distribution<RealType, Policy>& dist = c.dist;
0489 RealType result = 0;
0490 if(false == poisson_detail::check_prob(
0491 function,
0492 q,
0493 &result, Policy()))
0494 {
0495 return result;
0496 }
0497
0498 if (dist.mean() == 0)
0499 {
0500 if (false == poisson_detail::check_mean_NZ(
0501 function,
0502 dist.mean(),
0503 &result, Policy()))
0504 {
0505 return result;
0506 }
0507 }
0508 if(q == 0)
0509 {
0510 return policies::raise_overflow_error<RealType>(function, 0, Policy());
0511 }
0512 if(q == 1)
0513 {
0514 return 0;
0515 }
0516 using discrete_type = typename Policy::discrete_quantile_type;
0517 std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0518 RealType guess;
0519 RealType factor = 8;
0520 RealType z = dist.mean();
0521 if(z < 1)
0522 guess = z;
0523 else
0524 guess = boost::math::detail::inverse_poisson_cornish_fisher(z, RealType(1-q), q, Policy());
0525 if(z > 5)
0526 {
0527 if(z > 1000)
0528 factor = 1.01f;
0529 else if(z > 50)
0530 factor = 1.1f;
0531 else if(guess > 10)
0532 factor = 1.25f;
0533 else
0534 factor = 2;
0535 if(guess < 1.1)
0536 factor = 8;
0537 }
0538
0539 return detail::inverse_discrete_quantile(
0540 dist,
0541 q,
0542 true,
0543 guess,
0544 factor,
0545 RealType(1),
0546 discrete_type(),
0547 max_iter);
0548 }
0549
0550 }
0551 }
0552
0553
0554
0555
0556 #include <boost/math/distributions/detail/derived_accessors.hpp>
0557
0558 #endif
0559
0560
0561