1#ifndef STAN_MATH_PRIM_FUNCTOR_MAP_HPP
2#define STAN_MATH_PRIM_FUNCTOR_MAP_HPP
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());
43 result.push_back(f(xi, args...));
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";
72 [&f, &args...](
auto&&... xs_inner) {
73 check_consistent_sizes(function, xs_inner...);
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;
81 for (std::size_t i = 0; i < n; ++i) {
82 result.push_back(f((xs_inner[i])..., args...));
86 std::forward<Tuple>(xs));
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));
110 using matrix_t = Eigen::Matrix<
112 Eigen::Dynamic, Eigen::Dynamic>;
114 const Eigen::Index n_rows = m_ref.rows();
116 return matrix_t(0, 0);
119 auto row_i =
eval(f(m_ref.row(0), args...));
121 if (row_i.size() == 0) {
122 return matrix_t(0, 0);
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...);
129 "columns of returned row", row_i.cols());
130 result.row(i) = row_i;
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));
156 using matrix_t = Eigen::Matrix<
158 Eigen::Dynamic, Eigen::Dynamic>;
160 const Eigen::Index n_cols = m_ref.cols();
162 return matrix_t(0, 0);
165 auto col_j =
eval(f(m_ref.col(0), args...));
167 if (col_j.size() == 0) {
168 return matrix_t(0, 0);
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...);
175 "rows of returned column", col_j.rows());
176 result.col(j) = col_j;
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";
205 [&f, &args...](
auto&&... mats) {
207 (is_eigen_matrix_dynamic<std::decay_t<decltype(mats)>>::value
209 "row_mapN tuple elements must be Eigen matrices.");
210 check_matching_dims(function, mats...);
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();
216 [&f, &args..., &n_rows](
auto&&... mrs) {
218 = Eigen::Matrix<scalar_type_t<plain_type_t<decltype(
219 f((mrs.row(0))..., args...))>>,
220 Eigen::Dynamic, Eigen::Dynamic>;
223 return matrix_t(0, 0);
226 auto row_i =
eval(f((mrs.row(0))..., args...));
228 if (row_i.size() == 0) {
229 return matrix_t(0, 0);
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...);
236 "columns of returned row", row_i.cols());
237 result.row(i) = row_i;
243 std::forward<Tuple>(ms));
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";
270 [&f, &args...](
auto&&... mats) {
272 (is_eigen_matrix_dynamic<std::decay_t<decltype(mats)>>::value
274 "col_mapN tuple elements must be Eigen matrices.");
275 check_matching_dims(function, mats...);
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();
281 [&f, &args..., &n_cols](
auto&&... mrs) {
283 = Eigen::Matrix<scalar_type_t<plain_type_t<decltype(
284 f((mrs.col(0))..., args...))>>,
285 Eigen::Dynamic, Eigen::Dynamic>;
288 return matrix_t(0, 0);
291 auto col_j =
eval(f((mrs.col(0))..., args...));
293 if (col_j.size() == 0) {
294 return matrix_t(0, 0);
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...);
301 "rows of returned column", col_j.rows());
302 result.col(j) = col_j;
308 std::forward<Tuple>(ms));
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...).
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....
T eval(T &&arg)
Inputs which have a plain_type equal to the own time are forwarded unmodified (for Eigen expressions ...
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....
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....
auto row_map(F &&f, T &&m, Args &&... args)
Return a matrix whose i-th row is f(m.row(i), args...).
ref_type_t< T && > to_ref(T &&a)
This evaluates expensive Eigen expressions.
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...).
constexpr decltype(auto) apply(F &&f, Tuple &&t, PreArgs &&... pre_args)
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 ...