1 #ifndef STAN_MATH_PRIM_FUN_LOG1M_INV_LOGIT_HPP
2 #define STAN_MATH_PRIM_FUN_LOG1M_INV_LOGIT_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/fun/exp.hpp>
6 #include <stan/math/prim/fun/log1p.hpp>
7 #include <stan/math/prim/functor/apply_scalar_unary.hpp>
8 #include <cmath>
9 
10 namespace stan {
11 namespace math {
12 
13 /**
14  * Returns the natural logarithm of 1 minus the inverse logit
15  * of the specified argument.
16  *
17    \f[
18    \mbox{log1m\_inv\_logit}(x) =
19    \begin{cases}
20      -\ln(\exp(x)+1) & \mbox{if } -\infty\leq x \leq \infty \\[6pt]
21      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
22    \end{cases}
23    \f]
24 
25    \f[
26    \frac{\partial\, \mbox{log1m\_inv\_logit}(x)}{\partial x} =
27    \begin{cases}
28      -\frac{\exp(x)}{\exp(x)+1} & \mbox{if } -\infty\leq x\leq \infty \\[6pt]
29      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
30    \end{cases}
31    \f]
32  *
33  * @param u argument
34  * @return log of one minus the inverse logit of the argument
35  */
log1m_inv_logit(double u)36 inline double log1m_inv_logit(double u) {
37   using std::exp;
38   if (u > 0.0) {
39     return -u - log1p(exp(-u));  // prevent underflow
40   }
41   return -log1p(exp(u));
42 }
43 
44 /**
45  * Return the natural logarithm of one minus the inverse logit of
46  * the specified argument.
47  *
48  * @param u argument
49  * @return log of one minus the inverse logit of the argument
50  */
log1m_inv_logit(int u)51 inline double log1m_inv_logit(int u) {
52   return log1m_inv_logit(static_cast<double>(u));
53 }
54 
55 /**
56  * Structure to wrap log1m_inv_logit() so it can be vectorized.
57  */
58 struct log1m_inv_logit_fun {
59   /**
60    * Return the natural logarithm of one minus the inverse logit
61    * of the specified argument.
62    *
63    * @tparam T type of argument
64    * @param x argument
65    * @return natural log of one minus inverse logit of argument
66    */
67   template <typename T>
funstan::math::log1m_inv_logit_fun68   static inline T fun(const T& x) {
69     return log1m_inv_logit(x);
70   }
71 };
72 
73 /**
74  * Return the elementwise application of
75  * <code>log1m_inv_logit()</code> to specified argument container.
76  * The return type promotes the underlying scalar argument type to
77  * double if it is an integer, and otherwise is the argument type.
78  *
79  * @tparam T type of container
80  * @param x container
81  * @return Elementwise log1m_inv_logit of members of container.
82  */
83 template <typename T, require_not_var_matrix_t<T>* = nullptr,
84           require_not_nonscalar_prim_or_rev_kernel_expression_t<T>* = nullptr>
85 inline typename apply_scalar_unary<log1m_inv_logit_fun, T>::return_t
log1m_inv_logit(const T & x)86 log1m_inv_logit(const T& x) {
87   return apply_scalar_unary<log1m_inv_logit_fun, T>::apply(x);
88 }
89 
90 }  // namespace math
91 }  // namespace stan
92 
93 #endif
94