Automatic Differentiation
 
Loading...
Searching...
No Matches
map.hpp
Go to the documentation of this file.
1#ifndef STAN_MATH_PRIM_FUNCTOR_MAP_HPP
2#define STAN_MATH_PRIM_FUNCTOR_MAP_HPP
3
12
13#include <cstddef>
14#include <tuple>
15#include <type_traits>
16#include <utility>
17#include <vector>
18
19namespace stan {
20namespace math {
21
35template <typename F, typename T, typename... Args,
36 require_std_vector_t<T>* = nullptr>
37inline auto map(F&& f, T&& x, Args&&... args) {
38 using T_return = std::decay_t<decltype(f(x[0], args...))>;
39 std::vector<T_return> result;
40 result.reserve(x.size());
41
42 for (auto&& xi : x) {
43 result.push_back(f(xi, args...));
44 }
45
46 return result;
47}
48
66template <typename F, typename Tuple, typename... Args,
67 require_all_tuple_elements_t<is_std_vector, Tuple>* = nullptr>
68inline auto mapN(F&& f, Tuple&& xs, Args&&... args) {
69 static constexpr const char* function = "mapN";
70
71 return apply(
72 [&f, &args...](auto&&... xs_inner) {
73 check_consistent_sizes(function, xs_inner...);
74
75 const std::size_t n
76 = std::get<0>(std::forward_as_tuple(xs_inner...)).size();
77 using T_return = std::decay_t<decltype(f((xs_inner[0])..., args...))>;
78 std::vector<T_return> result;
79 result.reserve(n);
80
81 for (std::size_t i = 0; i < n; ++i) {
82 result.push_back(f((xs_inner[i])..., args...));
83 }
84 return result;
85 },
86 std::forward<Tuple>(xs));
87}
88
104template <typename F, typename T, typename... Args,
105 require_eigen_matrix_dynamic_t<T>* = nullptr>
106inline auto row_map(F&& f, T&& m, Args&&... args) {
107 static constexpr const char* function = "row_map";
108 decltype(auto) m_ref = to_ref(std::forward<T>(m));
109
110 using matrix_t = Eigen::Matrix<
111 scalar_type_t<plain_type_t<decltype(f(m_ref.row(0), args...))>>,
112 Eigen::Dynamic, Eigen::Dynamic>;
113
114 const Eigen::Index n_rows = m_ref.rows();
115 if (n_rows == 0) {
116 return matrix_t(0, 0);
117 }
118
119 auto row_i = eval(f(m_ref.row(0), args...));
120
121 if (row_i.size() == 0) {
122 return matrix_t(0, 0);
123 }
124 matrix_t result(n_rows, row_i.cols());
125 result.row(0) = row_i;
126 for (Eigen::Index i = 1; i < n_rows; ++i) {
127 row_i = f(m_ref.row(i), args...);
128 check_size_match(function, "columns of result", result.cols(),
129 "columns of returned row", row_i.cols());
130 result.row(i) = row_i;
131 }
132 return result;
133}
134
150template <typename F, typename T, typename... Args,
152inline auto col_map(F&& f, T&& m, Args&&... args) {
153 static constexpr const char* function = "col_map";
154 decltype(auto) m_ref = to_ref(std::forward<T>(m));
155
156 using matrix_t = Eigen::Matrix<
157 scalar_type_t<plain_type_t<decltype(f(m_ref.col(0), args...))>>,
158 Eigen::Dynamic, Eigen::Dynamic>;
159
160 const Eigen::Index n_cols = m_ref.cols();
161 if (n_cols == 0) {
162 return matrix_t(0, 0);
163 }
164
165 auto col_j = eval(f(m_ref.col(0), args...));
166
167 if (col_j.size() == 0) {
168 return matrix_t(0, 0);
169 }
170 matrix_t result(col_j.rows(), n_cols);
171 result.col(0) = col_j;
172 for (Eigen::Index j = 1; j < n_cols; ++j) {
173 col_j = f(m_ref.col(j), args...);
174 check_size_match(function, "rows of result", result.rows(),
175 "rows of returned column", col_j.rows());
176 result.col(j) = col_j;
177 }
178 return result;
179}
180
199template <typename F, typename Tuple, typename... Args,
200 require_tuple_t<Tuple>* = nullptr>
201inline auto row_mapN(F&& f, Tuple&& ms, Args&&... args) {
202 static constexpr const char* function = "row_mapN";
203
204 return apply(
205 [&f, &args...](auto&&... mats) {
206 static_assert(
207 (is_eigen_matrix_dynamic<std::decay_t<decltype(mats)>>::value
208 && ...),
209 "row_mapN tuple elements must be Eigen matrices.");
210 check_matching_dims(function, mats...);
211
212 auto m_refs = std::tuple{to_ref(std::forward<decltype(mats)>(mats))...};
213 const Eigen::Index n_rows = std::get<0>(m_refs).rows();
214
215 return apply(
216 [&f, &args..., &n_rows](auto&&... mrs) {
217 using matrix_t
218 = Eigen::Matrix<scalar_type_t<plain_type_t<decltype(
219 f((mrs.row(0))..., args...))>>,
220 Eigen::Dynamic, Eigen::Dynamic>;
221
222 if (n_rows == 0) {
223 return matrix_t(0, 0);
224 }
225
226 auto row_i = eval(f((mrs.row(0))..., args...));
227
228 if (row_i.size() == 0) {
229 return matrix_t(0, 0);
230 }
231 matrix_t result(n_rows, row_i.cols());
232 result.row(0) = row_i;
233 for (Eigen::Index i = 1; i < n_rows; ++i) {
234 row_i = f((mrs.row(i))..., args...);
235 check_size_match(function, "columns of result", result.cols(),
236 "columns of returned row", row_i.cols());
237 result.row(i) = row_i;
238 }
239 return result;
240 },
241 m_refs);
242 },
243 std::forward<Tuple>(ms));
244}
245
264template <typename F, typename Tuple, typename... Args,
265 require_tuple_t<Tuple>* = nullptr>
266inline auto col_mapN(F&& f, Tuple&& ms, Args&&... args) {
267 static constexpr const char* function = "col_mapN";
268
269 return apply(
270 [&f, &args...](auto&&... mats) {
271 static_assert(
272 (is_eigen_matrix_dynamic<std::decay_t<decltype(mats)>>::value
273 && ...),
274 "col_mapN tuple elements must be Eigen matrices.");
275 check_matching_dims(function, mats...);
276
277 auto m_refs = std::tuple{to_ref(std::forward<decltype(mats)>(mats))...};
278 const Eigen::Index n_cols = std::get<0>(m_refs).cols();
279
280 return apply(
281 [&f, &args..., &n_cols](auto&&... mrs) {
282 using matrix_t
283 = Eigen::Matrix<scalar_type_t<plain_type_t<decltype(
284 f((mrs.col(0))..., args...))>>,
285 Eigen::Dynamic, Eigen::Dynamic>;
286
287 if (n_cols == 0) {
288 return matrix_t(0, 0);
289 }
290
291 auto col_j = eval(f((mrs.col(0))..., args...));
292
293 if (col_j.size() == 0) {
294 return matrix_t(0, 0);
295 }
296 matrix_t result(col_j.rows(), n_cols);
297 result.col(0) = col_j;
298 for (Eigen::Index j = 1; j < n_cols; ++j) {
299 col_j = f((mrs.col(j))..., args...);
300 check_size_match(function, "rows of result", result.rows(),
301 "rows of returned column", col_j.rows());
302 result.col(j) = col_j;
303 }
304 return result;
305 },
306 m_refs);
307 },
308 std::forward<Tuple>(ms));
309}
310
311} // namespace math
312} // namespace stan
313
314#endif
require_t< is_eigen_matrix_dynamic< std::decay_t< T > > > require_eigen_matrix_dynamic_t
Require type satisfies is_eigen_matrix_dynamic.
auto map(F &&f, T &&x, Args &&... args)
Return a std::vector whose i-th element is f(x[i], args...).
Definition map.hpp:37
auto col_mapN(F &&f, Tuple &&ms, Args &&... args)
Return a matrix whose j-th column is f(get<0>(ms).col(j), get<1>(ms).col(j), ..., args....
Definition map.hpp:266
T eval(T &&arg)
Inputs which have a plain_type equal to the own time are forwarded unmodified (for Eigen expressions ...
Definition eval.hpp:20
auto row_mapN(F &&f, Tuple &&ms, Args &&... args)
Return a matrix whose i-th row is f(get<0>(ms).row(i), get<1>(ms).row(i), ..., args....
Definition map.hpp:201
auto mapN(F &&f, Tuple &&xs, Args &&... args)
Return a std::vector whose i-th element is f(get<0>(xs)[i], get<1>(xs)[i], ..., args....
Definition map.hpp:68
auto row_map(F &&f, T &&m, Args &&... args)
Return a matrix whose i-th row is f(m.row(i), args...).
Definition map.hpp:106
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
Definition to_ref.hpp:18
void check_size_match(const char *function, const char *name_i, T_size1 i, const char *name_j, T_size2 j)
Check if the provided sizes match.
auto col_map(F &&f, T &&m, Args &&... args)
Return a matrix whose j-th column is f(m.col(j), args...).
Definition map.hpp:152
constexpr decltype(auto) apply(F &&f, Tuple &&t, PreArgs &&... pre_args)
Definition apply.hpp:51
typename plain_type< std::decay_t< T > >::type plain_type_t
typename scalar_type< T >::type scalar_type_t
The lgamma implementation in stan-math is based on either the reentrant safe lgamma_r implementation ...