1 #ifndef STAN_MATH_PRIM_FUN_VALUE_OF_REC_HPP
2 #define STAN_MATH_PRIM_FUN_VALUE_OF_REC_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/fun/Eigen.hpp>
6 #include <complex>
7 #include <cstddef>
8 #include <vector>
9 
10 namespace stan {
11 namespace math {
12 
13 /**
14  * Return the value of the specified scalar argument
15  * converted to a double value.
16  *
17  * <p>See the <code>primitive_value</code> function to
18  * extract values without casting to <code>double</code>.
19  *
20  * <p>This function is meant to cover the primitive types. For
21  * types requiring pass-by-reference, this template function
22  * should be specialized.
23  *
24  * @tparam T Type of scalar.
25  * @param x Scalar to convert to double.
26  * @return Value of scalar cast to a double.
27  */
28 template <typename T, typename = require_stan_scalar_t<T>>
value_of_rec(const T x)29 inline double value_of_rec(const T x) {
30   return static_cast<double>(x);
31 }
32 
33 /**
34  * Return the specified argument.
35  *
36  * <p>See <code>value_of(T)</code> for a polymorphic
37  * implementation using static casts.
38  *
39  * <p>This inline pass-through no-op should be compiled away.
40  *
41  * @param x Specified value.
42  * @return Specified value.
43  */
value_of_rec(double x)44 inline double value_of_rec(double x) { return x; }
45 
46 /**
47  * Recursively apply value-of to the parts of the argument.
48  *
49  * @tparam T value type of argument
50  * @param[in] x argument
51  * @return real complex value of argument
52  */
53 template <typename T>
value_of_rec(const std::complex<T> & x)54 inline std::complex<double> value_of_rec(const std::complex<T>& x) {
55   return {value_of_rec(x.real()), value_of_rec(x.imag())};
56 }
57 
58 /**
59  * Convert a std::vector of type T to a std::vector of doubles.
60  *
61  * T must implement value_of_rec. See
62  * test/math/fwd/fun/value_of_rec.cpp for fvar and var usage.
63  *
64  * @tparam T Scalar type in std::vector
65  * @param[in] x std::vector to be converted
66  * @return std::vector of values
67  **/
68 template <typename T, require_not_same_t<double, T>* = nullptr>
value_of_rec(const std::vector<T> & x)69 inline std::vector<double> value_of_rec(const std::vector<T>& x) {
70   size_t x_size = x.size();
71   std::vector<double> result(x_size);
72   for (size_t i = 0; i < x_size; i++) {
73     result[i] = value_of_rec(x[i]);
74   }
75   return result;
76 }
77 
78 /**
79  * Return the specified argument.
80  *
81  * <p>See <code>value_of_rec(T)</code> for a polymorphic
82  * implementation using static casts.
83  *
84  * <p>This inline pass-through no-op should be compiled away.
85  *
86  * @param x Specified std::vector.
87  * @return Specified std::vector.
88  */
89 template <typename T, require_std_vector_t<T>* = nullptr,
90           require_vt_same<double, T>* = nullptr>
value_of_rec(T && x)91 inline T value_of_rec(T&& x) {
92   return std::forward<T>(x);
93 }
94 
95 /**
96  * Convert a matrix of type T to a matrix of doubles.
97  *
98  * T must implement value_of_rec. See
99  * test/unit/math/fwd/fun/value_of_test.cpp for fvar and var usage.
100  *
101  * @tparam T Type of matrix
102  * @param[in] M Matrix to be converted
103  * @return Matrix of values
104  **/
105 template <typename T, typename = require_not_st_same<T, double>,
106           typename = require_eigen_t<T>>
value_of_rec(T && M)107 inline auto value_of_rec(T&& M) {
108   return make_holder(
109       [](auto& m) {
110         return m.unaryExpr([](auto x) { return value_of_rec(x); });
111       },
112       std::forward<T>(M));
113 }
114 
115 /**
116  * Return the specified argument.
117  *
118  * <p>See <code>value_of_rec(T)</code> for a polymorphic
119  * implementation using static casts.
120  *
121  * <p>This inline pass-through no-op should be compiled away.
122  *
123  * @tparam T Type of matrix.
124  * @param x Specified matrix.
125  * @return Specified matrix.
126  */
127 template <typename T, typename = require_st_same<T, double>,
128           typename = require_eigen_t<T>>
value_of_rec(T && x)129 inline T value_of_rec(T&& x) {
130   return std::forward<T>(x);
131 }
132 }  // namespace math
133 }  // namespace stan
134 
135 #endif
136