gamma.hpp 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223
  1. // Copyright John Maddock 2006-7, 2013-20.
  2. // Copyright Paul A. Bristow 2007, 2013-14.
  3. // Copyright Nikhar Agrawal 2013-14
  4. // Copyright Christopher Kormanyos 2013-14, 2020, 2024
  5. // Use, modification and distribution are subject to the
  6. // Boost Software License, Version 1.0. (See accompanying file
  7. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. #ifndef BOOST_MATH_SF_GAMMA_HPP
  9. #define BOOST_MATH_SF_GAMMA_HPP
  10. #ifdef _MSC_VER
  11. #pragma once
  12. #endif
  13. #include <boost/math/tools/series.hpp>
  14. #include <boost/math/tools/fraction.hpp>
  15. #include <boost/math/tools/precision.hpp>
  16. #include <boost/math/tools/promotion.hpp>
  17. #include <boost/math/tools/assert.hpp>
  18. #include <boost/math/tools/config.hpp>
  19. #include <boost/math/policies/error_handling.hpp>
  20. #include <boost/math/constants/constants.hpp>
  21. #include <boost/math/special_functions/math_fwd.hpp>
  22. #include <boost/math/special_functions/log1p.hpp>
  23. #include <boost/math/special_functions/trunc.hpp>
  24. #include <boost/math/special_functions/powm1.hpp>
  25. #include <boost/math/special_functions/sqrt1pm1.hpp>
  26. #include <boost/math/special_functions/lanczos.hpp>
  27. #include <boost/math/special_functions/fpclassify.hpp>
  28. #include <boost/math/special_functions/detail/igamma_large.hpp>
  29. #include <boost/math/special_functions/detail/unchecked_factorial.hpp>
  30. #include <boost/math/special_functions/detail/lgamma_small.hpp>
  31. #include <boost/math/special_functions/bernoulli.hpp>
  32. #include <boost/math/special_functions/polygamma.hpp>
  33. #include <cmath>
  34. #include <algorithm>
  35. #include <type_traits>
  36. #ifdef _MSC_VER
  37. # pragma warning(push)
  38. # pragma warning(disable: 4702) // unreachable code (return after domain_error throw).
  39. # pragma warning(disable: 4127) // conditional expression is constant.
  40. # pragma warning(disable: 4100) // unreferenced formal parameter.
  41. # pragma warning(disable: 6326) // potential comparison of a constant with another constant
  42. // Several variables made comments,
  43. // but some difficulty as whether referenced on not may depend on macro values.
  44. // So to be safe, 4100 warnings suppressed.
  45. // TODO - revisit this?
  46. #endif
  47. namespace boost{ namespace math{
  48. namespace detail{
  49. template <class T>
  50. inline bool is_odd(T v, const std::true_type&)
  51. {
  52. int i = static_cast<int>(v);
  53. return i&1;
  54. }
  55. template <class T>
  56. inline bool is_odd(T v, const std::false_type&)
  57. {
  58. // Oh dear can't cast T to int!
  59. BOOST_MATH_STD_USING
  60. T modulus = v - 2 * floor(v/2);
  61. return static_cast<bool>(modulus != 0);
  62. }
  63. template <class T>
  64. inline bool is_odd(T v)
  65. {
  66. return is_odd(v, ::std::is_convertible<T, int>());
  67. }
  68. template <class T>
  69. T sinpx(T z)
  70. {
  71. // Ad hoc function calculates x * sin(pi * x),
  72. // taking extra care near when x is near a whole number.
  73. BOOST_MATH_STD_USING
  74. int sign = 1;
  75. if(z < 0)
  76. {
  77. z = -z;
  78. }
  79. T fl = floor(z);
  80. T dist;
  81. if(is_odd(fl))
  82. {
  83. fl += 1;
  84. dist = fl - z;
  85. sign = -sign;
  86. }
  87. else
  88. {
  89. dist = z - fl;
  90. }
  91. BOOST_MATH_ASSERT(fl >= 0);
  92. if(dist > T(0.5))
  93. dist = 1 - dist;
  94. T result = sin(dist*boost::math::constants::pi<T>());
  95. return sign*z*result;
  96. } // template <class T> T sinpx(T z)
  97. //
  98. // tgamma(z), with Lanczos support:
  99. //
  100. template <class T, class Policy, class Lanczos>
  101. T gamma_imp(T z, const Policy& pol, const Lanczos& l)
  102. {
  103. BOOST_MATH_STD_USING
  104. T result = 1;
  105. #ifdef BOOST_MATH_INSTRUMENT
  106. static bool b = false;
  107. if(!b)
  108. {
  109. std::cout << "tgamma_imp called with " << typeid(z).name() << " " << typeid(l).name() << std::endl;
  110. b = true;
  111. }
  112. #endif
  113. static const char* function = "boost::math::tgamma<%1%>(%1%)";
  114. if(z <= 0)
  115. {
  116. if(floor(z) == z)
  117. return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol);
  118. if(z <= -20)
  119. {
  120. result = gamma_imp(T(-z), pol, l) * sinpx(z);
  121. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  122. if((fabs(result) < 1) && (tools::max_value<T>() * fabs(result) < boost::math::constants::pi<T>()))
  123. return -boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
  124. result = -boost::math::constants::pi<T>() / result;
  125. if(result == 0)
  126. return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol);
  127. if((boost::math::fpclassify)(result) == (int)FP_SUBNORMAL)
  128. return policies::raise_denorm_error<T>(function, "Result of tgamma is denormalized.", result, pol);
  129. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  130. return result;
  131. }
  132. // shift z to > 1:
  133. while(z < 0)
  134. {
  135. result /= z;
  136. z += 1;
  137. }
  138. }
  139. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  140. if((floor(z) == z) && (z < max_factorial<T>::value))
  141. {
  142. result *= unchecked_factorial<T>(itrunc(z, pol) - 1);
  143. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  144. }
  145. else if (z < tools::root_epsilon<T>())
  146. {
  147. if (z < 1 / tools::max_value<T>())
  148. result = policies::raise_overflow_error<T>(function, nullptr, pol);
  149. result *= 1 / z - constants::euler<T>();
  150. }
  151. else
  152. {
  153. result *= Lanczos::lanczos_sum(z);
  154. T zgh = (z + static_cast<T>(Lanczos::g()) - boost::math::constants::half<T>());
  155. T lzgh = log(zgh);
  156. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  157. BOOST_MATH_INSTRUMENT_VARIABLE(tools::log_max_value<T>());
  158. if(z * lzgh > tools::log_max_value<T>())
  159. {
  160. // we're going to overflow unless this is done with care:
  161. BOOST_MATH_INSTRUMENT_VARIABLE(zgh);
  162. if(lzgh * z / 2 > tools::log_max_value<T>())
  163. return boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
  164. T hp = pow(zgh, T((z / 2) - T(0.25)));
  165. BOOST_MATH_INSTRUMENT_VARIABLE(hp);
  166. result *= hp / exp(zgh);
  167. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  168. if(tools::max_value<T>() / hp < result)
  169. return boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
  170. result *= hp;
  171. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  172. }
  173. else
  174. {
  175. BOOST_MATH_INSTRUMENT_VARIABLE(zgh);
  176. BOOST_MATH_INSTRUMENT_VARIABLE(pow(zgh, T(z - boost::math::constants::half<T>())));
  177. BOOST_MATH_INSTRUMENT_VARIABLE(exp(zgh));
  178. result *= pow(zgh, T(z - boost::math::constants::half<T>())) / exp(zgh);
  179. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  180. }
  181. }
  182. return result;
  183. }
  184. //
  185. // lgamma(z) with Lanczos support:
  186. //
  187. template <class T, class Policy, class Lanczos>
  188. T lgamma_imp(T z, const Policy& pol, const Lanczos& l, int* sign = nullptr)
  189. {
  190. #ifdef BOOST_MATH_INSTRUMENT
  191. static bool b = false;
  192. if(!b)
  193. {
  194. std::cout << "lgamma_imp called with " << typeid(z).name() << " " << typeid(l).name() << std::endl;
  195. b = true;
  196. }
  197. #endif
  198. BOOST_MATH_STD_USING
  199. static const char* function = "boost::math::lgamma<%1%>(%1%)";
  200. T result = 0;
  201. int sresult = 1;
  202. if(z <= -tools::root_epsilon<T>())
  203. {
  204. // reflection formula:
  205. if(floor(z) == z)
  206. return policies::raise_pole_error<T>(function, "Evaluation of lgamma at a negative integer %1%.", z, pol);
  207. T t = sinpx(z);
  208. z = -z;
  209. if(t < 0)
  210. {
  211. t = -t;
  212. }
  213. else
  214. {
  215. sresult = -sresult;
  216. }
  217. result = log(boost::math::constants::pi<T>()) - lgamma_imp(z, pol, l) - log(t);
  218. }
  219. else if (z < tools::root_epsilon<T>())
  220. {
  221. if (0 == z)
  222. return policies::raise_pole_error<T>(function, "Evaluation of lgamma at %1%.", z, pol);
  223. if (4 * fabs(z) < tools::epsilon<T>())
  224. result = -log(fabs(z));
  225. else
  226. result = log(fabs(1 / z - constants::euler<T>()));
  227. if (z < 0)
  228. sresult = -1;
  229. }
  230. else if(z < 15)
  231. {
  232. typedef typename policies::precision<T, Policy>::type precision_type;
  233. typedef std::integral_constant<int,
  234. precision_type::value <= 0 ? 0 :
  235. precision_type::value <= 64 ? 64 :
  236. precision_type::value <= 113 ? 113 : 0
  237. > tag_type;
  238. result = lgamma_small_imp<T>(z, T(z - 1), T(z - 2), tag_type(), pol, l);
  239. }
  240. else if((z >= 3) && (z < 100) && (std::numeric_limits<T>::max_exponent >= 1024))
  241. {
  242. // taking the log of tgamma reduces the error, no danger of overflow here:
  243. result = log(gamma_imp(z, pol, l));
  244. }
  245. else
  246. {
  247. // regular evaluation:
  248. T zgh = static_cast<T>(z + T(Lanczos::g()) - boost::math::constants::half<T>());
  249. result = log(zgh) - 1;
  250. result *= z - 0.5f;
  251. //
  252. // Only add on the lanczos sum part if we're going to need it:
  253. //
  254. if(result * tools::epsilon<T>() < 20)
  255. result += log(Lanczos::lanczos_sum_expG_scaled(z));
  256. }
  257. if(sign)
  258. *sign = sresult;
  259. return result;
  260. }
  261. //
  262. // Incomplete gamma functions follow:
  263. //
  264. template <class T>
  265. struct upper_incomplete_gamma_fract
  266. {
  267. private:
  268. T z, a;
  269. int k;
  270. public:
  271. typedef std::pair<T,T> result_type;
  272. upper_incomplete_gamma_fract(T a1, T z1)
  273. : z(z1-a1+1), a(a1), k(0)
  274. {
  275. }
  276. result_type operator()()
  277. {
  278. ++k;
  279. z += 2;
  280. return result_type(k * (a - k), z);
  281. }
  282. };
  283. template <class T>
  284. inline T upper_gamma_fraction(T a, T z, T eps)
  285. {
  286. // Multiply result by z^a * e^-z to get the full
  287. // upper incomplete integral. Divide by tgamma(z)
  288. // to normalise.
  289. upper_incomplete_gamma_fract<T> f(a, z);
  290. return 1 / (z - a + 1 + boost::math::tools::continued_fraction_a(f, eps));
  291. }
  292. template <class T>
  293. struct lower_incomplete_gamma_series
  294. {
  295. private:
  296. T a, z, result;
  297. public:
  298. typedef T result_type;
  299. lower_incomplete_gamma_series(T a1, T z1) : a(a1), z(z1), result(1){}
  300. T operator()()
  301. {
  302. T r = result;
  303. a += 1;
  304. result *= z/a;
  305. return r;
  306. }
  307. };
  308. template <class T, class Policy>
  309. inline T lower_gamma_series(T a, T z, const Policy& pol, T init_value = 0)
  310. {
  311. // Multiply result by ((z^a) * (e^-z) / a) to get the full
  312. // lower incomplete integral. Then divide by tgamma(a)
  313. // to get the normalised value.
  314. lower_incomplete_gamma_series<T> s(a, z);
  315. std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  316. T factor = policies::get_epsilon<T, Policy>();
  317. T result = boost::math::tools::sum_series(s, factor, max_iter, init_value);
  318. policies::check_series_iterations<T>("boost::math::detail::lower_gamma_series<%1%>(%1%)", max_iter, pol);
  319. return result;
  320. }
  321. //
  322. // Fully generic tgamma and lgamma use Stirling's approximation
  323. // with Bernoulli numbers.
  324. //
  325. template<class T>
  326. std::size_t highest_bernoulli_index()
  327. {
  328. const float digits10_of_type = (std::numeric_limits<T>::is_specialized
  329. ? static_cast<float>(std::numeric_limits<T>::digits10)
  330. : static_cast<float>(boost::math::tools::digits<T>() * 0.301F));
  331. // Find the high index n for Bn to produce the desired precision in Stirling's calculation.
  332. return static_cast<std::size_t>(18.0F + (0.6F * digits10_of_type));
  333. }
  334. template<class T>
  335. int minimum_argument_for_bernoulli_recursion()
  336. {
  337. BOOST_MATH_STD_USING
  338. const float digits10_of_type = (std::numeric_limits<T>::is_specialized
  339. ? (float) std::numeric_limits<T>::digits10
  340. : (float) (boost::math::tools::digits<T>() * 0.301F));
  341. int min_arg = (int) (digits10_of_type * 1.7F);
  342. if(digits10_of_type < 50.0F)
  343. {
  344. // The following code sequence has been modified
  345. // within the context of issue 396.
  346. // The calculation of the test-variable limit has now
  347. // been protected against overflow/underflow dangers.
  348. // The previous line looked like this and did, in fact,
  349. // underflow ldexp when using certain multiprecision types.
  350. // const float limit = std::ceil(std::pow(1.0f / std::ldexp(1.0f, 1-boost::math::tools::digits<T>()), 1.0f / 20.0f));
  351. // The new safe version of the limit check is now here.
  352. const float d2_minus_one = ((digits10_of_type / 0.301F) - 1.0F);
  353. const float limit = ceil(exp((d2_minus_one * log(2.0F)) / 20.0F));
  354. min_arg = (int) ((std::min)(digits10_of_type * 1.7F, limit));
  355. }
  356. return min_arg;
  357. }
  358. template <class T, class Policy>
  359. T scaled_tgamma_no_lanczos(const T& z, const Policy& pol, bool islog = false)
  360. {
  361. BOOST_MATH_STD_USING
  362. //
  363. // Calculates tgamma(z) / (z/e)^z
  364. // Requires that our argument is large enough for Sterling's approximation to hold.
  365. // Used internally when combining gamma's of similar magnitude without logarithms.
  366. //
  367. BOOST_MATH_ASSERT(minimum_argument_for_bernoulli_recursion<T>() <= z);
  368. // Perform the Bernoulli series expansion of Stirling's approximation.
  369. const std::size_t number_of_bernoullis_b2n = policies::get_max_series_iterations<Policy>();
  370. T one_over_x_pow_two_n_minus_one = 1 / z;
  371. const T one_over_x2 = one_over_x_pow_two_n_minus_one * one_over_x_pow_two_n_minus_one;
  372. T sum = (boost::math::bernoulli_b2n<T>(1) / 2) * one_over_x_pow_two_n_minus_one;
  373. const T target_epsilon_to_break_loop = sum * boost::math::tools::epsilon<T>();
  374. const T half_ln_two_pi_over_z = sqrt(boost::math::constants::two_pi<T>() / z);
  375. T last_term = 2 * sum;
  376. for (std::size_t n = 2U;; ++n)
  377. {
  378. one_over_x_pow_two_n_minus_one *= one_over_x2;
  379. const std::size_t n2 = static_cast<std::size_t>(n * 2U);
  380. const T term = (boost::math::bernoulli_b2n<T>(static_cast<int>(n)) * one_over_x_pow_two_n_minus_one) / (n2 * (n2 - 1U));
  381. if ((n >= 3U) && (abs(term) < target_epsilon_to_break_loop))
  382. {
  383. // We have reached the desired precision in Stirling's expansion.
  384. // Adding additional terms to the sum of this divergent asymptotic
  385. // expansion will not improve the result.
  386. // Break from the loop.
  387. break;
  388. }
  389. if (n > number_of_bernoullis_b2n)
  390. return policies::raise_evaluation_error("scaled_tgamma_no_lanczos<%1%>()", "Exceeded maximum series iterations without reaching convergence, best approximation was %1%", T(exp(sum) * half_ln_two_pi_over_z), pol);
  391. sum += term;
  392. // Sanity check for divergence:
  393. T fterm = fabs(term);
  394. if(fterm > last_term)
  395. return policies::raise_evaluation_error("scaled_tgamma_no_lanczos<%1%>()", "Series became divergent without reaching convergence, best approximation was %1%", T(exp(sum) * half_ln_two_pi_over_z), pol);
  396. last_term = fterm;
  397. }
  398. // Complete Stirling's approximation.
  399. T scaled_gamma_value = islog ? T(sum + log(half_ln_two_pi_over_z)) : T(exp(sum) * half_ln_two_pi_over_z);
  400. return scaled_gamma_value;
  401. }
  402. // Forward declaration of the lgamma_imp template specialization.
  403. template <class T, class Policy>
  404. T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sign = nullptr);
  405. template <class T, class Policy>
  406. T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&)
  407. {
  408. BOOST_MATH_STD_USING
  409. static const char* function = "boost::math::tgamma<%1%>(%1%)";
  410. // Check if the argument of tgamma is identically zero.
  411. const bool is_at_zero = (z == 0);
  412. if((boost::math::isnan)(z) || (is_at_zero) || ((boost::math::isinf)(z) && (z < 0)))
  413. return policies::raise_domain_error<T>(function, "Evaluation of tgamma at %1%.", z, pol);
  414. const bool b_neg = (z < 0);
  415. const bool floor_of_z_is_equal_to_z = (floor(z) == z);
  416. // Special case handling of small factorials:
  417. if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial<T>::value))
  418. {
  419. return boost::math::unchecked_factorial<T>(itrunc(z) - 1);
  420. }
  421. // Make a local, unsigned copy of the input argument.
  422. T zz((!b_neg) ? z : -z);
  423. // Special case for ultra-small z:
  424. if(zz < tools::cbrt_epsilon<T>())
  425. {
  426. const T a0(1);
  427. const T a1(boost::math::constants::euler<T>());
  428. const T six_euler_squared((boost::math::constants::euler<T>() * boost::math::constants::euler<T>()) * 6);
  429. const T a2((six_euler_squared - boost::math::constants::pi_sqr<T>()) / 12);
  430. const T inverse_tgamma_series = z * ((a2 * z + a1) * z + a0);
  431. return 1 / inverse_tgamma_series;
  432. }
  433. // Scale the argument up for the calculation of lgamma,
  434. // and use downward recursion later for the final result.
  435. const int min_arg_for_recursion = minimum_argument_for_bernoulli_recursion<T>();
  436. int n_recur;
  437. if(zz < min_arg_for_recursion)
  438. {
  439. n_recur = boost::math::itrunc(min_arg_for_recursion - zz) + 1;
  440. zz += n_recur;
  441. }
  442. else
  443. {
  444. n_recur = 0;
  445. }
  446. if (!n_recur)
  447. {
  448. if (zz > tools::log_max_value<T>())
  449. return policies::raise_overflow_error<T>(function, nullptr, pol);
  450. if (log(zz) * zz / 2 > tools::log_max_value<T>())
  451. return policies::raise_overflow_error<T>(function, nullptr, pol);
  452. }
  453. T gamma_value = scaled_tgamma_no_lanczos(zz, pol);
  454. T power_term = pow(zz, zz / 2);
  455. T exp_term = exp(-zz);
  456. gamma_value *= (power_term * exp_term);
  457. if(!n_recur && (tools::max_value<T>() / power_term < gamma_value))
  458. return policies::raise_overflow_error<T>(function, nullptr, pol);
  459. gamma_value *= power_term;
  460. // Rescale the result using downward recursion if necessary.
  461. if(n_recur)
  462. {
  463. // The order of divides is important, if we keep subtracting 1 from zz
  464. // we DO NOT get back to z (cancellation error). Further if z < epsilon
  465. // we would end up dividing by zero. Also in order to prevent spurious
  466. // overflow with the first division, we must save dividing by |z| till last,
  467. // so the optimal order of divides is z+1, z+2, z+3...z+n_recur-1,z.
  468. zz = fabs(z) + 1;
  469. for(int k = 1; k < n_recur; ++k)
  470. {
  471. gamma_value /= zz;
  472. zz += 1;
  473. }
  474. gamma_value /= fabs(z);
  475. }
  476. // Return the result, accounting for possible negative arguments.
  477. if(b_neg)
  478. {
  479. // Provide special error analysis for:
  480. // * arguments in the neighborhood of a negative integer
  481. // * arguments exactly equal to a negative integer.
  482. // Check if the argument of tgamma is exactly equal to a negative integer.
  483. if(floor_of_z_is_equal_to_z)
  484. return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol);
  485. gamma_value *= sinpx(z);
  486. BOOST_MATH_INSTRUMENT_VARIABLE(gamma_value);
  487. const bool result_is_too_large_to_represent = ( (abs(gamma_value) < 1)
  488. && ((tools::max_value<T>() * abs(gamma_value)) < boost::math::constants::pi<T>()));
  489. if(result_is_too_large_to_represent)
  490. return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
  491. gamma_value = -boost::math::constants::pi<T>() / gamma_value;
  492. BOOST_MATH_INSTRUMENT_VARIABLE(gamma_value);
  493. if(gamma_value == 0)
  494. return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol);
  495. if((boost::math::fpclassify)(gamma_value) == static_cast<int>(FP_SUBNORMAL))
  496. return policies::raise_denorm_error<T>(function, "Result of tgamma is denormalized.", gamma_value, pol);
  497. }
  498. return gamma_value;
  499. }
  500. template <class T, class Policy>
  501. inline T log_gamma_near_1(const T& z, Policy const& pol)
  502. {
  503. //
  504. // This is for the multiprecision case where there is
  505. // no lanczos support, use a taylor series at z = 1,
  506. // see https://www.wolframalpha.com/input/?i=taylor+series+lgamma(x)+at+x+%3D+1
  507. //
  508. BOOST_MATH_STD_USING // ADL of std names
  509. BOOST_MATH_ASSERT(fabs(z) < 1);
  510. T result = -constants::euler<T>() * z;
  511. T power_term = z * z / 2;
  512. int n = 2;
  513. T term = 0;
  514. do
  515. {
  516. term = power_term * boost::math::polygamma(n - 1, T(1), pol);
  517. result += term;
  518. ++n;
  519. power_term *= z / n;
  520. } while (fabs(result) * tools::epsilon<T>() < fabs(term));
  521. return result;
  522. }
  523. template <class T, class Policy>
  524. T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sign)
  525. {
  526. BOOST_MATH_STD_USING
  527. static const char* function = "boost::math::lgamma<%1%>(%1%)";
  528. // Check if the argument of lgamma is identically zero.
  529. const bool is_at_zero = (z == 0);
  530. if(is_at_zero)
  531. return policies::raise_domain_error<T>(function, "Evaluation of lgamma at zero %1%.", z, pol);
  532. if((boost::math::isnan)(z))
  533. return policies::raise_domain_error<T>(function, "Evaluation of lgamma at %1%.", z, pol);
  534. if((boost::math::isinf)(z))
  535. return policies::raise_overflow_error<T>(function, nullptr, pol);
  536. const bool b_neg = (z < 0);
  537. const bool floor_of_z_is_equal_to_z = (floor(z) == z);
  538. // Special case handling of small factorials:
  539. if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial<T>::value))
  540. {
  541. if (sign)
  542. *sign = 1;
  543. return log(boost::math::unchecked_factorial<T>(itrunc(z) - 1));
  544. }
  545. // Make a local, unsigned copy of the input argument.
  546. T zz((!b_neg) ? z : -z);
  547. const int min_arg_for_recursion = minimum_argument_for_bernoulli_recursion<T>();
  548. T log_gamma_value;
  549. if (zz < min_arg_for_recursion)
  550. {
  551. // Here we simply take the logarithm of tgamma(). This is somewhat
  552. // inefficient, but simple. The rationale is that the argument here
  553. // is relatively small and overflow is not expected to be likely.
  554. if (sign)
  555. * sign = 1;
  556. if(fabs(z - 1) < 0.25)
  557. {
  558. log_gamma_value = log_gamma_near_1(T(zz - 1), pol);
  559. }
  560. else if(fabs(z - 2) < 0.25)
  561. {
  562. log_gamma_value = log_gamma_near_1(T(zz - 2), pol) + log(zz - 1);
  563. }
  564. else if (z > -tools::root_epsilon<T>())
  565. {
  566. // Reflection formula may fail if z is very close to zero, let the series
  567. // expansion for tgamma close to zero do the work:
  568. if (sign)
  569. *sign = z < 0 ? -1 : 1;
  570. return log(abs(gamma_imp(z, pol, lanczos::undefined_lanczos())));
  571. }
  572. else
  573. {
  574. // No issue with spurious overflow in reflection formula,
  575. // just fall through to regular code:
  576. T g = gamma_imp(zz, pol, lanczos::undefined_lanczos());
  577. if (sign)
  578. {
  579. *sign = g < 0 ? -1 : 1;
  580. }
  581. log_gamma_value = log(abs(g));
  582. }
  583. }
  584. else
  585. {
  586. // Perform the Bernoulli series expansion of Stirling's approximation.
  587. T sum = scaled_tgamma_no_lanczos(zz, pol, true);
  588. log_gamma_value = zz * (log(zz) - 1) + sum;
  589. }
  590. int sign_of_result = 1;
  591. if(b_neg)
  592. {
  593. // Provide special error analysis if the argument is exactly
  594. // equal to a negative integer.
  595. // Check if the argument of lgamma is exactly equal to a negative integer.
  596. if(floor_of_z_is_equal_to_z)
  597. return policies::raise_pole_error<T>(function, "Evaluation of lgamma at a negative integer %1%.", z, pol);
  598. T t = sinpx(z);
  599. if(t < 0)
  600. {
  601. t = -t;
  602. }
  603. else
  604. {
  605. sign_of_result = -sign_of_result;
  606. }
  607. log_gamma_value = - log_gamma_value
  608. + log(boost::math::constants::pi<T>())
  609. - log(t);
  610. }
  611. if(sign != static_cast<int*>(nullptr)) { *sign = sign_of_result; }
  612. return log_gamma_value;
  613. }
  614. //
  615. // This helper calculates tgamma(dz+1)-1 without cancellation errors,
  616. // used by the upper incomplete gamma with z < 1:
  617. //
  618. template <class T, class Policy, class Lanczos>
  619. T tgammap1m1_imp(T dz, Policy const& pol, const Lanczos& l)
  620. {
  621. BOOST_MATH_STD_USING
  622. typedef typename policies::precision<T,Policy>::type precision_type;
  623. typedef std::integral_constant<int,
  624. precision_type::value <= 0 ? 0 :
  625. precision_type::value <= 64 ? 64 :
  626. precision_type::value <= 113 ? 113 : 0
  627. > tag_type;
  628. T result;
  629. if(dz < 0)
  630. {
  631. if(dz < T(-0.5))
  632. {
  633. // Best method is simply to subtract 1 from tgamma:
  634. result = boost::math::tgamma(1+dz, pol) - 1;
  635. BOOST_MATH_INSTRUMENT_CODE(result);
  636. }
  637. else
  638. {
  639. // Use expm1 on lgamma:
  640. result = boost::math::expm1(-boost::math::log1p(dz, pol)
  641. + lgamma_small_imp<T>(dz+2, dz + 1, dz, tag_type(), pol, l), pol);
  642. BOOST_MATH_INSTRUMENT_CODE(result);
  643. }
  644. }
  645. else
  646. {
  647. if(dz < 2)
  648. {
  649. // Use expm1 on lgamma:
  650. result = boost::math::expm1(lgamma_small_imp<T>(dz+1, dz, dz-1, tag_type(), pol, l), pol);
  651. BOOST_MATH_INSTRUMENT_CODE(result);
  652. }
  653. else
  654. {
  655. // Best method is simply to subtract 1 from tgamma:
  656. result = boost::math::tgamma(1+dz, pol) - 1;
  657. BOOST_MATH_INSTRUMENT_CODE(result);
  658. }
  659. }
  660. return result;
  661. }
  662. template <class T, class Policy>
  663. inline T tgammap1m1_imp(T z, Policy const& pol,
  664. const ::boost::math::lanczos::undefined_lanczos&)
  665. {
  666. BOOST_MATH_STD_USING // ADL of std names
  667. if(fabs(z) < T(0.55))
  668. {
  669. return boost::math::expm1(log_gamma_near_1(z, pol));
  670. }
  671. return boost::math::expm1(boost::math::lgamma(1 + z, pol));
  672. }
  673. //
  674. // Series representation for upper fraction when z is small:
  675. //
  676. template <class T>
  677. struct small_gamma2_series
  678. {
  679. typedef T result_type;
  680. small_gamma2_series(T a_, T x_) : result(-x_), x(-x_), apn(a_+1), n(1){}
  681. T operator()()
  682. {
  683. T r = result / (apn);
  684. result *= x;
  685. result /= ++n;
  686. apn += 1;
  687. return r;
  688. }
  689. private:
  690. T result, x, apn;
  691. int n;
  692. };
  693. //
  694. // calculate power term prefix (z^a)(e^-z) used in the non-normalised
  695. // incomplete gammas:
  696. //
  697. template <class T, class Policy>
  698. T full_igamma_prefix(T a, T z, const Policy& pol)
  699. {
  700. BOOST_MATH_STD_USING
  701. if (z > tools::max_value<T>())
  702. return 0;
  703. T alz = a * log(z);
  704. T prefix { };
  705. if(z >= 1)
  706. {
  707. if((alz < tools::log_max_value<T>()) && (-z > tools::log_min_value<T>()))
  708. {
  709. prefix = pow(z, a) * exp(-z);
  710. }
  711. else if(a >= 1)
  712. {
  713. prefix = pow(T(z / exp(z/a)), a);
  714. }
  715. else
  716. {
  717. prefix = exp(alz - z);
  718. }
  719. }
  720. else
  721. {
  722. if(alz > tools::log_min_value<T>())
  723. {
  724. prefix = pow(z, a) * exp(-z);
  725. }
  726. else if(z/a < tools::log_max_value<T>())
  727. {
  728. prefix = pow(T(z / exp(z/a)), a);
  729. }
  730. else
  731. {
  732. prefix = exp(alz - z);
  733. }
  734. }
  735. //
  736. // This error handling isn't very good: it happens after the fact
  737. // rather than before it...
  738. //
  739. if((boost::math::fpclassify)(prefix) == (int)FP_INFINITE)
  740. return policies::raise_overflow_error<T>("boost::math::detail::full_igamma_prefix<%1%>(%1%, %1%)", "Result of incomplete gamma function is too large to represent.", pol);
  741. return prefix;
  742. }
  743. //
  744. // Compute (z^a)(e^-z)/tgamma(a)
  745. // most if the error occurs in this function:
  746. //
  747. template <class T, class Policy, class Lanczos>
  748. T regularised_gamma_prefix(T a, T z, const Policy& pol, const Lanczos& l)
  749. {
  750. BOOST_MATH_STD_USING
  751. if (z >= tools::max_value<T>())
  752. return 0;
  753. T agh = a + static_cast<T>(Lanczos::g()) - T(0.5);
  754. T prefix;
  755. T d = ((z - a) - static_cast<T>(Lanczos::g()) + T(0.5)) / agh;
  756. if(a < 1)
  757. {
  758. //
  759. // We have to treat a < 1 as a special case because our Lanczos
  760. // approximations are optimised against the factorials with a > 1,
  761. // and for high precision types especially (128-bit reals for example)
  762. // very small values of a can give rather erroneous results for gamma
  763. // unless we do this:
  764. //
  765. // TODO: is this still required? Lanczos approx should be better now?
  766. //
  767. if((z <= tools::log_min_value<T>()) || (a < 1 / tools::max_value<T>()))
  768. {
  769. // Oh dear, have to use logs, should be free of cancellation errors though:
  770. return exp(a * log(z) - z - lgamma_imp(a, pol, l));
  771. }
  772. else
  773. {
  774. // direct calculation, no danger of overflow as gamma(a) < 1/a
  775. // for small a.
  776. return pow(z, a) * exp(-z) / gamma_imp(a, pol, l);
  777. }
  778. }
  779. else if((fabs(d*d*a) <= 100) && (a > 150))
  780. {
  781. // special case for large a and a ~ z.
  782. prefix = a * boost::math::log1pmx(d, pol) + z * static_cast<T>(0.5 - Lanczos::g()) / agh;
  783. prefix = exp(prefix);
  784. }
  785. else
  786. {
  787. //
  788. // general case.
  789. // direct computation is most accurate, but use various fallbacks
  790. // for different parts of the problem domain:
  791. //
  792. T alz = a * log(z / agh);
  793. T amz = a - z;
  794. if(((std::min)(alz, amz) <= tools::log_min_value<T>()) || ((std::max)(alz, amz) >= tools::log_max_value<T>()))
  795. {
  796. T amza = amz / a;
  797. if(((std::min)(alz, amz)/2 > tools::log_min_value<T>()) && ((std::max)(alz, amz)/2 < tools::log_max_value<T>()))
  798. {
  799. // compute square root of the result and then square it:
  800. T sq = pow(z / agh, a / 2) * exp(amz / 2);
  801. prefix = sq * sq;
  802. }
  803. else if(((std::min)(alz, amz)/4 > tools::log_min_value<T>()) && ((std::max)(alz, amz)/4 < tools::log_max_value<T>()) && (z > a))
  804. {
  805. // compute the 4th root of the result then square it twice:
  806. T sq = pow(z / agh, a / 4) * exp(amz / 4);
  807. prefix = sq * sq;
  808. prefix *= prefix;
  809. }
  810. else if((amza > tools::log_min_value<T>()) && (amza < tools::log_max_value<T>()))
  811. {
  812. prefix = pow(T((z * exp(amza)) / agh), a);
  813. }
  814. else
  815. {
  816. prefix = exp(alz + amz);
  817. }
  818. }
  819. else
  820. {
  821. prefix = pow(T(z / agh), a) * exp(amz);
  822. }
  823. }
  824. prefix *= sqrt(agh / boost::math::constants::e<T>()) / Lanczos::lanczos_sum_expG_scaled(a);
  825. return prefix;
  826. }
  827. //
  828. // And again, without Lanczos support:
  829. //
  830. template <class T, class Policy>
  831. T regularised_gamma_prefix(T a, T z, const Policy& pol, const lanczos::undefined_lanczos& l)
  832. {
  833. BOOST_MATH_STD_USING
  834. if((a < 1) && (z < 1))
  835. {
  836. // No overflow possible since the power terms tend to unity as a,z -> 0
  837. return pow(z, a) * exp(-z) / boost::math::tgamma(a, pol);
  838. }
  839. else if(a > minimum_argument_for_bernoulli_recursion<T>())
  840. {
  841. T scaled_gamma = scaled_tgamma_no_lanczos(a, pol);
  842. T power_term = pow(z / a, a / 2);
  843. T a_minus_z = a - z;
  844. if ((0 == power_term) || (fabs(a_minus_z) > tools::log_max_value<T>()))
  845. {
  846. // The result is probably zero, but we need to be sure:
  847. return exp(a * log(z / a) + a_minus_z - log(scaled_gamma));
  848. }
  849. return (power_term * exp(a_minus_z)) * (power_term / scaled_gamma);
  850. }
  851. else
  852. {
  853. //
  854. // Usual case is to calculate the prefix at a+shift and recurse down
  855. // to the value we want:
  856. //
  857. const int min_z = minimum_argument_for_bernoulli_recursion<T>();
  858. long shift = 1 + ltrunc(min_z - a);
  859. T result = regularised_gamma_prefix(T(a + shift), z, pol, l);
  860. if (result != 0)
  861. {
  862. for (long i = 0; i < shift; ++i)
  863. {
  864. result /= z;
  865. result *= a + i;
  866. }
  867. return result;
  868. }
  869. else
  870. {
  871. //
  872. // We failed, most probably we have z << 1, try again, this time
  873. // we calculate z^a e^-z / tgamma(a+shift), combining power terms
  874. // as we go. And again recurse down to the result.
  875. //
  876. T scaled_gamma = scaled_tgamma_no_lanczos(T(a + shift), pol);
  877. T power_term_1 = pow(T(z / (a + shift)), a);
  878. T power_term_2 = pow(T(a + shift), T(-shift));
  879. T power_term_3 = exp(a + shift - z);
  880. if ((0 == power_term_1) || (0 == power_term_2) || (0 == power_term_3) || (fabs(a + shift - z) > tools::log_max_value<T>()))
  881. {
  882. // We have no test case that gets here, most likely the type T
  883. // has a high precision but low exponent range:
  884. return exp(a * log(z) - z - boost::math::lgamma(a, pol));
  885. }
  886. result = power_term_1 * power_term_2 * power_term_3 / scaled_gamma;
  887. for (long i = 0; i < shift; ++i)
  888. {
  889. result *= a + i;
  890. }
  891. return result;
  892. }
  893. }
  894. }
  895. //
  896. // Upper gamma fraction for very small a:
  897. //
  898. template <class T, class Policy>
  899. inline T tgamma_small_upper_part(T a, T x, const Policy& pol, T* pgam = 0, bool invert = false, T* pderivative = 0)
  900. {
  901. BOOST_MATH_STD_USING // ADL of std functions.
  902. //
  903. // Compute the full upper fraction (Q) when a is very small:
  904. //
  905. T result { boost::math::tgamma1pm1(a, pol) };
  906. if(pgam)
  907. *pgam = (result + 1) / a;
  908. T p = boost::math::powm1(x, a, pol);
  909. result -= p;
  910. result /= a;
  911. detail::small_gamma2_series<T> s(a, x);
  912. std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>() - 10;
  913. p += 1;
  914. if(pderivative)
  915. *pderivative = p / (*pgam * exp(x));
  916. T init_value = invert ? *pgam : 0;
  917. result = -p * tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, (init_value - result) / p);
  918. policies::check_series_iterations<T>("boost::math::tgamma_small_upper_part<%1%>(%1%, %1%)", max_iter, pol);
  919. if(invert)
  920. result = -result;
  921. return result;
  922. }
  923. //
  924. // Upper gamma fraction for integer a:
  925. //
  926. template <class T, class Policy>
  927. inline T finite_gamma_q(T a, T x, Policy const& pol, T* pderivative = 0)
  928. {
  929. //
  930. // Calculates normalised Q when a is an integer:
  931. //
  932. BOOST_MATH_STD_USING
  933. T e = exp(-x);
  934. T sum = e;
  935. if(sum != 0)
  936. {
  937. T term = sum;
  938. for(unsigned n = 1; n < a; ++n)
  939. {
  940. term /= n;
  941. term *= x;
  942. sum += term;
  943. }
  944. }
  945. if(pderivative)
  946. {
  947. *pderivative = e * pow(x, a) / boost::math::unchecked_factorial<T>(itrunc(T(a - 1), pol));
  948. }
  949. return sum;
  950. }
  951. //
  952. // Upper gamma fraction for half integer a:
  953. //
  954. template <class T, class Policy>
  955. T finite_half_gamma_q(T a, T x, T* p_derivative, const Policy& pol)
  956. {
  957. //
  958. // Calculates normalised Q when a is a half-integer:
  959. //
  960. BOOST_MATH_STD_USING
  961. T e = boost::math::erfc(sqrt(x), pol);
  962. if((e != 0) && (a > 1))
  963. {
  964. T term = exp(-x) / sqrt(constants::pi<T>() * x);
  965. term *= x;
  966. static const T half = T(1) / 2;
  967. term /= half;
  968. T sum = term;
  969. for(unsigned n = 2; n < a; ++n)
  970. {
  971. term /= n - half;
  972. term *= x;
  973. sum += term;
  974. }
  975. e += sum;
  976. if(p_derivative)
  977. {
  978. *p_derivative = 0;
  979. }
  980. }
  981. else if(p_derivative)
  982. {
  983. // We'll be dividing by x later, so calculate derivative * x:
  984. *p_derivative = sqrt(x) * exp(-x) / constants::root_pi<T>();
  985. }
  986. return e;
  987. }
  988. //
  989. // Asymptotic approximation for large argument, see: https://dlmf.nist.gov/8.11#E2
  990. //
  991. template <class T>
  992. struct incomplete_tgamma_large_x_series
  993. {
  994. typedef T result_type;
  995. incomplete_tgamma_large_x_series(const T& a, const T& x)
  996. : a_poch(a - 1), z(x), term(1) {}
  997. T operator()()
  998. {
  999. T result = term;
  1000. term *= a_poch / z;
  1001. a_poch -= 1;
  1002. return result;
  1003. }
  1004. T a_poch, z, term;
  1005. };
  1006. template <class T, class Policy>
  1007. T incomplete_tgamma_large_x(const T& a, const T& x, const Policy& pol)
  1008. {
  1009. BOOST_MATH_STD_USING
  1010. incomplete_tgamma_large_x_series<T> s(a, x);
  1011. std::uintmax_t max_iter = boost::math::policies::get_max_series_iterations<Policy>();
  1012. T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
  1013. boost::math::policies::check_series_iterations<T>("boost::math::tgamma<%1%>(%1%,%1%)", max_iter, pol);
  1014. return result;
  1015. }
  1016. //
  1017. // Main incomplete gamma entry point, handles all four incomplete gamma's:
  1018. //
  1019. template <class T, class Policy>
  1020. T gamma_incomplete_imp(T a, T x, bool normalised, bool invert,
  1021. const Policy& pol, T* p_derivative)
  1022. {
  1023. static const char* function = "boost::math::gamma_p<%1%>(%1%, %1%)";
  1024. if(a <= 0)
  1025. return policies::raise_domain_error<T>(function, "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol);
  1026. if(x < 0)
  1027. return policies::raise_domain_error<T>(function, "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol);
  1028. BOOST_MATH_STD_USING
  1029. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  1030. T result = 0; // Just to avoid warning C4701: potentially uninitialized local variable 'result' used
  1031. if(a >= max_factorial<T>::value && !normalised)
  1032. {
  1033. //
  1034. // When we're computing the non-normalized incomplete gamma
  1035. // and a is large the result is rather hard to compute unless
  1036. // we use logs. There are really two options - if x is a long
  1037. // way from a in value then we can reliably use methods 2 and 4
  1038. // below in logarithmic form and go straight to the result.
  1039. // Otherwise we let the regularized gamma take the strain
  1040. // (the result is unlikely to underflow in the central region anyway)
  1041. // and combine with lgamma in the hopes that we get a finite result.
  1042. //
  1043. if(invert && (a * 4 < x))
  1044. {
  1045. // This is method 4 below, done in logs:
  1046. result = a * log(x) - x;
  1047. if(p_derivative)
  1048. *p_derivative = exp(result);
  1049. result += log(upper_gamma_fraction(a, x, policies::get_epsilon<T, Policy>()));
  1050. }
  1051. else if(!invert && (a > 4 * x))
  1052. {
  1053. // This is method 2 below, done in logs:
  1054. result = a * log(x) - x;
  1055. if(p_derivative)
  1056. *p_derivative = exp(result);
  1057. T init_value = 0;
  1058. result += log(detail::lower_gamma_series(a, x, pol, init_value) / a);
  1059. }
  1060. else
  1061. {
  1062. result = gamma_incomplete_imp(a, x, true, invert, pol, p_derivative);
  1063. if(result == 0)
  1064. {
  1065. if(invert)
  1066. {
  1067. // Try http://functions.wolfram.com/06.06.06.0039.01
  1068. result = 1 + 1 / (12 * a) + 1 / (288 * a * a);
  1069. result = log(result) - a + (a - 0.5f) * log(a) + log(boost::math::constants::root_two_pi<T>());
  1070. if(p_derivative)
  1071. *p_derivative = exp(a * log(x) - x);
  1072. }
  1073. else
  1074. {
  1075. // This is method 2 below, done in logs, we're really outside the
  1076. // range of this method, but since the result is almost certainly
  1077. // infinite, we should probably be OK:
  1078. result = a * log(x) - x;
  1079. if(p_derivative)
  1080. *p_derivative = exp(result);
  1081. T init_value = 0;
  1082. result += log(detail::lower_gamma_series(a, x, pol, init_value) / a);
  1083. }
  1084. }
  1085. else
  1086. {
  1087. result = log(result) + boost::math::lgamma(a, pol);
  1088. }
  1089. }
  1090. if(result > tools::log_max_value<T>())
  1091. return policies::raise_overflow_error<T>(function, nullptr, pol);
  1092. return exp(result);
  1093. }
  1094. BOOST_MATH_ASSERT((p_derivative == nullptr) || normalised);
  1095. bool is_int, is_half_int;
  1096. bool is_small_a = (a < 30) && (a <= x + 1) && (x < tools::log_max_value<T>());
  1097. if(is_small_a)
  1098. {
  1099. T fa = floor(a);
  1100. is_int = (fa == a);
  1101. is_half_int = is_int ? false : (fabs(fa - a) == 0.5f);
  1102. }
  1103. else
  1104. {
  1105. is_int = is_half_int = false;
  1106. }
  1107. int eval_method;
  1108. if(is_int && (x > 0.6))
  1109. {
  1110. // calculate Q via finite sum:
  1111. invert = !invert;
  1112. eval_method = 0;
  1113. }
  1114. else if(is_half_int && (x > 0.2))
  1115. {
  1116. // calculate Q via finite sum for half integer a:
  1117. invert = !invert;
  1118. eval_method = 1;
  1119. }
  1120. else if((x < tools::root_epsilon<T>()) && (a > 1))
  1121. {
  1122. eval_method = 6;
  1123. }
  1124. else if ((x > 1000) && ((a < x) || (fabs(a - 50) / x < 1)))
  1125. {
  1126. // calculate Q via asymptotic approximation:
  1127. invert = !invert;
  1128. eval_method = 7;
  1129. }
  1130. else if(x < T(0.5))
  1131. {
  1132. //
  1133. // Changeover criterion chosen to give a changeover at Q ~ 0.33
  1134. //
  1135. if(T(-0.4) / log(x) < a)
  1136. {
  1137. eval_method = 2;
  1138. }
  1139. else
  1140. {
  1141. eval_method = 3;
  1142. }
  1143. }
  1144. else if(x < T(1.1))
  1145. {
  1146. //
  1147. // Changeover here occurs when P ~ 0.75 or Q ~ 0.25:
  1148. //
  1149. if(x * 0.75f < a)
  1150. {
  1151. eval_method = 2;
  1152. }
  1153. else
  1154. {
  1155. eval_method = 3;
  1156. }
  1157. }
  1158. else
  1159. {
  1160. //
  1161. // Begin by testing whether we're in the "bad" zone
  1162. // where the result will be near 0.5 and the usual
  1163. // series and continued fractions are slow to converge:
  1164. //
  1165. bool use_temme = false;
  1166. if(normalised && std::numeric_limits<T>::is_specialized && (a > 20))
  1167. {
  1168. T sigma = fabs((x-a)/a);
  1169. if((a > 200) && (policies::digits<T, Policy>() <= 113))
  1170. {
  1171. //
  1172. // This limit is chosen so that we use Temme's expansion
  1173. // only if the result would be larger than about 10^-6.
  1174. // Below that the regular series and continued fractions
  1175. // converge OK, and if we use Temme's method we get increasing
  1176. // errors from the dominant erfc term as it's (inexact) argument
  1177. // increases in magnitude.
  1178. //
  1179. if(20 / a > sigma * sigma)
  1180. use_temme = true;
  1181. }
  1182. else if(policies::digits<T, Policy>() <= 64)
  1183. {
  1184. // Note in this zone we can't use Temme's expansion for
  1185. // types longer than an 80-bit real:
  1186. // it would require too many terms in the polynomials.
  1187. if(sigma < 0.4)
  1188. use_temme = true;
  1189. }
  1190. }
  1191. if(use_temme)
  1192. {
  1193. eval_method = 5;
  1194. }
  1195. else
  1196. {
  1197. //
  1198. // Regular case where the result will not be too close to 0.5.
  1199. //
  1200. // Changeover here occurs at P ~ Q ~ 0.5
  1201. // Note that series computation of P is about x2 faster than continued fraction
  1202. // calculation of Q, so try and use the CF only when really necessary, especially
  1203. // for small x.
  1204. //
  1205. if(x - (1 / (3 * x)) < a)
  1206. {
  1207. eval_method = 2;
  1208. }
  1209. else
  1210. {
  1211. eval_method = 4;
  1212. invert = !invert;
  1213. }
  1214. }
  1215. }
  1216. switch(eval_method)
  1217. {
  1218. case 0:
  1219. {
  1220. result = finite_gamma_q(a, x, pol, p_derivative);
  1221. if(!normalised)
  1222. result *= boost::math::tgamma(a, pol);
  1223. break;
  1224. }
  1225. case 1:
  1226. {
  1227. result = finite_half_gamma_q(a, x, p_derivative, pol);
  1228. if(!normalised)
  1229. result *= boost::math::tgamma(a, pol);
  1230. if(p_derivative && (*p_derivative == 0))
  1231. *p_derivative = regularised_gamma_prefix(a, x, pol, lanczos_type());
  1232. break;
  1233. }
  1234. case 2:
  1235. {
  1236. // Compute P:
  1237. result = normalised ? regularised_gamma_prefix(a, x, pol, lanczos_type()) : full_igamma_prefix(a, x, pol);
  1238. if(p_derivative)
  1239. *p_derivative = result;
  1240. if(result != 0)
  1241. {
  1242. //
  1243. // If we're going to be inverting the result then we can
  1244. // reduce the number of series evaluations by quite
  1245. // a few iterations if we set an initial value for the
  1246. // series sum based on what we'll end up subtracting it from
  1247. // at the end.
  1248. // Have to be careful though that this optimization doesn't
  1249. // lead to spurious numeric overflow. Note that the
  1250. // scary/expensive overflow checks below are more often
  1251. // than not bypassed in practice for "sensible" input
  1252. // values:
  1253. //
  1254. T init_value = 0;
  1255. bool optimised_invert = false;
  1256. if(invert)
  1257. {
  1258. init_value = (normalised ? 1 : boost::math::tgamma(a, pol));
  1259. if(normalised || (result >= 1) || (tools::max_value<T>() * result > init_value))
  1260. {
  1261. init_value /= result;
  1262. if(normalised || (a < 1) || (tools::max_value<T>() / a > init_value))
  1263. {
  1264. init_value *= -a;
  1265. optimised_invert = true;
  1266. }
  1267. else
  1268. init_value = 0;
  1269. }
  1270. else
  1271. init_value = 0;
  1272. }
  1273. result *= detail::lower_gamma_series(a, x, pol, init_value) / a;
  1274. if(optimised_invert)
  1275. {
  1276. invert = false;
  1277. result = -result;
  1278. }
  1279. }
  1280. break;
  1281. }
  1282. case 3:
  1283. {
  1284. // Compute Q:
  1285. invert = !invert;
  1286. T g;
  1287. result = tgamma_small_upper_part(a, x, pol, &g, invert, p_derivative);
  1288. invert = false;
  1289. if(normalised)
  1290. result /= g;
  1291. break;
  1292. }
  1293. case 4:
  1294. {
  1295. // Compute Q:
  1296. result = normalised ? regularised_gamma_prefix(a, x, pol, lanczos_type()) : full_igamma_prefix(a, x, pol);
  1297. if(p_derivative)
  1298. *p_derivative = result;
  1299. if(result != 0)
  1300. result *= upper_gamma_fraction(a, x, policies::get_epsilon<T, Policy>());
  1301. break;
  1302. }
  1303. case 5:
  1304. {
  1305. //
  1306. // Use compile time dispatch to the appropriate
  1307. // Temme asymptotic expansion. This may be dead code
  1308. // if T does not have numeric limits support, or has
  1309. // too many digits for the most precise version of
  1310. // these expansions, in that case we'll be calling
  1311. // an empty function.
  1312. //
  1313. typedef typename policies::precision<T, Policy>::type precision_type;
  1314. typedef std::integral_constant<int,
  1315. precision_type::value <= 0 ? 0 :
  1316. precision_type::value <= 53 ? 53 :
  1317. precision_type::value <= 64 ? 64 :
  1318. precision_type::value <= 113 ? 113 : 0
  1319. > tag_type;
  1320. result = igamma_temme_large(a, x, pol, static_cast<tag_type const*>(nullptr));
  1321. if(x >= a)
  1322. invert = !invert;
  1323. if(p_derivative)
  1324. *p_derivative = regularised_gamma_prefix(a, x, pol, lanczos_type());
  1325. break;
  1326. }
  1327. case 6:
  1328. {
  1329. // x is so small that P is necessarily very small too,
  1330. // use http://functions.wolfram.com/GammaBetaErf/GammaRegularized/06/01/05/01/01/
  1331. if(!normalised)
  1332. result = pow(x, a) / (a);
  1333. else
  1334. {
  1335. #ifndef BOOST_MATH_NO_EXCEPTIONS
  1336. try
  1337. {
  1338. #endif
  1339. result = pow(x, a) / boost::math::tgamma(a + 1, pol);
  1340. #ifndef BOOST_MATH_NO_EXCEPTIONS
  1341. }
  1342. catch (const std::overflow_error&)
  1343. {
  1344. result = 0;
  1345. }
  1346. #endif
  1347. }
  1348. result *= 1 - a * x / (a + 1);
  1349. if (p_derivative)
  1350. *p_derivative = regularised_gamma_prefix(a, x, pol, lanczos_type());
  1351. break;
  1352. }
  1353. case 7:
  1354. {
  1355. // x is large,
  1356. // Compute Q:
  1357. result = normalised ? regularised_gamma_prefix(a, x, pol, lanczos_type()) : full_igamma_prefix(a, x, pol);
  1358. if (p_derivative)
  1359. *p_derivative = result;
  1360. result /= x;
  1361. if (result != 0)
  1362. result *= incomplete_tgamma_large_x(a, x, pol);
  1363. break;
  1364. }
  1365. }
  1366. if(normalised && (result > 1))
  1367. result = 1;
  1368. if(invert)
  1369. {
  1370. T gam = normalised ? 1 : boost::math::tgamma(a, pol);
  1371. result = gam - result;
  1372. }
  1373. if(p_derivative)
  1374. {
  1375. //
  1376. // Need to convert prefix term to derivative:
  1377. //
  1378. if((x < 1) && (tools::max_value<T>() * x < *p_derivative))
  1379. {
  1380. // overflow, just return an arbitrarily large value:
  1381. *p_derivative = tools::max_value<T>() / 2;
  1382. }
  1383. *p_derivative /= x;
  1384. }
  1385. return result;
  1386. }
  1387. //
  1388. // Ratios of two gamma functions:
  1389. //
  1390. template <class T, class Policy, class Lanczos>
  1391. T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const Lanczos& l)
  1392. {
  1393. BOOST_MATH_STD_USING
  1394. if(z < tools::epsilon<T>())
  1395. {
  1396. //
  1397. // We get spurious numeric overflow unless we're very careful, this
  1398. // can occur either inside Lanczos::lanczos_sum(z) or in the
  1399. // final combination of terms, to avoid this, split the product up
  1400. // into 2 (or 3) parts:
  1401. //
  1402. // G(z) / G(L) = 1 / (z * G(L)) ; z < eps, L = z + delta = delta
  1403. // z * G(L) = z * G(lim) * (G(L)/G(lim)) ; lim = largest factorial
  1404. //
  1405. if(boost::math::max_factorial<T>::value < delta)
  1406. {
  1407. T ratio = tgamma_delta_ratio_imp_lanczos(delta, T(boost::math::max_factorial<T>::value - delta), pol, l);
  1408. ratio *= z;
  1409. ratio *= boost::math::unchecked_factorial<T>(boost::math::max_factorial<T>::value - 1);
  1410. return 1 / ratio;
  1411. }
  1412. else
  1413. {
  1414. return 1 / (z * boost::math::tgamma(z + delta, pol));
  1415. }
  1416. }
  1417. T zgh = static_cast<T>(z + T(Lanczos::g()) - constants::half<T>());
  1418. T result;
  1419. if(z + delta == z)
  1420. {
  1421. if (fabs(delta / zgh) < boost::math::tools::epsilon<T>())
  1422. {
  1423. // We have:
  1424. // result = exp((constants::half<T>() - z) * boost::math::log1p(delta / zgh, pol));
  1425. // 0.5 - z == -z
  1426. // log1p(delta / zgh) = delta / zgh = delta / z
  1427. // multiplying we get -delta.
  1428. result = exp(-delta);
  1429. }
  1430. else
  1431. // from the pow formula below... but this may actually be wrong, we just can't really calculate it :(
  1432. result = 1;
  1433. }
  1434. else
  1435. {
  1436. if(fabs(delta) < 10)
  1437. {
  1438. result = exp((constants::half<T>() - z) * boost::math::log1p(delta / zgh, pol));
  1439. }
  1440. else
  1441. {
  1442. result = pow(T(zgh / (zgh + delta)), T(z - constants::half<T>()));
  1443. }
  1444. // Split the calculation up to avoid spurious overflow:
  1445. result *= Lanczos::lanczos_sum(z) / Lanczos::lanczos_sum(T(z + delta));
  1446. }
  1447. result *= pow(T(constants::e<T>() / (zgh + delta)), delta);
  1448. return result;
  1449. }
  1450. //
  1451. // And again without Lanczos support this time:
  1452. //
  1453. template <class T, class Policy>
  1454. T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const lanczos::undefined_lanczos& l)
  1455. {
  1456. BOOST_MATH_STD_USING
  1457. //
  1458. // We adjust z and delta so that both z and z+delta are large enough for
  1459. // Sterling's approximation to hold. We can then calculate the ratio
  1460. // for the adjusted values, and rescale back down to z and z+delta.
  1461. //
  1462. // Get the required shifts first:
  1463. //
  1464. long numerator_shift = 0;
  1465. long denominator_shift = 0;
  1466. const int min_z = minimum_argument_for_bernoulli_recursion<T>();
  1467. if (min_z > z)
  1468. numerator_shift = 1 + ltrunc(min_z - z);
  1469. if (min_z > z + delta)
  1470. denominator_shift = 1 + ltrunc(min_z - z - delta);
  1471. //
  1472. // If the shifts are zero, then we can just combine scaled tgamma's
  1473. // and combine the remaining terms:
  1474. //
  1475. if (numerator_shift == 0 && denominator_shift == 0)
  1476. {
  1477. T scaled_tgamma_num = scaled_tgamma_no_lanczos(z, pol);
  1478. T scaled_tgamma_denom = scaled_tgamma_no_lanczos(T(z + delta), pol);
  1479. T result = scaled_tgamma_num / scaled_tgamma_denom;
  1480. result *= exp(z * boost::math::log1p(-delta / (z + delta), pol)) * pow(T((delta + z) / constants::e<T>()), -delta);
  1481. return result;
  1482. }
  1483. //
  1484. // We're going to have to rescale first, get the adjusted z and delta values,
  1485. // plus the ratio for the adjusted values:
  1486. //
  1487. T zz = z + numerator_shift;
  1488. T dd = delta - (numerator_shift - denominator_shift);
  1489. T ratio = tgamma_delta_ratio_imp_lanczos(zz, dd, pol, l);
  1490. //
  1491. // Use gamma recurrence relations to get back to the original
  1492. // z and z+delta:
  1493. //
  1494. for (long long i = 0; i < numerator_shift; ++i)
  1495. {
  1496. ratio /= (z + i);
  1497. if (i < denominator_shift)
  1498. ratio *= (z + delta + i);
  1499. }
  1500. for (long long i = numerator_shift; i < denominator_shift; ++i)
  1501. {
  1502. ratio *= (z + delta + i);
  1503. }
  1504. return ratio;
  1505. }
  1506. template <class T, class Policy>
  1507. T tgamma_delta_ratio_imp(T z, T delta, const Policy& pol)
  1508. {
  1509. BOOST_MATH_STD_USING
  1510. if((z <= 0) || (z + delta <= 0))
  1511. {
  1512. // This isn't very sophisticated, or accurate, but it does work:
  1513. return boost::math::tgamma(z, pol) / boost::math::tgamma(z + delta, pol);
  1514. }
  1515. if(floor(delta) == delta)
  1516. {
  1517. if(floor(z) == z)
  1518. {
  1519. //
  1520. // Both z and delta are integers, see if we can just use table lookup
  1521. // of the factorials to get the result:
  1522. //
  1523. if((z <= max_factorial<T>::value) && (z + delta <= max_factorial<T>::value))
  1524. {
  1525. return unchecked_factorial<T>((unsigned)itrunc(z, pol) - 1) / unchecked_factorial<T>((unsigned)itrunc(T(z + delta), pol) - 1);
  1526. }
  1527. }
  1528. if(fabs(delta) < 20)
  1529. {
  1530. //
  1531. // delta is a small integer, we can use a finite product:
  1532. //
  1533. if(delta == 0)
  1534. return 1;
  1535. if(delta < 0)
  1536. {
  1537. z -= 1;
  1538. T result = z;
  1539. while(0 != (delta += 1))
  1540. {
  1541. z -= 1;
  1542. result *= z;
  1543. }
  1544. return result;
  1545. }
  1546. else
  1547. {
  1548. T result = 1 / z;
  1549. while(0 != (delta -= 1))
  1550. {
  1551. z += 1;
  1552. result /= z;
  1553. }
  1554. return result;
  1555. }
  1556. }
  1557. }
  1558. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  1559. return tgamma_delta_ratio_imp_lanczos(z, delta, pol, lanczos_type());
  1560. }
  1561. template <class T, class Policy>
  1562. T tgamma_ratio_imp(T x, T y, const Policy& pol)
  1563. {
  1564. BOOST_MATH_STD_USING
  1565. if((x <= 0) || (boost::math::isinf)(x))
  1566. return policies::raise_domain_error<T>("boost::math::tgamma_ratio<%1%>(%1%, %1%)", "Gamma function ratios only implemented for positive arguments (got a=%1%).", x, pol);
  1567. if((y <= 0) || (boost::math::isinf)(y))
  1568. return policies::raise_domain_error<T>("boost::math::tgamma_ratio<%1%>(%1%, %1%)", "Gamma function ratios only implemented for positive arguments (got b=%1%).", y, pol);
  1569. if(x <= tools::min_value<T>())
  1570. {
  1571. // Special case for denorms...Ugh.
  1572. T shift = ldexp(T(1), tools::digits<T>());
  1573. return shift * tgamma_ratio_imp(T(x * shift), y, pol);
  1574. }
  1575. if((x < max_factorial<T>::value) && (y < max_factorial<T>::value))
  1576. {
  1577. // Rather than subtracting values, lets just call the gamma functions directly:
  1578. return boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
  1579. }
  1580. T prefix = 1;
  1581. if(x < 1)
  1582. {
  1583. if(y < 2 * max_factorial<T>::value)
  1584. {
  1585. // We need to sidestep on x as well, otherwise we'll underflow
  1586. // before we get to factor in the prefix term:
  1587. prefix /= x;
  1588. x += 1;
  1589. while(y >= max_factorial<T>::value)
  1590. {
  1591. y -= 1;
  1592. prefix /= y;
  1593. }
  1594. return prefix * boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
  1595. }
  1596. //
  1597. // result is almost certainly going to underflow to zero, try logs just in case:
  1598. //
  1599. return exp(boost::math::lgamma(x, pol) - boost::math::lgamma(y, pol));
  1600. }
  1601. if(y < 1)
  1602. {
  1603. if(x < 2 * max_factorial<T>::value)
  1604. {
  1605. // We need to sidestep on y as well, otherwise we'll overflow
  1606. // before we get to factor in the prefix term:
  1607. prefix *= y;
  1608. y += 1;
  1609. while(x >= max_factorial<T>::value)
  1610. {
  1611. x -= 1;
  1612. prefix *= x;
  1613. }
  1614. return prefix * boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
  1615. }
  1616. //
  1617. // Result will almost certainly overflow, try logs just in case:
  1618. //
  1619. return exp(boost::math::lgamma(x, pol) - boost::math::lgamma(y, pol));
  1620. }
  1621. //
  1622. // Regular case, x and y both large and similar in magnitude:
  1623. //
  1624. return boost::math::tgamma_delta_ratio(x, y - x, pol);
  1625. }
  1626. template <class T, class Policy>
  1627. T gamma_p_derivative_imp(T a, T x, const Policy& pol)
  1628. {
  1629. BOOST_MATH_STD_USING
  1630. //
  1631. // Usual error checks first:
  1632. //
  1633. if(a <= 0)
  1634. return policies::raise_domain_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", "Argument a to the incomplete gamma function must be greater than zero (got a=%1%).", a, pol);
  1635. if(x < 0)
  1636. return policies::raise_domain_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", "Argument x to the incomplete gamma function must be >= 0 (got x=%1%).", x, pol);
  1637. //
  1638. // Now special cases:
  1639. //
  1640. if(x == 0)
  1641. {
  1642. return (a > 1) ? 0 :
  1643. (a == 1) ? 1 : policies::raise_overflow_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", nullptr, pol);
  1644. }
  1645. //
  1646. // Normal case:
  1647. //
  1648. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  1649. T f1 = detail::regularised_gamma_prefix(a, x, pol, lanczos_type());
  1650. if((x < 1) && (tools::max_value<T>() * x < f1))
  1651. {
  1652. // overflow:
  1653. return policies::raise_overflow_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", nullptr, pol);
  1654. }
  1655. if(f1 == 0)
  1656. {
  1657. // Underflow in calculation, use logs instead:
  1658. f1 = a * log(x) - x - lgamma(a, pol) - log(x);
  1659. f1 = exp(f1);
  1660. }
  1661. else
  1662. f1 /= x;
  1663. return f1;
  1664. }
  1665. template <class T, class Policy>
  1666. inline typename tools::promote_args<T>::type
  1667. tgamma(T z, const Policy& /* pol */, const std::true_type)
  1668. {
  1669. BOOST_FPU_EXCEPTION_GUARD
  1670. typedef typename tools::promote_args<T>::type result_type;
  1671. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1672. typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1673. typedef typename policies::normalise<
  1674. Policy,
  1675. policies::promote_float<false>,
  1676. policies::promote_double<false>,
  1677. policies::discrete_quantile<>,
  1678. policies::assert_undefined<> >::type forwarding_policy;
  1679. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::gamma_imp(static_cast<value_type>(z), forwarding_policy(), evaluation_type()), "boost::math::tgamma<%1%>(%1%)");
  1680. }
  1681. template <class T, class Policy>
  1682. struct igamma_initializer
  1683. {
  1684. struct init
  1685. {
  1686. init()
  1687. {
  1688. typedef typename policies::precision<T, Policy>::type precision_type;
  1689. typedef std::integral_constant<int,
  1690. precision_type::value <= 0 ? 0 :
  1691. precision_type::value <= 53 ? 53 :
  1692. precision_type::value <= 64 ? 64 :
  1693. precision_type::value <= 113 ? 113 : 0
  1694. > tag_type;
  1695. do_init(tag_type());
  1696. }
  1697. template <int N>
  1698. static void do_init(const std::integral_constant<int, N>&)
  1699. {
  1700. // If std::numeric_limits<T>::digits is zero, we must not call
  1701. // our initialization code here as the precision presumably
  1702. // varies at runtime, and will not have been set yet. Plus the
  1703. // code requiring initialization isn't called when digits == 0.
  1704. if(std::numeric_limits<T>::digits)
  1705. {
  1706. boost::math::gamma_p(static_cast<T>(400), static_cast<T>(400), Policy());
  1707. }
  1708. }
  1709. static void do_init(const std::integral_constant<int, 53>&){}
  1710. void force_instantiate()const{}
  1711. };
  1712. static const init initializer;
  1713. static void force_instantiate()
  1714. {
  1715. initializer.force_instantiate();
  1716. }
  1717. };
  1718. template <class T, class Policy>
  1719. const typename igamma_initializer<T, Policy>::init igamma_initializer<T, Policy>::initializer;
  1720. template <class T, class Policy>
  1721. struct lgamma_initializer
  1722. {
  1723. struct init
  1724. {
  1725. init()
  1726. {
  1727. typedef typename policies::precision<T, Policy>::type precision_type;
  1728. typedef std::integral_constant<int,
  1729. precision_type::value <= 0 ? 0 :
  1730. precision_type::value <= 64 ? 64 :
  1731. precision_type::value <= 113 ? 113 : 0
  1732. > tag_type;
  1733. do_init(tag_type());
  1734. }
  1735. static void do_init(const std::integral_constant<int, 64>&)
  1736. {
  1737. boost::math::lgamma(static_cast<T>(2.5), Policy());
  1738. boost::math::lgamma(static_cast<T>(1.25), Policy());
  1739. boost::math::lgamma(static_cast<T>(1.75), Policy());
  1740. }
  1741. static void do_init(const std::integral_constant<int, 113>&)
  1742. {
  1743. boost::math::lgamma(static_cast<T>(2.5), Policy());
  1744. boost::math::lgamma(static_cast<T>(1.25), Policy());
  1745. boost::math::lgamma(static_cast<T>(1.5), Policy());
  1746. boost::math::lgamma(static_cast<T>(1.75), Policy());
  1747. }
  1748. static void do_init(const std::integral_constant<int, 0>&)
  1749. {
  1750. }
  1751. void force_instantiate()const{}
  1752. };
  1753. static const init initializer;
  1754. static void force_instantiate()
  1755. {
  1756. initializer.force_instantiate();
  1757. }
  1758. };
  1759. template <class T, class Policy>
  1760. const typename lgamma_initializer<T, Policy>::init lgamma_initializer<T, Policy>::initializer;
  1761. template <class T1, class T2, class Policy>
  1762. inline tools::promote_args_t<T1, T2>
  1763. tgamma(T1 a, T2 z, const Policy&, const std::false_type)
  1764. {
  1765. BOOST_FPU_EXCEPTION_GUARD
  1766. typedef tools::promote_args_t<T1, T2> result_type;
  1767. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1768. // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1769. typedef typename policies::normalise<
  1770. Policy,
  1771. policies::promote_float<false>,
  1772. policies::promote_double<false>,
  1773. policies::discrete_quantile<>,
  1774. policies::assert_undefined<> >::type forwarding_policy;
  1775. igamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1776. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  1777. detail::gamma_incomplete_imp(static_cast<value_type>(a),
  1778. static_cast<value_type>(z), false, true,
  1779. forwarding_policy(), static_cast<value_type*>(nullptr)), "boost::math::tgamma<%1%>(%1%, %1%)");
  1780. }
  1781. template <class T1, class T2>
  1782. inline tools::promote_args_t<T1, T2>
  1783. tgamma(T1 a, T2 z, const std::false_type& tag)
  1784. {
  1785. return tgamma(a, z, policies::policy<>(), tag);
  1786. }
  1787. } // namespace detail
  1788. template <class T>
  1789. inline typename tools::promote_args<T>::type
  1790. tgamma(T z)
  1791. {
  1792. return tgamma(z, policies::policy<>());
  1793. }
  1794. template <class T, class Policy>
  1795. inline typename tools::promote_args<T>::type
  1796. lgamma(T z, int* sign, const Policy&)
  1797. {
  1798. BOOST_FPU_EXCEPTION_GUARD
  1799. typedef typename tools::promote_args<T>::type result_type;
  1800. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1801. typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1802. typedef typename policies::normalise<
  1803. Policy,
  1804. policies::promote_float<false>,
  1805. policies::promote_double<false>,
  1806. policies::discrete_quantile<>,
  1807. policies::assert_undefined<> >::type forwarding_policy;
  1808. detail::lgamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1809. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::lgamma_imp(static_cast<value_type>(z), forwarding_policy(), evaluation_type(), sign), "boost::math::lgamma<%1%>(%1%)");
  1810. }
  1811. template <class T>
  1812. inline typename tools::promote_args<T>::type
  1813. lgamma(T z, int* sign)
  1814. {
  1815. return lgamma(z, sign, policies::policy<>());
  1816. }
  1817. template <class T, class Policy>
  1818. inline typename tools::promote_args<T>::type
  1819. lgamma(T x, const Policy& pol)
  1820. {
  1821. return ::boost::math::lgamma(x, nullptr, pol);
  1822. }
  1823. template <class T>
  1824. inline typename tools::promote_args<T>::type
  1825. lgamma(T x)
  1826. {
  1827. return ::boost::math::lgamma(x, nullptr, policies::policy<>());
  1828. }
  1829. template <class T, class Policy>
  1830. inline typename tools::promote_args<T>::type
  1831. tgamma1pm1(T z, const Policy& /* pol */)
  1832. {
  1833. BOOST_FPU_EXCEPTION_GUARD
  1834. typedef typename tools::promote_args<T>::type result_type;
  1835. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1836. typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1837. typedef typename policies::normalise<
  1838. Policy,
  1839. policies::promote_float<false>,
  1840. policies::promote_double<false>,
  1841. policies::discrete_quantile<>,
  1842. policies::assert_undefined<> >::type forwarding_policy;
  1843. return policies::checked_narrowing_cast<typename std::remove_cv<result_type>::type, forwarding_policy>(detail::tgammap1m1_imp(static_cast<value_type>(z), forwarding_policy(), evaluation_type()), "boost::math::tgamma1pm1<%!%>(%1%)");
  1844. }
  1845. template <class T>
  1846. inline typename tools::promote_args<T>::type
  1847. tgamma1pm1(T z)
  1848. {
  1849. return tgamma1pm1(z, policies::policy<>());
  1850. }
  1851. //
  1852. // Full upper incomplete gamma:
  1853. //
  1854. template <class T1, class T2>
  1855. inline tools::promote_args_t<T1, T2>
  1856. tgamma(T1 a, T2 z)
  1857. {
  1858. //
  1859. // Type T2 could be a policy object, or a value, select the
  1860. // right overload based on T2:
  1861. //
  1862. using maybe_policy = typename policies::is_policy<T2>::type;
  1863. using result_type = tools::promote_args_t<T1, T2>;
  1864. return static_cast<result_type>(detail::tgamma(a, z, maybe_policy()));
  1865. }
  1866. template <class T1, class T2, class Policy>
  1867. inline tools::promote_args_t<T1, T2>
  1868. tgamma(T1 a, T2 z, const Policy& pol)
  1869. {
  1870. using result_type = tools::promote_args_t<T1, T2>;
  1871. return static_cast<result_type>(detail::tgamma(a, z, pol, std::false_type()));
  1872. }
  1873. //
  1874. // Full lower incomplete gamma:
  1875. //
  1876. template <class T1, class T2, class Policy>
  1877. inline tools::promote_args_t<T1, T2>
  1878. tgamma_lower(T1 a, T2 z, const Policy&)
  1879. {
  1880. BOOST_FPU_EXCEPTION_GUARD
  1881. typedef tools::promote_args_t<T1, T2> result_type;
  1882. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1883. // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1884. typedef typename policies::normalise<
  1885. Policy,
  1886. policies::promote_float<false>,
  1887. policies::promote_double<false>,
  1888. policies::discrete_quantile<>,
  1889. policies::assert_undefined<> >::type forwarding_policy;
  1890. detail::igamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1891. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  1892. detail::gamma_incomplete_imp(static_cast<value_type>(a),
  1893. static_cast<value_type>(z), false, false,
  1894. forwarding_policy(), static_cast<value_type*>(nullptr)), "tgamma_lower<%1%>(%1%, %1%)");
  1895. }
  1896. template <class T1, class T2>
  1897. inline tools::promote_args_t<T1, T2>
  1898. tgamma_lower(T1 a, T2 z)
  1899. {
  1900. return tgamma_lower(a, z, policies::policy<>());
  1901. }
  1902. //
  1903. // Regularised upper incomplete gamma:
  1904. //
  1905. template <class T1, class T2, class Policy>
  1906. inline tools::promote_args_t<T1, T2>
  1907. gamma_q(T1 a, T2 z, const Policy& /* pol */)
  1908. {
  1909. BOOST_FPU_EXCEPTION_GUARD
  1910. typedef tools::promote_args_t<T1, T2> result_type;
  1911. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1912. // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1913. typedef typename policies::normalise<
  1914. Policy,
  1915. policies::promote_float<false>,
  1916. policies::promote_double<false>,
  1917. policies::discrete_quantile<>,
  1918. policies::assert_undefined<> >::type forwarding_policy;
  1919. detail::igamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1920. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  1921. detail::gamma_incomplete_imp(static_cast<value_type>(a),
  1922. static_cast<value_type>(z), true, true,
  1923. forwarding_policy(), static_cast<value_type*>(nullptr)), "gamma_q<%1%>(%1%, %1%)");
  1924. }
  1925. template <class T1, class T2>
  1926. inline tools::promote_args_t<T1, T2>
  1927. gamma_q(T1 a, T2 z)
  1928. {
  1929. return gamma_q(a, z, policies::policy<>());
  1930. }
  1931. //
  1932. // Regularised lower incomplete gamma:
  1933. //
  1934. template <class T1, class T2, class Policy>
  1935. inline tools::promote_args_t<T1, T2>
  1936. gamma_p(T1 a, T2 z, const Policy&)
  1937. {
  1938. BOOST_FPU_EXCEPTION_GUARD
  1939. typedef tools::promote_args_t<T1, T2> result_type;
  1940. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1941. // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1942. typedef typename policies::normalise<
  1943. Policy,
  1944. policies::promote_float<false>,
  1945. policies::promote_double<false>,
  1946. policies::discrete_quantile<>,
  1947. policies::assert_undefined<> >::type forwarding_policy;
  1948. detail::igamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1949. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  1950. detail::gamma_incomplete_imp(static_cast<value_type>(a),
  1951. static_cast<value_type>(z), true, false,
  1952. forwarding_policy(), static_cast<value_type*>(nullptr)), "gamma_p<%1%>(%1%, %1%)");
  1953. }
  1954. template <class T1, class T2>
  1955. inline tools::promote_args_t<T1, T2>
  1956. gamma_p(T1 a, T2 z)
  1957. {
  1958. return gamma_p(a, z, policies::policy<>());
  1959. }
  1960. // ratios of gamma functions:
  1961. template <class T1, class T2, class Policy>
  1962. inline tools::promote_args_t<T1, T2>
  1963. tgamma_delta_ratio(T1 z, T2 delta, const Policy& /* pol */)
  1964. {
  1965. BOOST_FPU_EXCEPTION_GUARD
  1966. typedef tools::promote_args_t<T1, T2> result_type;
  1967. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1968. typedef typename policies::normalise<
  1969. Policy,
  1970. policies::promote_float<false>,
  1971. policies::promote_double<false>,
  1972. policies::discrete_quantile<>,
  1973. policies::assert_undefined<> >::type forwarding_policy;
  1974. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::tgamma_delta_ratio_imp(static_cast<value_type>(z), static_cast<value_type>(delta), forwarding_policy()), "boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)");
  1975. }
  1976. template <class T1, class T2>
  1977. inline tools::promote_args_t<T1, T2>
  1978. tgamma_delta_ratio(T1 z, T2 delta)
  1979. {
  1980. return tgamma_delta_ratio(z, delta, policies::policy<>());
  1981. }
  1982. template <class T1, class T2, class Policy>
  1983. inline tools::promote_args_t<T1, T2>
  1984. tgamma_ratio(T1 a, T2 b, const Policy&)
  1985. {
  1986. typedef tools::promote_args_t<T1, T2> result_type;
  1987. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1988. typedef typename policies::normalise<
  1989. Policy,
  1990. policies::promote_float<false>,
  1991. policies::promote_double<false>,
  1992. policies::discrete_quantile<>,
  1993. policies::assert_undefined<> >::type forwarding_policy;
  1994. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::tgamma_ratio_imp(static_cast<value_type>(a), static_cast<value_type>(b), forwarding_policy()), "boost::math::tgamma_delta_ratio<%1%>(%1%, %1%)");
  1995. }
  1996. template <class T1, class T2>
  1997. inline tools::promote_args_t<T1, T2>
  1998. tgamma_ratio(T1 a, T2 b)
  1999. {
  2000. return tgamma_ratio(a, b, policies::policy<>());
  2001. }
  2002. template <class T1, class T2, class Policy>
  2003. inline tools::promote_args_t<T1, T2>
  2004. gamma_p_derivative(T1 a, T2 x, const Policy&)
  2005. {
  2006. BOOST_FPU_EXCEPTION_GUARD
  2007. typedef tools::promote_args_t<T1, T2> result_type;
  2008. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  2009. typedef typename policies::normalise<
  2010. Policy,
  2011. policies::promote_float<false>,
  2012. policies::promote_double<false>,
  2013. policies::discrete_quantile<>,
  2014. policies::assert_undefined<> >::type forwarding_policy;
  2015. return policies::checked_narrowing_cast<result_type, forwarding_policy>(detail::gamma_p_derivative_imp(static_cast<value_type>(a), static_cast<value_type>(x), forwarding_policy()), "boost::math::gamma_p_derivative<%1%>(%1%, %1%)");
  2016. }
  2017. template <class T1, class T2>
  2018. inline tools::promote_args_t<T1, T2>
  2019. gamma_p_derivative(T1 a, T2 x)
  2020. {
  2021. return gamma_p_derivative(a, x, policies::policy<>());
  2022. }
  2023. } // namespace math
  2024. } // namespace boost
  2025. #ifdef _MSC_VER
  2026. # pragma warning(pop)
  2027. #endif
  2028. #include <boost/math/special_functions/detail/igamma_inverse.hpp>
  2029. #include <boost/math/special_functions/detail/gamma_inva.hpp>
  2030. #include <boost/math/special_functions/erf.hpp>
  2031. #endif // BOOST_MATH_SF_GAMMA_HPP