|
8 | 8 | #include <stan/math/prim/fun/gamma_p.hpp> |
9 | 9 | #include <stan/math/prim/fun/gamma_q.hpp> |
10 | 10 | #include <stan/math/prim/fun/grad_reg_inc_gamma.hpp> |
| 11 | +#include <stan/math/prim/fun/inv.hpp> |
11 | 12 | #include <stan/math/prim/fun/lgamma.hpp> |
12 | 13 | #include <stan/math/prim/fun/log.hpp> |
13 | 14 | #include <stan/math/prim/fun/log1m.hpp> |
@@ -41,41 +42,40 @@ namespace internal { |
41 | 42 | * @param z Value at which to evaluate |
42 | 43 | * @param precision Convergence threshold |
43 | 44 | * @param max_steps Maximum number of continued fraction iterations |
44 | | - * @return log(Q(a,z)) with same type as T_a and T_z |
| 45 | + * @return log(Q(a,z)) with the return type of T_a and T_z |
45 | 46 | */ |
46 | 47 | template <typename T_a, typename T_z> |
47 | | -inline auto log_q_gamma_cf(const T_a& a, const T_z& z, double precision = 1e-16, |
48 | | - int max_steps = 250) { |
| 48 | +inline return_type_t<T_a, T_z> log_q_gamma_cf(const T_a& a, const T_z& z, |
| 49 | + double precision = 1e-16, |
| 50 | + int max_steps = 250) { |
49 | 51 | using stan::math::lgamma; |
50 | 52 | using stan::math::log; |
51 | 53 | using stan::math::value_of; |
52 | 54 | using std::fabs; |
53 | 55 | using T_return = return_type_t<T_a, T_z>; |
54 | 56 |
|
55 | | - const T_return a_ret = a; |
56 | | - const T_return z_ret = z; |
57 | | - const auto log_prefactor = a_ret * log(z_ret) - z_ret - lgamma(a_ret); |
| 57 | + const T_return log_prefactor = a * log(z) - z - lgamma(a); |
58 | 58 |
|
59 | | - auto b = z_ret + 1.0 - a_ret; |
60 | | - auto C = (fabs(value_of(b)) >= EPSILON) ? b : T_return(EPSILON); |
61 | | - auto D = T_return(0.0); |
62 | | - auto f = C; |
| 59 | + T_return b = z + 1.0 - a; |
| 60 | + T_return C = (fabs(value_of(b)) >= EPSILON) ? b : T_return(EPSILON); |
| 61 | + T_return D = 0.0; |
| 62 | + T_return f = C; |
63 | 63 |
|
64 | 64 | for (int i = 1; i <= max_steps; ++i) { |
65 | | - auto an = -i * (i - a_ret); |
| 65 | + T_a an = -i * (i - a); |
66 | 66 | b += 2.0; |
67 | 67 |
|
68 | 68 | D = b + an * D; |
69 | | - if (fabs(value_of(D)) < EPSILON) { |
70 | | - D = T_return(EPSILON); |
| 69 | + if (fabs(D) < EPSILON) { |
| 70 | + D = EPSILON; |
71 | 71 | } |
72 | 72 | C = b + an / C; |
73 | | - if (fabs(value_of(C)) < EPSILON) { |
74 | | - C = T_return(EPSILON); |
| 73 | + if (fabs(C) < EPSILON) { |
| 74 | + C = EPSILON; |
75 | 75 | } |
76 | 76 |
|
77 | | - D = 1.0 / D; |
78 | | - auto delta = C * D; |
| 77 | + D = inv(D); |
| 78 | + T_return delta = C * D; |
79 | 79 | f *= delta; |
80 | 80 |
|
81 | 81 | const double delta_m1 = value_of(fabs(value_of(delta) - 1.0)); |
|
0 commit comments