1 #ifndef STAN_MATH_PRIM_FUN_LOG1P_EXP_HPP
2 #define STAN_MATH_PRIM_FUN_LOG1P_EXP_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/fun/exp.hpp>
6 #include <stan/math/prim/fun/log.hpp>
7 #include <stan/math/prim/fun/log1p.hpp>
8 #include <stan/math/prim/functor/apply_scalar_unary.hpp>
9 #include <cmath>
10 
11 namespace stan {
12 namespace math {
13 
14 /**
15  * Calculates the log of 1 plus the exponential of the specified
16  * value without overflow.
17  *
18  * This function is related to other special functions by:
19  *
20  * <code>log1p_exp(x) </code>
21  *
22  * <code> = log1p(exp(a))</code>
23  *
24  * <code> = log(1 + exp(x))</code>
25  *
26  * <code> = log_sum_exp(0, x)</code>.
27  *
28    \f[
29    \mbox{log1p\_exp}(x) =
30    \begin{cases}
31      \ln(1+\exp(x)) & \mbox{if } -\infty\leq x \leq \infty \\[6pt]
32      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
33    \end{cases}
34    \f]
35 
36    \f[
37    \frac{\partial\, \mbox{log1p\_exp}(x)}{\partial x} =
38    \begin{cases}
39      \frac{\exp(x)}{1+\exp(x)} & \mbox{if } -\infty\leq x\leq \infty \\[6pt]
40      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
41    \end{cases}
42    \f]
43  *
44  */
log1p_exp(double a)45 inline double log1p_exp(double a) {
46   using std::exp;
47   // like log_sum_exp below with b=0.0; prevents underflow
48   if (a > 0.0) {
49     return a + log1p(exp(-a));
50   }
51   return log1p(exp(a));
52 }
53 
54 /**
55  * Structure to wrap log1p_exp() so that it can be vectorized.
56  *
57  * @tparam T type of variable
58  * @param x variable
59  * @return Natural log of (1 + exp(x)).
60  */
61 struct log1p_exp_fun {
62   template <typename T>
funstan::math::log1p_exp_fun63   static inline T fun(const T& x) {
64     return log1p_exp(x);
65   }
66 };
67 
68 /**
69  * Vectorized version of log1p_exp().
70  *
71  * @tparam T type of container
72  * @param x container
73  * @return Natural log of (1 + exp()) applied to each value in x.
74  */
75 template <typename T,
76           require_not_nonscalar_prim_or_rev_kernel_expression_t<T>* = nullptr,
77           require_not_var_matrix_t<T>* = nullptr>
log1p_exp(const T & x)78 inline auto log1p_exp(const T& x) {
79   return apply_scalar_unary<log1p_exp_fun, T>::apply(x);
80 }
81 
82 }  // namespace math
83 }  // namespace stan
84 
85 #endif
86