From e46a24b034c2c0587ebbf94c9d52512c8e17e67d Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 8 Jan 2024 11:45:12 -0500 Subject: [PATCH 1/9] uses Eigen's internal multiindexing for multi indexing on vectors and matrices --- src/stan/model/indexing/rvalue.hpp | 194 ++++++++++--------- src/test/unit/model/indexing/rvalue_test.cpp | 2 +- 2 files changed, 101 insertions(+), 95 deletions(-) diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index 7a07726c33..a8f3e0a2cc 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -151,18 +151,20 @@ inline auto rvalue(Vec&& v, const char* name, index_uni idx) { * @throw std::invalid_argument If the value size isn't the same as * the indexed size. */ -template * = nullptr> -inline auto rvalue(EigVec&& v, const char* name, const index_multi& idx) { +template * = nullptr, + require_same_t* = nullptr> +inline auto rvalue(EigVec&& v, const char* name, MultiIndex&& idx) { + using fwd_t = decltype(stan::math::to_ref(std::forward(v))); + for (auto idx_i : idx.ns_) { + math::check_range("vector[multi] indexing", name, v.size(), idx_i); + } return stan::math::make_holder( - [name, &idx](auto& v_ref) { - return plain_type_t::NullaryExpr( - idx.ns_.size(), [name, &idx, &v_ref](Eigen::Index i) { - math::check_range("vector[multi] indexing", name, v_ref.size(), - idx.ns_[i]); - return v_ref.coeff(idx.ns_[i] - 1); - }); - }, - stan::math::to_ref(v)); + [name](auto&& v_ref, auto&& idx_inner) { + Eigen::Map> idx2(idx_inner.ns_.data(), idx_inner.ns_.size()); + return std::forward(v_ref)(idx2 - 1); + }, + std::forward(stan::math::to_ref(std::forward(v))), + std::forward(idx)); } /** @@ -262,21 +264,19 @@ inline auto rvalue(Mat&& x, const char* name, index_uni idx) { * @param[in] idx A multi index for selecting a set of rows. * @throw std::out_of_range If any of the indices are out of bounds. */ -template * = nullptr> -inline plain_type_t rvalue(EigMat&& x, const char* name, - const index_multi& idx) { +template * = nullptr, + require_same_t* = nullptr> +inline auto rvalue(EigMat&& x, const char* name, + MultiIndex&& idx) { for (int i = 0; i < idx.ns_.size(); ++i) { math::check_range("matrix[multi] row indexing", name, x.rows(), idx.ns_[i]); } return stan::math::make_holder( - [&idx](auto& x_ref) { - return plain_type_t::NullaryExpr( - idx.ns_.size(), x_ref.cols(), - [&idx, &x_ref](Eigen::Index i, Eigen::Index j) { - return x_ref.coeff(idx.ns_[i] - 1, j); - }); + [&idx](auto&& x_ref, auto&& idx_inner) { + using vec_map = Eigen::Map>; + return x_ref((vec_map(idx_inner.ns_.data(), idx_inner.ns_.size()) - 1), Eigen::all); }, - stan::math::to_ref(x)); + stan::math::to_ref(x), std::forward(idx)); } /** @@ -425,23 +425,23 @@ inline auto rvalue(Mat&& x, const char* name, index_uni row_idx, * @param[in] col_idx multi index for selecting cols. * @throw std::out_of_range If any of the indices are out of bounds. */ -template * = nullptr> -inline Eigen::Matrix, 1, Eigen::Dynamic> rvalue( - EigMat&& x, const char* name, index_uni row_idx, - const index_multi& col_idx) { +template * = nullptr, + require_same_t* = nullptr> +inline auto rvalue(EigMat&& x, const char* name, index_uni row_idx, + MultiIndex&& col_idx) { math::check_range("matrix[uni, multi] row indexing", name, x.rows(), row_idx.n_); + for (auto idx_i : col_idx.ns_) { + math::check_range("matrix[uni, multi] column indexing", name, x.cols(), + idx_i); + } return stan::math::make_holder( - [name, row_idx, &col_idx](auto& x_ref) { - return Eigen::Matrix, 1, Eigen::Dynamic>:: - NullaryExpr(col_idx.ns_.size(), [name, row_i = row_idx.n_ - 1, - &col_idx, &x_ref](Eigen::Index i) { - math::check_range("matrix[uni, multi] column indexing", name, - x_ref.cols(), col_idx.ns_[i]); - return x_ref.coeff(row_i, col_idx.ns_[i] - 1); - }); + [name, row_idx](auto&& x_ref, auto&& col_idx_inner) { + using vec_map = Eigen::Map>; + return x_ref(row_idx.n_ - 1, (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)); }, - stan::math::to_ref(x)); + stan::math::to_ref(std::forward(x)), + std::forward(col_idx)); } /** @@ -457,25 +457,22 @@ inline Eigen::Matrix, 1, Eigen::Dynamic> rvalue( * @param[in] col_idx uni index for selecting cols. * @throw std::out_of_range If any of the indices are out of bounds. */ -template * = nullptr> -inline Eigen::Matrix, Eigen::Dynamic, 1> rvalue( - EigMat&& x, const char* name, const index_multi& row_idx, +template * = nullptr, + require_same_t* = nullptr> +inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& row_idx, index_uni col_idx) { math::check_range("matrix[multi, uni] column indexing", name, x.cols(), col_idx.n_); - + for (auto idx_i : row_idx.ns_) { + math::check_range("matrix[uni, multi] row indexing", name, x.rows(), + idx_i); + } return stan::math::make_holder( - [name, &row_idx, col_idx](auto& x_ref) { - return Eigen::Matrix, Eigen::Dynamic, 1>:: - NullaryExpr(row_idx.ns_.size(), - [name, &row_idx, col_i = col_idx.n_ - 1, - &x_ref](Eigen::Index i) { - math::check_range("matrix[multi, uni] row indexing", - name, x_ref.rows(), row_idx.ns_[i]); - return x_ref.coeff(row_idx.ns_[i] - 1, col_i); - }); + [name, col_idx](auto&& x_ref, auto&& row_idx_inner) { + using vec_map = Eigen::Map>; + return x_ref((vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), col_idx.n_ - 1); }, - stan::math::to_ref(x)); + stan::math::to_ref(x), std::forward(row_idx)); } /** @@ -491,26 +488,30 @@ inline Eigen::Matrix, Eigen::Dynamic, 1> rvalue( * @param[in] col_idx multi index for selecting cols. * @return Result of indexing matrix. */ -template * = nullptr> -inline plain_type_t rvalue(EigMat&& x, const char* name, - const index_multi& row_idx, - const index_multi& col_idx) { - const auto& x_ref = stan::math::to_ref(x); +template * = nullptr, + require_all_same_t * = nullptr> +inline auto rvalue(EigMat&& x, const char* name, RowIndexMulti&& row_idx, + ColIndexMulti&& col_idx) { const Eigen::Index rows = row_idx.ns_.size(); const Eigen::Index cols = col_idx.ns_.size(); - plain_type_t x_ret(rows, cols); - for (Eigen::Index j = 0; j < cols; ++j) { - for (Eigen::Index i = 0; i < rows; ++i) { - const Eigen::Index m = row_idx.ns_[i]; - const Eigen::Index n = col_idx.ns_[j]; - math::check_range("matrix[multi,multi] row indexing", name, x_ref.rows(), - m); - math::check_range("matrix[multi,multi] column indexing", name, - x_ref.cols(), n); - x_ret.coeffRef(i, j) = x_ref.coeff(m - 1, n - 1); - } + for (auto idx_i : row_idx.ns_) { + math::check_range("matrix[uni, multi] row indexing", name, x.rows(), + idx_i); } - return x_ret; + for (auto idx_j : col_idx.ns_) { + math::check_range("matrix[uni, multi] col indexing", name, x.cols(), + idx_j); + } + return stan::math::make_holder( + [name](auto&& x_ref, auto&& row_idx_inner, auto&& col_idx_inner) { + using vec_map = Eigen::Map>; + return x_ref((vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), + (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)); + }, + stan::math::to_ref(std::forward(x)), + std::forward(row_idx), + std::forward(col_idx)); } /** @@ -547,22 +548,27 @@ inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, * @param[in] col_idx multi index for selecting cols. * @return Result of indexing matrix. */ -template * = nullptr, - require_not_same_t, index_uni>* = nullptr> -inline plain_type_t rvalue(EigMat&& x, const char* name, - const Idx& row_idx, - const index_multi& col_idx) { - const auto& x_ref = stan::math::to_ref(x); - const int rows = rvalue_index_size(row_idx, x_ref.rows()); - plain_type_t x_ret(rows, col_idx.ns_.size()); - for (int j = 0; j < col_idx.ns_.size(); ++j) { - const Eigen::Index n = col_idx.ns_[j]; - math::check_range("matrix[..., multi] column indexing", name, x_ref.cols(), - n); - x_ret.col(j) = rvalue(x_ref.col(n - 1), name, row_idx); + require_not_same_t, index_uni>* = nullptr, + require_same_t* = nullptr> +inline auto rvalue(EigMat&& x, const char* name, + Idx&& row_idx, + MultiIndex&& col_idx) { + for (auto idx_j : col_idx.ns_) { + math::check_range("matrix[..., multi] column indexing", name, x.cols(), + idx_j); } - return x_ret; + return stan::math::make_holder( + [name](auto&& x_ref, auto&& row_idx_inner, auto&& col_idx_inner) { + using vec_map = Eigen::Map>; + return rvalue(x_ref(Eigen::all, + (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)), + name, std::forward(row_idx_inner)); + }, + stan::math::to_ref(std::forward(x)), + std::forward(row_idx), + std::forward(col_idx)); } /** @@ -578,9 +584,9 @@ inline plain_type_t rvalue(EigMat&& x, const char* name, * @throw std::out_of_range If any of the indices are out of bounds. */ template * = nullptr> -inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, +inline auto rvalue(Mat&& x, const char* name, Idx&& row_idx, index_omni /*col_idx*/) { - return rvalue(std::forward(x), name, row_idx); + return rvalue(std::forward(x), name, std::forward(row_idx)); } /** @@ -599,12 +605,12 @@ inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, * @throw std::out_of_range If any of the indices are out of bounds. */ template * = nullptr> -inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, +inline auto rvalue(Mat&& x, const char* name, Idx&& row_idx, index_min col_idx) { const Eigen::Index col_size = x.cols() - (col_idx.min_ - 1); math::check_range("matrix[..., min] column indexing", name, x.cols(), col_idx.min_); - return rvalue(x.rightCols(col_size), name, row_idx); + return rvalue(x.rightCols(col_size), name, std::forward(row_idx)); } /** @@ -623,14 +629,14 @@ inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, * @throw std::out_of_range If any of the indices are out of bounds. */ template * = nullptr> -inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, +inline auto rvalue(Mat&& x, const char* name, Idx&& row_idx, index_max col_idx) { if (col_idx.max_ > 0) { math::check_range("matrix[..., max] column indexing", name, x.cols(), col_idx.max_); - return rvalue(x.leftCols(col_idx.max_), name, row_idx); + return rvalue(x.leftCols(col_idx.max_), name, std::forward(row_idx)); } else { - return rvalue(x.leftCols(0), name, row_idx); + return rvalue(x.leftCols(0), name, std::forward(row_idx)); } } @@ -650,7 +656,7 @@ inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, * @return Result of indexing matrix. */ template * = nullptr> -inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, +inline auto rvalue(Mat&& x, const char* name, Idx&& row_idx, index_min_max col_idx) { math::check_range("matrix[..., min_max] min column indexing", name, x.cols(), col_idx.min_); @@ -659,9 +665,9 @@ inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, math::check_range("matrix[..., min_max] max column indexing", name, x.cols(), col_idx.max_); return rvalue(x.middleCols(col_start, col_idx.max_ - col_start), name, - row_idx); + std::forward(row_idx)); } else { - return rvalue(x.middleCols(col_start, 0), name, row_idx); + return rvalue(x.middleCols(col_start, 0), name, std::forward(row_idx)); } } @@ -685,16 +691,16 @@ template * = nullptr, require_not_t>* = nullptr> inline auto rvalue(StdVec&& v, const char* name, index_uni idx1, - const Idxs&... idxs) { + Idxs&&... idxs) { math::check_range("array[uni, ...] index", name, v.size(), idx1.n_); - return rvalue(std::move(v[idx1.n_ - 1]), name, idxs...); + return rvalue(std::move(v[idx1.n_ - 1]), name, std::forward(idxs)...); } template * = nullptr> inline auto rvalue(StdVec& v, const char* name, index_uni idx1, - const Idxs&... idxs) { + Idxs&&... idxs) { math::check_range("array[uni, ...] index", name, v.size(), idx1.n_); - return rvalue(v[idx1.n_ - 1], name, idxs...); + return rvalue(v[idx1.n_ - 1], name, std::forward(idxs)...); } /** @@ -749,7 +755,7 @@ template * = nullptr, require_not_same_t* = nullptr> inline auto rvalue(StdVec&& v, const char* name, const Idx1& idx1, - const Idxs&... idxs) { + Idxs&&... idxs) { using inner_type = plain_type_t; const auto index_size = rvalue_index_size(idx1, v.size()); diff --git a/src/test/unit/model/indexing/rvalue_test.cpp b/src/test/unit/model/indexing/rvalue_test.cpp index d9abc7b6e6..1a5678c579 100644 --- a/src/test/unit/model/indexing/rvalue_test.cpp +++ b/src/test/unit/model/indexing/rvalue_test.cpp @@ -719,7 +719,7 @@ void vector_multi_test() { test_out_of_range(v, index_multi(ns)); } -TEST(ModelIndexing, rvalueVectorMulti) { vector_multi_test(); } +TEST(ModelIndexing, x) { vector_multi_test(); } TEST(ModelIndexing, rvalueRowVectorMulti) { vector_multi_test(); From fc3d4ff3da500f69828809a897c74d33aa9a039b Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 8 Jan 2024 11:59:34 -0500 Subject: [PATCH 2/9] fix docs --- src/stan/model/indexing/rvalue.hpp | 127 ++++++++++++++++------------- 1 file changed, 72 insertions(+), 55 deletions(-) diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index a8f3e0a2cc..2a23c9fba7 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -144,6 +144,7 @@ inline auto rvalue(Vec&& v, const char* name, index_uni idx) { * Types: vector[multi] = vector * * @tparam EigVec Eigen type with either dynamic rows or columns, but not both. + * @tparam MultiIndex A multi index. * @param[in] v Eigen vector type. * @param[in] name Name of variable * @param[in] idx Sequence of integers. @@ -151,20 +152,22 @@ inline auto rvalue(Vec&& v, const char* name, index_uni idx) { * @throw std::invalid_argument If the value size isn't the same as * the indexed size. */ -template * = nullptr, - require_same_t* = nullptr> +template * = nullptr, + require_same_t* = nullptr> inline auto rvalue(EigVec&& v, const char* name, MultiIndex&& idx) { using fwd_t = decltype(stan::math::to_ref(std::forward(v))); for (auto idx_i : idx.ns_) { math::check_range("vector[multi] indexing", name, v.size(), idx_i); } return stan::math::make_holder( - [name](auto&& v_ref, auto&& idx_inner) { - Eigen::Map> idx2(idx_inner.ns_.data(), idx_inner.ns_.size()); - return std::forward(v_ref)(idx2 - 1); - }, - std::forward(stan::math::to_ref(std::forward(v))), - std::forward(idx)); + [name](auto&& v_ref, auto&& idx_inner) { + Eigen::Map> idx2(idx_inner.ns_.data(), + idx_inner.ns_.size()); + return std::forward(v_ref)(idx2 - 1); + }, + std::forward(stan::math::to_ref(std::forward(v))), + std::forward(idx)); } /** @@ -259,22 +262,24 @@ inline auto rvalue(Mat&& x, const char* name, index_uni idx) { * Types: matrix[multi] = matrix * * @tparam EigMat Eigen type with dynamic rows and columns. + * @tparam MultiIndex A multi index. * @param[in] x Eigen type * @param[in] name Name of variable * @param[in] idx A multi index for selecting a set of rows. * @throw std::out_of_range If any of the indices are out of bounds. */ -template * = nullptr, - require_same_t* = nullptr> -inline auto rvalue(EigMat&& x, const char* name, - MultiIndex&& idx) { +template * = nullptr, + require_same_t* = nullptr> +inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& idx) { for (int i = 0; i < idx.ns_.size(); ++i) { math::check_range("matrix[multi] row indexing", name, x.rows(), idx.ns_[i]); } return stan::math::make_holder( [&idx](auto&& x_ref, auto&& idx_inner) { using vec_map = Eigen::Map>; - return x_ref((vec_map(idx_inner.ns_.data(), idx_inner.ns_.size()) - 1), Eigen::all); + return x_ref((vec_map(idx_inner.ns_.data(), idx_inner.ns_.size()) - 1), + Eigen::all); }, stan::math::to_ref(x), std::forward(idx)); } @@ -419,29 +424,33 @@ inline auto rvalue(Mat&& x, const char* name, index_uni row_idx, * Types: matrix[uni, multi] = row vector * * @tparam EigMat Eigen type with dynamic rows and columns. + * @tparam MultiIndex A multi index. * @param[in] x Matrix to index. * @param[in] name Name of variable * @param[in] row_idx uni index for selecting rows. * @param[in] col_idx multi index for selecting cols. * @throw std::out_of_range If any of the indices are out of bounds. */ -template * = nullptr, - require_same_t* = nullptr> +template * = nullptr, + require_same_t* = nullptr> inline auto rvalue(EigMat&& x, const char* name, index_uni row_idx, - MultiIndex&& col_idx) { + MultiIndex&& col_idx) { math::check_range("matrix[uni, multi] row indexing", name, x.rows(), row_idx.n_); for (auto idx_i : col_idx.ns_) { - math::check_range("matrix[uni, multi] column indexing", name, x.cols(), - idx_i); + math::check_range("matrix[uni, multi] column indexing", name, x.cols(), + idx_i); } return stan::math::make_holder( [name, row_idx](auto&& x_ref, auto&& col_idx_inner) { using vec_map = Eigen::Map>; - return x_ref(row_idx.n_ - 1, (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)); + return x_ref( + row_idx.n_ - 1, + (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)); }, stan::math::to_ref(std::forward(x)), - std::forward(col_idx)); + std::forward(col_idx)); } /** @@ -451,26 +460,29 @@ inline auto rvalue(EigMat&& x, const char* name, index_uni row_idx, * Types: matrix[multi, uni] = vector * * @tparam EigMat Eigen type with dynamic rows and columns. + * @tparam MultiIndex A multi index. * @param[in] x Matrix to index. * @param[in] name Name of variable * @param[in] row_idx multi index for selecting rows. * @param[in] col_idx uni index for selecting cols. * @throw std::out_of_range If any of the indices are out of bounds. */ -template * = nullptr, - require_same_t* = nullptr> +template * = nullptr, + require_same_t* = nullptr> inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& row_idx, - index_uni col_idx) { + index_uni col_idx) { math::check_range("matrix[multi, uni] column indexing", name, x.cols(), col_idx.n_); for (auto idx_i : row_idx.ns_) { - math::check_range("matrix[uni, multi] row indexing", name, x.rows(), - idx_i); + math::check_range("matrix[uni, multi] row indexing", name, x.rows(), idx_i); } return stan::math::make_holder( [name, col_idx](auto&& x_ref, auto&& row_idx_inner) { using vec_map = Eigen::Map>; - return x_ref((vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), col_idx.n_ - 1); + return x_ref( + (vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), + col_idx.n_ - 1); }, stan::math::to_ref(x), std::forward(row_idx)); } @@ -482,36 +494,38 @@ inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& row_idx, * Types: matrix[multi, multi] = matrix * * @tparam EigMat An eigen matrix + * @tparam RowMultiIndex A multi index. + * @tparam ColMultiIndex A multi index. * @param[in] x Matrix to index. * @param[in] name String form of expression being evaluated. * @param[in] row_idx multi index for selecting rows. * @param[in] col_idx multi index for selecting cols. * @return Result of indexing matrix. */ -template * = nullptr, - require_all_same_t * = nullptr> -inline auto rvalue(EigMat&& x, const char* name, RowIndexMulti&& row_idx, - ColIndexMulti&& col_idx) { +template < + typename EigMat, typename RowIndexMulti, typename ColIndexMulti, + require_eigen_dense_dynamic_t* = nullptr, + require_all_same_t* = nullptr> +inline auto rvalue(EigMat&& x, const char* name, RowMultiMulti&& row_idx, + ColMultiIndex&& col_idx) { const Eigen::Index rows = row_idx.ns_.size(); const Eigen::Index cols = col_idx.ns_.size(); for (auto idx_i : row_idx.ns_) { - math::check_range("matrix[uni, multi] row indexing", name, x.rows(), - idx_i); + math::check_range("matrix[uni, multi] row indexing", name, x.rows(), idx_i); } for (auto idx_j : col_idx.ns_) { - math::check_range("matrix[uni, multi] col indexing", name, x.cols(), - idx_j); + math::check_range("matrix[uni, multi] col indexing", name, x.cols(), idx_j); } return stan::math::make_holder( [name](auto&& x_ref, auto&& row_idx_inner, auto&& col_idx_inner) { using vec_map = Eigen::Map>; - return x_ref((vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), - (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)); + return x_ref( + (vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), + (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)); }, stan::math::to_ref(std::forward(x)), - std::forward(row_idx), - std::forward(col_idx)); + std::forward(row_idx), + std::forward(col_idx)); } /** @@ -542,7 +556,9 @@ inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, * Types: matrix[Idx, multi] = matrix * * @tparam EigMat An eigen matrix - * @param[in] x Eigen matrix. + * @tparam Idx An index type + * @tparam MultiIndex A multi index + * @param[in] x Eigen matrix * @param[in] name String form of expression being evaluated. * @param[in] row_idx index for selecting rows. * @param[in] col_idx multi index for selecting cols. @@ -552,23 +568,23 @@ template * = nullptr, require_not_same_t, index_uni>* = nullptr, require_same_t* = nullptr> -inline auto rvalue(EigMat&& x, const char* name, - Idx&& row_idx, - MultiIndex&& col_idx) { +inline auto rvalue(EigMat&& x, const char* name, Idx&& row_idx, + MultiIndex&& col_idx) { for (auto idx_j : col_idx.ns_) { - math::check_range("matrix[..., multi] column indexing", name, x.cols(), - idx_j); + math::check_range("matrix[..., multi] column indexing", name, x.cols(), + idx_j); } return stan::math::make_holder( [name](auto&& x_ref, auto&& row_idx_inner, auto&& col_idx_inner) { using vec_map = Eigen::Map>; - return rvalue(x_ref(Eigen::all, - (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)), - name, std::forward(row_idx_inner)); + return rvalue( + x_ref(Eigen::all, + (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) + - 1)), + name, std::forward(row_idx_inner)); }, - stan::math::to_ref(std::forward(x)), - std::forward(row_idx), - std::forward(col_idx)); + stan::math::to_ref(std::forward(x)), std::forward(row_idx), + std::forward(col_idx)); } /** @@ -578,6 +594,7 @@ inline auto rvalue(EigMat&& x, const char* name, * * @tparam Mat An eigen matrix or `var_value` whose inner type is an Eigen * matrix. + * @tparam Idx An index type * @param[in] x type * @param[in] name Name of variable * @param[in] row_idx index for selecting rows. @@ -680,7 +697,7 @@ inline auto rvalue(Mat&& x, const char* name, Idx&& row_idx, * Types: std::vector[uni | Idx] : T[Idx] * * @tparam T Type of list elements. - * @tparam Idx Index list type for indexes after first index. + * @tparam Idxs Index list type for indexes after first index. * @param[in] v Container of list elements. * @param[in] name String form of expression being evaluated. * @param[in] idx1 first index. @@ -744,7 +761,7 @@ inline auto rvalue(StdVec&& v, const char* name, index_uni idx) { * * @tparam T Type of list elements. * @tparam Idx1 Index list type for first index. - * @tparam Idx2 Index list type for second index index. + * @tparam Idxs Index list type for second index index. * @param[in] v Container of list elements. * @param[in] name String form of expression being evaluated. * @param[in] idx1 first index @@ -756,8 +773,8 @@ template * = nullptr> inline auto rvalue(StdVec&& v, const char* name, const Idx1& idx1, Idxs&&... idxs) { - using inner_type = plain_type_t; + using inner_type = plain_type_t; const auto index_size = rvalue_index_size(idx1, v.size()); stan::math::check_greater_or_equal("array[..., ...] indexing", "size", index_size, 0); From cb7d951e0db1796efd2f560e561da0892caff772 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 8 Jan 2024 12:00:14 -0500 Subject: [PATCH 3/9] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- src/stan/model/indexing/rvalue.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index 2a23c9fba7..473529d282 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -773,8 +773,8 @@ template * = nullptr> inline auto rvalue(StdVec&& v, const char* name, const Idx1& idx1, Idxs&&... idxs) { - using inner_type = plain_type_t; + using inner_type = plain_type_t; const auto index_size = rvalue_index_size(idx1, v.size()); stan::math::check_greater_or_equal("array[..., ...] indexing", "size", index_size, 0); From 0218f2e596d858d6cf0e4ec911fe00a5bdee8d7b Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Mon, 8 Jan 2024 12:36:02 -0500 Subject: [PATCH 4/9] fix template error --- src/stan/model/indexing/rvalue.hpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index 473529d282..6767d499d3 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -503,10 +503,11 @@ inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& row_idx, * @return Result of indexing matrix. */ template < - typename EigMat, typename RowIndexMulti, typename ColIndexMulti, + typename EigMat, typename RowMultiIndex, typename ColMultiIndex, require_eigen_dense_dynamic_t* = nullptr, - require_all_same_t* = nullptr> -inline auto rvalue(EigMat&& x, const char* name, RowMultiMulti&& row_idx, + require_same_t* = nullptr, + require_same_t* = nullptr> +inline auto rvalue(EigMat&& x, const char* name, RowMultiIndex&& row_idx, ColMultiIndex&& col_idx) { const Eigen::Index rows = row_idx.ns_.size(); const Eigen::Index cols = col_idx.ns_.size(); From 0173de3f4f0c0a4a50cedaf560bbffe1814d4246 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Mon, 8 Jan 2024 12:36:39 -0500 Subject: [PATCH 5/9] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- src/stan/model/indexing/rvalue.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index 6767d499d3..330a5bd2e5 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -502,11 +502,10 @@ inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& row_idx, * @param[in] col_idx multi index for selecting cols. * @return Result of indexing matrix. */ -template < - typename EigMat, typename RowMultiIndex, typename ColMultiIndex, - require_eigen_dense_dynamic_t* = nullptr, - require_same_t* = nullptr, - require_same_t* = nullptr> +template * = nullptr, + require_same_t* = nullptr, + require_same_t* = nullptr> inline auto rvalue(EigMat&& x, const char* name, RowMultiIndex&& row_idx, ColMultiIndex&& col_idx) { const Eigen::Index rows = row_idx.ns_.size(); From 6dc3f4c669b39724f8b33af6d3735b75a54bbc45 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Wed, 10 Jan 2024 16:05:04 -0500 Subject: [PATCH 6/9] fix requires for rvalue --- src/stan/model/indexing/rvalue.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index 330a5bd2e5..c4ebe1ba0e 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -567,6 +567,7 @@ inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx, template * = nullptr, require_not_same_t, index_uni>* = nullptr, + require_not_same_t, index_multi>* = nullptr, require_same_t* = nullptr> inline auto rvalue(EigMat&& x, const char* name, Idx&& row_idx, MultiIndex&& col_idx) { From b20db94abfcd61189c617d065f1558bd601ad5bb Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 11 Jan 2024 14:09:20 -0500 Subject: [PATCH 7/9] Make Eigen::Map for indexing have an inner const type --- src/stan/model/indexing/rvalue.hpp | 44 +++++++++++++++++------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index c4ebe1ba0e..c6b555a49e 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -157,12 +157,13 @@ template * = nullptr> inline auto rvalue(EigVec&& v, const char* name, MultiIndex&& idx) { using fwd_t = decltype(stan::math::to_ref(std::forward(v))); + const auto v_size = v.size(); for (auto idx_i : idx.ns_) { - math::check_range("vector[multi] indexing", name, v.size(), idx_i); + math::check_range("vector[multi] indexing", name, v_size, idx_i); } return stan::math::make_holder( - [name](auto&& v_ref, auto&& idx_inner) { - Eigen::Map> idx2(idx_inner.ns_.data(), + [](auto&& v_ref, auto&& idx_inner) { + Eigen::Map> idx2(idx_inner.ns_.data(), idx_inner.ns_.size()); return std::forward(v_ref)(idx2 - 1); }, @@ -276,12 +277,12 @@ inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& idx) { math::check_range("matrix[multi] row indexing", name, x.rows(), idx.ns_[i]); } return stan::math::make_holder( - [&idx](auto&& x_ref, auto&& idx_inner) { - using vec_map = Eigen::Map>; + [](auto&& x_ref, auto&& idx_inner) { + using vec_map = Eigen::Map>; return x_ref((vec_map(idx_inner.ns_.data(), idx_inner.ns_.size()) - 1), Eigen::all); }, - stan::math::to_ref(x), std::forward(idx)); + stan::math::to_ref(std::forward(x)), std::forward(idx)); } /** @@ -438,13 +439,14 @@ inline auto rvalue(EigMat&& x, const char* name, index_uni row_idx, MultiIndex&& col_idx) { math::check_range("matrix[uni, multi] row indexing", name, x.rows(), row_idx.n_); + const auto x_cols = x.cols(); for (auto idx_i : col_idx.ns_) { - math::check_range("matrix[uni, multi] column indexing", name, x.cols(), + math::check_range("matrix[uni, multi] column indexing", name, x_cols, idx_i); } return stan::math::make_holder( - [name, row_idx](auto&& x_ref, auto&& col_idx_inner) { - using vec_map = Eigen::Map>; + [row_idx](auto&& x_ref, auto&& col_idx_inner) { + using vec_map = Eigen::Map>; return x_ref( row_idx.n_ - 1, (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)); @@ -474,17 +476,18 @@ inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& row_idx, index_uni col_idx) { math::check_range("matrix[multi, uni] column indexing", name, x.cols(), col_idx.n_); + const auto x_rows = x.rows(); for (auto idx_i : row_idx.ns_) { - math::check_range("matrix[uni, multi] row indexing", name, x.rows(), idx_i); + math::check_range("matrix[uni, multi] row indexing", name, x_rows, idx_i); } return stan::math::make_holder( - [name, col_idx](auto&& x_ref, auto&& row_idx_inner) { - using vec_map = Eigen::Map>; + [col_idx](auto&& x_ref, auto&& row_idx_inner) { + using vec_map = Eigen::Map>; return x_ref( (vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), col_idx.n_ - 1); }, - stan::math::to_ref(x), std::forward(row_idx)); + stan::math::to_ref(std::forward(x)), std::forward(row_idx)); } /** @@ -510,15 +513,17 @@ inline auto rvalue(EigMat&& x, const char* name, RowMultiIndex&& row_idx, ColMultiIndex&& col_idx) { const Eigen::Index rows = row_idx.ns_.size(); const Eigen::Index cols = col_idx.ns_.size(); + const auto x_rows = x.rows(); + const auto x_cols = x.cols(); for (auto idx_i : row_idx.ns_) { - math::check_range("matrix[uni, multi] row indexing", name, x.rows(), idx_i); + math::check_range("matrix[uni, multi] row indexing", name, x_rows, idx_i); } for (auto idx_j : col_idx.ns_) { - math::check_range("matrix[uni, multi] col indexing", name, x.cols(), idx_j); + math::check_range("matrix[uni, multi] col indexing", name, x_cols, idx_j); } return stan::math::make_holder( - [name](auto&& x_ref, auto&& row_idx_inner, auto&& col_idx_inner) { - using vec_map = Eigen::Map>; + [](auto&& x_ref, auto&& row_idx_inner, auto&& col_idx_inner) { + using vec_map = Eigen::Map>; return x_ref( (vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) - 1)); @@ -571,13 +576,14 @@ template * = nullptr> inline auto rvalue(EigMat&& x, const char* name, Idx&& row_idx, MultiIndex&& col_idx) { + const auto x_cols = x.cols(); for (auto idx_j : col_idx.ns_) { - math::check_range("matrix[..., multi] column indexing", name, x.cols(), + math::check_range("matrix[..., multi] column indexing", name, x_cols, idx_j); } return stan::math::make_holder( [name](auto&& x_ref, auto&& row_idx_inner, auto&& col_idx_inner) { - using vec_map = Eigen::Map>; + using vec_map = Eigen::Map>; return rvalue( x_ref(Eigen::all, (vec_map(col_idx_inner.ns_.data(), col_idx_inner.ns_.size()) From a84f6a96717d2d6b42ebc61ab444e842e4645c75 Mon Sep 17 00:00:00 2001 From: Stan Jenkins Date: Thu, 11 Jan 2024 14:10:00 -0500 Subject: [PATCH 8/9] [Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1 --- src/stan/model/indexing/rvalue.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/stan/model/indexing/rvalue.hpp b/src/stan/model/indexing/rvalue.hpp index c6b555a49e..3090ece9cc 100644 --- a/src/stan/model/indexing/rvalue.hpp +++ b/src/stan/model/indexing/rvalue.hpp @@ -164,7 +164,7 @@ inline auto rvalue(EigVec&& v, const char* name, MultiIndex&& idx) { return stan::math::make_holder( [](auto&& v_ref, auto&& idx_inner) { Eigen::Map> idx2(idx_inner.ns_.data(), - idx_inner.ns_.size()); + idx_inner.ns_.size()); return std::forward(v_ref)(idx2 - 1); }, std::forward(stan::math::to_ref(std::forward(v))), @@ -282,7 +282,8 @@ inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& idx) { return x_ref((vec_map(idx_inner.ns_.data(), idx_inner.ns_.size()) - 1), Eigen::all); }, - stan::math::to_ref(std::forward(x)), std::forward(idx)); + stan::math::to_ref(std::forward(x)), + std::forward(idx)); } /** @@ -487,7 +488,8 @@ inline auto rvalue(EigMat&& x, const char* name, MultiIndex&& row_idx, (vec_map(row_idx_inner.ns_.data(), row_idx_inner.ns_.size()) - 1), col_idx.n_ - 1); }, - stan::math::to_ref(std::forward(x)), std::forward(row_idx)); + stan::math::to_ref(std::forward(x)), + std::forward(row_idx)); } /** From cc1cf334b0b8060a0e499a1884f7014002298f89 Mon Sep 17 00:00:00 2001 From: Steve Bronder Date: Thu, 18 Jan 2024 12:38:15 -0500 Subject: [PATCH 9/9] change back name of rvalue test function --- src/test/unit/model/indexing/rvalue_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/unit/model/indexing/rvalue_test.cpp b/src/test/unit/model/indexing/rvalue_test.cpp index 1a5678c579..d9abc7b6e6 100644 --- a/src/test/unit/model/indexing/rvalue_test.cpp +++ b/src/test/unit/model/indexing/rvalue_test.cpp @@ -719,7 +719,7 @@ void vector_multi_test() { test_out_of_range(v, index_multi(ns)); } -TEST(ModelIndexing, x) { vector_multi_test(); } +TEST(ModelIndexing, rvalueVectorMulti) { vector_multi_test(); } TEST(ModelIndexing, rvalueRowVectorMulti) { vector_multi_test();