1 #ifndef STAN_MATH_PRIM_FUN_BETA_HPP
2 #define STAN_MATH_PRIM_FUN_BETA_HPP
3
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/fun/exp.hpp>
6 #include <stan/math/prim/fun/lgamma.hpp>
7 #include <stan/math/prim/functor/apply_scalar_binary.hpp>
8 #include <cmath>
9
10 namespace stan {
11 namespace math {
12
13 /**
14 * Return the beta function applied to the specified
15 * arguments.
16 *
17 * The beta function is defined for \f$a > 0\f$ and \f$b > 0\f$ by
18 *
19 * \f$\mbox{B}(a, b) = \frac{\Gamma(a) \Gamma(b)}{\Gamma(a+b)}\f$.
20 *
21 \f[
22 \mbox{beta}(\alpha, \beta) =
23 \begin{cases}
24 \int_0^1 u^{\alpha - 1} (1 - u)^{\beta - 1} \, du & \mbox{if } \alpha,
25 \beta>0 \\[6pt] \textrm{NaN} & \mbox{if } \alpha = \textrm{NaN or } \beta =
26 \textrm{NaN} \end{cases} \f]
27
28 \f[
29 \frac{\partial\, \mbox{beta}(\alpha, \beta)}{\partial \alpha} =
30 \begin{cases}
31 \left(\psi(\alpha)-\psi(\alpha+\beta)\right)*\mbox{beta}(\alpha, \beta)
32 & \mbox{if } \alpha, \beta>0 \\[6pt]
33 \textrm{NaN} & \mbox{if } \alpha = \textrm{NaN or } \beta = \textrm{NaN}
34 \end{cases}
35 \f]
36
37 \f[
38 \frac{\partial\, \mbox{beta}(\alpha, \beta)}{\partial \beta} =
39 \begin{cases}
40 \left(\psi(\beta)-\psi(\alpha+\beta)\right)*\mbox{beta}(\alpha, \beta)
41 & \mbox{if } \alpha, \beta>0 \\[6pt]
42 \textrm{NaN} & \mbox{if } \alpha = \textrm{NaN or } \beta = \textrm{NaN}
43 \end{cases}
44 \f]
45 *
46 * @tparam T1 type of first value
47 * @tparam T2 type of second value
48 * @param a First value
49 * @param b Second value
50 * @return Beta function applied to the two values.
51 */
52 template <typename T1, typename T2, require_all_arithmetic_t<T1, T2>* = nullptr>
beta(const T1 a,const T2 b)53 inline return_type_t<T1, T2> beta(const T1 a, const T2 b) {
54 using std::exp;
55 return exp(lgamma(a) + lgamma(b) - lgamma(a + b));
56 }
57
58 /**
59 * Enables the vectorised application of the beta function, when
60 * the first and/or second arguments are containers.
61 *
62 * @tparam T1 type of first input
63 * @tparam T2 type of second input
64 * @param a First input
65 * @param b Second input
66 * @return Beta function applied to the two inputs.
67 */
68 template <typename T1, typename T2, require_any_container_t<T1, T2>* = nullptr,
69 require_all_not_var_matrix_t<T1, T2>* = nullptr>
beta(const T1 & a,const T2 & b)70 inline auto beta(const T1& a, const T2& b) {
71 return apply_scalar_binary(
72 a, b, [](const auto& c, const auto& d) { return beta(c, d); });
73 }
74
75 } // namespace math
76 } // namespace stan
77
78 #endif
79