1 #ifndef STAN_MATH_PRIM_SCAL_FUN_LOG_SUM_EXP_HPP
2 #define STAN_MATH_PRIM_SCAL_FUN_LOG_SUM_EXP_HPP
3 
4 #include <stan/math/prim/scal/fun/log1p_exp.hpp>
5 #include <boost/math/tools/promotion.hpp>
6 #include <limits>
7 
8 namespace stan {
9 namespace math {
10 
11 /**
12  * Calculates the log sum of exponetials without overflow.
13  *
14  * \f$\log (\exp(a) + \exp(b)) = m + \log(\exp(a-m) + \exp(b-m))\f$,
15  *
16  * where \f$m = max(a, b)\f$.
17  *
18  *
19    \f[
20    \mbox{log\_sum\_exp}(x, y) =
21    \begin{cases}
22      \ln(\exp(x)+\exp(y)) & \mbox{if } -\infty\leq x, y \leq \infty \\[6pt]
23      \textrm{NaN} & \mbox{if } x = \textrm{NaN or } y = \textrm{NaN}
24    \end{cases}
25    \f]
26 
27    \f[
28    \frac{\partial\, \mbox{log\_sum\_exp}(x, y)}{\partial x} =
29    \begin{cases}
30      \frac{\exp(x)}{\exp(x)+\exp(y)} & \mbox{if } -\infty\leq x, y \leq \infty
31  \\[6pt] \textrm{NaN} & \mbox{if } x = \textrm{NaN or } y = \textrm{NaN}
32    \end{cases}
33    \f]
34 
35    \f[
36    \frac{\partial\, \mbox{log\_sum\_exp}(x, y)}{\partial y} =
37    \begin{cases}
38      \frac{\exp(y)}{\exp(x)+\exp(y)} & \mbox{if } -\infty\leq x, y \leq \infty
39  \\[6pt] \textrm{NaN} & \mbox{if } x = \textrm{NaN or } y = \textrm{NaN}
40    \end{cases}
41    \f]
42  *
43  * @param a the first variable
44  * @param b the second variable
45  */
46 template <typename T1, typename T2>
log_sum_exp(const T2 & a,const T1 & b)47 inline typename boost::math::tools::promote_args<T1, T2>::type log_sum_exp(
48     const T2& a, const T1& b) {
49   using std::exp;
50   if (a > b)
51     return a + log1p_exp(b - a);
52   return b + log1p_exp(a - b);
53 }
54 
55 }  // namespace math
56 }  // namespace stan
57 
58 #endif
59