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)45inline 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)78inline 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