1 #ifndef STAN_MATH_PRIM_FUN_INV_CLOGLOG_HPP
2 #define STAN_MATH_PRIM_FUN_INV_CLOGLOG_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/fun/exp.hpp>
6 #include <stan/math/prim/functor/apply_scalar_unary.hpp>
7 #include <stan/math/prim/functor/apply_vector_unary.hpp>
8 #include <cmath>
9 
10 namespace stan {
11 namespace math {
12 
13 /**
14  * The inverse complementary log-log function.
15  *
16  * The function is defined by
17  *
18  * <code>inv_cloglog(x) = 1 - exp(-exp(x))</code>.
19  *
20  * This function can be used to implement the inverse link
21  * function for complementary-log-log regression.
22  *
23  *
24    \f[
25    \mbox{inv\_cloglog}(y) =
26    \begin{cases}
27      \mbox{cloglog}^{-1}(y) & \mbox{if } -\infty\leq y \leq \infty \\[6pt]
28      \textrm{NaN} & \mbox{if } y = \textrm{NaN}
29    \end{cases}
30    \f]
31    \f[
32    \frac{\partial\, \mbox{inv\_cloglog}(y)}{\partial y} =
33    \begin{cases}
34      \frac{\partial\, \mbox{cloglog}^{-1}(y)}{\partial y} & \mbox{if }
35  -\infty\leq y\leq \infty \\[6pt] \textrm{NaN} & \mbox{if } y = \textrm{NaN}
36    \end{cases}
37    \f]
38    \f[
39    \mbox{cloglog}^{-1}(y) = 1 - \exp \left( - \exp(y) \right)
40    \f]
41    \f[
42    \frac{\partial \, \mbox{cloglog}^{-1}(y)}{\partial y} = \exp(y-\exp(y))
43    \f]
44  *
45  * @param x Argument.
46  * @return Inverse complementary log-log of the argument.
47  */
inv_cloglog(double x)48 inline double inv_cloglog(double x) {
49   using std::exp;
50   return 1 - exp(-exp(x));
51 }
52 
53 /**
54  * Structure to wrap inv_cloglog() so that it can be vectorized.
55  *
56  * @tparam T type of variable
57  * @param x variable
58  * @return 1 - exp(-exp(x)).
59  */
60 struct inv_cloglog_fun {
61   template <typename T>
funstan::math::inv_cloglog_fun62   static inline T fun(const T& x) {
63     return inv_cloglog(x);
64   }
65 };
66 
67 /**
68  * Vectorized version of inv_cloglog().
69  *
70  * @tparam Container type of container
71  * @param x container
72  * @return 1 - exp(-exp()) applied to each value in x.
73  */
74 template <typename Container,
75           require_not_container_st<std::is_arithmetic, Container>* = nullptr,
76           require_not_var_matrix_t<Container>* = nullptr,
77           require_all_not_nonscalar_prim_or_rev_kernel_expression_t<
78               Container>* = nullptr>
inv_cloglog(const Container & x)79 inline auto inv_cloglog(const Container& x) {
80   return apply_scalar_unary<inv_cloglog_fun, Container>::apply(x);
81 }
82 
83 /**
84  * Version of inv_cloglog() that accepts std::vectors, Eigen Matrix/Array
85  * objects or expressions, and containers of these.
86  *
87  * @tparam Container Type of x
88  * @param x Container
89  * @return 1 - exp(-exp()) applied to each value in x.
90  */
91 template <typename Container,
92           require_container_st<std::is_arithmetic, Container>* = nullptr>
inv_cloglog(const Container & x)93 inline auto inv_cloglog(const Container& x) {
94   return apply_vector_unary<Container>::apply(
95       x, [](const auto& v) { return 1 - (-v.array().exp()).exp(); });
96 }
97 
98 }  // namespace math
99 }  // namespace stan
100 
101 #endif
102