1 #ifndef STAN_MATH_PRIM_FUN_ACOS_HPP
2 #define STAN_MATH_PRIM_FUN_ACOS_HPP
3 
4 #include <stan/math/prim/core.hpp>
5 #include <stan/math/prim/meta.hpp>
6 #include <stan/math/prim/fun/asin.hpp>
7 #include <stan/math/prim/fun/constants.hpp>
8 #include <stan/math/prim/fun/Eigen.hpp>
9 #include <stan/math/prim/fun/isinf.hpp>
10 #include <stan/math/prim/fun/isfinite.hpp>
11 #include <stan/math/prim/fun/isnan.hpp>
12 #include <stan/math/prim/fun/polar.hpp>
13 #include <stan/math/prim/functor/apply_scalar_unary.hpp>
14 #include <stan/math/prim/functor/apply_vector_unary.hpp>
15 #include <cmath>
16 #include <complex>
17 
18 namespace stan {
19 namespace math {
20 
21 /**
22  * Structure to wrap `acos()` so it can be vectorized.
23  *
24  * @tparam T type of variable
25  * @param x argument
26  * @return Arc cosine of variable in radians.
27  */
28 struct acos_fun {
29   template <typename T>
funstan::math::acos_fun30   static inline T fun(const T& x) {
31     using std::acos;
32     return acos(x);
33   }
34 };
35 
36 /**
37  * Returns the elementwise `acos()` of the input,
38  * which may be a scalar or any Stan container of numeric scalars.
39  *
40  * @tparam Container type of container
41  * @param x argument
42  * @return Arc cosine of each variable in the container, in radians.
43  */
44 template <typename Container,
45           require_not_container_st<std::is_arithmetic, Container>* = nullptr,
46           require_not_var_matrix_t<Container>* = nullptr,
47           require_all_not_nonscalar_prim_or_rev_kernel_expression_t<
48               Container>* = nullptr>
acos(const Container & x)49 inline auto acos(const Container& x) {
50   return apply_scalar_unary<acos_fun, Container>::apply(x);
51 }
52 
53 /**
54  * Version of `acos()` that accepts std::vectors, Eigen Matrix/Array objects
55  *  or expressions, and containers of these.
56  *
57  * @tparam Container Type of x
58  * @param x argument
59  * @return Arc cosine of each variable in the container, in radians.
60  */
61 template <typename Container,
62           require_container_st<std::is_arithmetic, Container>* = nullptr>
acos(const Container & x)63 inline auto acos(const Container& x) {
64   return apply_vector_unary<Container>::apply(
65       x, [](const auto& v) { return v.array().acos(); });
66 }
67 
68 namespace internal {
69 /**
70  * Return the arc cosine of the complex argument.
71  *
72  * @tparam V value type of argument
73  * @param[in] x argument
74  * @return arc cosine of the argument
75  */
76 template <typename V>
complex_acos(const std::complex<V> & x)77 inline std::complex<V> complex_acos(const std::complex<V>& x) {
78   return 0.5 * pi() - asin(x);
79 }
80 }  // namespace internal
81 
82 }  // namespace math
83 }  // namespace stan
84 
85 #endif
86