1 #ifndef STAN_MATH_PRIM_FUN_GAMMA_P_HPP
2 #define STAN_MATH_PRIM_FUN_GAMMA_P_HPP
3
4 #include <stan/math/prim/err.hpp>
5 #include <stan/math/prim/fun/boost_policy.hpp>
6 #include <stan/math/prim/fun/constants.hpp>
7 #include <stan/math/prim/fun/is_nan.hpp>
8 #include <stan/math/prim/functor/apply_scalar_binary.hpp>
9 #include <boost/math/special_functions/gamma.hpp>
10
11 namespace stan {
12 namespace math {
13
14 /**
15 * Return the value of the normalized, lower-incomplete gamma function
16 * applied to the specified argument.
17 *
18 * <p>This function is defined, including error conditions, as follows
19 \f[
20 \mbox{gamma\_p}(a, z) =
21 \begin{cases}
22 \textrm{error} & \mbox{if } a\leq 0 \textrm{ or } z < 0\\
23 P(a, z) & \mbox{if } a > 0, z \geq 0 \\[6pt]
24 \textrm{NaN} & \mbox{if } a = \textrm{NaN or } z = \textrm{NaN}
25 \end{cases}
26 \f]
27
28 \f[
29 \frac{\partial\, \mbox{gamma\_p}(a, z)}{\partial a} =
30 \begin{cases}
31 \textrm{error} & \mbox{if } a\leq 0 \textrm{ or } z < 0\\
32 \frac{\partial\, P(a, z)}{\partial a} & \mbox{if } a > 0, z \geq 0 \\[6pt]
33 \textrm{NaN} & \mbox{if } a = \textrm{NaN or } z = \textrm{NaN}
34 \end{cases}
35 \f]
36
37 \f[
38 \frac{\partial\, \mbox{gamma\_p}(a, z)}{\partial z} =
39 \begin{cases}
40 \textrm{error} & \mbox{if } a\leq 0 \textrm{ or } z < 0\\
41 \frac{\partial\, P(a, z)}{\partial z} & \mbox{if } a > 0, z \geq 0 \\[6pt]
42 \textrm{NaN} & \mbox{if } a = \textrm{NaN or } z = \textrm{NaN}
43 \end{cases}
44 \f]
45
46 \f[
47 P(a, z)=\frac{1}{\Gamma(a)}\int_0^zt^{a-1}e^{-t}dt
48 \f]
49
50 \f[
51 \frac{\partial \, P(a, z)}{\partial a} =
52 -\frac{\Psi(a)}{\Gamma^2(a)}\int_0^zt^{a-1}e^{-t}dt
53 + \frac{1}{\Gamma(a)}\int_0^z (a-1)t^{a-2}e^{-t}dt
54 \f]
55
56 \f[
57 \frac{\partial \, P(a, z)}{\partial z} = \frac{z^{a-1}e^{-z}}{\Gamma(a)}
58 \f]
59 *
60 * @param z first argument
61 * @param a second argument
62 * @return value of the normalized, lower-incomplete gamma function
63 * applied to z and a
64 * @throws std::domain_error if either argument is not positive or
65 * if z is at a pole of the function
66 */
gamma_p(double z,double a)67 inline double gamma_p(double z, double a) {
68 if (is_nan(z)) {
69 return not_a_number();
70 }
71 if (is_nan(a)) {
72 return not_a_number();
73 }
74 check_positive("gamma_p", "first argument (z)", z);
75 check_nonnegative("gamma_p", "second argument (a)", a);
76 return boost::math::gamma_p(z, a, boost_policy_t<>());
77 }
78
79 /**
80 * Enables the vectorised application of the gamma_p function,
81 * when the first and/or second arguments are containers.
82 *
83 * @tparam T1 type of first input
84 * @tparam T2 type of second input
85 * @param a First input
86 * @param b Second input
87 * @return gamma_p function applied to the two inputs.
88 */
89 template <typename T1, typename T2, require_any_container_t<T1, T2>* = nullptr>
gamma_p(const T1 & a,const T2 & b)90 inline auto gamma_p(const T1& a, const T2& b) {
91 return apply_scalar_binary(
92 a, b, [&](const auto& c, const auto& d) { return gamma_p(c, d); });
93 }
94
95 } // namespace math
96 } // namespace stan
97 #endif
98