1 #ifndef STAN_MATH_PRIM_FUN_RISING_FACTORIAL_HPP
2 #define STAN_MATH_PRIM_FUN_RISING_FACTORIAL_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/err.hpp>
6 #include <stan/math/prim/fun/boost_policy.hpp>
7 #include <stan/math/prim/functor/apply_scalar_binary.hpp>
8 #include <boost/math/special_functions/factorials.hpp>
9 
10 namespace stan {
11 namespace math {
12 
13 /**
14  * Return the rising factorial function evaluated
15  * at the inputs.
16  *
17  * @tparam T type of the first argument
18  * @param x first argument
19  * @param n second argument
20  * @return Result of rising factorial function.
21  * @throw std::domain_error if x is NaN
22  * @throw std::domain_error if n is negative
23  *
24  \f[
25  \mbox{rising\_factorial}(x, n) =
26  \begin{cases}
27  \textrm{error} & \mbox{if } x \leq 0\\
28  x^{(n)} & \mbox{if } x > 0 \textrm{ and } -\infty \leq n \leq \infty \\[6pt]
29  \textrm{NaN} & \mbox{if } x = \textrm{NaN or } n = \textrm{NaN}
30  \end{cases}
31  \f]
32 
33  \f[
34  \frac{\partial\, \mbox{rising\_factorial}(x, n)}{\partial x} =
35  \begin{cases}
36  \textrm{error} & \mbox{if } x \leq 0\\
37  \frac{\partial\, x^{(n)}}{\partial x} & \mbox{if } x > 0 \textrm{ and } -\infty
38  \leq n \leq \infty \\[6pt] \textrm{NaN} & \mbox{if } x = \textrm{NaN or } n =
39  \textrm{NaN} \end{cases} \f]
40 
41  \f[
42  \frac{\partial\, \mbox{rising\_factorial}(x, n)}{\partial n} =
43  \begin{cases}
44  \textrm{error} & \mbox{if } x \leq 0\\
45  \frac{\partial\, x^{(n)}}{\partial n} & \mbox{if } x > 0 \textrm{ and } -\infty
46  \leq n \leq \infty \\[6pt] \textrm{NaN} & \mbox{if } x = \textrm{NaN or } n =
47  \textrm{NaN} \end{cases} \f]
48 
49  \f[
50  x^{(n)}=\frac{\Gamma(x+n)}{\Gamma(x)}
51  \f]
52 
53  \f[
54  \frac{\partial \, x^{(n)}}{\partial x} = x^{(n)}(\Psi(x+n)-\Psi(x))
55  \f]
56 
57  \f[
58  \frac{\partial \, x^{(n)}}{\partial n} = (x)_n\Psi(x+n)
59  \f]
60  *
61  */
62 template <typename T, require_arithmetic_t<T>* = nullptr>
rising_factorial(const T & x,int n)63 inline return_type_t<T> rising_factorial(const T& x, int n) {
64   static const char* function = "rising_factorial";
65   check_not_nan(function, "first argument", x);
66   check_nonnegative(function, "second argument", n);
67   return boost::math::rising_factorial(x, n, boost_policy_t<>());
68 }
69 
70 /**
71  * Enables the vectorised application of the rising_factorial
72  * function, when the first and/or second arguments are containers.
73  *
74  * @tparam T1 type of first input
75  * @tparam T2 type of second input
76  * @param a First input
77  * @param b Second input
78  * @return rising_factorial function applied to the two inputs.
79  */
80 template <typename T1, typename T2, require_any_container_t<T1, T2>* = nullptr>
rising_factorial(const T1 & a,const T2 & b)81 inline auto rising_factorial(const T1& a, const T2& b) {
82   return apply_scalar_binary(a, b, [&](const auto& c, const auto& d) {
83     return rising_factorial(c, d);
84   });
85 }
86 
87 }  // namespace math
88 }  // namespace stan
89 #endif
90