gamma.hpp 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209
  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
  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/config.hpp>
  14. #include <boost/math/tools/series.hpp>
  15. #include <boost/math/tools/fraction.hpp>
  16. #include <boost/math/tools/precision.hpp>
  17. #include <boost/math/tools/promotion.hpp>
  18. #include <boost/math/policies/error_handling.hpp>
  19. #include <boost/math/constants/constants.hpp>
  20. #include <boost/math/special_functions/math_fwd.hpp>
  21. #include <boost/math/special_functions/log1p.hpp>
  22. #include <boost/math/special_functions/trunc.hpp>
  23. #include <boost/math/special_functions/powm1.hpp>
  24. #include <boost/math/special_functions/sqrt1pm1.hpp>
  25. #include <boost/math/special_functions/lanczos.hpp>
  26. #include <boost/math/special_functions/fpclassify.hpp>
  27. #include <boost/math/special_functions/detail/igamma_large.hpp>
  28. #include <boost/math/special_functions/detail/unchecked_factorial.hpp>
  29. #include <boost/math/special_functions/detail/lgamma_small.hpp>
  30. #include <boost/math/special_functions/bernoulli.hpp>
  31. #include <boost/math/special_functions/polygamma.hpp>
  32. #include <boost/type_traits/is_convertible.hpp>
  33. #include <boost/assert.hpp>
  34. #include <cmath>
  35. #include <algorithm>
  36. #ifdef BOOST_MSVC
  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. // Several variables made comments,
  42. // but some difficulty as whether referenced on not may depend on macro values.
  43. // So to be safe, 4100 warnings suppressed.
  44. // TODO - revisit this?
  45. #endif
  46. namespace boost{ namespace math{
  47. namespace detail{
  48. template <class T>
  49. inline bool is_odd(T v, const std::true_type&)
  50. {
  51. int i = static_cast<int>(v);
  52. return i&1;
  53. }
  54. template <class T>
  55. inline bool is_odd(T v, const std::false_type&)
  56. {
  57. // Oh dear can't cast T to int!
  58. BOOST_MATH_STD_USING
  59. T modulus = v - 2 * floor(v/2);
  60. return static_cast<bool>(modulus != 0);
  61. }
  62. template <class T>
  63. inline bool is_odd(T v)
  64. {
  65. return is_odd(v, ::std::is_convertible<T, int>());
  66. }
  67. template <class T>
  68. T sinpx(T z)
  69. {
  70. // Ad hoc function calculates x * sin(pi * x),
  71. // taking extra care near when x is near a whole number.
  72. BOOST_MATH_STD_USING
  73. int sign = 1;
  74. if(z < 0)
  75. {
  76. z = -z;
  77. }
  78. T fl = floor(z);
  79. T dist;
  80. if(is_odd(fl))
  81. {
  82. fl += 1;
  83. dist = fl - z;
  84. sign = -sign;
  85. }
  86. else
  87. {
  88. dist = z - fl;
  89. }
  90. BOOST_ASSERT(fl >= 0);
  91. if(dist > 0.5)
  92. dist = 1 - dist;
  93. T result = sin(dist*boost::math::constants::pi<T>());
  94. return sign*z*result;
  95. } // template <class T> T sinpx(T z)
  96. //
  97. // tgamma(z), with Lanczos support:
  98. //
  99. template <class T, class Policy, class Lanczos>
  100. T gamma_imp(T z, const Policy& pol, const Lanczos& l)
  101. {
  102. BOOST_MATH_STD_USING
  103. T result = 1;
  104. #ifdef BOOST_MATH_INSTRUMENT
  105. static bool b = false;
  106. if(!b)
  107. {
  108. std::cout << "tgamma_imp called with " << typeid(z).name() << " " << typeid(l).name() << std::endl;
  109. b = true;
  110. }
  111. #endif
  112. static const char* function = "boost::math::tgamma<%1%>(%1%)";
  113. if(z <= 0)
  114. {
  115. if(floor(z) == z)
  116. return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol);
  117. if(z <= -20)
  118. {
  119. result = gamma_imp(T(-z), pol, l) * sinpx(z);
  120. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  121. if((fabs(result) < 1) && (tools::max_value<T>() * fabs(result) < boost::math::constants::pi<T>()))
  122. return -boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
  123. result = -boost::math::constants::pi<T>() / result;
  124. if(result == 0)
  125. return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol);
  126. if((boost::math::fpclassify)(result) == (int)FP_SUBNORMAL)
  127. return policies::raise_denorm_error<T>(function, "Result of tgamma is denormalized.", result, pol);
  128. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  129. return result;
  130. }
  131. // shift z to > 1:
  132. while(z < 0)
  133. {
  134. result /= z;
  135. z += 1;
  136. }
  137. }
  138. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  139. if((floor(z) == z) && (z < max_factorial<T>::value))
  140. {
  141. result *= unchecked_factorial<T>(itrunc(z, pol) - 1);
  142. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  143. }
  144. else if (z < tools::root_epsilon<T>())
  145. {
  146. if (z < 1 / tools::max_value<T>())
  147. result = policies::raise_overflow_error<T>(function, 0, pol);
  148. result *= 1 / z - constants::euler<T>();
  149. }
  150. else
  151. {
  152. result *= Lanczos::lanczos_sum(z);
  153. T zgh = (z + static_cast<T>(Lanczos::g()) - boost::math::constants::half<T>());
  154. T lzgh = log(zgh);
  155. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  156. BOOST_MATH_INSTRUMENT_VARIABLE(tools::log_max_value<T>());
  157. if(z * lzgh > tools::log_max_value<T>())
  158. {
  159. // we're going to overflow unless this is done with care:
  160. BOOST_MATH_INSTRUMENT_VARIABLE(zgh);
  161. if(lzgh * z / 2 > tools::log_max_value<T>())
  162. return boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
  163. T hp = pow(zgh, (z / 2) - T(0.25));
  164. BOOST_MATH_INSTRUMENT_VARIABLE(hp);
  165. result *= hp / exp(zgh);
  166. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  167. if(tools::max_value<T>() / hp < result)
  168. return boost::math::sign(result) * policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
  169. result *= hp;
  170. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  171. }
  172. else
  173. {
  174. BOOST_MATH_INSTRUMENT_VARIABLE(zgh);
  175. BOOST_MATH_INSTRUMENT_VARIABLE(pow(zgh, z - boost::math::constants::half<T>()));
  176. BOOST_MATH_INSTRUMENT_VARIABLE(exp(zgh));
  177. result *= pow(zgh, z - boost::math::constants::half<T>()) / exp(zgh);
  178. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  179. }
  180. }
  181. return result;
  182. }
  183. //
  184. // lgamma(z) with Lanczos support:
  185. //
  186. template <class T, class Policy, class Lanczos>
  187. T lgamma_imp(T z, const Policy& pol, const Lanczos& l, int* sign = 0)
  188. {
  189. #ifdef BOOST_MATH_INSTRUMENT
  190. static bool b = false;
  191. if(!b)
  192. {
  193. std::cout << "lgamma_imp called with " << typeid(z).name() << " " << typeid(l).name() << std::endl;
  194. b = true;
  195. }
  196. #endif
  197. BOOST_MATH_STD_USING
  198. static const char* function = "boost::math::lgamma<%1%>(%1%)";
  199. T result = 0;
  200. int sresult = 1;
  201. if(z <= -tools::root_epsilon<T>())
  202. {
  203. // reflection formula:
  204. if(floor(z) == z)
  205. return policies::raise_pole_error<T>(function, "Evaluation of lgamma at a negative integer %1%.", z, pol);
  206. T t = sinpx(z);
  207. z = -z;
  208. if(t < 0)
  209. {
  210. t = -t;
  211. }
  212. else
  213. {
  214. sresult = -sresult;
  215. }
  216. result = log(boost::math::constants::pi<T>()) - lgamma_imp(z, pol, l) - log(t);
  217. }
  218. else if (z < tools::root_epsilon<T>())
  219. {
  220. if (0 == z)
  221. return policies::raise_pole_error<T>(function, "Evaluation of lgamma at %1%.", z, pol);
  222. if (4 * fabs(z) < tools::epsilon<T>())
  223. result = -log(fabs(z));
  224. else
  225. result = log(fabs(1 / z - constants::euler<T>()));
  226. if (z < 0)
  227. sresult = -1;
  228. }
  229. else if(z < 15)
  230. {
  231. typedef typename policies::precision<T, Policy>::type precision_type;
  232. typedef std::integral_constant<int,
  233. precision_type::value <= 0 ? 0 :
  234. precision_type::value <= 64 ? 64 :
  235. precision_type::value <= 113 ? 113 : 0
  236. > tag_type;
  237. result = lgamma_small_imp<T>(z, T(z - 1), T(z - 2), tag_type(), pol, l);
  238. }
  239. else if((z >= 3) && (z < 100) && (std::numeric_limits<T>::max_exponent >= 1024))
  240. {
  241. // taking the log of tgamma reduces the error, no danger of overflow here:
  242. result = log(gamma_imp(z, pol, l));
  243. }
  244. else
  245. {
  246. // regular evaluation:
  247. T zgh = static_cast<T>(z + Lanczos::g() - boost::math::constants::half<T>());
  248. result = log(zgh) - 1;
  249. result *= z - 0.5f;
  250. //
  251. // Only add on the lanczos sum part if we're going to need it:
  252. //
  253. if(result * tools::epsilon<T>() < 20)
  254. result += log(Lanczos::lanczos_sum_expG_scaled(z));
  255. }
  256. if(sign)
  257. *sign = sresult;
  258. return result;
  259. }
  260. //
  261. // Incomplete gamma functions follow:
  262. //
  263. template <class T>
  264. struct upper_incomplete_gamma_fract
  265. {
  266. private:
  267. T z, a;
  268. int k;
  269. public:
  270. typedef std::pair<T,T> result_type;
  271. upper_incomplete_gamma_fract(T a1, T z1)
  272. : z(z1-a1+1), a(a1), k(0)
  273. {
  274. }
  275. result_type operator()()
  276. {
  277. ++k;
  278. z += 2;
  279. return result_type(k * (a - k), z);
  280. }
  281. };
  282. template <class T>
  283. inline T upper_gamma_fraction(T a, T z, T eps)
  284. {
  285. // Multiply result by z^a * e^-z to get the full
  286. // upper incomplete integral. Divide by tgamma(z)
  287. // to normalise.
  288. upper_incomplete_gamma_fract<T> f(a, z);
  289. return 1 / (z - a + 1 + boost::math::tools::continued_fraction_a(f, eps));
  290. }
  291. template <class T>
  292. struct lower_incomplete_gamma_series
  293. {
  294. private:
  295. T a, z, result;
  296. public:
  297. typedef T result_type;
  298. lower_incomplete_gamma_series(T a1, T z1) : a(a1), z(z1), result(1){}
  299. T operator()()
  300. {
  301. T r = result;
  302. a += 1;
  303. result *= z/a;
  304. return r;
  305. }
  306. };
  307. template <class T, class Policy>
  308. inline T lower_gamma_series(T a, T z, const Policy& pol, T init_value = 0)
  309. {
  310. // Multiply result by ((z^a) * (e^-z) / a) to get the full
  311. // lower incomplete integral. Then divide by tgamma(a)
  312. // to get the normalised value.
  313. lower_incomplete_gamma_series<T> s(a, z);
  314. boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  315. T factor = policies::get_epsilon<T, Policy>();
  316. T result = boost::math::tools::sum_series(s, factor, max_iter, init_value);
  317. policies::check_series_iterations<T>("boost::math::detail::lower_gamma_series<%1%>(%1%)", max_iter, pol);
  318. return result;
  319. }
  320. //
  321. // Fully generic tgamma and lgamma use Stirling's approximation
  322. // with Bernoulli numbers.
  323. //
  324. template<class T>
  325. std::size_t highest_bernoulli_index()
  326. {
  327. const float digits10_of_type = (std::numeric_limits<T>::is_specialized
  328. ? static_cast<float>(std::numeric_limits<T>::digits10)
  329. : static_cast<float>(boost::math::tools::digits<T>() * 0.301F));
  330. // Find the high index n for Bn to produce the desired precision in Stirling's calculation.
  331. return static_cast<std::size_t>(18.0F + (0.6F * digits10_of_type));
  332. }
  333. template<class T>
  334. int minimum_argument_for_bernoulli_recursion()
  335. {
  336. BOOST_MATH_STD_USING
  337. const float digits10_of_type = (std::numeric_limits<T>::is_specialized
  338. ? (float) std::numeric_limits<T>::digits10
  339. : (float) (boost::math::tools::digits<T>() * 0.301F));
  340. int min_arg = (int) (digits10_of_type * 1.7F);
  341. if(digits10_of_type < 50.0F)
  342. {
  343. // The following code sequence has been modified
  344. // within the context of issue 396.
  345. // The calculation of the test-variable limit has now
  346. // been protected against overflow/underflow dangers.
  347. // The previous line looked like this and did, in fact,
  348. // underflow ldexp when using certain multiprecision types.
  349. // const float limit = std::ceil(std::pow(1.0f / std::ldexp(1.0f, 1-boost::math::tools::digits<T>()), 1.0f / 20.0f));
  350. // The new safe version of the limit check is now here.
  351. const float d2_minus_one = ((digits10_of_type / 0.301F) - 1.0F);
  352. const float limit = ceil(exp((d2_minus_one * log(2.0F)) / 20.0F));
  353. min_arg = (int) ((std::min)(digits10_of_type * 1.7F, limit));
  354. }
  355. return min_arg;
  356. }
  357. template <class T, class Policy>
  358. T scaled_tgamma_no_lanczos(const T& z, const Policy& pol, bool islog = false)
  359. {
  360. BOOST_MATH_STD_USING
  361. //
  362. // Calculates tgamma(z) / (z/e)^z
  363. // Requires that our argument is large enough for Sterling's approximation to hold.
  364. // Used internally when combining gamma's of similar magnitude without logarithms.
  365. //
  366. BOOST_ASSERT(minimum_argument_for_bernoulli_recursion<T>() <= z);
  367. // Perform the Bernoulli series expansion of Stirling's approximation.
  368. const std::size_t number_of_bernoullis_b2n = policies::get_max_series_iterations<Policy>();
  369. T one_over_x_pow_two_n_minus_one = 1 / z;
  370. const T one_over_x2 = one_over_x_pow_two_n_minus_one * one_over_x_pow_two_n_minus_one;
  371. T sum = (boost::math::bernoulli_b2n<T>(1) / 2) * one_over_x_pow_two_n_minus_one;
  372. const T target_epsilon_to_break_loop = sum * boost::math::tools::epsilon<T>();
  373. const T half_ln_two_pi_over_z = sqrt(boost::math::constants::two_pi<T>() / z);
  374. T last_term = 2 * sum;
  375. for (std::size_t n = 2U;; ++n)
  376. {
  377. one_over_x_pow_two_n_minus_one *= one_over_x2;
  378. const std::size_t n2 = static_cast<std::size_t>(n * 2U);
  379. const T term = (boost::math::bernoulli_b2n<T>(static_cast<int>(n)) * one_over_x_pow_two_n_minus_one) / (n2 * (n2 - 1U));
  380. if ((n >= 3U) && (abs(term) < target_epsilon_to_break_loop))
  381. {
  382. // We have reached the desired precision in Stirling's expansion.
  383. // Adding additional terms to the sum of this divergent asymptotic
  384. // expansion will not improve the result.
  385. // Break from the loop.
  386. break;
  387. }
  388. if (n > number_of_bernoullis_b2n)
  389. 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);
  390. sum += term;
  391. // Sanity check for divergence:
  392. T fterm = fabs(term);
  393. if(fterm > last_term)
  394. 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);
  395. last_term = fterm;
  396. }
  397. // Complete Stirling's approximation.
  398. T scaled_gamma_value = islog ? T(sum + log(half_ln_two_pi_over_z)) : T(exp(sum) * half_ln_two_pi_over_z);
  399. return scaled_gamma_value;
  400. }
  401. // Forward declaration of the lgamma_imp template specialization.
  402. template <class T, class Policy>
  403. T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sign = 0);
  404. template <class T, class Policy>
  405. T gamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&)
  406. {
  407. BOOST_MATH_STD_USING
  408. static const char* function = "boost::math::tgamma<%1%>(%1%)";
  409. // Check if the argument of tgamma is identically zero.
  410. const bool is_at_zero = (z == 0);
  411. if((boost::math::isnan)(z) || (is_at_zero) || ((boost::math::isinf)(z) && (z < 0)))
  412. return policies::raise_domain_error<T>(function, "Evaluation of tgamma at %1%.", z, pol);
  413. const bool b_neg = (z < 0);
  414. const bool floor_of_z_is_equal_to_z = (floor(z) == z);
  415. // Special case handling of small factorials:
  416. if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial<T>::value))
  417. {
  418. return boost::math::unchecked_factorial<T>(itrunc(z) - 1);
  419. }
  420. // Make a local, unsigned copy of the input argument.
  421. T zz((!b_neg) ? z : -z);
  422. // Special case for ultra-small z:
  423. if(zz < tools::cbrt_epsilon<T>())
  424. {
  425. const T a0(1);
  426. const T a1(boost::math::constants::euler<T>());
  427. const T six_euler_squared((boost::math::constants::euler<T>() * boost::math::constants::euler<T>()) * 6);
  428. const T a2((six_euler_squared - boost::math::constants::pi_sqr<T>()) / 12);
  429. const T inverse_tgamma_series = z * ((a2 * z + a1) * z + a0);
  430. return 1 / inverse_tgamma_series;
  431. }
  432. // Scale the argument up for the calculation of lgamma,
  433. // and use downward recursion later for the final result.
  434. const int min_arg_for_recursion = minimum_argument_for_bernoulli_recursion<T>();
  435. int n_recur;
  436. if(zz < min_arg_for_recursion)
  437. {
  438. n_recur = boost::math::itrunc(min_arg_for_recursion - zz) + 1;
  439. zz += n_recur;
  440. }
  441. else
  442. {
  443. n_recur = 0;
  444. }
  445. if (!n_recur)
  446. {
  447. if (zz > tools::log_max_value<T>())
  448. return policies::raise_overflow_error<T>(function, 0, pol);
  449. if (log(zz) * zz / 2 > tools::log_max_value<T>())
  450. return policies::raise_overflow_error<T>(function, 0, pol);
  451. }
  452. T gamma_value = scaled_tgamma_no_lanczos(zz, pol);
  453. T power_term = pow(zz, zz / 2);
  454. T exp_term = exp(-zz);
  455. gamma_value *= (power_term * exp_term);
  456. if(!n_recur && (tools::max_value<T>() / power_term < gamma_value))
  457. return policies::raise_overflow_error<T>(function, 0, pol);
  458. gamma_value *= power_term;
  459. // Rescale the result using downward recursion if necessary.
  460. if(n_recur)
  461. {
  462. // The order of divides is important, if we keep subtracting 1 from zz
  463. // we DO NOT get back to z (cancellation error). Further if z < epsilon
  464. // we would end up dividing by zero. Also in order to prevent spurious
  465. // overflow with the first division, we must save dividing by |z| till last,
  466. // so the optimal order of divides is z+1, z+2, z+3...z+n_recur-1,z.
  467. zz = fabs(z) + 1;
  468. for(int k = 1; k < n_recur; ++k)
  469. {
  470. gamma_value /= zz;
  471. zz += 1;
  472. }
  473. gamma_value /= fabs(z);
  474. }
  475. // Return the result, accounting for possible negative arguments.
  476. if(b_neg)
  477. {
  478. // Provide special error analysis for:
  479. // * arguments in the neighborhood of a negative integer
  480. // * arguments exactly equal to a negative integer.
  481. // Check if the argument of tgamma is exactly equal to a negative integer.
  482. if(floor_of_z_is_equal_to_z)
  483. return policies::raise_pole_error<T>(function, "Evaluation of tgamma at a negative integer %1%.", z, pol);
  484. gamma_value *= sinpx(z);
  485. BOOST_MATH_INSTRUMENT_VARIABLE(gamma_value);
  486. const bool result_is_too_large_to_represent = ( (abs(gamma_value) < 1)
  487. && ((tools::max_value<T>() * abs(gamma_value)) < boost::math::constants::pi<T>()));
  488. if(result_is_too_large_to_represent)
  489. return policies::raise_overflow_error<T>(function, "Result of tgamma is too large to represent.", pol);
  490. gamma_value = -boost::math::constants::pi<T>() / gamma_value;
  491. BOOST_MATH_INSTRUMENT_VARIABLE(gamma_value);
  492. if(gamma_value == 0)
  493. return policies::raise_underflow_error<T>(function, "Result of tgamma is too small to represent.", pol);
  494. if((boost::math::fpclassify)(gamma_value) == static_cast<int>(FP_SUBNORMAL))
  495. return policies::raise_denorm_error<T>(function, "Result of tgamma is denormalized.", gamma_value, pol);
  496. }
  497. return gamma_value;
  498. }
  499. template <class T, class Policy>
  500. inline T log_gamma_near_1(const T& z, Policy const& pol)
  501. {
  502. //
  503. // This is for the multiprecision case where there is
  504. // no lanczos support, use a taylor series at z = 1,
  505. // see https://www.wolframalpha.com/input/?i=taylor+series+lgamma(x)+at+x+%3D+1
  506. //
  507. BOOST_MATH_STD_USING // ADL of std names
  508. BOOST_ASSERT(fabs(z) < 1);
  509. T result = -constants::euler<T>() * z;
  510. T power_term = z * z / 2;
  511. int n = 2;
  512. T term = 0;
  513. do
  514. {
  515. term = power_term * boost::math::polygamma(n - 1, T(1), pol);
  516. result += term;
  517. ++n;
  518. power_term *= z / n;
  519. } while (fabs(result) * tools::epsilon<T>() < fabs(term));
  520. return result;
  521. }
  522. template <class T, class Policy>
  523. T lgamma_imp(T z, const Policy& pol, const lanczos::undefined_lanczos&, int* sign)
  524. {
  525. BOOST_MATH_STD_USING
  526. static const char* function = "boost::math::lgamma<%1%>(%1%)";
  527. // Check if the argument of lgamma is identically zero.
  528. const bool is_at_zero = (z == 0);
  529. if(is_at_zero)
  530. return policies::raise_domain_error<T>(function, "Evaluation of lgamma at zero %1%.", z, pol);
  531. if((boost::math::isnan)(z))
  532. return policies::raise_domain_error<T>(function, "Evaluation of lgamma at %1%.", z, pol);
  533. if((boost::math::isinf)(z))
  534. return policies::raise_overflow_error<T>(function, 0, pol);
  535. const bool b_neg = (z < 0);
  536. const bool floor_of_z_is_equal_to_z = (floor(z) == z);
  537. // Special case handling of small factorials:
  538. if((!b_neg) && floor_of_z_is_equal_to_z && (z < boost::math::max_factorial<T>::value))
  539. {
  540. if (sign)
  541. *sign = 1;
  542. return log(boost::math::unchecked_factorial<T>(itrunc(z) - 1));
  543. }
  544. // Make a local, unsigned copy of the input argument.
  545. T zz((!b_neg) ? z : -z);
  546. const int min_arg_for_recursion = minimum_argument_for_bernoulli_recursion<T>();
  547. T log_gamma_value;
  548. if (zz < min_arg_for_recursion)
  549. {
  550. // Here we simply take the logarithm of tgamma(). This is somewhat
  551. // inefficient, but simple. The rationale is that the argument here
  552. // is relatively small and overflow is not expected to be likely.
  553. if (sign)
  554. * sign = 1;
  555. if(fabs(z - 1) < 0.25)
  556. {
  557. log_gamma_value = log_gamma_near_1(T(zz - 1), pol);
  558. }
  559. else if(fabs(z - 2) < 0.25)
  560. {
  561. log_gamma_value = log_gamma_near_1(T(zz - 2), pol) + log(zz - 1);
  562. }
  563. else if (z > -tools::root_epsilon<T>())
  564. {
  565. // Reflection formula may fail if z is very close to zero, let the series
  566. // expansion for tgamma close to zero do the work:
  567. if (sign)
  568. *sign = z < 0 ? -1 : 1;
  569. return log(abs(gamma_imp(z, pol, lanczos::undefined_lanczos())));
  570. }
  571. else
  572. {
  573. // No issue with spurious overflow in reflection formula,
  574. // just fall through to regular code:
  575. T g = gamma_imp(zz, pol, lanczos::undefined_lanczos());
  576. if (sign)
  577. {
  578. *sign = g < 0 ? -1 : 1;
  579. }
  580. log_gamma_value = log(abs(g));
  581. }
  582. }
  583. else
  584. {
  585. // Perform the Bernoulli series expansion of Stirling's approximation.
  586. T sum = scaled_tgamma_no_lanczos(zz, pol, true);
  587. log_gamma_value = zz * (log(zz) - 1) + sum;
  588. }
  589. int sign_of_result = 1;
  590. if(b_neg)
  591. {
  592. // Provide special error analysis if the argument is exactly
  593. // equal to a negative integer.
  594. // Check if the argument of lgamma is exactly equal to a negative integer.
  595. if(floor_of_z_is_equal_to_z)
  596. return policies::raise_pole_error<T>(function, "Evaluation of lgamma at a negative integer %1%.", z, pol);
  597. T t = sinpx(z);
  598. if(t < 0)
  599. {
  600. t = -t;
  601. }
  602. else
  603. {
  604. sign_of_result = -sign_of_result;
  605. }
  606. log_gamma_value = - log_gamma_value
  607. + log(boost::math::constants::pi<T>())
  608. - log(t);
  609. }
  610. if(sign != static_cast<int*>(0U)) { *sign = sign_of_result; }
  611. return log_gamma_value;
  612. }
  613. //
  614. // This helper calculates tgamma(dz+1)-1 without cancellation errors,
  615. // used by the upper incomplete gamma with z < 1:
  616. //
  617. template <class T, class Policy, class Lanczos>
  618. T tgammap1m1_imp(T dz, Policy const& pol, const Lanczos& l)
  619. {
  620. BOOST_MATH_STD_USING
  621. typedef typename policies::precision<T,Policy>::type precision_type;
  622. typedef std::integral_constant<int,
  623. precision_type::value <= 0 ? 0 :
  624. precision_type::value <= 64 ? 64 :
  625. precision_type::value <= 113 ? 113 : 0
  626. > tag_type;
  627. T result;
  628. if(dz < 0)
  629. {
  630. if(dz < -0.5)
  631. {
  632. // Best method is simply to subtract 1 from tgamma:
  633. result = boost::math::tgamma(1+dz, pol) - 1;
  634. BOOST_MATH_INSTRUMENT_CODE(result);
  635. }
  636. else
  637. {
  638. // Use expm1 on lgamma:
  639. result = boost::math::expm1(-boost::math::log1p(dz, pol)
  640. + lgamma_small_imp<T>(dz+2, dz + 1, dz, tag_type(), pol, l), pol);
  641. BOOST_MATH_INSTRUMENT_CODE(result);
  642. }
  643. }
  644. else
  645. {
  646. if(dz < 2)
  647. {
  648. // Use expm1 on lgamma:
  649. result = boost::math::expm1(lgamma_small_imp<T>(dz+1, dz, dz-1, tag_type(), pol, l), pol);
  650. BOOST_MATH_INSTRUMENT_CODE(result);
  651. }
  652. else
  653. {
  654. // Best method is simply to subtract 1 from tgamma:
  655. result = boost::math::tgamma(1+dz, pol) - 1;
  656. BOOST_MATH_INSTRUMENT_CODE(result);
  657. }
  658. }
  659. return result;
  660. }
  661. template <class T, class Policy>
  662. inline T tgammap1m1_imp(T z, Policy const& pol,
  663. const ::boost::math::lanczos::undefined_lanczos&)
  664. {
  665. BOOST_MATH_STD_USING // ADL of std names
  666. if(fabs(z) < 0.55)
  667. {
  668. return boost::math::expm1(log_gamma_near_1(z, pol));
  669. }
  670. return boost::math::expm1(boost::math::lgamma(1 + z, pol));
  671. }
  672. //
  673. // Series representation for upper fraction when z is small:
  674. //
  675. template <class T>
  676. struct small_gamma2_series
  677. {
  678. typedef T result_type;
  679. small_gamma2_series(T a_, T x_) : result(-x_), x(-x_), apn(a_+1), n(1){}
  680. T operator()()
  681. {
  682. T r = result / (apn);
  683. result *= x;
  684. result /= ++n;
  685. apn += 1;
  686. return r;
  687. }
  688. private:
  689. T result, x, apn;
  690. int n;
  691. };
  692. //
  693. // calculate power term prefix (z^a)(e^-z) used in the non-normalised
  694. // incomplete gammas:
  695. //
  696. template <class T, class Policy>
  697. T full_igamma_prefix(T a, T z, const Policy& pol)
  698. {
  699. BOOST_MATH_STD_USING
  700. T prefix;
  701. if (z > tools::max_value<T>())
  702. return 0;
  703. T alz = a * log(z);
  704. if(z >= 1)
  705. {
  706. if((alz < tools::log_max_value<T>()) && (-z > tools::log_min_value<T>()))
  707. {
  708. prefix = pow(z, a) * exp(-z);
  709. }
  710. else if(a >= 1)
  711. {
  712. prefix = pow(z / exp(z/a), a);
  713. }
  714. else
  715. {
  716. prefix = exp(alz - z);
  717. }
  718. }
  719. else
  720. {
  721. if(alz > tools::log_min_value<T>())
  722. {
  723. prefix = pow(z, a) * exp(-z);
  724. }
  725. else if(z/a < tools::log_max_value<T>())
  726. {
  727. prefix = pow(z / exp(z/a), a);
  728. }
  729. else
  730. {
  731. prefix = exp(alz - z);
  732. }
  733. }
  734. //
  735. // This error handling isn't very good: it happens after the fact
  736. // rather than before it...
  737. //
  738. if((boost::math::fpclassify)(prefix) == (int)FP_INFINITE)
  739. 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);
  740. return prefix;
  741. }
  742. //
  743. // Compute (z^a)(e^-z)/tgamma(a)
  744. // most if the error occurs in this function:
  745. //
  746. template <class T, class Policy, class Lanczos>
  747. T regularised_gamma_prefix(T a, T z, const Policy& pol, const Lanczos& l)
  748. {
  749. BOOST_MATH_STD_USING
  750. if (z >= tools::max_value<T>())
  751. return 0;
  752. T agh = a + static_cast<T>(Lanczos::g()) - T(0.5);
  753. T prefix;
  754. T d = ((z - a) - static_cast<T>(Lanczos::g()) + T(0.5)) / agh;
  755. if(a < 1)
  756. {
  757. //
  758. // We have to treat a < 1 as a special case because our Lanczos
  759. // approximations are optimised against the factorials with a > 1,
  760. // and for high precision types especially (128-bit reals for example)
  761. // very small values of a can give rather erroneous results for gamma
  762. // unless we do this:
  763. //
  764. // TODO: is this still required? Lanczos approx should be better now?
  765. //
  766. if(z <= tools::log_min_value<T>())
  767. {
  768. // Oh dear, have to use logs, should be free of cancellation errors though:
  769. return exp(a * log(z) - z - lgamma_imp(a, pol, l));
  770. }
  771. else
  772. {
  773. // direct calculation, no danger of overflow as gamma(a) < 1/a
  774. // for small a.
  775. return pow(z, a) * exp(-z) / gamma_imp(a, pol, l);
  776. }
  777. }
  778. else if((fabs(d*d*a) <= 100) && (a > 150))
  779. {
  780. // special case for large a and a ~ z.
  781. prefix = a * boost::math::log1pmx(d, pol) + z * static_cast<T>(0.5 - Lanczos::g()) / agh;
  782. prefix = exp(prefix);
  783. }
  784. else
  785. {
  786. //
  787. // general case.
  788. // direct computation is most accurate, but use various fallbacks
  789. // for different parts of the problem domain:
  790. //
  791. T alz = a * log(z / agh);
  792. T amz = a - z;
  793. if(((std::min)(alz, amz) <= tools::log_min_value<T>()) || ((std::max)(alz, amz) >= tools::log_max_value<T>()))
  794. {
  795. T amza = amz / a;
  796. if(((std::min)(alz, amz)/2 > tools::log_min_value<T>()) && ((std::max)(alz, amz)/2 < tools::log_max_value<T>()))
  797. {
  798. // compute square root of the result and then square it:
  799. T sq = pow(z / agh, a / 2) * exp(amz / 2);
  800. prefix = sq * sq;
  801. }
  802. else if(((std::min)(alz, amz)/4 > tools::log_min_value<T>()) && ((std::max)(alz, amz)/4 < tools::log_max_value<T>()) && (z > a))
  803. {
  804. // compute the 4th root of the result then square it twice:
  805. T sq = pow(z / agh, a / 4) * exp(amz / 4);
  806. prefix = sq * sq;
  807. prefix *= prefix;
  808. }
  809. else if((amza > tools::log_min_value<T>()) && (amza < tools::log_max_value<T>()))
  810. {
  811. prefix = pow((z * exp(amza)) / agh, a);
  812. }
  813. else
  814. {
  815. prefix = exp(alz + amz);
  816. }
  817. }
  818. else
  819. {
  820. prefix = pow(z / agh, a) * exp(amz);
  821. }
  822. }
  823. prefix *= sqrt(agh / boost::math::constants::e<T>()) / Lanczos::lanczos_sum_expG_scaled(a);
  824. return prefix;
  825. }
  826. //
  827. // And again, without Lanczos support:
  828. //
  829. template <class T, class Policy>
  830. T regularised_gamma_prefix(T a, T z, const Policy& pol, const lanczos::undefined_lanczos& l)
  831. {
  832. BOOST_MATH_STD_USING
  833. if((a < 1) && (z < 1))
  834. {
  835. // No overflow possible since the power terms tend to unity as a,z -> 0
  836. return pow(z, a) * exp(-z) / boost::math::tgamma(a, pol);
  837. }
  838. else if(a > minimum_argument_for_bernoulli_recursion<T>())
  839. {
  840. T scaled_gamma = scaled_tgamma_no_lanczos(a, pol);
  841. T power_term = pow(z / a, a / 2);
  842. T a_minus_z = a - z;
  843. if ((0 == power_term) || (fabs(a_minus_z) > tools::log_max_value<T>()))
  844. {
  845. // The result is probably zero, but we need to be sure:
  846. return exp(a * log(z / a) + a_minus_z - log(scaled_gamma));
  847. }
  848. return (power_term * exp(a_minus_z)) * (power_term / scaled_gamma);
  849. }
  850. else
  851. {
  852. //
  853. // Usual case is to calculate the prefix at a+shift and recurse down
  854. // to the value we want:
  855. //
  856. const int min_z = minimum_argument_for_bernoulli_recursion<T>();
  857. long shift = 1 + ltrunc(min_z - a);
  858. T result = regularised_gamma_prefix(T(a + shift), z, pol, l);
  859. if (result != 0)
  860. {
  861. for (long i = 0; i < shift; ++i)
  862. {
  863. result /= z;
  864. result *= a + i;
  865. }
  866. return result;
  867. }
  868. else
  869. {
  870. //
  871. // We failed, most probably we have z << 1, try again, this time
  872. // we calculate z^a e^-z / tgamma(a+shift), combining power terms
  873. // as we go. And again recurse down to the result.
  874. //
  875. T scaled_gamma = scaled_tgamma_no_lanczos(T(a + shift), pol);
  876. T power_term_1 = pow(z / (a + shift), a);
  877. T power_term_2 = pow(a + shift, -shift);
  878. T power_term_3 = exp(a + shift - z);
  879. if ((0 == power_term_1) || (0 == power_term_2) || (0 == power_term_3) || (fabs(a + shift - z) > tools::log_max_value<T>()))
  880. {
  881. // We have no test case that gets here, most likely the type T
  882. // has a high precision but low exponent range:
  883. return exp(a * log(z) - z - boost::math::lgamma(a, pol));
  884. }
  885. result = power_term_1 * power_term_2 * power_term_3 / scaled_gamma;
  886. for (long i = 0; i < shift; ++i)
  887. {
  888. result *= a + i;
  889. }
  890. return result;
  891. }
  892. }
  893. }
  894. //
  895. // Upper gamma fraction for very small a:
  896. //
  897. template <class T, class Policy>
  898. inline T tgamma_small_upper_part(T a, T x, const Policy& pol, T* pgam = 0, bool invert = false, T* pderivative = 0)
  899. {
  900. BOOST_MATH_STD_USING // ADL of std functions.
  901. //
  902. // Compute the full upper fraction (Q) when a is very small:
  903. //
  904. T result;
  905. 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. boost::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. boost::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, 0, pol);
  1092. return exp(result);
  1093. }
  1094. BOOST_ASSERT((p_derivative == 0) || 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 < 0.5)
  1131. {
  1132. //
  1133. // Changeover criterion chosen to give a changeover at Q ~ 0.33
  1134. //
  1135. if(-0.4 / log(x) < a)
  1136. {
  1137. eval_method = 2;
  1138. }
  1139. else
  1140. {
  1141. eval_method = 3;
  1142. }
  1143. }
  1144. else if(x < 1.1)
  1145. {
  1146. //
  1147. // Changover 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*>(0));
  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_NO_EXCEPTIONS
  1336. try
  1337. {
  1338. result = pow(x, a) / boost::math::tgamma(a + 1, pol);
  1339. }
  1340. catch (const std::overflow_error&)
  1341. {
  1342. result = 0;
  1343. }
  1344. #else
  1345. result = pow(x, a) / boost::math::tgamma(a + 1, pol);
  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 + Lanczos::g() - constants::half<T>());
  1418. T result;
  1419. if(z + delta == z)
  1420. {
  1421. if(fabs(delta) < 10)
  1422. result = exp((constants::half<T>() - z) * boost::math::log1p(delta / zgh, pol));
  1423. else
  1424. result = 1;
  1425. }
  1426. else
  1427. {
  1428. if(fabs(delta) < 10)
  1429. {
  1430. result = exp((constants::half<T>() - z) * boost::math::log1p(delta / zgh, pol));
  1431. }
  1432. else
  1433. {
  1434. result = pow(zgh / (zgh + delta), z - constants::half<T>());
  1435. }
  1436. // Split the calculation up to avoid spurious overflow:
  1437. result *= Lanczos::lanczos_sum(z) / Lanczos::lanczos_sum(T(z + delta));
  1438. }
  1439. result *= pow(constants::e<T>() / (zgh + delta), delta);
  1440. return result;
  1441. }
  1442. //
  1443. // And again without Lanczos support this time:
  1444. //
  1445. template <class T, class Policy>
  1446. T tgamma_delta_ratio_imp_lanczos(T z, T delta, const Policy& pol, const lanczos::undefined_lanczos& l)
  1447. {
  1448. BOOST_MATH_STD_USING
  1449. //
  1450. // We adjust z and delta so that both z and z+delta are large enough for
  1451. // Sterling's approximation to hold. We can then calculate the ratio
  1452. // for the adjusted values, and rescale back down to z and z+delta.
  1453. //
  1454. // Get the required shifts first:
  1455. //
  1456. long numerator_shift = 0;
  1457. long denominator_shift = 0;
  1458. const int min_z = minimum_argument_for_bernoulli_recursion<T>();
  1459. if (min_z > z)
  1460. numerator_shift = 1 + ltrunc(min_z - z);
  1461. if (min_z > z + delta)
  1462. denominator_shift = 1 + ltrunc(min_z - z - delta);
  1463. //
  1464. // If the shifts are zero, then we can just combine scaled tgamma's
  1465. // and combine the remaining terms:
  1466. //
  1467. if (numerator_shift == 0 && denominator_shift == 0)
  1468. {
  1469. T scaled_tgamma_num = scaled_tgamma_no_lanczos(z, pol);
  1470. T scaled_tgamma_denom = scaled_tgamma_no_lanczos(T(z + delta), pol);
  1471. T result = scaled_tgamma_num / scaled_tgamma_denom;
  1472. result *= exp(z * boost::math::log1p(-delta / (z + delta), pol)) * pow((delta + z) / constants::e<T>(), -delta);
  1473. return result;
  1474. }
  1475. //
  1476. // We're going to have to rescale first, get the adjusted z and delta values,
  1477. // plus the ratio for the adjusted values:
  1478. //
  1479. T zz = z + numerator_shift;
  1480. T dd = delta - (numerator_shift - denominator_shift);
  1481. T ratio = tgamma_delta_ratio_imp_lanczos(zz, dd, pol, l);
  1482. //
  1483. // Use gamma recurrence relations to get back to the original
  1484. // z and z+delta:
  1485. //
  1486. for (long long i = 0; i < numerator_shift; ++i)
  1487. {
  1488. ratio /= (z + i);
  1489. if (i < denominator_shift)
  1490. ratio *= (z + delta + i);
  1491. }
  1492. for (long long i = numerator_shift; i < denominator_shift; ++i)
  1493. {
  1494. ratio *= (z + delta + i);
  1495. }
  1496. return ratio;
  1497. }
  1498. template <class T, class Policy>
  1499. T tgamma_delta_ratio_imp(T z, T delta, const Policy& pol)
  1500. {
  1501. BOOST_MATH_STD_USING
  1502. if((z <= 0) || (z + delta <= 0))
  1503. {
  1504. // This isn't very sophisticated, or accurate, but it does work:
  1505. return boost::math::tgamma(z, pol) / boost::math::tgamma(z + delta, pol);
  1506. }
  1507. if(floor(delta) == delta)
  1508. {
  1509. if(floor(z) == z)
  1510. {
  1511. //
  1512. // Both z and delta are integers, see if we can just use table lookup
  1513. // of the factorials to get the result:
  1514. //
  1515. if((z <= max_factorial<T>::value) && (z + delta <= max_factorial<T>::value))
  1516. {
  1517. return unchecked_factorial<T>((unsigned)itrunc(z, pol) - 1) / unchecked_factorial<T>((unsigned)itrunc(T(z + delta), pol) - 1);
  1518. }
  1519. }
  1520. if(fabs(delta) < 20)
  1521. {
  1522. //
  1523. // delta is a small integer, we can use a finite product:
  1524. //
  1525. if(delta == 0)
  1526. return 1;
  1527. if(delta < 0)
  1528. {
  1529. z -= 1;
  1530. T result = z;
  1531. while(0 != (delta += 1))
  1532. {
  1533. z -= 1;
  1534. result *= z;
  1535. }
  1536. return result;
  1537. }
  1538. else
  1539. {
  1540. T result = 1 / z;
  1541. while(0 != (delta -= 1))
  1542. {
  1543. z += 1;
  1544. result /= z;
  1545. }
  1546. return result;
  1547. }
  1548. }
  1549. }
  1550. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  1551. return tgamma_delta_ratio_imp_lanczos(z, delta, pol, lanczos_type());
  1552. }
  1553. template <class T, class Policy>
  1554. T tgamma_ratio_imp(T x, T y, const Policy& pol)
  1555. {
  1556. BOOST_MATH_STD_USING
  1557. if((x <= 0) || (boost::math::isinf)(x))
  1558. 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);
  1559. if((y <= 0) || (boost::math::isinf)(y))
  1560. 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);
  1561. if(x <= tools::min_value<T>())
  1562. {
  1563. // Special case for denorms...Ugh.
  1564. T shift = ldexp(T(1), tools::digits<T>());
  1565. return shift * tgamma_ratio_imp(T(x * shift), y, pol);
  1566. }
  1567. if((x < max_factorial<T>::value) && (y < max_factorial<T>::value))
  1568. {
  1569. // Rather than subtracting values, lets just call the gamma functions directly:
  1570. return boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
  1571. }
  1572. T prefix = 1;
  1573. if(x < 1)
  1574. {
  1575. if(y < 2 * max_factorial<T>::value)
  1576. {
  1577. // We need to sidestep on x as well, otherwise we'll underflow
  1578. // before we get to factor in the prefix term:
  1579. prefix /= x;
  1580. x += 1;
  1581. while(y >= max_factorial<T>::value)
  1582. {
  1583. y -= 1;
  1584. prefix /= y;
  1585. }
  1586. return prefix * boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
  1587. }
  1588. //
  1589. // result is almost certainly going to underflow to zero, try logs just in case:
  1590. //
  1591. return exp(boost::math::lgamma(x, pol) - boost::math::lgamma(y, pol));
  1592. }
  1593. if(y < 1)
  1594. {
  1595. if(x < 2 * max_factorial<T>::value)
  1596. {
  1597. // We need to sidestep on y as well, otherwise we'll overflow
  1598. // before we get to factor in the prefix term:
  1599. prefix *= y;
  1600. y += 1;
  1601. while(x >= max_factorial<T>::value)
  1602. {
  1603. x -= 1;
  1604. prefix *= x;
  1605. }
  1606. return prefix * boost::math::tgamma(x, pol) / boost::math::tgamma(y, pol);
  1607. }
  1608. //
  1609. // Result will almost certainly overflow, try logs just in case:
  1610. //
  1611. return exp(boost::math::lgamma(x, pol) - boost::math::lgamma(y, pol));
  1612. }
  1613. //
  1614. // Regular case, x and y both large and similar in magnitude:
  1615. //
  1616. return boost::math::tgamma_delta_ratio(x, y - x, pol);
  1617. }
  1618. template <class T, class Policy>
  1619. T gamma_p_derivative_imp(T a, T x, const Policy& pol)
  1620. {
  1621. BOOST_MATH_STD_USING
  1622. //
  1623. // Usual error checks first:
  1624. //
  1625. if(a <= 0)
  1626. 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);
  1627. if(x < 0)
  1628. 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);
  1629. //
  1630. // Now special cases:
  1631. //
  1632. if(x == 0)
  1633. {
  1634. return (a > 1) ? 0 :
  1635. (a == 1) ? 1 : policies::raise_overflow_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", 0, pol);
  1636. }
  1637. //
  1638. // Normal case:
  1639. //
  1640. typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
  1641. T f1 = detail::regularised_gamma_prefix(a, x, pol, lanczos_type());
  1642. if((x < 1) && (tools::max_value<T>() * x < f1))
  1643. {
  1644. // overflow:
  1645. return policies::raise_overflow_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", 0, pol);
  1646. }
  1647. if(f1 == 0)
  1648. {
  1649. // Underflow in calculation, use logs instead:
  1650. f1 = a * log(x) - x - lgamma(a, pol) - log(x);
  1651. f1 = exp(f1);
  1652. }
  1653. else
  1654. f1 /= x;
  1655. return f1;
  1656. }
  1657. template <class T, class Policy>
  1658. inline typename tools::promote_args<T>::type
  1659. tgamma(T z, const Policy& /* pol */, const std::true_type)
  1660. {
  1661. BOOST_FPU_EXCEPTION_GUARD
  1662. typedef typename tools::promote_args<T>::type result_type;
  1663. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1664. typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1665. typedef typename policies::normalise<
  1666. Policy,
  1667. policies::promote_float<false>,
  1668. policies::promote_double<false>,
  1669. policies::discrete_quantile<>,
  1670. policies::assert_undefined<> >::type forwarding_policy;
  1671. 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%)");
  1672. }
  1673. template <class T, class Policy>
  1674. struct igamma_initializer
  1675. {
  1676. struct init
  1677. {
  1678. init()
  1679. {
  1680. typedef typename policies::precision<T, Policy>::type precision_type;
  1681. typedef std::integral_constant<int,
  1682. precision_type::value <= 0 ? 0 :
  1683. precision_type::value <= 53 ? 53 :
  1684. precision_type::value <= 64 ? 64 :
  1685. precision_type::value <= 113 ? 113 : 0
  1686. > tag_type;
  1687. do_init(tag_type());
  1688. }
  1689. template <int N>
  1690. static void do_init(const std::integral_constant<int, N>&)
  1691. {
  1692. // If std::numeric_limits<T>::digits is zero, we must not call
  1693. // our initialization code here as the precision presumably
  1694. // varies at runtime, and will not have been set yet. Plus the
  1695. // code requiring initialization isn't called when digits == 0.
  1696. if(std::numeric_limits<T>::digits)
  1697. {
  1698. boost::math::gamma_p(static_cast<T>(400), static_cast<T>(400), Policy());
  1699. }
  1700. }
  1701. static void do_init(const std::integral_constant<int, 53>&){}
  1702. void force_instantiate()const{}
  1703. };
  1704. static const init initializer;
  1705. static void force_instantiate()
  1706. {
  1707. initializer.force_instantiate();
  1708. }
  1709. };
  1710. template <class T, class Policy>
  1711. const typename igamma_initializer<T, Policy>::init igamma_initializer<T, Policy>::initializer;
  1712. template <class T, class Policy>
  1713. struct lgamma_initializer
  1714. {
  1715. struct init
  1716. {
  1717. init()
  1718. {
  1719. typedef typename policies::precision<T, Policy>::type precision_type;
  1720. typedef std::integral_constant<int,
  1721. precision_type::value <= 0 ? 0 :
  1722. precision_type::value <= 64 ? 64 :
  1723. precision_type::value <= 113 ? 113 : 0
  1724. > tag_type;
  1725. do_init(tag_type());
  1726. }
  1727. static void do_init(const std::integral_constant<int, 64>&)
  1728. {
  1729. boost::math::lgamma(static_cast<T>(2.5), Policy());
  1730. boost::math::lgamma(static_cast<T>(1.25), Policy());
  1731. boost::math::lgamma(static_cast<T>(1.75), Policy());
  1732. }
  1733. static void do_init(const std::integral_constant<int, 113>&)
  1734. {
  1735. boost::math::lgamma(static_cast<T>(2.5), Policy());
  1736. boost::math::lgamma(static_cast<T>(1.25), Policy());
  1737. boost::math::lgamma(static_cast<T>(1.5), Policy());
  1738. boost::math::lgamma(static_cast<T>(1.75), Policy());
  1739. }
  1740. static void do_init(const std::integral_constant<int, 0>&)
  1741. {
  1742. }
  1743. void force_instantiate()const{}
  1744. };
  1745. static const init initializer;
  1746. static void force_instantiate()
  1747. {
  1748. initializer.force_instantiate();
  1749. }
  1750. };
  1751. template <class T, class Policy>
  1752. const typename lgamma_initializer<T, Policy>::init lgamma_initializer<T, Policy>::initializer;
  1753. template <class T1, class T2, class Policy>
  1754. inline typename tools::promote_args<T1, T2>::type
  1755. tgamma(T1 a, T2 z, const Policy&, const std::false_type)
  1756. {
  1757. BOOST_FPU_EXCEPTION_GUARD
  1758. typedef typename tools::promote_args<T1, T2>::type result_type;
  1759. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1760. // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1761. typedef typename policies::normalise<
  1762. Policy,
  1763. policies::promote_float<false>,
  1764. policies::promote_double<false>,
  1765. policies::discrete_quantile<>,
  1766. policies::assert_undefined<> >::type forwarding_policy;
  1767. igamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1768. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  1769. detail::gamma_incomplete_imp(static_cast<value_type>(a),
  1770. static_cast<value_type>(z), false, true,
  1771. forwarding_policy(), static_cast<value_type*>(0)), "boost::math::tgamma<%1%>(%1%, %1%)");
  1772. }
  1773. template <class T1, class T2>
  1774. inline typename tools::promote_args<T1, T2>::type
  1775. tgamma(T1 a, T2 z, const std::false_type& tag)
  1776. {
  1777. return tgamma(a, z, policies::policy<>(), tag);
  1778. }
  1779. } // namespace detail
  1780. template <class T>
  1781. inline typename tools::promote_args<T>::type
  1782. tgamma(T z)
  1783. {
  1784. return tgamma(z, policies::policy<>());
  1785. }
  1786. template <class T, class Policy>
  1787. inline typename tools::promote_args<T>::type
  1788. lgamma(T z, int* sign, const Policy&)
  1789. {
  1790. BOOST_FPU_EXCEPTION_GUARD
  1791. typedef typename tools::promote_args<T>::type result_type;
  1792. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1793. typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1794. typedef typename policies::normalise<
  1795. Policy,
  1796. policies::promote_float<false>,
  1797. policies::promote_double<false>,
  1798. policies::discrete_quantile<>,
  1799. policies::assert_undefined<> >::type forwarding_policy;
  1800. detail::lgamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1801. 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%)");
  1802. }
  1803. template <class T>
  1804. inline typename tools::promote_args<T>::type
  1805. lgamma(T z, int* sign)
  1806. {
  1807. return lgamma(z, sign, policies::policy<>());
  1808. }
  1809. template <class T, class Policy>
  1810. inline typename tools::promote_args<T>::type
  1811. lgamma(T x, const Policy& pol)
  1812. {
  1813. return ::boost::math::lgamma(x, 0, pol);
  1814. }
  1815. template <class T>
  1816. inline typename tools::promote_args<T>::type
  1817. lgamma(T x)
  1818. {
  1819. return ::boost::math::lgamma(x, 0, policies::policy<>());
  1820. }
  1821. template <class T, class Policy>
  1822. inline typename tools::promote_args<T>::type
  1823. tgamma1pm1(T z, const Policy& /* pol */)
  1824. {
  1825. BOOST_FPU_EXCEPTION_GUARD
  1826. typedef typename tools::promote_args<T>::type result_type;
  1827. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1828. typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1829. typedef typename policies::normalise<
  1830. Policy,
  1831. policies::promote_float<false>,
  1832. policies::promote_double<false>,
  1833. policies::discrete_quantile<>,
  1834. policies::assert_undefined<> >::type forwarding_policy;
  1835. return policies::checked_narrowing_cast<typename remove_cv<result_type>::type, forwarding_policy>(detail::tgammap1m1_imp(static_cast<value_type>(z), forwarding_policy(), evaluation_type()), "boost::math::tgamma1pm1<%!%>(%1%)");
  1836. }
  1837. template <class T>
  1838. inline typename tools::promote_args<T>::type
  1839. tgamma1pm1(T z)
  1840. {
  1841. return tgamma1pm1(z, policies::policy<>());
  1842. }
  1843. //
  1844. // Full upper incomplete gamma:
  1845. //
  1846. template <class T1, class T2>
  1847. inline typename tools::promote_args<T1, T2>::type
  1848. tgamma(T1 a, T2 z)
  1849. {
  1850. //
  1851. // Type T2 could be a policy object, or a value, select the
  1852. // right overload based on T2:
  1853. //
  1854. typedef typename policies::is_policy<T2>::type maybe_policy;
  1855. return detail::tgamma(a, z, maybe_policy());
  1856. }
  1857. template <class T1, class T2, class Policy>
  1858. inline typename tools::promote_args<T1, T2>::type
  1859. tgamma(T1 a, T2 z, const Policy& pol)
  1860. {
  1861. return detail::tgamma(a, z, pol, std::false_type());
  1862. }
  1863. //
  1864. // Full lower incomplete gamma:
  1865. //
  1866. template <class T1, class T2, class Policy>
  1867. inline typename tools::promote_args<T1, T2>::type
  1868. tgamma_lower(T1 a, T2 z, const Policy&)
  1869. {
  1870. BOOST_FPU_EXCEPTION_GUARD
  1871. typedef typename tools::promote_args<T1, T2>::type result_type;
  1872. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1873. // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1874. typedef typename policies::normalise<
  1875. Policy,
  1876. policies::promote_float<false>,
  1877. policies::promote_double<false>,
  1878. policies::discrete_quantile<>,
  1879. policies::assert_undefined<> >::type forwarding_policy;
  1880. detail::igamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1881. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  1882. detail::gamma_incomplete_imp(static_cast<value_type>(a),
  1883. static_cast<value_type>(z), false, false,
  1884. forwarding_policy(), static_cast<value_type*>(0)), "tgamma_lower<%1%>(%1%, %1%)");
  1885. }
  1886. template <class T1, class T2>
  1887. inline typename tools::promote_args<T1, T2>::type
  1888. tgamma_lower(T1 a, T2 z)
  1889. {
  1890. return tgamma_lower(a, z, policies::policy<>());
  1891. }
  1892. //
  1893. // Regularised upper incomplete gamma:
  1894. //
  1895. template <class T1, class T2, class Policy>
  1896. inline typename tools::promote_args<T1, T2>::type
  1897. gamma_q(T1 a, T2 z, const Policy& /* pol */)
  1898. {
  1899. BOOST_FPU_EXCEPTION_GUARD
  1900. typedef typename tools::promote_args<T1, T2>::type result_type;
  1901. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1902. // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1903. typedef typename policies::normalise<
  1904. Policy,
  1905. policies::promote_float<false>,
  1906. policies::promote_double<false>,
  1907. policies::discrete_quantile<>,
  1908. policies::assert_undefined<> >::type forwarding_policy;
  1909. detail::igamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1910. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  1911. detail::gamma_incomplete_imp(static_cast<value_type>(a),
  1912. static_cast<value_type>(z), true, true,
  1913. forwarding_policy(), static_cast<value_type*>(0)), "gamma_q<%1%>(%1%, %1%)");
  1914. }
  1915. template <class T1, class T2>
  1916. inline typename tools::promote_args<T1, T2>::type
  1917. gamma_q(T1 a, T2 z)
  1918. {
  1919. return gamma_q(a, z, policies::policy<>());
  1920. }
  1921. //
  1922. // Regularised lower incomplete gamma:
  1923. //
  1924. template <class T1, class T2, class Policy>
  1925. inline typename tools::promote_args<T1, T2>::type
  1926. gamma_p(T1 a, T2 z, const Policy&)
  1927. {
  1928. BOOST_FPU_EXCEPTION_GUARD
  1929. typedef typename tools::promote_args<T1, T2>::type result_type;
  1930. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1931. // typedef typename lanczos::lanczos<value_type, Policy>::type evaluation_type;
  1932. typedef typename policies::normalise<
  1933. Policy,
  1934. policies::promote_float<false>,
  1935. policies::promote_double<false>,
  1936. policies::discrete_quantile<>,
  1937. policies::assert_undefined<> >::type forwarding_policy;
  1938. detail::igamma_initializer<value_type, forwarding_policy>::force_instantiate();
  1939. return policies::checked_narrowing_cast<result_type, forwarding_policy>(
  1940. detail::gamma_incomplete_imp(static_cast<value_type>(a),
  1941. static_cast<value_type>(z), true, false,
  1942. forwarding_policy(), static_cast<value_type*>(0)), "gamma_p<%1%>(%1%, %1%)");
  1943. }
  1944. template <class T1, class T2>
  1945. inline typename tools::promote_args<T1, T2>::type
  1946. gamma_p(T1 a, T2 z)
  1947. {
  1948. return gamma_p(a, z, policies::policy<>());
  1949. }
  1950. // ratios of gamma functions:
  1951. template <class T1, class T2, class Policy>
  1952. inline typename tools::promote_args<T1, T2>::type
  1953. tgamma_delta_ratio(T1 z, T2 delta, const Policy& /* pol */)
  1954. {
  1955. BOOST_FPU_EXCEPTION_GUARD
  1956. typedef typename tools::promote_args<T1, T2>::type result_type;
  1957. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1958. typedef typename policies::normalise<
  1959. Policy,
  1960. policies::promote_float<false>,
  1961. policies::promote_double<false>,
  1962. policies::discrete_quantile<>,
  1963. policies::assert_undefined<> >::type forwarding_policy;
  1964. 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%)");
  1965. }
  1966. template <class T1, class T2>
  1967. inline typename tools::promote_args<T1, T2>::type
  1968. tgamma_delta_ratio(T1 z, T2 delta)
  1969. {
  1970. return tgamma_delta_ratio(z, delta, policies::policy<>());
  1971. }
  1972. template <class T1, class T2, class Policy>
  1973. inline typename tools::promote_args<T1, T2>::type
  1974. tgamma_ratio(T1 a, T2 b, const Policy&)
  1975. {
  1976. typedef typename tools::promote_args<T1, T2>::type result_type;
  1977. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1978. typedef typename policies::normalise<
  1979. Policy,
  1980. policies::promote_float<false>,
  1981. policies::promote_double<false>,
  1982. policies::discrete_quantile<>,
  1983. policies::assert_undefined<> >::type forwarding_policy;
  1984. 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%)");
  1985. }
  1986. template <class T1, class T2>
  1987. inline typename tools::promote_args<T1, T2>::type
  1988. tgamma_ratio(T1 a, T2 b)
  1989. {
  1990. return tgamma_ratio(a, b, policies::policy<>());
  1991. }
  1992. template <class T1, class T2, class Policy>
  1993. inline typename tools::promote_args<T1, T2>::type
  1994. gamma_p_derivative(T1 a, T2 x, const Policy&)
  1995. {
  1996. BOOST_FPU_EXCEPTION_GUARD
  1997. typedef typename tools::promote_args<T1, T2>::type result_type;
  1998. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  1999. typedef typename policies::normalise<
  2000. Policy,
  2001. policies::promote_float<false>,
  2002. policies::promote_double<false>,
  2003. policies::discrete_quantile<>,
  2004. policies::assert_undefined<> >::type forwarding_policy;
  2005. 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%)");
  2006. }
  2007. template <class T1, class T2>
  2008. inline typename tools::promote_args<T1, T2>::type
  2009. gamma_p_derivative(T1 a, T2 x)
  2010. {
  2011. return gamma_p_derivative(a, x, policies::policy<>());
  2012. }
  2013. } // namespace math
  2014. } // namespace boost
  2015. #ifdef BOOST_MSVC
  2016. # pragma warning(pop)
  2017. #endif
  2018. #include <boost/math/special_functions/detail/igamma_inverse.hpp>
  2019. #include <boost/math/special_functions/detail/gamma_inva.hpp>
  2020. #include <boost/math/special_functions/erf.hpp>
  2021. #endif // BOOST_MATH_SF_GAMMA_HPP