negative_binomial.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. // boost\math\special_functions\negative_binomial.hpp
  2. // Copyright Paul A. Bristow 2007.
  3. // Copyright John Maddock 2007.
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt
  7. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. // http://en.wikipedia.org/wiki/negative_binomial_distribution
  9. // http://mathworld.wolfram.com/NegativeBinomialDistribution.html
  10. // http://documents.wolfram.com/teachersedition/Teacher/Statistics/DiscreteDistributions.html
  11. // The negative binomial distribution NegativeBinomialDistribution[n, p]
  12. // is the distribution of the number (k) of failures that occur in a sequence of trials before
  13. // r successes have occurred, where the probability of success in each trial is p.
  14. // In a sequence of Bernoulli trials or events
  15. // (independent, yes or no, succeed or fail) with success_fraction probability p,
  16. // negative_binomial is the probability that k or fewer failures
  17. // precede the r th trial's success.
  18. // random variable k is the number of failures (NOT the probability).
  19. // Negative_binomial distribution is a discrete probability distribution.
  20. // But note that the negative binomial distribution
  21. // (like others including the binomial, Poisson & Bernoulli)
  22. // is strictly defined as a discrete function: only integral values of k are envisaged.
  23. // However because of the method of calculation using a continuous gamma function,
  24. // it is convenient to treat it as if a continuous function,
  25. // and permit non-integral values of k.
  26. // However, by default the policy is to use discrete_quantile_policy.
  27. // To enforce the strict mathematical model, users should use conversion
  28. // on k outside this function to ensure that k is integral.
  29. // MATHCAD cumulative negative binomial pnbinom(k, n, p)
  30. // Implementation note: much greater speed, and perhaps greater accuracy,
  31. // might be achieved for extreme values by using a normal approximation.
  32. // This is NOT been tested or implemented.
  33. #ifndef BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP
  34. #define BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP
  35. #include <boost/math/distributions/fwd.hpp>
  36. #include <boost/math/special_functions/beta.hpp> // for ibeta(a, b, x) == Ix(a, b).
  37. #include <boost/math/distributions/complement.hpp> // complement.
  38. #include <boost/math/distributions/detail/common_error_handling.hpp> // error checks domain_error & logic_error.
  39. #include <boost/math/special_functions/fpclassify.hpp> // isnan.
  40. #include <boost/math/tools/roots.hpp> // for root finding.
  41. #include <boost/math/distributions/detail/inv_discrete_quantile.hpp>
  42. #include <boost/type_traits/is_floating_point.hpp>
  43. #include <boost/type_traits/is_integral.hpp>
  44. #include <boost/type_traits/is_same.hpp>
  45. #include <limits> // using std::numeric_limits;
  46. #include <utility>
  47. #if defined (BOOST_MSVC)
  48. # pragma warning(push)
  49. // This believed not now necessary, so commented out.
  50. //# pragma warning(disable: 4702) // unreachable code.
  51. // in domain_error_imp in error_handling.
  52. #endif
  53. namespace boost
  54. {
  55. namespace math
  56. {
  57. namespace negative_binomial_detail
  58. {
  59. // Common error checking routines for negative binomial distribution functions:
  60. template <class RealType, class Policy>
  61. inline bool check_successes(const char* function, const RealType& r, RealType* result, const Policy& pol)
  62. {
  63. if( !(boost::math::isfinite)(r) || (r <= 0) )
  64. {
  65. *result = policies::raise_domain_error<RealType>(
  66. function,
  67. "Number of successes argument is %1%, but must be > 0 !", r, pol);
  68. return false;
  69. }
  70. return true;
  71. }
  72. template <class RealType, class Policy>
  73. inline bool check_success_fraction(const char* function, const RealType& p, RealType* result, const Policy& pol)
  74. {
  75. if( !(boost::math::isfinite)(p) || (p < 0) || (p > 1) )
  76. {
  77. *result = policies::raise_domain_error<RealType>(
  78. function,
  79. "Success fraction argument is %1%, but must be >= 0 and <= 1 !", p, pol);
  80. return false;
  81. }
  82. return true;
  83. }
  84. template <class RealType, class Policy>
  85. inline bool check_dist(const char* function, const RealType& r, const RealType& p, RealType* result, const Policy& pol)
  86. {
  87. return check_success_fraction(function, p, result, pol)
  88. && check_successes(function, r, result, pol);
  89. }
  90. template <class RealType, class Policy>
  91. inline bool check_dist_and_k(const char* function, const RealType& r, const RealType& p, RealType k, RealType* result, const Policy& pol)
  92. {
  93. if(check_dist(function, r, p, result, pol) == false)
  94. {
  95. return false;
  96. }
  97. if( !(boost::math::isfinite)(k) || (k < 0) )
  98. { // Check k failures.
  99. *result = policies::raise_domain_error<RealType>(
  100. function,
  101. "Number of failures argument is %1%, but must be >= 0 !", k, pol);
  102. return false;
  103. }
  104. return true;
  105. } // Check_dist_and_k
  106. template <class RealType, class Policy>
  107. inline bool check_dist_and_prob(const char* function, const RealType& r, RealType p, RealType prob, RealType* result, const Policy& pol)
  108. {
  109. if((check_dist(function, r, p, result, pol) && detail::check_probability(function, prob, result, pol)) == false)
  110. {
  111. return false;
  112. }
  113. return true;
  114. } // check_dist_and_prob
  115. } // namespace negative_binomial_detail
  116. template <class RealType = double, class Policy = policies::policy<> >
  117. class negative_binomial_distribution
  118. {
  119. public:
  120. typedef RealType value_type;
  121. typedef Policy policy_type;
  122. negative_binomial_distribution(RealType r, RealType p) : m_r(r), m_p(p)
  123. { // Constructor.
  124. RealType result;
  125. negative_binomial_detail::check_dist(
  126. "negative_binomial_distribution<%1%>::negative_binomial_distribution",
  127. m_r, // Check successes r > 0.
  128. m_p, // Check success_fraction 0 <= p <= 1.
  129. &result, Policy());
  130. } // negative_binomial_distribution constructor.
  131. // Private data getter class member functions.
  132. RealType success_fraction() const
  133. { // Probability of success as fraction in range 0 to 1.
  134. return m_p;
  135. }
  136. RealType successes() const
  137. { // Total number of successes r.
  138. return m_r;
  139. }
  140. static RealType find_lower_bound_on_p(
  141. RealType trials,
  142. RealType successes,
  143. RealType alpha) // alpha 0.05 equivalent to 95% for one-sided test.
  144. {
  145. static const char* function = "boost::math::negative_binomial<%1%>::find_lower_bound_on_p";
  146. RealType result = 0; // of error checks.
  147. RealType failures = trials - successes;
  148. if(false == detail::check_probability(function, alpha, &result, Policy())
  149. && negative_binomial_detail::check_dist_and_k(
  150. function, successes, RealType(0), failures, &result, Policy()))
  151. {
  152. return result;
  153. }
  154. // Use complement ibeta_inv function for lower bound.
  155. // This is adapted from the corresponding binomial formula
  156. // here: http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm
  157. // This is a Clopper-Pearson interval, and may be overly conservative,
  158. // see also "A Simple Improved Inferential Method for Some
  159. // Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY
  160. // http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf
  161. //
  162. return ibeta_inv(successes, failures + 1, alpha, static_cast<RealType*>(0), Policy());
  163. } // find_lower_bound_on_p
  164. static RealType find_upper_bound_on_p(
  165. RealType trials,
  166. RealType successes,
  167. RealType alpha) // alpha 0.05 equivalent to 95% for one-sided test.
  168. {
  169. static const char* function = "boost::math::negative_binomial<%1%>::find_upper_bound_on_p";
  170. RealType result = 0; // of error checks.
  171. RealType failures = trials - successes;
  172. if(false == negative_binomial_detail::check_dist_and_k(
  173. function, successes, RealType(0), failures, &result, Policy())
  174. && detail::check_probability(function, alpha, &result, Policy()))
  175. {
  176. return result;
  177. }
  178. if(failures == 0)
  179. return 1;
  180. // Use complement ibetac_inv function for upper bound.
  181. // Note adjusted failures value: *not* failures+1 as usual.
  182. // This is adapted from the corresponding binomial formula
  183. // here: http://www.itl.nist.gov/div898/handbook/prc/section2/prc241.htm
  184. // This is a Clopper-Pearson interval, and may be overly conservative,
  185. // see also "A Simple Improved Inferential Method for Some
  186. // Discrete Distributions" Yong CAI and K. KRISHNAMOORTHY
  187. // http://www.ucs.louisiana.edu/~kxk4695/Discrete_new.pdf
  188. //
  189. return ibetac_inv(successes, failures, alpha, static_cast<RealType*>(0), Policy());
  190. } // find_upper_bound_on_p
  191. // Estimate number of trials :
  192. // "How many trials do I need to be P% sure of seeing k or fewer failures?"
  193. static RealType find_minimum_number_of_trials(
  194. RealType k, // number of failures (k >= 0).
  195. RealType p, // success fraction 0 <= p <= 1.
  196. RealType alpha) // risk level threshold 0 <= alpha <= 1.
  197. {
  198. static const char* function = "boost::math::negative_binomial<%1%>::find_minimum_number_of_trials";
  199. // Error checks:
  200. RealType result = 0;
  201. if(false == negative_binomial_detail::check_dist_and_k(
  202. function, RealType(1), p, k, &result, Policy())
  203. && detail::check_probability(function, alpha, &result, Policy()))
  204. { return result; }
  205. result = ibeta_inva(k + 1, p, alpha, Policy()); // returns n - k
  206. return result + k;
  207. } // RealType find_number_of_failures
  208. static RealType find_maximum_number_of_trials(
  209. RealType k, // number of failures (k >= 0).
  210. RealType p, // success fraction 0 <= p <= 1.
  211. RealType alpha) // risk level threshold 0 <= alpha <= 1.
  212. {
  213. static const char* function = "boost::math::negative_binomial<%1%>::find_maximum_number_of_trials";
  214. // Error checks:
  215. RealType result = 0;
  216. if(false == negative_binomial_detail::check_dist_and_k(
  217. function, RealType(1), p, k, &result, Policy())
  218. && detail::check_probability(function, alpha, &result, Policy()))
  219. { return result; }
  220. result = ibetac_inva(k + 1, p, alpha, Policy()); // returns n - k
  221. return result + k;
  222. } // RealType find_number_of_trials complemented
  223. private:
  224. RealType m_r; // successes.
  225. RealType m_p; // success_fraction
  226. }; // template <class RealType, class Policy> class negative_binomial_distribution
  227. typedef negative_binomial_distribution<double> negative_binomial; // Reserved name of type double.
  228. template <class RealType, class Policy>
  229. inline const std::pair<RealType, RealType> range(const negative_binomial_distribution<RealType, Policy>& /* dist */)
  230. { // Range of permissible values for random variable k.
  231. using boost::math::tools::max_value;
  232. return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // max_integer?
  233. }
  234. template <class RealType, class Policy>
  235. inline const std::pair<RealType, RealType> support(const negative_binomial_distribution<RealType, Policy>& /* dist */)
  236. { // Range of supported values for random variable k.
  237. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
  238. using boost::math::tools::max_value;
  239. return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // max_integer?
  240. }
  241. template <class RealType, class Policy>
  242. inline RealType mean(const negative_binomial_distribution<RealType, Policy>& dist)
  243. { // Mean of Negative Binomial distribution = r(1-p)/p.
  244. return dist.successes() * (1 - dist.success_fraction() ) / dist.success_fraction();
  245. } // mean
  246. //template <class RealType, class Policy>
  247. //inline RealType median(const negative_binomial_distribution<RealType, Policy>& dist)
  248. //{ // Median of negative_binomial_distribution is not defined.
  249. // return policies::raise_domain_error<RealType>(BOOST_CURRENT_FUNCTION, "Median is not implemented, result is %1%!", std::numeric_limits<RealType>::quiet_NaN());
  250. //} // median
  251. // Now implemented via quantile(half) in derived accessors.
  252. template <class RealType, class Policy>
  253. inline RealType mode(const negative_binomial_distribution<RealType, Policy>& dist)
  254. { // Mode of Negative Binomial distribution = floor[(r-1) * (1 - p)/p]
  255. BOOST_MATH_STD_USING // ADL of std functions.
  256. return floor((dist.successes() -1) * (1 - dist.success_fraction()) / dist.success_fraction());
  257. } // mode
  258. template <class RealType, class Policy>
  259. inline RealType skewness(const negative_binomial_distribution<RealType, Policy>& dist)
  260. { // skewness of Negative Binomial distribution = 2-p / (sqrt(r(1-p))
  261. BOOST_MATH_STD_USING // ADL of std functions.
  262. RealType p = dist.success_fraction();
  263. RealType r = dist.successes();
  264. return (2 - p) /
  265. sqrt(r * (1 - p));
  266. } // skewness
  267. template <class RealType, class Policy>
  268. inline RealType kurtosis(const negative_binomial_distribution<RealType, Policy>& dist)
  269. { // kurtosis of Negative Binomial distribution
  270. // http://en.wikipedia.org/wiki/Negative_binomial is kurtosis_excess so add 3
  271. RealType p = dist.success_fraction();
  272. RealType r = dist.successes();
  273. return 3 + (6 / r) + ((p * p) / (r * (1 - p)));
  274. } // kurtosis
  275. template <class RealType, class Policy>
  276. inline RealType kurtosis_excess(const negative_binomial_distribution<RealType, Policy>& dist)
  277. { // kurtosis excess of Negative Binomial distribution
  278. // http://mathworld.wolfram.com/Kurtosis.html table of kurtosis_excess
  279. RealType p = dist.success_fraction();
  280. RealType r = dist.successes();
  281. return (6 - p * (6-p)) / (r * (1-p));
  282. } // kurtosis_excess
  283. template <class RealType, class Policy>
  284. inline RealType variance(const negative_binomial_distribution<RealType, Policy>& dist)
  285. { // Variance of Binomial distribution = r (1-p) / p^2.
  286. return dist.successes() * (1 - dist.success_fraction())
  287. / (dist.success_fraction() * dist.success_fraction());
  288. } // variance
  289. // RealType standard_deviation(const negative_binomial_distribution<RealType, Policy>& dist)
  290. // standard_deviation provided by derived accessors.
  291. // RealType hazard(const negative_binomial_distribution<RealType, Policy>& dist)
  292. // hazard of Negative Binomial distribution provided by derived accessors.
  293. // RealType chf(const negative_binomial_distribution<RealType, Policy>& dist)
  294. // chf of Negative Binomial distribution provided by derived accessors.
  295. template <class RealType, class Policy>
  296. inline RealType pdf(const negative_binomial_distribution<RealType, Policy>& dist, const RealType& k)
  297. { // Probability Density/Mass Function.
  298. BOOST_FPU_EXCEPTION_GUARD
  299. static const char* function = "boost::math::pdf(const negative_binomial_distribution<%1%>&, %1%)";
  300. RealType r = dist.successes();
  301. RealType p = dist.success_fraction();
  302. RealType result = 0;
  303. if(false == negative_binomial_detail::check_dist_and_k(
  304. function,
  305. r,
  306. dist.success_fraction(),
  307. k,
  308. &result, Policy()))
  309. {
  310. return result;
  311. }
  312. result = (p/(r + k)) * ibeta_derivative(r, static_cast<RealType>(k+1), p, Policy());
  313. // Equivalent to:
  314. // return exp(lgamma(r + k) - lgamma(r) - lgamma(k+1)) * pow(p, r) * pow((1-p), k);
  315. return result;
  316. } // negative_binomial_pdf
  317. template <class RealType, class Policy>
  318. inline RealType cdf(const negative_binomial_distribution<RealType, Policy>& dist, const RealType& k)
  319. { // Cumulative Distribution Function of Negative Binomial.
  320. static const char* function = "boost::math::cdf(const negative_binomial_distribution<%1%>&, %1%)";
  321. using boost::math::ibeta; // Regularized incomplete beta function.
  322. // k argument may be integral, signed, or unsigned, or floating point.
  323. // If necessary, it has already been promoted from an integral type.
  324. RealType p = dist.success_fraction();
  325. RealType r = dist.successes();
  326. // Error check:
  327. RealType result = 0;
  328. if(false == negative_binomial_detail::check_dist_and_k(
  329. function,
  330. r,
  331. dist.success_fraction(),
  332. k,
  333. &result, Policy()))
  334. {
  335. return result;
  336. }
  337. RealType probability = ibeta(r, static_cast<RealType>(k+1), p, Policy());
  338. // Ip(r, k+1) = ibeta(r, k+1, p)
  339. return probability;
  340. } // cdf Cumulative Distribution Function Negative Binomial.
  341. template <class RealType, class Policy>
  342. inline RealType cdf(const complemented2_type<negative_binomial_distribution<RealType, Policy>, RealType>& c)
  343. { // Complemented Cumulative Distribution Function Negative Binomial.
  344. static const char* function = "boost::math::cdf(const negative_binomial_distribution<%1%>&, %1%)";
  345. using boost::math::ibetac; // Regularized incomplete beta function complement.
  346. // k argument may be integral, signed, or unsigned, or floating point.
  347. // If necessary, it has already been promoted from an integral type.
  348. RealType const& k = c.param;
  349. negative_binomial_distribution<RealType, Policy> const& dist = c.dist;
  350. RealType p = dist.success_fraction();
  351. RealType r = dist.successes();
  352. // Error check:
  353. RealType result = 0;
  354. if(false == negative_binomial_detail::check_dist_and_k(
  355. function,
  356. r,
  357. p,
  358. k,
  359. &result, Policy()))
  360. {
  361. return result;
  362. }
  363. // Calculate cdf negative binomial using the incomplete beta function.
  364. // Use of ibeta here prevents cancellation errors in calculating
  365. // 1-p if p is very small, perhaps smaller than machine epsilon.
  366. // Ip(k+1, r) = ibetac(r, k+1, p)
  367. // constrain_probability here?
  368. RealType probability = ibetac(r, static_cast<RealType>(k+1), p, Policy());
  369. // Numerical errors might cause probability to be slightly outside the range < 0 or > 1.
  370. // This might cause trouble downstream, so warn, possibly throw exception, but constrain to the limits.
  371. return probability;
  372. } // cdf Cumulative Distribution Function Negative Binomial.
  373. template <class RealType, class Policy>
  374. inline RealType quantile(const negative_binomial_distribution<RealType, Policy>& dist, const RealType& P)
  375. { // Quantile, percentile/100 or Percent Point Negative Binomial function.
  376. // Return the number of expected failures k for a given probability p.
  377. // Inverse cumulative Distribution Function or Quantile (percentile / 100) of negative_binomial Probability.
  378. // MAthCAD pnbinom return smallest k such that negative_binomial(k, n, p) >= probability.
  379. // k argument may be integral, signed, or unsigned, or floating point.
  380. // BUT Cephes/CodeCogs says: finds argument p (0 to 1) such that cdf(k, n, p) = y
  381. static const char* function = "boost::math::quantile(const negative_binomial_distribution<%1%>&, %1%)";
  382. BOOST_MATH_STD_USING // ADL of std functions.
  383. RealType p = dist.success_fraction();
  384. RealType r = dist.successes();
  385. // Check dist and P.
  386. RealType result = 0;
  387. if(false == negative_binomial_detail::check_dist_and_prob
  388. (function, r, p, P, &result, Policy()))
  389. {
  390. return result;
  391. }
  392. // Special cases.
  393. if (P == 1)
  394. { // Would need +infinity failures for total confidence.
  395. result = policies::raise_overflow_error<RealType>(
  396. function,
  397. "Probability argument is 1, which implies infinite failures !", Policy());
  398. return result;
  399. // usually means return +std::numeric_limits<RealType>::infinity();
  400. // unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
  401. }
  402. if (P == 0)
  403. { // No failures are expected if P = 0.
  404. return 0; // Total trials will be just dist.successes.
  405. }
  406. if (P <= pow(dist.success_fraction(), dist.successes()))
  407. { // p <= pdf(dist, 0) == cdf(dist, 0)
  408. return 0;
  409. }
  410. if(p == 0)
  411. { // Would need +infinity failures for total confidence.
  412. result = policies::raise_overflow_error<RealType>(
  413. function,
  414. "Success fraction is 0, which implies infinite failures !", Policy());
  415. return result;
  416. // usually means return +std::numeric_limits<RealType>::infinity();
  417. // unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
  418. }
  419. /*
  420. // Calculate quantile of negative_binomial using the inverse incomplete beta function.
  421. using boost::math::ibeta_invb;
  422. return ibeta_invb(r, p, P, Policy()) - 1; //
  423. */
  424. RealType guess = 0;
  425. RealType factor = 5;
  426. if(r * r * r * P * p > 0.005)
  427. guess = detail::inverse_negative_binomial_cornish_fisher(r, p, RealType(1-p), P, RealType(1-P), Policy());
  428. if(guess < 10)
  429. {
  430. //
  431. // Cornish-Fisher Negative binomial approximation not accurate in this area:
  432. //
  433. guess = (std::min)(RealType(r * 2), RealType(10));
  434. }
  435. else
  436. factor = (1-P < sqrt(tools::epsilon<RealType>())) ? 2 : (guess < 20 ? 1.2f : 1.1f);
  437. BOOST_MATH_INSTRUMENT_CODE("guess = " << guess);
  438. //
  439. // Max iterations permitted:
  440. //
  441. boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
  442. typedef typename Policy::discrete_quantile_type discrete_type;
  443. return detail::inverse_discrete_quantile(
  444. dist,
  445. P,
  446. false,
  447. guess,
  448. factor,
  449. RealType(1),
  450. discrete_type(),
  451. max_iter);
  452. } // RealType quantile(const negative_binomial_distribution dist, p)
  453. template <class RealType, class Policy>
  454. inline RealType quantile(const complemented2_type<negative_binomial_distribution<RealType, Policy>, RealType>& c)
  455. { // Quantile or Percent Point Binomial function.
  456. // Return the number of expected failures k for a given
  457. // complement of the probability Q = 1 - P.
  458. static const char* function = "boost::math::quantile(const negative_binomial_distribution<%1%>&, %1%)";
  459. BOOST_MATH_STD_USING
  460. // Error checks:
  461. RealType Q = c.param;
  462. const negative_binomial_distribution<RealType, Policy>& dist = c.dist;
  463. RealType p = dist.success_fraction();
  464. RealType r = dist.successes();
  465. RealType result = 0;
  466. if(false == negative_binomial_detail::check_dist_and_prob(
  467. function,
  468. r,
  469. p,
  470. Q,
  471. &result, Policy()))
  472. {
  473. return result;
  474. }
  475. // Special cases:
  476. //
  477. if(Q == 1)
  478. { // There may actually be no answer to this question,
  479. // since the probability of zero failures may be non-zero,
  480. return 0; // but zero is the best we can do:
  481. }
  482. if(Q == 0)
  483. { // Probability 1 - Q == 1 so infinite failures to achieve certainty.
  484. // Would need +infinity failures for total confidence.
  485. result = policies::raise_overflow_error<RealType>(
  486. function,
  487. "Probability argument complement is 0, which implies infinite failures !", Policy());
  488. return result;
  489. // usually means return +std::numeric_limits<RealType>::infinity();
  490. // unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
  491. }
  492. if (-Q <= boost::math::powm1(dist.success_fraction(), dist.successes(), Policy()))
  493. { // q <= cdf(complement(dist, 0)) == pdf(dist, 0)
  494. return 0; //
  495. }
  496. if(p == 0)
  497. { // Success fraction is 0 so infinite failures to achieve certainty.
  498. // Would need +infinity failures for total confidence.
  499. result = policies::raise_overflow_error<RealType>(
  500. function,
  501. "Success fraction is 0, which implies infinite failures !", Policy());
  502. return result;
  503. // usually means return +std::numeric_limits<RealType>::infinity();
  504. // unless #define BOOST_MATH_THROW_ON_OVERFLOW_ERROR
  505. }
  506. //return ibetac_invb(r, p, Q, Policy()) -1;
  507. RealType guess = 0;
  508. RealType factor = 5;
  509. if(r * r * r * (1-Q) * p > 0.005)
  510. guess = detail::inverse_negative_binomial_cornish_fisher(r, p, RealType(1-p), RealType(1-Q), Q, Policy());
  511. if(guess < 10)
  512. {
  513. //
  514. // Cornish-Fisher Negative binomial approximation not accurate in this area:
  515. //
  516. guess = (std::min)(RealType(r * 2), RealType(10));
  517. }
  518. else
  519. factor = (Q < sqrt(tools::epsilon<RealType>())) ? 2 : (guess < 20 ? 1.2f : 1.1f);
  520. BOOST_MATH_INSTRUMENT_CODE("guess = " << guess);
  521. //
  522. // Max iterations permitted:
  523. //
  524. boost::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
  525. typedef typename Policy::discrete_quantile_type discrete_type;
  526. return detail::inverse_discrete_quantile(
  527. dist,
  528. Q,
  529. true,
  530. guess,
  531. factor,
  532. RealType(1),
  533. discrete_type(),
  534. max_iter);
  535. } // quantile complement
  536. } // namespace math
  537. } // namespace boost
  538. // This include must be at the end, *after* the accessors
  539. // for this distribution have been defined, in order to
  540. // keep compilers that support two-phase lookup happy.
  541. #include <boost/math/distributions/detail/derived_accessors.hpp>
  542. #if defined (BOOST_MSVC)
  543. # pragma warning(pop)
  544. #endif
  545. #endif // BOOST_MATH_SPECIAL_NEGATIVE_BINOMIAL_HPP