Automatic Differentiation
 
Loading...
Searching...
No Matches
grad_reg_inc_gamma.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_FUN_GRAD_REG_INC_GAMMA_HPP
2#define STAN_MATH_PRIM_FUN_GRAD_REG_INC_GAMMA_HPP
3
12#include <cmath>
13#include <limits>
14
15namespace stan {
16namespace math {
17
49template <typename T1, typename T2>
50inline return_type_t<T1, T2> grad_reg_inc_gamma(T1 a, T2 z, T1 g, T1 dig,
51 double precision = 1e-6,
52 int max_steps = 1e5) {
53 using std::exp;
54 using std::fabs;
55 using std::log;
56 using TP = return_type_t<T1, T2>;
57
58 if (is_any_nan(a, z, g, dig)) {
59 return std::numeric_limits<TP>::quiet_NaN();
60 }
61
62 T2 l = log(z);
63 if (z >= a && z >= 8) {
64 // asymptotic expansion http://dlmf.nist.gov/8.11#E2
65 TP S = 0;
66 T1 a_minus_one_minus_k = a - 1;
67 T1 fac = a_minus_one_minus_k; // falling_factorial(a-1, k)
68 T1 dfac = 1; // d/da[falling_factorial(a-1, k)]
69 T2 zpow = z; // z ** k
70 TP delta = dfac / zpow;
71
72 for (int k = 1; k < 10; ++k) {
73 a_minus_one_minus_k -= 1;
74
75 S += delta;
76
77 zpow *= z;
78 dfac = a_minus_one_minus_k * dfac + fac;
79 fac *= a_minus_one_minus_k;
80 delta = dfac / zpow;
81
82 if (is_inf(delta)) {
83 throw_domain_error("grad_reg_inc_gamma", "is not converging", "", "");
84 }
85 }
86
87 return gamma_q(a, z) * (l - dig) + exp(-z + (a - 1) * l) * S / g;
88 } else {
89 // gradient of series expansion http://dlmf.nist.gov/8.7#E3
90 TP S = 0;
91 TP log_s = 0.0;
92 double s_sign = 1.0;
93 T2 log_z = log(z);
94 TP log_delta = log_s - lmultiply(2, a);
95 for (int k = 1; k <= max_steps; ++k) {
96 S += s_sign >= 0.0 ? exp(log_delta) : -exp(log_delta);
97 log_s += log_z - log(k);
98 s_sign = -s_sign;
99 log_delta = log_s - lmultiply(2, k + a);
100 if (is_inf(log_delta)) {
101 throw_domain_error("grad_reg_inc_gamma", "is not converging", "", "");
102 }
103 if (log_delta <= log(precision)) {
104 return gamma_p(a, z) * (dig - l) + exp(a * l) * S / g;
105 }
106 }
108 "grad_reg_inc_gamma", "k (internal counter)", max_steps, "exceeded ",
109 " iterations, gamma function gradient did not converge.");
110 return INFTY;
111 }
112}
113
114} // namespace math
115} // namespace stan
116#endif
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
static constexpr double e()
Return the base of the natural logarithm.
Definition constants.hpp:18
fvar< T > log(const fvar< T > &x)
Definition log.hpp:18
void throw_domain_error(const char *function, const char *name, const T &y, const char *msg1, const char *msg2)
Throw a domain error with a consistently formatted message.
fvar< T > lmultiply(const fvar< T > &x1, const fvar< T > &x2)
Definition lmultiply.hpp:14
return_type_t< T1, T2 > grad_reg_inc_gamma(T1 a, T2 z, T1 g, T1 dig, double precision=1e-6, int max_steps=1e5)
Gradient of the regularized incomplete gamma functions igamma(a, z)
fvar< T > gamma_p(const fvar< T > &x1, const fvar< T > &x2)
Definition gamma_p.hpp:18
int is_inf(const fvar< T > &x)
Returns 1 if the input's value is infinite and 0 otherwise.
Definition is_inf.hpp:21
bool is_any_nan(const T &x)
Returns true if the input is NaN and false otherwise.
fvar< T > gamma_q(const fvar< T > &x1, const fvar< T > &x2)
Definition gamma_q.hpp:19
static constexpr double INFTY
Positive infinity.
Definition constants.hpp:44
fvar< T > exp(const fvar< T > &x)
Definition exp.hpp:15
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...