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