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