1 #ifndef STAN_MATH_PRIM_FUN_INV_LOGIT_HPP 2 #define STAN_MATH_PRIM_FUN_INV_LOGIT_HPP 3 4 #include <stan/math/prim/meta.hpp> 5 #include <stan/math/prim/fun/constants.hpp> 6 #include <stan/math/prim/fun/exp.hpp> 7 #include <stan/math/prim/fun/inv.hpp> 8 #include <stan/math/prim/functor/apply_scalar_unary.hpp> 9 #include <cmath> 10 11 namespace stan { 12 namespace math { 13 14 /** 15 * Returns the inverse logit function applied to the argument. 16 * 17 * The inverse logit function is defined by 18 * 19 * \f$\mbox{logit}^{-1}(x) = \frac{1}{1 + \exp(-x)}\f$. 20 * 21 * This function can be used to implement the inverse link function 22 * for logistic regression. 23 * 24 * The inverse to this function is <code>logit</code>. 25 * 26 \f[ 27 \mbox{inv\_logit}(y) = 28 \begin{cases} 29 \mbox{logit}^{-1}(y) & \mbox{if } -\infty\leq y \leq \infty \\[6pt] 30 \textrm{NaN} & \mbox{if } y = \textrm{NaN} 31 \end{cases} 32 \f] 33 34 \f[ 35 \frac{\partial\, \mbox{inv\_logit}(y)}{\partial y} = 36 \begin{cases} 37 \frac{\partial\, \mbox{logit}^{-1}(y)}{\partial y} & \mbox{if } -\infty\leq 38 y\leq \infty \\[6pt] \textrm{NaN} & \mbox{if } y = \textrm{NaN} \end{cases} \f] 39 40 \f[ 41 \mbox{logit}^{-1}(y) = \frac{1}{1 + \exp(-y)} 42 \f] 43 44 \f[ 45 \frac{\partial \, \mbox{logit}^{-1}(y)}{\partial y} = 46 \frac{\exp(y)}{(\exp(y)+1)^2} \f] 47 * 48 * @param a Argument. 49 * @return Inverse logit of argument. 50 */ inv_logit(double a)51inline double inv_logit(double a) { 52 using std::exp; 53 if (a < 0) { 54 double exp_a = exp(a); 55 if (a < LOG_EPSILON) { 56 return exp_a; 57 } 58 return exp_a / (1 + exp_a); 59 } 60 return inv(1 + exp(-a)); 61 } 62 63 /** 64 * Structure to wrap inv_logit() so that it can be vectorized. 65 * 66 * @tparam T type of variable 67 * @param x variable 68 * @return Inverse logit of x. 69 */ 70 struct inv_logit_fun { 71 template <typename T> funstan::math::inv_logit_fun72 static inline T fun(const T& x) { 73 return inv_logit(x); 74 } 75 }; 76 77 /** 78 * Vectorized version of inv_logit(). 79 * 80 * @tparam T type of container 81 * @param x container 82 * @return Inverse logit applied to each value in x. 83 */ 84 template < 85 typename T, require_not_var_matrix_t<T>* = nullptr, 86 require_all_not_nonscalar_prim_or_rev_kernel_expression_t<T>* = nullptr> inv_logit(const T & x)87inline auto inv_logit(const T& x) { 88 return apply_scalar_unary<inv_logit_fun, T>::apply(x); 89 } 90 91 // TODO(Tadej): Eigen is introducing their implementation logistic() of this 92 // in 3.4. Use that once we switch to Eigen 3.4 93 94 } // namespace math 95 } // namespace stan 96 97 #endif 98