Warning, file /include/boost/math/distributions/negative_binomial.hpp was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
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
0037
0038
0039
0040
0041
0042
0043
0044 #ifndef BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP
0045 #define BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP
0046
0047 #include <boost/math/tools/config.hpp>
0048 #include <boost/math/tools/tuple.hpp>
0049 #include <boost/math/tools/numeric_limits.hpp>
0050 #include <boost/math/tools/cstdint.hpp>
0051 #include <boost/math/distributions/fwd.hpp>
0052 #include <boost/math/special_functions/beta.hpp> // for ibeta(a, b, x) == Ix(a, b).
0053 #include <boost/math/distributions/complement.hpp> // complement.
0054 #include <boost/math/distributions/detail/common_error_handling.hpp> // error checks domain_error & logic_error.
0055 #include <boost/math/special_functions/fpclassify.hpp> // isnan.
0056 #include <boost/math/tools/roots.hpp> // for root finding.
0057 #include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
0058 #include <boost/math/policies/error_handling.hpp>
0059
0060 #if defined (BOOST_MSVC)
0061 # pragma warning(push)
0062
0063
0064
0065 #endif
0066
0067 namespace boost
0068 {
0069 namespace math
0070 {
0071 namespace negative_binomial_detail
0072 {
0073
0074 template <class RealType, class Policy>
0075 BOOST_MATH_GPU_ENABLED inline bool check_successes(const char* function, const RealType& r, RealType* result, const Policy& pol)
0076 {
0077 if( !(boost::math::isfinite)(r) || (r <= 0) )
0078 {
0079 *result = policies::raise_domain_error<RealType>(
0080 function,
0081 "Number of successes argument is %1%, but must be > 0 !", r, pol);
0082 return false;
0083 }
0084 return true;
0085 }
0086 template <class RealType, class Policy>
0087 BOOST_MATH_GPU_ENABLED inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol)
0088 {
0089 if( !(boost::math::isfinite)(p) || (p < 0) || (p > 1) )
0090 {
0091 *result = policies::raise_domain_error<RealType>(
0092 function,
0093 "Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, pol);
0094 return false;
0095 }
0096 return true;
0097 }
0098 template <class RealType, class Policy>
0099 BOOST_MATH_GPU_ENABLED inline bool check_dist(const char* function, const RealType& r, const RealType& p, RealType* result, const Policy& pol)
0100 {
0101 return check_success_fraction(function, p, result, pol)
0102 && check_successes(function, r, result, pol);
0103 }
0104 template <class RealType, class Policy>
0105 BOOST_MATH_GPU_ENABLED inline bool check_dist_and_k(const char* function, const RealType& r, const RealType& p, RealType k, RealType* result, const Policy& pol)
0106 {
0107 if(check_dist(function, r, p, result, pol) == false)
0108 {
0109 return false;
0110 }
0111 if( !(boost::math::isfinite)(k) || (k < 0) )
0112 {
0113 *result = policies::raise_domain_error<RealType>(
0114 function,
0115 "Number of failures argument is %1%, but must be >= 0 !", k, pol);
0116 return false;
0117 }
0118 return true;
0119 }
0120
0121 template <class RealType, class Policy>
0122 BOOST_MATH_GPU_ENABLED inline bool check_dist_and_prob(const char* function, const RealType& r, RealType p, RealType prob, RealType* result, const Policy& pol)
0123 {
0124 if((check_dist(function, r, p, result, pol) && detail::check_probability(function, prob, result, pol)) == false)
0125 {
0126 return false;
0127 }
0128 return true;
0129 }
0130 }
0131
0132 template <class RealType = double, class Policy = policies::policy<> >
0133 class negative_binomial_distribution
0134 {
0135 public:
0136 typedef RealType value_type;
0137 typedef Policy policy_type;
0138
0139 BOOST_MATH_GPU_ENABLED negative_binomial_distribution(RealType r, RealType p) : m_r(r), m_p(p)
0140 {
0141 RealType result;
0142 negative_binomial_detail::check_dist(
0143 "negative_binomial_distribution<%1%>::negative_binomial_distribution",
0144 m_r,
0145 m_p,
0146 &result, Policy());
0147 }
0148
0149
0150 BOOST_MATH_GPU_ENABLED RealType success_fraction() const
0151 {
0152 return m_p;
0153 }
0154 BOOST_MATH_GPU_ENABLED RealType successes() const
0155 {
0156 return m_r;
0157 }
0158
0159 BOOST_MATH_GPU_ENABLED static RealType find_lower_bound_on_p(
0160 RealType trials,
0161 RealType successes,
0162 RealType alpha)
0163 {
0164 constexpr auto function = "boost::math::negative_binomial<%1%>::find_lower_bound_on_p";
0165 RealType result = 0;
0166 RealType failures = trials - successes;
0167 if(false == detail::check_probability(function, alpha, &result, Policy())
0168 && negative_binomial_detail::check_dist_and_k(
0169 function, successes, RealType(0), failures, &result, Policy()))
0170 {
0171 return result;
0172 }
0173
0174
0175
0176
0177
0178
0179
0180
0181 return ibeta_inv(successes, failures + 1, alpha, static_cast<RealType*>(nullptr), Policy());
0182 }
0183
0184 BOOST_MATH_GPU_ENABLED static RealType find_upper_bound_on_p(
0185 RealType trials,
0186 RealType successes,
0187 RealType alpha)
0188 {
0189 constexpr auto function = "boost::math::negative_binomial<%1%>::find_upper_bound_on_p";
0190 RealType result = 0;
0191 RealType failures = trials - successes;
0192 if(false == negative_binomial_detail::check_dist_and_k(
0193 function, successes, RealType(0), failures, &result, Policy())
0194 && detail::check_probability(function, alpha, &result, Policy()))
0195 {
0196 return result;
0197 }
0198 if(failures == 0)
0199 return 1;
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209 return ibetac_inv(successes, failures, alpha, static_cast<RealType*>(nullptr), Policy());
0210 }
0211
0212
0213
0214
0215 BOOST_MATH_GPU_ENABLED static RealType find_minimum_number_of_trials(
0216 RealType k,
0217 RealType p,
0218 RealType alpha)
0219 {
0220 constexpr auto function = "boost::math::negative_binomial<%1%>::find_minimum_number_of_trials";
0221
0222 RealType result = 0;
0223 if(false == negative_binomial_detail::check_dist_and_k(
0224 function, RealType(1), p, k, &result, Policy())
0225 && detail::check_probability(function, alpha, &result, Policy()))
0226 { return result; }
0227
0228 result = ibeta_inva(k + 1, p, alpha, Policy());
0229 return result + k;
0230 }
0231
0232 BOOST_MATH_GPU_ENABLED static RealType find_maximum_number_of_trials(
0233 RealType k,
0234 RealType p,
0235 RealType alpha)
0236 {
0237 constexpr auto function = "boost::math::negative_binomial<%1%>::find_maximum_number_of_trials";
0238
0239 RealType result = 0;
0240 if(false == negative_binomial_detail::check_dist_and_k(
0241 function, RealType(1), p, k, &result, Policy())
0242 && detail::check_probability(function, alpha, &result, Policy()))
0243 { return result; }
0244
0245 result = ibetac_inva(k + 1, p, alpha, Policy());
0246 return result + k;
0247 }
0248
0249 private:
0250 RealType m_r;
0251 RealType m_p;
0252 };
0253
0254 typedef negative_binomial_distribution<double> negative_binomial;
0255
0256 #ifdef __cpp_deduction_guides
0257 template <class RealType>
0258 negative_binomial_distribution(RealType,RealType)->negative_binomial_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0259 #endif
0260
0261 template <class RealType, class Policy>
0262 BOOST_MATH_GPU_ENABLED inline const boost::math::pair<RealType, RealType> range(const negative_binomial_distribution<RealType, Policy>& )
0263 {
0264 using boost::math::tools::max_value;
0265 return boost::math::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0266 }
0267
0268 template <class RealType, class Policy>
0269 BOOST_MATH_GPU_ENABLED inline const boost::math::pair<RealType, RealType> support(const negative_binomial_distribution<RealType, Policy>& )
0270 {
0271
0272 using boost::math::tools::max_value;
0273 return boost::math::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0274 }
0275
0276 template <class RealType, class Policy>
0277 BOOST_MATH_GPU_ENABLED inline RealType mean(const negative_binomial_distribution<RealType, Policy>& dist)
0278 {
0279 return dist.successes() * (1 - dist.success_fraction() ) / dist.success_fraction();
0280 }
0281
0282
0283
0284
0285
0286
0287
0288
0289 template <class RealType, class Policy>
0290 BOOST_MATH_GPU_ENABLED inline RealType mode(const negative_binomial_distribution<RealType, Policy>& dist)
0291 {
0292 BOOST_MATH_STD_USING
0293 return floor((dist.successes() -1) * (1 - dist.success_fraction()) / dist.success_fraction());
0294 }
0295
0296 template <class RealType, class Policy>
0297 BOOST_MATH_GPU_ENABLED inline RealType skewness(const negative_binomial_distribution<RealType, Policy>& dist)
0298 {
0299 BOOST_MATH_STD_USING
0300 RealType p = dist.success_fraction();
0301 RealType r = dist.successes();
0302
0303 return (2 - p) /
0304 sqrt(r * (1 - p));
0305 }
0306
0307 template <class RealType, class Policy>
0308 BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const negative_binomial_distribution<RealType, Policy>& dist)
0309 {
0310
0311 RealType p = dist.success_fraction();
0312 RealType r = dist.successes();
0313 return 3 + (6 / r) + ((p * p) / (r * (1 - p)));
0314 }
0315
0316 template <class RealType, class Policy>
0317 BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const negative_binomial_distribution<RealType, Policy>& dist)
0318 {
0319
0320 RealType p = dist.success_fraction();
0321 RealType r = dist.successes();
0322 return (6 - p * (6-p)) / (r * (1-p));
0323 }
0324
0325 template <class RealType, class Policy>
0326 BOOST_MATH_GPU_ENABLED inline RealType variance(const negative_binomial_distribution<RealType, Policy>& dist)
0327 {
0328 return dist.successes() * (1 - dist.success_fraction())
0329 / (dist.success_fraction() * dist.success_fraction());
0330 }
0331
0332
0333
0334
0335
0336
0337
0338
0339 template <class RealType, class Policy>
0340 BOOST_MATH_GPU_ENABLED inline RealType pdf(const negative_binomial_distribution<RealType, Policy>& dist, const RealType& k)
0341 {
0342 BOOST_FPU_EXCEPTION_GUARD
0343
0344 constexpr auto function = "boost::math::pdf(const negative_binomial_distribution<%1%>&, %1%)";
0345
0346 RealType r = dist.successes();
0347 RealType p = dist.success_fraction();
0348 RealType result = 0;
0349 if(false == negative_binomial_detail::check_dist_and_k(
0350 function,
0351 r,
0352 dist.success_fraction(),
0353 k,
0354 &result, Policy()))
0355 {
0356 return result;
0357 }
0358
0359 result = (p/(r + k)) * ibeta_derivative(r, static_cast<RealType>(k+1), p, Policy());
0360
0361
0362 return result;
0363 }
0364
0365 template <class RealType, class Policy>
0366 BOOST_MATH_GPU_ENABLED inline RealType cdf(const negative_binomial_distribution<RealType, Policy>& dist, const RealType& k)
0367 {
0368 constexpr auto function = "boost::math::cdf(const negative_binomial_distribution<%1%>&, %1%)";
0369 using boost::math::ibeta;
0370
0371
0372 RealType p = dist.success_fraction();
0373 RealType r = dist.successes();
0374
0375 RealType result = 0;
0376 if(false == negative_binomial_detail::check_dist_and_k(
0377 function,
0378 r,
0379 dist.success_fraction(),
0380 k,
0381 &result, Policy()))
0382 {
0383 return result;
0384 }
0385
0386 RealType probability = ibeta(r, static_cast<RealType>(k+1), p, Policy());
0387
0388 return probability;
0389 }
0390
0391 template <class RealType, class Policy>
0392 BOOST_MATH_GPU_ENABLED inline RealType cdf(const complemented2_type<negative_binomial_distribution<RealType, Policy>, RealType>& c)
0393 {
0394
0395 constexpr auto function = "boost::math::cdf(const negative_binomial_distribution<%1%>&, %1%)";
0396 using boost::math::ibetac;
0397
0398
0399 RealType const& k = c.param;
0400 negative_binomial_distribution<RealType, Policy> const& dist = c.dist;
0401 RealType p = dist.success_fraction();
0402 RealType r = dist.successes();
0403
0404 RealType result = 0;
0405 if(false == negative_binomial_detail::check_dist_and_k(
0406 function,
0407 r,
0408 p,
0409 k,
0410 &result, Policy()))
0411 {
0412 return result;
0413 }
0414
0415
0416
0417
0418
0419 RealType probability = ibetac(r, static_cast<RealType>(k+1), p, Policy());
0420
0421
0422 return probability;
0423 }
0424
0425 template <class RealType, class Policy>
0426 BOOST_MATH_GPU_ENABLED inline RealType quantile(const negative_binomial_distribution<RealType, Policy>& dist, const RealType& P)
0427 {
0428
0429
0430
0431
0432
0433
0434 constexpr auto function = "boost::math::quantile(const negative_binomial_distribution<%1%>&, %1%)";
0435 BOOST_MATH_STD_USING
0436
0437 RealType p = dist.success_fraction();
0438 RealType r = dist.successes();
0439
0440 RealType result = 0;
0441 if(false == negative_binomial_detail::check_dist_and_prob
0442 (function, r, p, P, &result, Policy()))
0443 {
0444 return result;
0445 }
0446
0447
0448 if (P == 1)
0449 {
0450 result = policies::raise_overflow_error<RealType>(
0451 function,
0452 "Probability argument is 1, which implies infinite failures !", Policy());
0453 return result;
0454
0455
0456 }
0457 if (P == 0)
0458 {
0459 return 0;
0460 }
0461 if (P <= pow(dist.success_fraction(), dist.successes()))
0462 {
0463 return 0;
0464 }
0465 if(p == 0)
0466 {
0467 result = policies::raise_overflow_error<RealType>(
0468 function,
0469 "Success fraction is 0, which implies infinite failures !", Policy());
0470 return result;
0471
0472
0473 }
0474
0475
0476
0477
0478
0479 RealType guess = 0;
0480 RealType factor = 5;
0481 if(r * r * r * P * p > 0.005)
0482 guess = detail::inverse_negative_binomial_cornish_fisher(r, p, RealType(1-p), P, RealType(1-P), Policy());
0483
0484 if(guess < 10)
0485 {
0486
0487
0488
0489 guess = BOOST_MATH_GPU_SAFE_MIN(RealType(r * 2), RealType(10));
0490 }
0491 else
0492 factor = (1-P < sqrt(tools::epsilon<RealType>())) ? 2 : (guess < 20 ? 1.2f : 1.1f);
0493 BOOST_MATH_INSTRUMENT_CODE("guess = " << guess);
0494
0495
0496
0497 boost::math::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0498 typedef typename Policy::discrete_quantile_type discrete_type;
0499 return detail::inverse_discrete_quantile(
0500 dist,
0501 P,
0502 false,
0503 guess,
0504 factor,
0505 RealType(1),
0506 discrete_type(),
0507 max_iter);
0508 }
0509
0510 template <class RealType, class Policy>
0511 BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type<negative_binomial_distribution<RealType, Policy>, RealType>& c)
0512 {
0513
0514
0515 constexpr auto function = "boost::math::quantile(const negative_binomial_distribution<%1%>&, %1%)";
0516 BOOST_MATH_STD_USING
0517
0518
0519 RealType Q = c.param;
0520 const negative_binomial_distribution<RealType, Policy>& dist = c.dist;
0521 RealType p = dist.success_fraction();
0522 RealType r = dist.successes();
0523 RealType result = 0;
0524 if(false == negative_binomial_detail::check_dist_and_prob(
0525 function,
0526 r,
0527 p,
0528 Q,
0529 &result, Policy()))
0530 {
0531 return result;
0532 }
0533
0534
0535
0536 if(Q == 1)
0537 {
0538
0539 return 0;
0540 }
0541 if(Q == 0)
0542 {
0543
0544 result = policies::raise_overflow_error<RealType>(
0545 function,
0546 "Probability argument complement is 0, which implies infinite failures !", Policy());
0547 return result;
0548
0549
0550 }
0551 if (-Q <= boost::math::powm1(dist.success_fraction(), dist.successes(), Policy()))
0552 {
0553 return 0;
0554 }
0555 if(p == 0)
0556 {
0557
0558 result = policies::raise_overflow_error<RealType>(
0559 function,
0560 "Success fraction is 0, which implies infinite failures !", Policy());
0561 return result;
0562
0563
0564 }
0565
0566 RealType guess = 0;
0567 RealType factor = 5;
0568 if(r * r * r * (1-Q) * p > 0.005)
0569 guess = detail::inverse_negative_binomial_cornish_fisher(r, p, RealType(1-p), RealType(1-Q), Q, Policy());
0570
0571 if(guess < 10)
0572 {
0573
0574
0575
0576 guess = BOOST_MATH_GPU_SAFE_MIN(RealType(r * 2), RealType(10));
0577 }
0578 else
0579 factor = (Q < sqrt(tools::epsilon<RealType>())) ? 2 : (guess < 20 ? 1.2f : 1.1f);
0580 BOOST_MATH_INSTRUMENT_CODE("guess = " << guess);
0581
0582
0583
0584 boost::math::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
0585 typedef typename Policy::discrete_quantile_type discrete_type;
0586 return detail::inverse_discrete_quantile(
0587 dist,
0588 Q,
0589 true,
0590 guess,
0591 factor,
0592 RealType(1),
0593 discrete_type(),
0594 max_iter);
0595 }
0596
0597 }
0598 }
0599
0600
0601
0602
0603 #include <boost/math/distributions/detail/derived_accessors.hpp>
0604
0605 #if defined (BOOST_MSVC)
0606 # pragma warning(pop)
0607 #endif
0608
0609 #endif