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