Automatic Differentiation
 
Loading...
Searching...
No Matches
log_gamma_q_dgamma.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_FUN_LOG_GAMMA_Q_DGAMMA_HPP
2#define STAN_MATH_PRIM_FUN_LOG_GAMMA_Q_DGAMMA_HPP
3
19#include <cmath>
20
21namespace stan {
22namespace math {
23
24namespace internal {
25
26constexpr double LOG_Q_GAMMA_CF_PRECISION = 1.49012e-12;
27
40template <typename T_a, typename T_z>
41inline return_type_t<T_a, T_z> log_q_gamma_cf(const T_a& a, const T_z& z,
42 double precision
44 int max_steps = 250) {
45 using T_return = return_type_t<T_a, T_z>;
46 const T_return log_prefactor = a * log(z) - z - lgamma(a);
47
48 T_return b_init = z + 1.0 - a;
49 T_return C = (fabs(value_of_rec(b_init)) >= EPSILON)
50 ? b_init
51 : std::decay_t<decltype(b_init)>(EPSILON);
52 T_return D = 0.0;
53 T_return f = C;
54 for (int i = 1; i <= max_steps; ++i) {
55 T_a an = -i * (i - a);
56 const T_return b = b_init + 2.0 * i;
57 D = b + an * D;
58 D = (fabs(value_of_rec(D)) >= EPSILON) ? D
59 : std::decay_t<decltype(D)>(EPSILON);
60 C = b + an / C;
61 C = (fabs(value_of_rec(C)) >= EPSILON) ? C
62 : std::decay_t<decltype(C)>(EPSILON);
63 D = inv(D);
64 const T_return delta = C * D;
65 f *= delta;
66 const double delta_m1 = fabs(value_of_rec(delta) - 1.0);
67 if (delta_m1 < precision) {
68 break;
69 }
70 }
71 return log_prefactor - log(f);
72}
73
74} // namespace internal
75
93template <typename T_a, typename T_z>
94inline std::pair<return_type_t<T_a, T_z>, return_type_t<T_a, T_z>>
95log_gamma_q_dgamma(const T_a& a, const T_z& z,
96 double precision = internal::LOG_Q_GAMMA_CF_PRECISION,
97 int max_steps = 250) {
98 using T_return = return_type_t<T_a, T_z>;
99 const double a_val = value_of(a);
100 const double z_val = value_of(z);
101 // For z > a + 1, use continued fraction for better numerical stability
102 if (z_val > a_val + 1.0) {
103 std::pair<T_return, T_return> result{
104 internal::log_q_gamma_cf(a_val, z_val, precision, max_steps), 0.0};
105 // For gradient, use: d/da log(Q) = (1/Q) * dQ/da
106 // grad_reg_inc_gamma computes dQ/da
107 const T_return Q_val = exp(result.first);
108 const double dQ_da
109 = grad_reg_inc_gamma(a_val, z_val, tgamma(a_val), digamma(a_val));
110 result.second = dQ_da / Q_val;
111 return result;
112 } else {
113 // For z <= a + 1, use log1m(P(a,z)) for better numerical accuracy
114 const double P_val = gamma_p(a_val, z_val);
115 std::pair<T_return, T_return> result{log1m(P_val), 0.0};
116 // Gradient: d/da log(Q) = (1/Q) * dQ/da
117 // grad_reg_inc_gamma computes dQ/da
118 const T_return Q_val = exp(result.first);
119 if (Q_val > 0) {
120 const double dQ_da
121 = grad_reg_inc_gamma(a_val, z_val, tgamma(a_val), digamma(a_val));
122 result.second = dQ_da / Q_val;
123 } else {
124 // Fallback if Q rounds to zero - use asymptotic approximation
125 result.second = log(z_val) - digamma(a_val);
126 }
127 return result;
128 }
129}
130
131} // namespace math
132} // namespace stan
133
134#endif
typename return_type< Ts... >::type return_type_t
Convenience type for the return type of the specified template parameters.
constexpr double LOG_Q_GAMMA_CF_PRECISION
return_type_t< T_a, T_z > log_q_gamma_cf(const T_a &a, const T_z &z, double precision=LOG_Q_GAMMA_CF_PRECISION, int max_steps=250)
Compute log(Q(a,z)) using continued fraction expansion for upper incomplete gamma function.
double value_of_rec(const fvar< T > &v)
Return the value of the specified variable.
std::pair< return_type_t< T_a, T_z >, return_type_t< T_a, T_z > > log_gamma_q_dgamma(const T_a &a, const T_z &z, double precision=internal::LOG_Q_GAMMA_CF_PRECISION, int max_steps=250)
Compute log(Q(a,z)) and its gradient with respect to a using continued fraction expansion,...
static constexpr double EPSILON
Smallest positive value.
Definition constants.hpp:41
T value_of(const fvar< T > &v)
Return the value of the specified variable.
Definition value_of.hpp:18
fvar< T > log(const fvar< T > &x)
Definition log.hpp:18
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 > lgamma(const fvar< T > &x)
Return the natural logarithm of the gamma function applied to the specified argument.
Definition lgamma.hpp:21
fvar< T > gamma_p(const fvar< T > &x1, const fvar< T > &x2)
Definition gamma_p.hpp:18
fvar< T > tgamma(const fvar< T > &x)
Return the result of applying the gamma function to the specified argument.
Definition tgamma.hpp:21
fvar< T > log1m(const fvar< T > &x)
Definition log1m.hpp:12
fvar< T > inv(const fvar< T > &x)
Definition inv.hpp:13
fvar< T > digamma(const fvar< T > &x)
Return the derivative of the log gamma function at the specified argument.
Definition digamma.hpp:23
fvar< T > fabs(const fvar< T > &x)
Definition fabs.hpp:16
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 ...