beta.hpp 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490
  1. // (C) Copyright John Maddock 2006.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MATH_SPECIAL_BETA_HPP
  6. #define BOOST_MATH_SPECIAL_BETA_HPP
  7. #ifdef _MSC_VER
  8. #pragma once
  9. #endif
  10. #include <boost/math/special_functions/math_fwd.hpp>
  11. #include <boost/math/tools/config.hpp>
  12. #include <boost/math/special_functions/gamma.hpp>
  13. #include <boost/math/special_functions/factorials.hpp>
  14. #include <boost/math/special_functions/erf.hpp>
  15. #include <boost/math/special_functions/log1p.hpp>
  16. #include <boost/math/special_functions/expm1.hpp>
  17. #include <boost/math/special_functions/trunc.hpp>
  18. #include <boost/math/tools/roots.hpp>
  19. #include <boost/static_assert.hpp>
  20. #include <boost/config/no_tr1/cmath.hpp>
  21. namespace boost{ namespace math{
  22. namespace detail{
  23. //
  24. // Implementation of Beta(a,b) using the Lanczos approximation:
  25. //
  26. template <class T, class Lanczos, class Policy>
  27. T beta_imp(T a, T b, const Lanczos&, const Policy& pol)
  28. {
  29. BOOST_MATH_STD_USING // for ADL of std names
  30. if(a <= 0)
  31. policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got a=%1%).", a, pol);
  32. if(b <= 0)
  33. policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got b=%1%).", b, pol);
  34. T result;
  35. T prefix = 1;
  36. T c = a + b;
  37. // Special cases:
  38. if((c == a) && (b < tools::epsilon<T>()))
  39. return boost::math::tgamma(b, pol);
  40. else if((c == b) && (a < tools::epsilon<T>()))
  41. return boost::math::tgamma(a, pol);
  42. if(b == 1)
  43. return 1/a;
  44. else if(a == 1)
  45. return 1/b;
  46. /*
  47. //
  48. // This code appears to be no longer necessary: it was
  49. // used to offset errors introduced from the Lanczos
  50. // approximation, but the current Lanczos approximations
  51. // are sufficiently accurate for all z that we can ditch
  52. // this. It remains in the file for future reference...
  53. //
  54. // If a or b are less than 1, shift to greater than 1:
  55. if(a < 1)
  56. {
  57. prefix *= c / a;
  58. c += 1;
  59. a += 1;
  60. }
  61. if(b < 1)
  62. {
  63. prefix *= c / b;
  64. c += 1;
  65. b += 1;
  66. }
  67. */
  68. if(a < b)
  69. std::swap(a, b);
  70. // Lanczos calculation:
  71. T agh = a + Lanczos::g() - T(0.5);
  72. T bgh = b + Lanczos::g() - T(0.5);
  73. T cgh = c + Lanczos::g() - T(0.5);
  74. result = Lanczos::lanczos_sum_expG_scaled(a) * Lanczos::lanczos_sum_expG_scaled(b) / Lanczos::lanczos_sum_expG_scaled(c);
  75. T ambh = a - T(0.5) - b;
  76. if((fabs(b * ambh) < (cgh * 100)) && (a > 100))
  77. {
  78. // Special case where the base of the power term is close to 1
  79. // compute (1+x)^y instead:
  80. result *= exp(ambh * boost::math::log1p(-b / cgh, pol));
  81. }
  82. else
  83. {
  84. result *= pow(agh / cgh, a - T(0.5) - b);
  85. }
  86. if(cgh > 1e10f)
  87. // this avoids possible overflow, but appears to be marginally less accurate:
  88. result *= pow((agh / cgh) * (bgh / cgh), b);
  89. else
  90. result *= pow((agh * bgh) / (cgh * cgh), b);
  91. result *= sqrt(boost::math::constants::e<T>() / bgh);
  92. // If a and b were originally less than 1 we need to scale the result:
  93. result *= prefix;
  94. return result;
  95. } // template <class T, class Lanczos> beta_imp(T a, T b, const Lanczos&)
  96. //
  97. // Generic implementation of Beta(a,b) without Lanczos approximation support
  98. // (Caution this is slow!!!):
  99. //
  100. template <class T, class Policy>
  101. T beta_imp(T a, T b, const lanczos::undefined_lanczos& /* l */, const Policy& pol)
  102. {
  103. BOOST_MATH_STD_USING
  104. if(a <= 0)
  105. policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got a=%1%).", a, pol);
  106. if(b <= 0)
  107. policies::raise_domain_error<T>("boost::math::beta<%1%>(%1%,%1%)", "The arguments to the beta function must be greater than zero (got b=%1%).", b, pol);
  108. T result;
  109. T prefix = 1;
  110. T c = a + b;
  111. // special cases:
  112. if((c == a) && (b < tools::epsilon<T>()))
  113. return boost::math::tgamma(b, pol);
  114. else if((c == b) && (a < tools::epsilon<T>()))
  115. return boost::math::tgamma(a, pol);
  116. if(b == 1)
  117. return 1/a;
  118. else if(a == 1)
  119. return 1/b;
  120. // shift to a and b > 1 if required:
  121. if(a < 1)
  122. {
  123. prefix *= c / a;
  124. c += 1;
  125. a += 1;
  126. }
  127. if(b < 1)
  128. {
  129. prefix *= c / b;
  130. c += 1;
  131. b += 1;
  132. }
  133. if(a < b)
  134. std::swap(a, b);
  135. // set integration limits:
  136. T la = (std::max)(T(10), a);
  137. T lb = (std::max)(T(10), b);
  138. T lc = (std::max)(T(10), T(a+b));
  139. // calculate the fraction parts:
  140. T sa = detail::lower_gamma_series(a, la, pol) / a;
  141. sa += detail::upper_gamma_fraction(a, la, ::boost::math::policies::get_epsilon<T, Policy>());
  142. T sb = detail::lower_gamma_series(b, lb, pol) / b;
  143. sb += detail::upper_gamma_fraction(b, lb, ::boost::math::policies::get_epsilon<T, Policy>());
  144. T sc = detail::lower_gamma_series(c, lc, pol) / c;
  145. sc += detail::upper_gamma_fraction(c, lc, ::boost::math::policies::get_epsilon<T, Policy>());
  146. // and the exponent part:
  147. result = exp(lc - la - lb) * pow(la/lc, a) * pow(lb/lc, b);
  148. // and combine:
  149. result *= sa * sb / sc;
  150. // if a and b were originally less than 1 we need to scale the result:
  151. result *= prefix;
  152. return result;
  153. } // template <class T>T beta_imp(T a, T b, const lanczos::undefined_lanczos& l)
  154. //
  155. // Compute the leading power terms in the incomplete Beta:
  156. //
  157. // (x^a)(y^b)/Beta(a,b) when normalised, and
  158. // (x^a)(y^b) otherwise.
  159. //
  160. // Almost all of the error in the incomplete beta comes from this
  161. // function: particularly when a and b are large. Computing large
  162. // powers are *hard* though, and using logarithms just leads to
  163. // horrendous cancellation errors.
  164. //
  165. template <class T, class Lanczos, class Policy>
  166. T ibeta_power_terms(T a,
  167. T b,
  168. T x,
  169. T y,
  170. const Lanczos&,
  171. bool normalised,
  172. const Policy& pol)
  173. {
  174. BOOST_MATH_STD_USING
  175. if(!normalised)
  176. {
  177. // can we do better here?
  178. return pow(x, a) * pow(y, b);
  179. }
  180. T result;
  181. T prefix = 1;
  182. T c = a + b;
  183. // combine power terms with Lanczos approximation:
  184. T agh = a + Lanczos::g() - T(0.5);
  185. T bgh = b + Lanczos::g() - T(0.5);
  186. T cgh = c + Lanczos::g() - T(0.5);
  187. result = Lanczos::lanczos_sum_expG_scaled(c) / (Lanczos::lanczos_sum_expG_scaled(a) * Lanczos::lanczos_sum_expG_scaled(b));
  188. // l1 and l2 are the base of the exponents minus one:
  189. T l1 = (x * b - y * agh) / agh;
  190. T l2 = (y * a - x * bgh) / bgh;
  191. if(((std::min)(fabs(l1), fabs(l2)) < 0.2))
  192. {
  193. // when the base of the exponent is very near 1 we get really
  194. // gross errors unless extra care is taken:
  195. if((l1 * l2 > 0) || ((std::min)(a, b) < 1))
  196. {
  197. //
  198. // This first branch handles the simple cases where either:
  199. //
  200. // * The two power terms both go in the same direction
  201. // (towards zero or towards infinity). In this case if either
  202. // term overflows or underflows, then the product of the two must
  203. // do so also.
  204. // *Alternatively if one exponent is less than one, then we
  205. // can't productively use it to eliminate overflow or underflow
  206. // from the other term. Problems with spurious overflow/underflow
  207. // can't be ruled out in this case, but it is *very* unlikely
  208. // since one of the power terms will evaluate to a number close to 1.
  209. //
  210. if(fabs(l1) < 0.1)
  211. {
  212. result *= exp(a * boost::math::log1p(l1, pol));
  213. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  214. }
  215. else
  216. {
  217. result *= pow((x * cgh) / agh, a);
  218. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  219. }
  220. if(fabs(l2) < 0.1)
  221. {
  222. result *= exp(b * boost::math::log1p(l2, pol));
  223. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  224. }
  225. else
  226. {
  227. result *= pow((y * cgh) / bgh, b);
  228. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  229. }
  230. }
  231. else if((std::max)(fabs(l1), fabs(l2)) < 0.5)
  232. {
  233. //
  234. // Both exponents are near one and both the exponents are
  235. // greater than one and further these two
  236. // power terms tend in opposite directions (one towards zero,
  237. // the other towards infinity), so we have to combine the terms
  238. // to avoid any risk of overflow or underflow.
  239. //
  240. // We do this by moving one power term inside the other, we have:
  241. //
  242. // (1 + l1)^a * (1 + l2)^b
  243. // = ((1 + l1)*(1 + l2)^(b/a))^a
  244. // = (1 + l1 + l3 + l1*l3)^a ; l3 = (1 + l2)^(b/a) - 1
  245. // = exp((b/a) * log(1 + l2)) - 1
  246. //
  247. // The tricky bit is deciding which term to move inside :-)
  248. // By preference we move the larger term inside, so that the
  249. // size of the largest exponent is reduced. However, that can
  250. // only be done as long as l3 (see above) is also small.
  251. //
  252. bool small_a = a < b;
  253. T ratio = b / a;
  254. if((small_a && (ratio * l2 < 0.1)) || (!small_a && (l1 / ratio > 0.1)))
  255. {
  256. T l3 = boost::math::expm1(ratio * boost::math::log1p(l2, pol), pol);
  257. l3 = l1 + l3 + l3 * l1;
  258. l3 = a * boost::math::log1p(l3, pol);
  259. result *= exp(l3);
  260. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  261. }
  262. else
  263. {
  264. T l3 = boost::math::expm1(boost::math::log1p(l1, pol) / ratio, pol);
  265. l3 = l2 + l3 + l3 * l2;
  266. l3 = b * boost::math::log1p(l3, pol);
  267. result *= exp(l3);
  268. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  269. }
  270. }
  271. else if(fabs(l1) < fabs(l2))
  272. {
  273. // First base near 1 only:
  274. T l = a * boost::math::log1p(l1, pol)
  275. + b * log((y * cgh) / bgh);
  276. result *= exp(l);
  277. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  278. }
  279. else
  280. {
  281. // Second base near 1 only:
  282. T l = b * boost::math::log1p(l2, pol)
  283. + a * log((x * cgh) / agh);
  284. result *= exp(l);
  285. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  286. }
  287. }
  288. else
  289. {
  290. // general case:
  291. T b1 = (x * cgh) / agh;
  292. T b2 = (y * cgh) / bgh;
  293. l1 = a * log(b1);
  294. l2 = b * log(b2);
  295. BOOST_MATH_INSTRUMENT_VARIABLE(b1);
  296. BOOST_MATH_INSTRUMENT_VARIABLE(b2);
  297. BOOST_MATH_INSTRUMENT_VARIABLE(l1);
  298. BOOST_MATH_INSTRUMENT_VARIABLE(l2);
  299. if((l1 >= tools::log_max_value<T>())
  300. || (l1 <= tools::log_min_value<T>())
  301. || (l2 >= tools::log_max_value<T>())
  302. || (l2 <= tools::log_min_value<T>())
  303. )
  304. {
  305. // Oops, overflow, sidestep:
  306. if(a < b)
  307. result *= pow(pow(b2, b/a) * b1, a);
  308. else
  309. result *= pow(pow(b1, a/b) * b2, b);
  310. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  311. }
  312. else
  313. {
  314. // finally the normal case:
  315. result *= pow(b1, a) * pow(b2, b);
  316. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  317. }
  318. }
  319. // combine with the leftover terms from the Lanczos approximation:
  320. result *= sqrt(bgh / boost::math::constants::e<T>());
  321. result *= sqrt(agh / cgh);
  322. result *= prefix;
  323. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  324. return result;
  325. }
  326. //
  327. // Compute the leading power terms in the incomplete Beta:
  328. //
  329. // (x^a)(y^b)/Beta(a,b) when normalised, and
  330. // (x^a)(y^b) otherwise.
  331. //
  332. // Almost all of the error in the incomplete beta comes from this
  333. // function: particularly when a and b are large. Computing large
  334. // powers are *hard* though, and using logarithms just leads to
  335. // horrendous cancellation errors.
  336. //
  337. // This version is generic, slow, and does not use the Lanczos approximation.
  338. //
  339. template <class T, class Policy>
  340. T ibeta_power_terms(T a,
  341. T b,
  342. T x,
  343. T y,
  344. const boost::math::lanczos::undefined_lanczos&,
  345. bool normalised,
  346. const Policy& pol)
  347. {
  348. BOOST_MATH_STD_USING
  349. if(!normalised)
  350. {
  351. return pow(x, a) * pow(y, b);
  352. }
  353. T result= 0; // assignment here silences warnings later
  354. T c = a + b;
  355. // integration limits for the gamma functions:
  356. //T la = (std::max)(T(10), a);
  357. //T lb = (std::max)(T(10), b);
  358. //T lc = (std::max)(T(10), a+b);
  359. T la = a + 5;
  360. T lb = b + 5;
  361. T lc = a + b + 5;
  362. // gamma function partials:
  363. T sa = detail::lower_gamma_series(a, la, pol) / a;
  364. sa += detail::upper_gamma_fraction(a, la, ::boost::math::policies::get_epsilon<T, Policy>());
  365. T sb = detail::lower_gamma_series(b, lb, pol) / b;
  366. sb += detail::upper_gamma_fraction(b, lb, ::boost::math::policies::get_epsilon<T, Policy>());
  367. T sc = detail::lower_gamma_series(c, lc, pol) / c;
  368. sc += detail::upper_gamma_fraction(c, lc, ::boost::math::policies::get_epsilon<T, Policy>());
  369. // gamma function powers combined with incomplete beta powers:
  370. T b1 = (x * lc) / la;
  371. T b2 = (y * lc) / lb;
  372. T e1 = lc - la - lb;
  373. T lb1 = a * log(b1);
  374. T lb2 = b * log(b2);
  375. if((lb1 >= tools::log_max_value<T>())
  376. || (lb1 <= tools::log_min_value<T>())
  377. || (lb2 >= tools::log_max_value<T>())
  378. || (lb2 <= tools::log_min_value<T>())
  379. || (e1 >= tools::log_max_value<T>())
  380. || (e1 <= tools::log_min_value<T>())
  381. )
  382. {
  383. result = exp(lb1 + lb2 - e1);
  384. }
  385. else
  386. {
  387. T p1, p2;
  388. if((fabs(b1 - 1) * a < 10) && (a > 1))
  389. p1 = exp(a * boost::math::log1p((x * b - y * la) / la, pol));
  390. else
  391. p1 = pow(b1, a);
  392. if((fabs(b2 - 1) * b < 10) && (b > 1))
  393. p2 = exp(b * boost::math::log1p((y * a - x * lb) / lb, pol));
  394. else
  395. p2 = pow(b2, b);
  396. T p3 = exp(e1);
  397. result = p1 * p2 / p3;
  398. }
  399. // and combine with the remaining gamma function components:
  400. result /= sa * sb / sc;
  401. return result;
  402. }
  403. //
  404. // Series approximation to the incomplete beta:
  405. //
  406. template <class T>
  407. struct ibeta_series_t
  408. {
  409. typedef T result_type;
  410. ibeta_series_t(T a_, T b_, T x_, T mult) : result(mult), x(x_), apn(a_), poch(1-b_), n(1) {}
  411. T operator()()
  412. {
  413. T r = result / apn;
  414. apn += 1;
  415. result *= poch * x / n;
  416. ++n;
  417. poch += 1;
  418. return r;
  419. }
  420. private:
  421. T result, x, apn, poch;
  422. int n;
  423. };
  424. template <class T, class Lanczos, class Policy>
  425. T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool normalised, T* p_derivative, T y, const Policy& pol)
  426. {
  427. BOOST_MATH_STD_USING
  428. T result;
  429. BOOST_ASSERT((p_derivative == 0) || normalised);
  430. if(normalised)
  431. {
  432. T c = a + b;
  433. // incomplete beta power term, combined with the Lanczos approximation:
  434. T agh = a + Lanczos::g() - T(0.5);
  435. T bgh = b + Lanczos::g() - T(0.5);
  436. T cgh = c + Lanczos::g() - T(0.5);
  437. result = Lanczos::lanczos_sum_expG_scaled(c) / (Lanczos::lanczos_sum_expG_scaled(a) * Lanczos::lanczos_sum_expG_scaled(b));
  438. if(a * b < bgh * 10)
  439. result *= exp((b - 0.5f) * boost::math::log1p(a / bgh, pol));
  440. else
  441. result *= pow(cgh / bgh, b - 0.5f);
  442. result *= pow(x * cgh / agh, a);
  443. result *= sqrt(agh / boost::math::constants::e<T>());
  444. if(p_derivative)
  445. {
  446. *p_derivative = result * pow(y, b);
  447. BOOST_ASSERT(*p_derivative >= 0);
  448. }
  449. }
  450. else
  451. {
  452. // Non-normalised, just compute the power:
  453. result = pow(x, a);
  454. }
  455. if(result < tools::min_value<T>())
  456. return s0; // Safeguard: series can't cope with denorms.
  457. ibeta_series_t<T> s(a, b, x, result);
  458. boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  459. result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, s0);
  460. policies::check_series_iterations<T>("boost::math::ibeta<%1%>(%1%, %1%, %1%) in ibeta_series (with lanczos)", max_iter, pol);
  461. return result;
  462. }
  463. //
  464. // Incomplete Beta series again, this time without Lanczos support:
  465. //
  466. template <class T, class Policy>
  467. T ibeta_series(T a, T b, T x, T s0, const boost::math::lanczos::undefined_lanczos&, bool normalised, T* p_derivative, T y, const Policy& pol)
  468. {
  469. BOOST_MATH_STD_USING
  470. T result;
  471. BOOST_ASSERT((p_derivative == 0) || normalised);
  472. if(normalised)
  473. {
  474. T c = a + b;
  475. // figure out integration limits for the gamma function:
  476. //T la = (std::max)(T(10), a);
  477. //T lb = (std::max)(T(10), b);
  478. //T lc = (std::max)(T(10), a+b);
  479. T la = a + 5;
  480. T lb = b + 5;
  481. T lc = a + b + 5;
  482. // calculate the gamma parts:
  483. T sa = detail::lower_gamma_series(a, la, pol) / a;
  484. sa += detail::upper_gamma_fraction(a, la, ::boost::math::policies::get_epsilon<T, Policy>());
  485. T sb = detail::lower_gamma_series(b, lb, pol) / b;
  486. sb += detail::upper_gamma_fraction(b, lb, ::boost::math::policies::get_epsilon<T, Policy>());
  487. T sc = detail::lower_gamma_series(c, lc, pol) / c;
  488. sc += detail::upper_gamma_fraction(c, lc, ::boost::math::policies::get_epsilon<T, Policy>());
  489. // and their combined power-terms:
  490. T b1 = (x * lc) / la;
  491. T b2 = lc/lb;
  492. T e1 = lc - la - lb;
  493. T lb1 = a * log(b1);
  494. T lb2 = b * log(b2);
  495. if((lb1 >= tools::log_max_value<T>())
  496. || (lb1 <= tools::log_min_value<T>())
  497. || (lb2 >= tools::log_max_value<T>())
  498. || (lb2 <= tools::log_min_value<T>())
  499. || (e1 >= tools::log_max_value<T>())
  500. || (e1 <= tools::log_min_value<T>()) )
  501. {
  502. T p = lb1 + lb2 - e1;
  503. result = exp(p);
  504. }
  505. else
  506. {
  507. result = pow(b1, a);
  508. if(a * b < lb * 10)
  509. result *= exp(b * boost::math::log1p(a / lb, pol));
  510. else
  511. result *= pow(b2, b);
  512. result /= exp(e1);
  513. }
  514. // and combine the results:
  515. result /= sa * sb / sc;
  516. if(p_derivative)
  517. {
  518. *p_derivative = result * pow(y, b);
  519. BOOST_ASSERT(*p_derivative >= 0);
  520. }
  521. }
  522. else
  523. {
  524. // Non-normalised, just compute the power:
  525. result = pow(x, a);
  526. }
  527. if(result < tools::min_value<T>())
  528. return s0; // Safeguard: series can't cope with denorms.
  529. ibeta_series_t<T> s(a, b, x, result);
  530. boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  531. result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, s0);
  532. policies::check_series_iterations<T>("boost::math::ibeta<%1%>(%1%, %1%, %1%) in ibeta_series (without lanczos)", max_iter, pol);
  533. return result;
  534. }
  535. //
  536. // Continued fraction for the incomplete beta:
  537. //
  538. template <class T>
  539. struct ibeta_fraction2_t
  540. {
  541. typedef std::pair<T, T> result_type;
  542. ibeta_fraction2_t(T a_, T b_, T x_, T y_) : a(a_), b(b_), x(x_), y(y_), m(0) {}
  543. result_type operator()()
  544. {
  545. T aN = (a + m - 1) * (a + b + m - 1) * m * (b - m) * x * x;
  546. T denom = (a + 2 * m - 1);
  547. aN /= denom * denom;
  548. T bN = m;
  549. bN += (m * (b - m) * x) / (a + 2*m - 1);
  550. bN += ((a + m) * (a * y - b * x + 1 + m *(2 - x))) / (a + 2*m + 1);
  551. ++m;
  552. return std::make_pair(aN, bN);
  553. }
  554. private:
  555. T a, b, x, y;
  556. int m;
  557. };
  558. //
  559. // Evaluate the incomplete beta via the continued fraction representation:
  560. //
  561. template <class T, class Policy>
  562. inline T ibeta_fraction2(T a, T b, T x, T y, const Policy& pol, bool normalised, T* p_derivative)
  563. {
  564. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  565. BOOST_MATH_STD_USING
  566. T result = ibeta_power_terms(a, b, x, y, lanczos_type(), normalised, pol);
  567. if(p_derivative)
  568. {
  569. *p_derivative = result;
  570. BOOST_ASSERT(*p_derivative >= 0);
  571. }
  572. if(result == 0)
  573. return result;
  574. ibeta_fraction2_t<T> f(a, b, x, y);
  575. T fract = boost::math::tools::continued_fraction_b(f, boost::math::policies::get_epsilon<T, Policy>());
  576. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  577. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  578. return result / fract;
  579. }
  580. //
  581. // Computes the difference between ibeta(a,b,x) and ibeta(a+k,b,x):
  582. //
  583. template <class T, class Policy>
  584. T ibeta_a_step(T a, T b, T x, T y, int k, const Policy& pol, bool normalised, T* p_derivative)
  585. {
  586. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  587. BOOST_MATH_INSTRUMENT_VARIABLE(k);
  588. T prefix = ibeta_power_terms(a, b, x, y, lanczos_type(), normalised, pol);
  589. if(p_derivative)
  590. {
  591. *p_derivative = prefix;
  592. BOOST_ASSERT(*p_derivative >= 0);
  593. }
  594. prefix /= a;
  595. if(prefix == 0)
  596. return prefix;
  597. T sum = 1;
  598. T term = 1;
  599. // series summation from 0 to k-1:
  600. for(int i = 0; i < k-1; ++i)
  601. {
  602. term *= (a+b+i) * x / (a+i+1);
  603. sum += term;
  604. }
  605. prefix *= sum;
  606. return prefix;
  607. }
  608. //
  609. // This function is only needed for the non-regular incomplete beta,
  610. // it computes the delta in:
  611. // beta(a,b,x) = prefix + delta * beta(a+k,b,x)
  612. // it is currently only called for small k.
  613. //
  614. template <class T>
  615. inline T rising_factorial_ratio(T a, T b, int k)
  616. {
  617. // calculate:
  618. // (a)(a+1)(a+2)...(a+k-1)
  619. // _______________________
  620. // (b)(b+1)(b+2)...(b+k-1)
  621. // This is only called with small k, for large k
  622. // it is grossly inefficient, do not use outside it's
  623. // intended purpose!!!
  624. BOOST_MATH_INSTRUMENT_VARIABLE(k);
  625. if(k == 0)
  626. return 1;
  627. T result = 1;
  628. for(int i = 0; i < k; ++i)
  629. result *= (a+i) / (b+i);
  630. return result;
  631. }
  632. //
  633. // Routine for a > 15, b < 1
  634. //
  635. // Begin by figuring out how large our table of Pn's should be,
  636. // quoted accuracies are "guestimates" based on empiracal observation.
  637. // Note that the table size should never exceed the size of our
  638. // tables of factorials.
  639. //
  640. template <class T>
  641. struct Pn_size
  642. {
  643. // This is likely to be enough for ~35-50 digit accuracy
  644. // but it's hard to quantify exactly:
  645. BOOST_STATIC_CONSTANT(unsigned, value = 50);
  646. BOOST_STATIC_ASSERT(::boost::math::max_factorial<T>::value >= 100);
  647. };
  648. template <>
  649. struct Pn_size<float>
  650. {
  651. BOOST_STATIC_CONSTANT(unsigned, value = 15); // ~8-15 digit accuracy
  652. BOOST_STATIC_ASSERT(::boost::math::max_factorial<float>::value >= 30);
  653. };
  654. template <>
  655. struct Pn_size<double>
  656. {
  657. BOOST_STATIC_CONSTANT(unsigned, value = 30); // 16-20 digit accuracy
  658. BOOST_STATIC_ASSERT(::boost::math::max_factorial<double>::value >= 60);
  659. };
  660. template <>
  661. struct Pn_size<long double>
  662. {
  663. BOOST_STATIC_CONSTANT(unsigned, value = 50); // ~35-50 digit accuracy
  664. BOOST_STATIC_ASSERT(::boost::math::max_factorial<long double>::value >= 100);
  665. };
  666. template <class T, class Policy>
  667. T beta_small_b_large_a_series(T a, T b, T x, T y, T s0, T mult, const Policy& pol, bool normalised)
  668. {
  669. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  670. BOOST_MATH_STD_USING
  671. //
  672. // This is DiDonato and Morris's BGRAT routine, see Eq's 9 through 9.6.
  673. //
  674. // Some values we'll need later, these are Eq 9.1:
  675. //
  676. T bm1 = b - 1;
  677. T t = a + bm1 / 2;
  678. T lx, u;
  679. if(y < 0.35)
  680. lx = boost::math::log1p(-y, pol);
  681. else
  682. lx = log(x);
  683. u = -t * lx;
  684. // and from from 9.2:
  685. T prefix;
  686. T h = regularised_gamma_prefix(b, u, pol, lanczos_type());
  687. if(h <= tools::min_value<T>())
  688. return s0;
  689. if(normalised)
  690. {
  691. prefix = h / boost::math::tgamma_delta_ratio(a, b, pol);
  692. prefix /= pow(t, b);
  693. }
  694. else
  695. {
  696. prefix = full_igamma_prefix(b, u, pol) / pow(t, b);
  697. }
  698. prefix *= mult;
  699. //
  700. // now we need the quantity Pn, unfortunatately this is computed
  701. // recursively, and requires a full history of all the previous values
  702. // so no choice but to declare a big table and hope it's big enough...
  703. //
  704. T p[ ::boost::math::detail::Pn_size<T>::value ] = { 1 }; // see 9.3.
  705. //
  706. // Now an initial value for J, see 9.6:
  707. //
  708. T j = boost::math::gamma_q(b, u, pol) / h;
  709. //
  710. // Now we can start to pull things together and evaluate the sum in Eq 9:
  711. //
  712. T sum = s0 + prefix * j; // Value at N = 0
  713. // some variables we'll need:
  714. unsigned tnp1 = 1; // 2*N+1
  715. T lx2 = lx / 2;
  716. lx2 *= lx2;
  717. T lxp = 1;
  718. T t4 = 4 * t * t;
  719. T b2n = b;
  720. for(unsigned n = 1; n < sizeof(p)/sizeof(p[0]); ++n)
  721. {
  722. /*
  723. // debugging code, enable this if you want to determine whether
  724. // the table of Pn's is large enough...
  725. //
  726. static int max_count = 2;
  727. if(n > max_count)
  728. {
  729. max_count = n;
  730. std::cerr << "Max iterations in BGRAT was " << n << std::endl;
  731. }
  732. */
  733. //
  734. // begin by evaluating the next Pn from Eq 9.4:
  735. //
  736. tnp1 += 2;
  737. p[n] = 0;
  738. T mbn = b - n;
  739. unsigned tmp1 = 3;
  740. for(unsigned m = 1; m < n; ++m)
  741. {
  742. mbn = m * b - n;
  743. p[n] += mbn * p[n-m] / boost::math::unchecked_factorial<T>(tmp1);
  744. tmp1 += 2;
  745. }
  746. p[n] /= n;
  747. p[n] += bm1 / boost::math::unchecked_factorial<T>(tnp1);
  748. //
  749. // Now we want Jn from Jn-1 using Eq 9.6:
  750. //
  751. j = (b2n * (b2n + 1) * j + (u + b2n + 1) * lxp) / t4;
  752. lxp *= lx2;
  753. b2n += 2;
  754. //
  755. // pull it together with Eq 9:
  756. //
  757. T r = prefix * p[n] * j;
  758. sum += r;
  759. if(r > 1)
  760. {
  761. if(fabs(r) < fabs(tools::epsilon<T>() * sum))
  762. break;
  763. }
  764. else
  765. {
  766. if(fabs(r / tools::epsilon<T>()) < fabs(sum))
  767. break;
  768. }
  769. }
  770. return sum;
  771. } // template <class T, class Lanczos>T beta_small_b_large_a_series(T a, T b, T x, T y, T s0, T mult, const Lanczos& l, bool normalised)
  772. //
  773. // For integer arguments we can relate the incomplete beta to the
  774. // complement of the binomial distribution cdf and use this finite sum.
  775. //
  776. template <class T>
  777. inline T binomial_ccdf(T n, T k, T x, T y)
  778. {
  779. BOOST_MATH_STD_USING // ADL of std names
  780. T result = pow(x, n);
  781. T term = result;
  782. for(unsigned i = itrunc(T(n - 1)); i > k; --i)
  783. {
  784. term *= ((i + 1) * y) / ((n - i) * x) ;
  785. result += term;
  786. }
  787. return result;
  788. }
  789. //
  790. // The incomplete beta function implementation:
  791. // This is just a big bunch of spagetti code to divide up the
  792. // input range and select the right implementation method for
  793. // each domain:
  794. //
  795. template <class T, class Policy>
  796. T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, bool normalised, T* p_derivative)
  797. {
  798. static const char* function = "boost::math::ibeta<%1%>(%1%, %1%, %1%)";
  799. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  800. BOOST_MATH_STD_USING // for ADL of std math functions.
  801. BOOST_MATH_INSTRUMENT_VARIABLE(a);
  802. BOOST_MATH_INSTRUMENT_VARIABLE(b);
  803. BOOST_MATH_INSTRUMENT_VARIABLE(x);
  804. BOOST_MATH_INSTRUMENT_VARIABLE(inv);
  805. BOOST_MATH_INSTRUMENT_VARIABLE(normalised);
  806. bool invert = inv;
  807. T fract;
  808. T y = 1 - x;
  809. BOOST_ASSERT((p_derivative == 0) || normalised);
  810. if(p_derivative)
  811. *p_derivative = -1; // value not set.
  812. if((x < 0) || (x > 1))
  813. policies::raise_domain_error<T>(function, "Parameter x outside the range [0,1] in the incomplete beta function (got x=%1%).", x, pol);
  814. if(normalised)
  815. {
  816. if(a < 0)
  817. policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be >= zero (got a=%1%).", a, pol);
  818. if(b < 0)
  819. policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be >= zero (got b=%1%).", b, pol);
  820. // extend to a few very special cases:
  821. if(a == 0)
  822. {
  823. if(b == 0)
  824. policies::raise_domain_error<T>(function, "The arguments a and b to the incomplete beta function cannot both be zero, with x=%1%.", x, pol);
  825. if(b > 0)
  826. return inv ? 0 : 1;
  827. }
  828. else if(b == 0)
  829. {
  830. if(a > 0)
  831. return inv ? 1 : 0;
  832. }
  833. }
  834. else
  835. {
  836. if(a <= 0)
  837. policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be greater than zero (got a=%1%).", a, pol);
  838. if(b <= 0)
  839. policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be greater than zero (got b=%1%).", b, pol);
  840. }
  841. if(x == 0)
  842. {
  843. if(p_derivative)
  844. {
  845. *p_derivative = (a == 1) ? (T)1 : (a < 1) ? T(tools::max_value<T>() / 2) : T(tools::min_value<T>() * 2);
  846. }
  847. return (invert ? (normalised ? T(1) : boost::math::beta(a, b, pol)) : T(0));
  848. }
  849. if(x == 1)
  850. {
  851. if(p_derivative)
  852. {
  853. *p_derivative = (b == 1) ? T(1) : (b < 1) ? T(tools::max_value<T>() / 2) : T(tools::min_value<T>() * 2);
  854. }
  855. return (invert == 0 ? (normalised ? 1 : boost::math::beta(a, b, pol)) : 0);
  856. }
  857. if((a == 0.5f) && (b == 0.5f))
  858. {
  859. // We have an arcsine distribution:
  860. if(p_derivative)
  861. {
  862. *p_derivative = (invert ? -1 : 1) / constants::pi<T>() * sqrt(y * x);
  863. }
  864. T p = invert ? asin(sqrt(y)) / constants::half_pi<T>() : asin(sqrt(x)) / constants::half_pi<T>();
  865. if(!normalised)
  866. p *= constants::pi<T>();
  867. return p;
  868. }
  869. if(a == 1)
  870. {
  871. std::swap(a, b);
  872. std::swap(x, y);
  873. invert = !invert;
  874. }
  875. if(b == 1)
  876. {
  877. //
  878. // Special case see: http://functions.wolfram.com/GammaBetaErf/BetaRegularized/03/01/01/
  879. //
  880. if(a == 1)
  881. {
  882. if(p_derivative)
  883. *p_derivative = invert ? -1 : 1;
  884. return invert ? y : x;
  885. }
  886. if(p_derivative)
  887. {
  888. *p_derivative = (invert ? -1 : 1) * a * pow(x, a - 1);
  889. }
  890. T p;
  891. if(y < 0.5)
  892. p = invert ? T(-expm1(a * log1p(-y))) : T(exp(a * log1p(-y)));
  893. else
  894. p = invert ? T(-powm1(x, a)) : T(pow(x, a));
  895. if(!normalised)
  896. p /= a;
  897. return p;
  898. }
  899. if((std::min)(a, b) <= 1)
  900. {
  901. if(x > 0.5)
  902. {
  903. std::swap(a, b);
  904. std::swap(x, y);
  905. invert = !invert;
  906. BOOST_MATH_INSTRUMENT_VARIABLE(invert);
  907. }
  908. if((std::max)(a, b) <= 1)
  909. {
  910. // Both a,b < 1:
  911. if((a >= (std::min)(T(0.2), b)) || (pow(x, a) <= 0.9))
  912. {
  913. if(!invert)
  914. {
  915. fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
  916. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  917. }
  918. else
  919. {
  920. fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
  921. invert = false;
  922. fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
  923. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  924. }
  925. }
  926. else
  927. {
  928. std::swap(a, b);
  929. std::swap(x, y);
  930. invert = !invert;
  931. if(y >= 0.3)
  932. {
  933. if(!invert)
  934. {
  935. fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
  936. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  937. }
  938. else
  939. {
  940. fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
  941. invert = false;
  942. fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
  943. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  944. }
  945. }
  946. else
  947. {
  948. // Sidestep on a, and then use the series representation:
  949. T prefix;
  950. if(!normalised)
  951. {
  952. prefix = rising_factorial_ratio(T(a+b), a, 20);
  953. }
  954. else
  955. {
  956. prefix = 1;
  957. }
  958. fract = ibeta_a_step(a, b, x, y, 20, pol, normalised, p_derivative);
  959. if(!invert)
  960. {
  961. fract = beta_small_b_large_a_series(T(a + 20), b, x, y, fract, prefix, pol, normalised);
  962. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  963. }
  964. else
  965. {
  966. fract -= (normalised ? 1 : boost::math::beta(a, b, pol));
  967. invert = false;
  968. fract = -beta_small_b_large_a_series(T(a + 20), b, x, y, fract, prefix, pol, normalised);
  969. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  970. }
  971. }
  972. }
  973. }
  974. else
  975. {
  976. // One of a, b < 1 only:
  977. if((b <= 1) || ((x < 0.1) && (pow(b * x, a) <= 0.7)))
  978. {
  979. if(!invert)
  980. {
  981. fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
  982. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  983. }
  984. else
  985. {
  986. fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
  987. invert = false;
  988. fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
  989. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  990. }
  991. }
  992. else
  993. {
  994. std::swap(a, b);
  995. std::swap(x, y);
  996. invert = !invert;
  997. if(y >= 0.3)
  998. {
  999. if(!invert)
  1000. {
  1001. fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
  1002. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1003. }
  1004. else
  1005. {
  1006. fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
  1007. invert = false;
  1008. fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
  1009. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1010. }
  1011. }
  1012. else if(a >= 15)
  1013. {
  1014. if(!invert)
  1015. {
  1016. fract = beta_small_b_large_a_series(a, b, x, y, T(0), T(1), pol, normalised);
  1017. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1018. }
  1019. else
  1020. {
  1021. fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
  1022. invert = false;
  1023. fract = -beta_small_b_large_a_series(a, b, x, y, fract, T(1), pol, normalised);
  1024. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1025. }
  1026. }
  1027. else
  1028. {
  1029. // Sidestep to improve errors:
  1030. T prefix;
  1031. if(!normalised)
  1032. {
  1033. prefix = rising_factorial_ratio(T(a+b), a, 20);
  1034. }
  1035. else
  1036. {
  1037. prefix = 1;
  1038. }
  1039. fract = ibeta_a_step(a, b, x, y, 20, pol, normalised, p_derivative);
  1040. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1041. if(!invert)
  1042. {
  1043. fract = beta_small_b_large_a_series(T(a + 20), b, x, y, fract, prefix, pol, normalised);
  1044. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1045. }
  1046. else
  1047. {
  1048. fract -= (normalised ? 1 : boost::math::beta(a, b, pol));
  1049. invert = false;
  1050. fract = -beta_small_b_large_a_series(T(a + 20), b, x, y, fract, prefix, pol, normalised);
  1051. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1052. }
  1053. }
  1054. }
  1055. }
  1056. }
  1057. else
  1058. {
  1059. // Both a,b >= 1:
  1060. T lambda;
  1061. if(a < b)
  1062. {
  1063. lambda = a - (a + b) * x;
  1064. }
  1065. else
  1066. {
  1067. lambda = (a + b) * y - b;
  1068. }
  1069. if(lambda < 0)
  1070. {
  1071. std::swap(a, b);
  1072. std::swap(x, y);
  1073. invert = !invert;
  1074. BOOST_MATH_INSTRUMENT_VARIABLE(invert);
  1075. }
  1076. if(b < 40)
  1077. {
  1078. if((floor(a) == a) && (floor(b) == b) && (a < (std::numeric_limits<int>::max)() - 100))
  1079. {
  1080. // relate to the binomial distribution and use a finite sum:
  1081. T k = a - 1;
  1082. T n = b + k;
  1083. fract = binomial_ccdf(n, k, x, y);
  1084. if(!normalised)
  1085. fract *= boost::math::beta(a, b, pol);
  1086. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1087. }
  1088. else if(b * x <= 0.7)
  1089. {
  1090. if(!invert)
  1091. {
  1092. fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
  1093. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1094. }
  1095. else
  1096. {
  1097. fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
  1098. invert = false;
  1099. fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
  1100. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1101. }
  1102. }
  1103. else if(a > 15)
  1104. {
  1105. // sidestep so we can use the series representation:
  1106. int n = itrunc(T(floor(b)), pol);
  1107. if(n == b)
  1108. --n;
  1109. T bbar = b - n;
  1110. T prefix;
  1111. if(!normalised)
  1112. {
  1113. prefix = rising_factorial_ratio(T(a+bbar), bbar, n);
  1114. }
  1115. else
  1116. {
  1117. prefix = 1;
  1118. }
  1119. fract = ibeta_a_step(bbar, a, y, x, n, pol, normalised, static_cast<T*>(0));
  1120. fract = beta_small_b_large_a_series(a, bbar, x, y, fract, T(1), pol, normalised);
  1121. fract /= prefix;
  1122. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1123. }
  1124. else if(normalised)
  1125. {
  1126. // the formula here for the non-normalised case is tricky to figure
  1127. // out (for me!!), and requires two pochhammer calculations rather
  1128. // than one, so leave it for now....
  1129. int n = itrunc(T(floor(b)), pol);
  1130. T bbar = b - n;
  1131. if(bbar <= 0)
  1132. {
  1133. --n;
  1134. bbar += 1;
  1135. }
  1136. fract = ibeta_a_step(bbar, a, y, x, n, pol, normalised, static_cast<T*>(0));
  1137. fract += ibeta_a_step(a, bbar, x, y, 20, pol, normalised, static_cast<T*>(0));
  1138. if(invert)
  1139. fract -= (normalised ? 1 : boost::math::beta(a, b, pol));
  1140. //fract = ibeta_series(a+20, bbar, x, fract, l, normalised, p_derivative, y);
  1141. fract = beta_small_b_large_a_series(T(a+20), bbar, x, y, fract, T(1), pol, normalised);
  1142. if(invert)
  1143. {
  1144. fract = -fract;
  1145. invert = false;
  1146. }
  1147. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1148. }
  1149. else
  1150. {
  1151. fract = ibeta_fraction2(a, b, x, y, pol, normalised, p_derivative);
  1152. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1153. }
  1154. }
  1155. else
  1156. {
  1157. fract = ibeta_fraction2(a, b, x, y, pol, normalised, p_derivative);
  1158. BOOST_MATH_INSTRUMENT_VARIABLE(fract);
  1159. }
  1160. }
  1161. if(p_derivative)
  1162. {
  1163. if(*p_derivative < 0)
  1164. {
  1165. *p_derivative = ibeta_power_terms(a, b, x, y, lanczos_type(), true, pol);
  1166. }
  1167. T div = y * x;
  1168. if(*p_derivative != 0)
  1169. {
  1170. if((tools::max_value<T>() * div < *p_derivative))
  1171. {
  1172. // overflow, return an arbitarily large value:
  1173. *p_derivative = tools::max_value<T>() / 2;
  1174. }
  1175. else
  1176. {
  1177. *p_derivative /= div;
  1178. }
  1179. }
  1180. }
  1181. return invert ? (normalised ? 1 : boost::math::beta(a, b, pol)) - fract : fract;
  1182. } // template <class T, class Lanczos>T ibeta_imp(T a, T b, T x, const Lanczos& l, bool inv, bool normalised)
  1183. template <class T, class Policy>
  1184. inline T ibeta_imp(T a, T b, T x, const Policy& pol, bool inv, bool normalised)
  1185. {
  1186. return ibeta_imp(a, b, x, pol, inv, normalised, static_cast<T*>(0));
  1187. }
  1188. template <class T, class Policy>
  1189. T ibeta_derivative_imp(T a, T b, T x, const Policy& pol)
  1190. {
  1191. static const char* function = "ibeta_derivative<%1%>(%1%,%1%,%1%)";
  1192. //
  1193. // start with the usual error checks:
  1194. //
  1195. if(a <= 0)
  1196. policies::raise_domain_error<T>(function, "The argument a to the incomplete beta function must be greater than zero (got a=%1%).", a, pol);
  1197. if(b <= 0)
  1198. policies::raise_domain_error<T>(function, "The argument b to the incomplete beta function must be greater than zero (got b=%1%).", b, pol);
  1199. if((x < 0) || (x > 1))
  1200. policies::raise_domain_error<T>(function, "Parameter x outside the range [0,1] in the incomplete beta function (got x=%1%).", x, pol);
  1201. //
  1202. // Now the corner cases:
  1203. //
  1204. if(x == 0)
  1205. {
  1206. return (a > 1) ? 0 :
  1207. (a == 1) ? 1 / boost::math::beta(a, b, pol) : policies::raise_overflow_error<T>(function, 0, pol);
  1208. }
  1209. else if(x == 1)
  1210. {
  1211. return (b > 1) ? 0 :
  1212. (b == 1) ? 1 / boost::math::beta(a, b, pol) : policies::raise_overflow_error<T>(function, 0, pol);
  1213. }
  1214. //
  1215. // Now the regular cases:
  1216. //
  1217. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  1218. T f1 = ibeta_power_terms<T>(a, b, x, 1 - x, lanczos_type(), true, pol);
  1219. T y = (1 - x) * x;
  1220. if(f1 == 0)
  1221. return 0;
  1222. if((tools::max_value<T>() * y < f1))
  1223. {
  1224. // overflow:
  1225. return policies::raise_overflow_error<T>(function, 0, pol);
  1226. }
  1227. f1 /= y;
  1228. return f1;
  1229. }
  1230. //
  1231. // Some forwarding functions that dis-ambiguate the third argument type:
  1232. //
  1233. template <class RT1, class RT2, class Policy>
  1234. inline typename tools::promote_args<RT1, RT2>::type
  1235. beta(RT1 a, RT2 b, const Policy&, const mpl::true_*)
  1236. {
  1237. BOOST_FPU_EXCEPTION_GUARD
  1238. typedef typename tools::promote_args<RT1, RT2>::type result_type;
  1239. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1240. typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1241. typedef typename policies::normalise<
  1242. Policy,
  1243. policies::promote_float<false>,
  1244. policies::promote_double<false>,
  1245. policies::discrete_quantile<>,
  1246. policies::assert_undefined<> >::type forwarding_policy;
  1247. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::beta_imp(static_cast<value_type>(a), static_cast<value_type>(b), evaluation_type(), forwarding_policy()), "boost::math::beta<%1%>(%1%,%1%)");
  1248. }
  1249. template <class RT1, class RT2, class RT3>
  1250. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1251. beta(RT1 a, RT2 b, RT3 x, const mpl::false_*)
  1252. {
  1253. return boost::math::beta(a, b, x, policies::policy<>());
  1254. }
  1255. } // namespace detail
  1256. //
  1257. // The actual function entry-points now follow, these just figure out
  1258. // which Lanczos approximation to use
  1259. // and forward to the implementation functions:
  1260. //
  1261. template <class RT1, class RT2, class A>
  1262. inline typename tools::promote_args<RT1, RT2, A>::type
  1263. beta(RT1 a, RT2 b, A arg)
  1264. {
  1265. typedef typename policies::is_policy<A>::type tag;
  1266. return boost::math::detail::beta(a, b, arg, static_cast<tag*>(0));
  1267. }
  1268. template <class RT1, class RT2>
  1269. inline typename tools::promote_args<RT1, RT2>::type
  1270. beta(RT1 a, RT2 b)
  1271. {
  1272. return boost::math::beta(a, b, policies::policy<>());
  1273. }
  1274. template <class RT1, class RT2, class RT3, class Policy>
  1275. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1276. beta(RT1 a, RT2 b, RT3 x, const Policy&)
  1277. {
  1278. BOOST_FPU_EXCEPTION_GUARD
  1279. typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
  1280. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1281. typedef typename policies::normalise<
  1282. Policy,
  1283. policies::promote_float<false>,
  1284. policies::promote_double<false>,
  1285. policies::discrete_quantile<>,
  1286. policies::assert_undefined<> >::type forwarding_policy;
  1287. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy(), false, false), "boost::math::beta<%1%>(%1%,%1%,%1%)");
  1288. }
  1289. template <class RT1, class RT2, class RT3, class Policy>
  1290. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1291. betac(RT1 a, RT2 b, RT3 x, const Policy&)
  1292. {
  1293. BOOST_FPU_EXCEPTION_GUARD
  1294. typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
  1295. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1296. typedef typename policies::normalise<
  1297. Policy,
  1298. policies::promote_float<false>,
  1299. policies::promote_double<false>,
  1300. policies::discrete_quantile<>,
  1301. policies::assert_undefined<> >::type forwarding_policy;
  1302. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy(), true, false), "boost::math::betac<%1%>(%1%,%1%,%1%)");
  1303. }
  1304. template <class RT1, class RT2, class RT3>
  1305. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1306. betac(RT1 a, RT2 b, RT3 x)
  1307. {
  1308. return boost::math::betac(a, b, x, policies::policy<>());
  1309. }
  1310. template <class RT1, class RT2, class RT3, class Policy>
  1311. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1312. ibeta(RT1 a, RT2 b, RT3 x, const Policy&)
  1313. {
  1314. BOOST_FPU_EXCEPTION_GUARD
  1315. typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
  1316. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1317. typedef typename policies::normalise<
  1318. Policy,
  1319. policies::promote_float<false>,
  1320. policies::promote_double<false>,
  1321. policies::discrete_quantile<>,
  1322. policies::assert_undefined<> >::type forwarding_policy;
  1323. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy(), false, true), "boost::math::ibeta<%1%>(%1%,%1%,%1%)");
  1324. }
  1325. template <class RT1, class RT2, class RT3>
  1326. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1327. ibeta(RT1 a, RT2 b, RT3 x)
  1328. {
  1329. return boost::math::ibeta(a, b, x, policies::policy<>());
  1330. }
  1331. template <class RT1, class RT2, class RT3, class Policy>
  1332. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1333. ibetac(RT1 a, RT2 b, RT3 x, const Policy&)
  1334. {
  1335. BOOST_FPU_EXCEPTION_GUARD
  1336. typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
  1337. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1338. typedef typename policies::normalise<
  1339. Policy,
  1340. policies::promote_float<false>,
  1341. policies::promote_double<false>,
  1342. policies::discrete_quantile<>,
  1343. policies::assert_undefined<> >::type forwarding_policy;
  1344. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy(), true, true), "boost::math::ibetac<%1%>(%1%,%1%,%1%)");
  1345. }
  1346. template <class RT1, class RT2, class RT3>
  1347. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1348. ibetac(RT1 a, RT2 b, RT3 x)
  1349. {
  1350. return boost::math::ibetac(a, b, x, policies::policy<>());
  1351. }
  1352. template <class RT1, class RT2, class RT3, class Policy>
  1353. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1354. ibeta_derivative(RT1 a, RT2 b, RT3 x, const Policy&)
  1355. {
  1356. BOOST_FPU_EXCEPTION_GUARD
  1357. typedef typename tools::promote_args<RT1, RT2, RT3>::type result_type;
  1358. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1359. typedef typename policies::normalise<
  1360. Policy,
  1361. policies::promote_float<false>,
  1362. policies::promote_double<false>,
  1363. policies::discrete_quantile<>,
  1364. policies::assert_undefined<> >::type forwarding_policy;
  1365. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::ibeta_derivative_imp(static_cast<value_type>(a), static_cast<value_type>(b), static_cast<value_type>(x), forwarding_policy()), "boost::math::ibeta_derivative<%1%>(%1%,%1%,%1%)");
  1366. }
  1367. template <class RT1, class RT2, class RT3>
  1368. inline typename tools::promote_args<RT1, RT2, RT3>::type
  1369. ibeta_derivative(RT1 a, RT2 b, RT3 x)
  1370. {
  1371. return boost::math::ibeta_derivative(a, b, x, policies::policy<>());
  1372. }
  1373. } // namespace math
  1374. } // namespace boost
  1375. #include <boost/math/special_functions/detail/ibeta_inverse.hpp>
  1376. #include <boost/math/special_functions/detail/ibeta_inv_ab.hpp>
  1377. #endif // BOOST_MATH_SPECIAL_BETA_HPP