1 #ifndef STAN_MATH_PRIM_FUN_LOG1M_HPP
2 #define STAN_MATH_PRIM_FUN_LOG1M_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/err.hpp>
6 #include <stan/math/prim/fun/is_nan.hpp>
7 #include <stan/math/prim/fun/log1p.hpp>
8 #include <stan/math/prim/functor/apply_scalar_unary.hpp>
9 
10 namespace stan {
11 namespace math {
12 
13 /**
14  * Return the natural logarithm of one minus the specified value.
15  *
16  * The main use of this function is to cut down on intermediate
17  * values during algorithmic differentiation.
18  *
19    \f[
20    \mbox{log1m}(x) =
21    \begin{cases}
22      \ln(1-x) & \mbox{if } x \leq 1 \\
23      \textrm{NaN} & \mbox{if } x > 1\\[6pt]
24      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
25    \end{cases}
26    \f]
27 
28    \f[
29    \frac{\partial\, \mbox{log1m}(x)}{\partial x} =
30    \begin{cases}
31      -\frac{1}{1-x} & \mbox{if } x \leq 1 \\
32      \textrm{NaN} & \mbox{if } x > 1\\[6pt]
33      \textrm{NaN} & \mbox{if } x = \textrm{NaN}
34    \end{cases}
35    \f]
36  *
37  * @param[in] x Argument.
38  * @return Natural log of one minus the argument.
39  * @throw <code>std::domain_error</code> If the argument is greater than 1.
40  * @throw <code>std::overflow_error</code> If the computation overflows.
41  */
log1m(double x)42 inline double log1m(double x) {
43   if (!is_nan(x)) {
44     check_less_or_equal("log1m", "x", x, 1);
45   }
46   return stan::math::log1p(-x);
47 }
48 
49 /**
50  * Structure to wrap log1m() so it can be vectorized.
51  *
52  * @tparam T type of variable
53  * @param x variable
54  * @return Natural log of (1 - x).
55  */
56 struct log1m_fun {
57   template <typename T>
funstan::math::log1m_fun58   static inline T fun(const T& x) {
59     return log1m(x);
60   }
61 };
62 
63 /**
64  * Vectorized version of log1m().
65  *
66  * @tparam T type of container
67  * @param x container
68  * @return Natural log of 1 minus each value in x.
69  */
70 template <
71     typename T, require_not_var_matrix_t<T>* = nullptr,
72     require_all_not_nonscalar_prim_or_rev_kernel_expression_t<T>* = nullptr>
log1m(const T & x)73 inline auto log1m(const T& x) {
74   return apply_scalar_unary<log1m_fun, T>::apply(x);
75 }
76 
77 }  // namespace math
78 }  // namespace stan
79 
80 #endif
81