1 #ifndef STAN_MODEL_INDEXING_RVALUE_HPP
2 #define STAN_MODEL_INDEXING_RVALUE_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/err.hpp>
6 #include <stan/math/prim/fun/to_ref.hpp>
7 #include <stan/model/indexing/index.hpp>
8 #include <stan/model/indexing/rvalue_at.hpp>
9 #include <stan/model/indexing/rvalue_index_size.hpp>
10 #include <stan/model/indexing/access_helpers.hpp>
11 #include <type_traits>
12 #include <vector>
13 
14 namespace stan {
15 
16 namespace model {
17 
18 /**
19  * Indexing Notes:
20  * The different index types:
21  * index_uni - A single cell.
22  * index_multi - Access multiple cells.
23  * index_omni - A no-op for all indices along a dimension.
24  * index_min - index from min:N
25  * index_max - index from 1:max
26  * index_min_max - index from min:max
27  * nil_index_list - no-op
28  * The order of the overloads are
29  * vector / row_vector:
30  *  - all index overloads
31  * matrix:
32  *  - all row index overloads
33  *    - Return a subset of rows.
34  *  - column/row overloads
35  *    - overload on both the row and column indices.
36  *  - column overloads
37  *    - These take a subset of columns and then call the row slice rvalue
38  *       over the column subset.
39  * Std vector:
40  *  - single element and elementwise overloads
41  *  - General overload for nested std vectors.
42  */
43 
44 /**
45  * Return the result of indexing a specified value with
46  * a nil index list, which just returns the value.
47  *
48  * Types:  T[] : T
49  *
50  * @tparam T Scalar type.
51  * @param[in] x Value to index.
52  * @return Input value.
53  */
54 template <typename T>
rvalue(T && x,const char *)55 inline T rvalue(T&& x, const char* /*name*/) {
56   return std::forward<T>(x);
57 }
58 
59 template <typename T>
rvalue(T & x,const char *)60 inline T& rvalue(T& x, const char* /*name*/) {
61   return x;
62 }
63 
64 template <typename T>
rvalue(const T & x,const char *)65 inline const T& rvalue(const T& x, const char* /*name*/) {
66   return x;
67 }
68 
69 /**
70  * Return the result of indexing a type without taking a subset. Mostly used as
71  * an intermediary rvalue function when doing multiple subsets.
72  *
73  * Types:  plain_type[omni] : plain_type
74  *
75  * @tparam T A type that is a plain object.
76  * @param[in] x an object.
77  * @return Result of indexing matrix.
78  */
79 template <typename T>
rvalue(T && x,const char *,index_omni)80 inline T rvalue(T&& x, const char* /*name*/, index_omni /*idx*/) {
81   return std::forward<T>(x);
82 }
83 
84 template <typename T>
rvalue(T & x,const char *,index_omni)85 inline T& rvalue(T& x, const char* /*name*/, index_omni /*idx*/) {
86   return x;
87 }
88 
89 template <typename T>
rvalue(const T & x,const char *,index_omni)90 inline const T& rvalue(const T& x, const char* /*name*/, index_omni /*idx*/) {
91   return x;
92 }
93 
94 /**
95  * Return the result of indexing a type without taking a subset
96  *
97  * Types:  type[omni, omni] : type
98  *
99  * @tparam T Any type.
100  * @param[in] x an object.
101  * @param[in] name String form of expression being evaluated.
102  * @return Result of indexing matrix.
103  */
104 template <typename T>
rvalue(T && x,const char * name,index_omni,index_omni)105 inline T rvalue(T&& x, const char* name, index_omni /*idx1*/,
106                 index_omni /*idx2*/) {
107   return std::forward<T>(x);
108 }
109 
110 template <typename T>
rvalue(T & x,const char * name,index_omni,index_omni)111 inline T& rvalue(T& x, const char* name, index_omni /*idx1*/,
112                  index_omni /*idx2*/) {
113   return x;
114 }
115 
116 template <typename T>
rvalue(const T & x,const char * name,index_omni,index_omni)117 inline const T& rvalue(const T& x, const char* name, index_omni /*idx1*/,
118                        index_omni /*idx2*/) {
119   return x;
120 }
121 
122 /**
123  * Return a single element of a Vector.
124  *
125  * Types:  vector[uni] : scaler
126  *
127  * @tparam Vec An Eigen vector or `var_value<T>` where `T` is an eigen vector.
128  * @param[in] v Vector being indexed.
129  * @param[in] name String form of expression being evaluated.
130  * @param[in] idx One single index.
131  * @return Result of indexing vector.
132  */
133 template <typename Vec, require_vector_t<Vec>* = nullptr,
134           require_not_std_vector_t<Vec>* = nullptr>
rvalue(Vec && v,const char * name,index_uni idx)135 inline auto rvalue(Vec&& v, const char* name, index_uni idx) {
136   using stan::math::to_ref;
137   math::check_range("vector[uni] indexing", name, v.size(), idx.n_);
138   return v.coeff(idx.n_ - 1);
139 }
140 
141 /**
142  * Return a non-contiguous subset of elements in a vector.
143  *
144  * Types:  vector[multi] = vector
145  *
146  * @tparam EigVec Eigen type with either dynamic rows or columns, but not both.
147  * @param[in] v Eigen vector type.
148  * @param[in] name Name of variable
149  * @param[in] idx Sequence of integers.
150  * @throw std::out_of_range If any of the indices are out of bounds.
151  * @throw std::invalid_argument If the value size isn't the same as
152  * the indexed size.
153  */
154 template <typename EigVec, require_eigen_vector_t<EigVec>* = nullptr>
rvalue(EigVec && v,const char * name,const index_multi & idx)155 inline auto rvalue(EigVec&& v, const char* name, const index_multi& idx) {
156   return stan::math::make_holder(
157       [name, &idx](auto& v_ref) {
158         return plain_type_t<EigVec>::NullaryExpr(
159             idx.ns_.size(), [name, &idx, &v_ref](Eigen::Index i) {
160               math::check_range("vector[multi] indexing", name, v_ref.size(),
161                                 idx.ns_[i]);
162               return v_ref.coeff(idx.ns_[i] - 1);
163             });
164       },
165       stan::math::to_ref(v));
166 }
167 
168 /**
169  * Return a range of a vector
170  *
171  * Types:  vector[min_max] = vector
172  *
173  * @tparam Vec An Eigen vector or `var_value<T>` where `T` is an eigen vector.
174  * @param[in] v Vector being indexed.
175  * @param[in] name String form of expression being evaluated.
176  * @param[in] idx An index to select from a minimum to maximum range.
177  * @return Result of indexing vector.
178  */
179 template <typename Vec, require_vector_t<Vec>* = nullptr,
180           require_not_std_vector_t<Vec>* = nullptr>
rvalue(Vec && v,const char * name,index_min_max idx)181 inline auto rvalue(Vec&& v, const char* name, index_min_max idx) {
182   math::check_range("vector[min_max] min indexing", name, v.size(), idx.min_);
183   math::check_range("vector[min_max] max indexing", name, v.size(), idx.max_);
184   if (idx.is_ascending()) {
185     const auto slice_start = idx.min_ - 1;
186     const auto slice_size = idx.max_ - slice_start;
187     return v.segment(slice_start, slice_size).eval();
188   } else {
189     const auto slice_start = idx.max_ - 1;
190     const auto slice_size = idx.min_ - slice_start;
191     return v.segment(slice_start, slice_size).reverse().eval();
192   }
193 }
194 
195 /**
196  * Return a tail slice of a vector
197  *
198  * Types:  vector[min:N] = vector
199  *
200  * @tparam Vec An Eigen vector or `var_value<T>` where `T` is an eigen vector.
201  * @param[in] x vector
202  * @param[in] name Name of variable
203  * @param[in] idx An indexing from a specific minimum index to the end out
204  *  of a bottom row of a matrix
205  * @throw std::out_of_range If any of the indices are out of bounds.
206  */
207 template <typename Vec, require_vector_t<Vec>* = nullptr,
208           require_not_std_vector_t<Vec>* = nullptr>
rvalue(Vec && x,const char * name,index_min idx)209 inline auto rvalue(Vec&& x, const char* name, index_min idx) {
210   stan::math::check_range("vector[min] indexing", name, x.size(), idx.min_);
211   return x.tail(x.size() - idx.min_ + 1);
212 }
213 
214 /**
215  * Return a head slice of a vector
216  *
217  * Types:  vector[1:max] <- vector
218  *
219  * @tparam Vec An Eigen vector or `var_value<T>` where `T` is an eigen vector.
220  * @param[in] x vector.
221  * @param[in] name Name of variable
222  * @param[in] idx An indexing from the start of the container up to
223  * the specified maximum index (inclusive).
224  * @throw std::out_of_range If any of the indices are out of bounds.
225  */
226 template <typename Vec, require_vector_t<Vec>* = nullptr,
227           require_not_std_vector_t<Vec>* = nullptr>
rvalue(Vec && x,const char * name,index_max idx)228 inline auto rvalue(Vec&& x, const char* name, index_max idx) {
229   stan::math::check_range("vector[max] indexing", name, x.size(), idx.max_);
230   return x.head(idx.max_);
231 }
232 
233 /**
234  * Return the result of indexing the matrix with a
235  * sequence consisting of one single index, returning a row vector.
236  *
237  * Types:  matrix[uni] : row vector
238  *
239  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
240  * matrix.
241  * @param[in] x matrix.
242  * @param[in] name String form of expression being evaluated.
243  * @param[in] idx uni-index
244  * @return Result of indexing matrix.
245  */
246 template <typename Mat, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,index_uni idx)247 inline auto rvalue(Mat&& x, const char* name, index_uni idx) {
248   math::check_range("matrix[uni] indexing", name, x.rows(), idx.n_);
249   return x.row(idx.n_ - 1);
250 }
251 
252 /**
253  * Return the specified Eigen matrix at the specified multi index.
254  *
255  * Types:  matrix[multi] = matrix
256  *
257  * @tparam EigMat Eigen type with dynamic rows and columns.
258  * @param[in] x Eigen type
259  * @param[in] name Name of variable
260  * @param[in] idx A multi index for selecting a set of rows.
261  * @throw std::out_of_range If any of the indices are out of bounds.
262  */
263 template <typename EigMat, require_eigen_dense_dynamic_t<EigMat>* = nullptr>
rvalue(EigMat && x,const char * name,const index_multi & idx)264 inline plain_type_t<EigMat> rvalue(EigMat&& x, const char* name,
265                                    const index_multi& idx) {
266   for (int i = 0; i < idx.ns_.size(); ++i) {
267     math::check_range("matrix[multi] row indexing", name, x.rows(), idx.ns_[i]);
268   }
269   return stan::math::make_holder(
270       [&idx](auto& x_ref) {
271         return plain_type_t<EigMat>::NullaryExpr(
272             idx.ns_.size(), x_ref.cols(),
273             [&idx, &x_ref](Eigen::Index i, Eigen::Index j) {
274               return x_ref.coeff(idx.ns_[i] - 1, j);
275             });
276       },
277       stan::math::to_ref(x));
278 }
279 
280 /**
281  * Return the result of indexing the matrix with a min index
282  * returning back a block of rows min:N and all cols
283  *
284  * Types:  matrix[min:N] = matrix
285  *
286  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
287  * matrix.
288  * @param[in] x matrix.
289  * @param[in] name String form of expression being evaluated.
290  * @param[in] idx index_min
291  * @return Result of indexing matrix.
292  */
293 template <typename Mat, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,index_min idx)294 inline auto rvalue(Mat&& x, const char* name, index_min idx) {
295   const auto row_size = x.rows() - (idx.min_ - 1);
296   math::check_range("matrix[min] row indexing", name, x.rows(), idx.min_);
297   return x.bottomRows(row_size);
298 }
299 
300 /**
301  * Return the 1:max rows of a matrix.
302  *
303  * Types:  matrix[:max] = matrix
304  *
305  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
306  * matrix.
307  * @param[in] x matrix
308  * @param[in] name Name of variable
309  * @param[in] idx An indexing from the start of the container up to
310  * the specified maximum index (inclusive).
311  * @throw std::out_of_range If any of the indices are out of bounds.
312  */
313 template <typename Mat, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,index_max idx)314 inline auto rvalue(Mat&& x, const char* name, index_max idx) {
315   math::check_range("matrix[max] row indexing", name, x.rows(), idx.max_);
316   return x.topRows(idx.max_);
317 }
318 
319 /**
320  * Return a range of rows for a matrix.
321  *
322  * Types:  matrix[min_max] = matrix
323  *
324  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
325  * matrix.
326  * @param[in] x Dense matrix
327  * @param[in] name Name of variable
328  * @param[in] idx A min max index to select a range of rows.
329  * @throw std::out_of_range If any of the indices are out of bounds.
330  */
331 template <typename Mat, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,index_min_max idx)332 inline auto rvalue(Mat&& x, const char* name, index_min_max idx) {
333   math::check_range("matrix[min_max] max row indexing", name, x.rows(),
334                     idx.max_);
335   math::check_range("matrix[min_max] min row indexing", name, x.rows(),
336                     idx.min_);
337   if (idx.is_ascending()) {
338     const auto row_size = idx.max_ - idx.min_ + 1;
339     return x.middleRows(idx.min_ - 1, row_size).eval();
340   } else {
341     const auto row_size = idx.min_ - idx.max_ + 1;
342     return internal::colwise_reverse(x.middleRows(idx.max_ - 1, row_size))
343         .eval();
344   }
345 }
346 
347 /**
348  * Return the result of indexing a matrix with two min_max
349  * indices, returning back a block of a matrix.
350  *
351  * Types:  matrix[min_max, min_max] = matrix
352  *
353  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
354  * matrix.
355  * @param[in] x Eigen matrix.
356  * @param[in] name String form of expression being evaluated.
357  * @param[in] row_idx Min max index for selecting rows.
358  * @param[in] col_idx Min max index for selecting cols.
359  * @return Result of indexing matrix.
360  */
361 template <typename Mat, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,index_min_max row_idx,index_min_max col_idx)362 inline auto rvalue(Mat&& x, const char* name, index_min_max row_idx,
363                    index_min_max col_idx) {
364   math::check_range("matrix[min_max, min_max] min row indexing", name, x.rows(),
365                     row_idx.min_);
366   math::check_range("matrix[min_max, min_max] max row indexing", name, x.rows(),
367                     row_idx.max_);
368   math::check_range("matrix[min_max, min_max] min column indexing", name,
369                     x.cols(), col_idx.min_);
370   math::check_range("matrix[min_max, min_max] max column indexing", name,
371                     x.cols(), col_idx.max_);
372   if (row_idx.is_ascending()) {
373     if (col_idx.is_ascending()) {
374       return x
375           .block(row_idx.min_ - 1, col_idx.min_ - 1,
376                  row_idx.max_ - (row_idx.min_ - 1),
377                  col_idx.max_ - (col_idx.min_ - 1))
378           .eval();
379     } else {
380       return internal::rowwise_reverse(
381                  x.block(row_idx.min_ - 1, col_idx.max_ - 1,
382                          row_idx.max_ - (row_idx.min_ - 1),
383                          col_idx.min_ - (col_idx.max_ - 1)))
384           .eval();
385     }
386   } else {
387     if (col_idx.is_ascending()) {
388       return internal::colwise_reverse(
389                  x.block(row_idx.max_ - 1, col_idx.min_ - 1,
390                          row_idx.min_ - (row_idx.max_ - 1),
391                          col_idx.max_ - (col_idx.min_ - 1)))
392           .eval();
393     } else {
394       return x
395           .block(row_idx.max_ - 1, col_idx.max_ - 1,
396                  row_idx.min_ - (row_idx.max_ - 1),
397                  col_idx.min_ - (col_idx.max_ - 1))
398           .reverse()
399           .eval();
400     }
401   }
402 }
403 
404 /**
405  * Return a scalar from a matrix
406  *
407  * Types:  matrix[uni,uni] : scalar
408  *
409  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
410  * matrix.
411  * @param[in] x Matrix to index.
412  * @param[in] name String form of expression being evaluated.
413  * @param[in] row_idx uni index for selecting rows.
414  * @param[in] col_idx uni index for selecting cols.
415  * @return Result of indexing matrix.
416  */
417 template <typename Mat, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,index_uni row_idx,index_uni col_idx)418 inline auto rvalue(Mat&& x, const char* name, index_uni row_idx,
419                    index_uni col_idx) {
420   math::check_range("matrix[uni,uni] row indexing", name, x.rows(), row_idx.n_);
421   math::check_range("matrix[uni,uni] column indexing", name, x.cols(),
422                     col_idx.n_);
423   return x.coeff(row_idx.n_ - 1, col_idx.n_ - 1);
424 }
425 
426 /**
427  * Return a row of an Eigen matrix with possibly unordered cells.
428  *
429  * Types:  matrix[uni, multi] = row vector
430  *
431  * @tparam EigMat Eigen type with dynamic rows and columns.
432  * @param[in] x Matrix to index.
433  * @param[in] name Name of variable
434  * @param[in] row_idx uni index for selecting rows.
435  * @param[in] col_idx multi index for selecting cols.
436  * @throw std::out_of_range If any of the indices are out of bounds.
437  */
438 template <typename EigMat, require_eigen_dense_dynamic_t<EigMat>* = nullptr>
rvalue(EigMat && x,const char * name,index_uni row_idx,const index_multi & col_idx)439 inline Eigen::Matrix<value_type_t<EigMat>, 1, Eigen::Dynamic> rvalue(
440     EigMat&& x, const char* name, index_uni row_idx,
441     const index_multi& col_idx) {
442   math::check_range("matrix[uni, multi] row indexing", name, x.rows(),
443                     row_idx.n_);
444 
445   return stan::math::make_holder(
446       [name, row_idx, &col_idx](auto& x_ref) {
447         return Eigen::Matrix<value_type_t<EigMat>, 1, Eigen::Dynamic>::
448             NullaryExpr(col_idx.ns_.size(), [name, row_i = row_idx.n_ - 1,
449                                              &col_idx, &x_ref](Eigen::Index i) {
450               math::check_range("matrix[uni, multi] column indexing", name,
451                                 x_ref.cols(), col_idx.ns_[i]);
452               return x_ref.coeff(row_i, col_idx.ns_[i] - 1);
453             });
454       },
455       stan::math::to_ref(x));
456 }
457 
458 /**
459  * Return a column of an Eigen matrix that is a possibly non-contiguous subset
460  *  of the input Eigen matrix.
461  *
462  * Types:  matrix[multi, uni] = vector
463  *
464  * @tparam EigMat Eigen type with dynamic rows and columns.
465  * @param[in] x Matrix to index.
466  * @param[in] name Name of variable
467  * @param[in] row_idx multi index for selecting rows.
468  * @param[in] col_idx uni index for selecting cols.
469  * @throw std::out_of_range If any of the indices are out of bounds.
470  */
471 template <typename EigMat, require_eigen_dense_dynamic_t<EigMat>* = nullptr>
rvalue(EigMat && x,const char * name,const index_multi & row_idx,index_uni col_idx)472 inline Eigen::Matrix<value_type_t<EigMat>, Eigen::Dynamic, 1> rvalue(
473     EigMat&& x, const char* name, const index_multi& row_idx,
474     index_uni col_idx) {
475   math::check_range("matrix[multi, uni] column indexing", name, x.cols(),
476                     col_idx.n_);
477 
478   return stan::math::make_holder(
479       [name, &row_idx, col_idx](auto& x_ref) {
480         return Eigen::Matrix<value_type_t<EigMat>, Eigen::Dynamic, 1>::
481             NullaryExpr(row_idx.ns_.size(),
482                         [name, &row_idx, col_i = col_idx.n_ - 1,
483                          &x_ref](Eigen::Index i) {
484                           math::check_range("matrix[multi, uni] row indexing",
485                                             name, x_ref.rows(), row_idx.ns_[i]);
486                           return x_ref.coeff(row_idx.ns_[i] - 1, col_i);
487                         });
488       },
489       stan::math::to_ref(x));
490 }
491 
492 /**
493  * Return an Eigen matrix that is a possibly non-contiguous subset of the input
494  *  Eigen matrix.
495  *
496  * Types:  matrix[multi, multi] = matrix
497  *
498  * @tparam EigMat An eigen matrix
499  * @param[in] x Matrix to index.
500  * @param[in] name String form of expression being evaluated.
501  * @param[in] row_idx multi index for selecting rows.
502  * @param[in] col_idx multi index for selecting cols.
503  * @return Result of indexing matrix.
504  */
505 template <typename EigMat, require_eigen_dense_dynamic_t<EigMat>* = nullptr>
rvalue(EigMat && x,const char * name,const index_multi & row_idx,const index_multi & col_idx)506 inline plain_type_t<EigMat> rvalue(EigMat&& x, const char* name,
507                                    const index_multi& row_idx,
508                                    const index_multi& col_idx) {
509   const auto& x_ref = stan::math::to_ref(x);
510   const int rows = row_idx.ns_.size();
511   const int cols = col_idx.ns_.size();
512   plain_type_t<EigMat> x_ret(rows, cols);
513   for (int j = 0; j < cols; ++j) {
514     for (int i = 0; i < rows; ++i) {
515       const int m = row_idx.ns_[i];
516       const int n = col_idx.ns_[j];
517       math::check_range("matrix[multi,multi] row indexing", name, x_ref.rows(),
518                         m);
519       math::check_range("matrix[multi,multi] column indexing", name,
520                         x_ref.cols(), n);
521       x_ret.coeffRef(i, j) = x_ref.coeff(m - 1, n - 1);
522     }
523   }
524   return x_ret;
525 }
526 
527 /**
528  * Return a column of a matrix with the range of the column specificed
529  *  by another index.
530  *
531  * Types:  matrix[Idx, uni] = vector
532  *
533  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
534  * matrix.
535  * @param[in] x matrix.
536  * @param[in] name String form of expression being evaluated.
537  * @param[in] row_idx index for selecting rows.
538  * @param[in] col_idx uni index for selecting cols.
539  */
540 template <typename Mat, typename Idx, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,const Idx & row_idx,index_uni col_idx)541 inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx,
542                    index_uni col_idx) {
543   math::check_range("matrix[..., uni] column indexing", name, x.cols(),
544                     col_idx.n_);
545   return rvalue(x.col(col_idx.n_ - 1), name, row_idx);
546 }
547 
548 /**
549  * Return an Eigen matrix of possibly unordered columns with each column
550  *  range specified by another index.
551  *
552  * Types:  matrix[Idx, multi] = matrix
553  *
554  * @tparam EigMat An eigen matrix
555  * @param[in] x Eigen matrix.
556  * @param[in] name String form of expression being evaluated.
557  * @param[in] row_idx index for selecting rows.
558  * @param[in] col_idx multi index for selecting cols.
559  * @return Result of indexing matrix.
560  */
561 template <typename EigMat, typename Idx,
562           require_eigen_dense_dynamic_t<EigMat>* = nullptr,
563           require_not_same_t<std::decay_t<Idx>, index_uni>* = nullptr>
rvalue(EigMat && x,const char * name,const Idx & row_idx,const index_multi & col_idx)564 inline plain_type_t<EigMat> rvalue(EigMat&& x, const char* name,
565                                    const Idx& row_idx,
566                                    const index_multi& col_idx) {
567   const auto& x_ref = stan::math::to_ref(x);
568   const int rows = rvalue_index_size(row_idx, x_ref.rows());
569   const int cols = rvalue_index_size(col_idx, x_ref.cols());
570   plain_type_t<EigMat> x_ret(rows, col_idx.ns_.size());
571   for (int j = 0; j < col_idx.ns_.size(); ++j) {
572     const int n = col_idx.ns_[j];
573     math::check_range("matrix[..., multi] column indexing", name, x_ref.cols(),
574                       n);
575     x_ret.col(j) = rvalue(x_ref.col(n - 1), name, row_idx);
576   }
577   return x_ret;
578 }
579 
580 /**
581  * Return the matrix with all columns and a slice of rows.
582  *
583  * Types:  matrix[Idx, omni] = matrix
584  *
585  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
586  * matrix.
587  * @param[in] x type
588  * @param[in] name Name of variable
589  * @param[in] row_idx index for selecting rows.
590  * @throw std::out_of_range If any of the indices are out of bounds.
591  */
592 template <typename Mat, typename Idx, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,const Idx & row_idx,index_omni)593 inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx,
594                    index_omni /*col_idx*/) {
595   return rvalue(std::forward<Mat>(x), name, row_idx);
596 }
597 
598 /**
599  * Return columns min:N of the matrix with the range of the columns
600  *  defined by another index.
601  *
602  * Types:  matrix[Idx, min] = matrix
603  *
604  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
605  * matrix.
606  * @tparam Idx An index.
607  * @param[in] x type
608  * @param[in] name Name of variable
609  * @param[in] row_idx index for selecting rows.
610  * @param[in] col_idx min index for selecting cols.
611  * @throw std::out_of_range If any of the indices are out of bounds.
612  */
613 template <typename Mat, typename Idx, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,const Idx & row_idx,index_min col_idx)614 inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx,
615                    index_min col_idx) {
616   const auto col_size = x.cols() - (col_idx.min_ - 1);
617   math::check_range("matrix[..., min] column indexing", name, x.cols(),
618                     col_idx.min_);
619   return rvalue(x.rightCols(col_size), name, row_idx);
620 }
621 
622 /**
623  * Return columns 1:max of input matrix with the range of the columns
624  *  defined by another index.
625  *
626  * Types:  matrix[Idx, max] = matrix
627  *
628  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
629  * matrix.
630  * @tparam Idx An index.
631  * @param[in] x Eigen type
632  * @param[in] name Name of variable
633  * @param[in] row_idx index for selecting rows.
634  * @param[in] col_idx max index for selecting cols.
635  * @throw std::out_of_range If any of the indices are out of bounds.
636  */
637 template <typename Mat, typename Idx, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,const Idx & row_idx,index_max col_idx)638 inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx,
639                    index_max col_idx) {
640   math::check_range("matrix[..., max] column indexing", name, x.cols(),
641                     col_idx.max_);
642   return rvalue(x.leftCols(col_idx.max_), name, row_idx);
643 }
644 
645 /**
646  * Return the result of indexing the specified matrix with a
647  * min_max_index returning a block from min to max.
648  *
649  * Types:  matrix[Idx, min_max] = matrix
650  *
651  * @tparam Mat An eigen matrix or `var_value<T>` whose inner type is an Eigen
652  * matrix.
653  * @tparam Idx Type of index.
654  * @param[in] x Matrix to index.
655  * @param[in] name String form of expression being evaluated.
656  * @param[in] row_idx index for selecting rows.
657  * @param[in] col_idx min max index for selecting cols.
658  * @return Result of indexing matrix.
659  */
660 template <typename Mat, typename Idx, require_dense_dynamic_t<Mat>* = nullptr>
rvalue(Mat && x,const char * name,const Idx & row_idx,index_min_max col_idx)661 inline auto rvalue(Mat&& x, const char* name, const Idx& row_idx,
662                    index_min_max col_idx) {
663   math::check_range("matrix[..., min_max] min column indexing", name, x.cols(),
664                     col_idx.min_);
665   math::check_range("matrix[..., min_max] max column indexing", name, x.cols(),
666                     col_idx.max_);
667   if (col_idx.is_ascending()) {
668     const auto col_start = col_idx.min_ - 1;
669     return rvalue(x.middleCols(col_start, col_idx.max_ - col_start), name,
670                   row_idx)
671         .eval();
672   } else {
673     const auto col_start = col_idx.max_ - 1;
674     return rvalue(internal::rowwise_reverse(
675                       x.middleCols(col_start, col_idx.min_ - col_start)),
676                   name, row_idx)
677         .eval();
678   }
679 }
680 
681 /**
682  * Return the result of indexing the specified array with
683  * a list of indexes beginning with a single index;  the result is
684  * determined recursively.  Note that arrays are represented as
685  * standard library vectors.
686  *
687  * Types:  std::vector<T>[uni | Idx] : T[Idx]
688  *
689  * @tparam T Type of list elements.
690  * @tparam Idx Index list type for indexes after first index.
691  * @param[in] v Container of list elements.
692  * @param[in] name String form of expression being evaluated.
693  * @param[in] idx1 first index.
694  * @param[in] idxs remaining indices.
695  * @return Result of indexing array.
696  */
697 template <typename StdVec, typename... Idxs,
698           require_std_vector_t<StdVec>* = nullptr,
699           require_not_t<std::is_lvalue_reference<StdVec&&>>* = nullptr>
rvalue(StdVec && v,const char * name,index_uni idx1,const Idxs &...idxs)700 inline auto rvalue(StdVec&& v, const char* name, index_uni idx1,
701                    const Idxs&... idxs) {
702   math::check_range("array[uni, ...] index", name, v.size(), idx1.n_);
703   return rvalue(std::move(v[idx1.n_ - 1]), name, idxs...);
704 }
705 template <typename StdVec, typename... Idxs,
706           require_std_vector_t<StdVec>* = nullptr>
rvalue(StdVec & v,const char * name,index_uni idx1,const Idxs &...idxs)707 inline auto rvalue(StdVec& v, const char* name, index_uni idx1,
708                    const Idxs&... idxs) {
709   math::check_range("array[uni, ...] index", name, v.size(), idx1.n_);
710   return rvalue(v[idx1.n_ - 1], name, idxs...);
711 }
712 
713 /**
714  * Return the result of indexing the specified array with
715  * a single index.
716  *
717  * Types:  std::vector<T>[uni] : T
718  *
719  * @tparam StdVec a standard vector
720  * @param[in] v Container of list elements.
721  * @param[in] name String form of expression being evaluated.
722  * @param[in] idx single index
723  * @return Result of indexing array.
724  */
725 template <typename StdVec, require_std_vector_t<StdVec>* = nullptr,
726           require_not_t<std::is_lvalue_reference<StdVec&&>>* = nullptr>
rvalue(StdVec && v,const char * name,index_uni idx)727 inline auto rvalue(StdVec&& v, const char* name, index_uni idx) {
728   math::check_range("array[uni, ...] index", name, v.size(), idx.n_);
729   return v[idx.n_ - 1];
730 }
731 template <typename StdVec, require_std_vector_t<StdVec>* = nullptr>
rvalue(StdVec & v,const char * name,index_uni idx)732 inline auto& rvalue(StdVec& v, const char* name, index_uni idx) {
733   math::check_range("array[uni, ...] index", name, v.size(), idx.n_);
734   return v[idx.n_ - 1];
735 }
736 
737 /**
738  * Return the result of indexing the specified array with
739  * a list of indexes beginning with a multiple index;  the result is
740  * determined recursively.  Note that arrays are represented as
741  * standard library vectors.
742  *
743  * Types:  std::vector<T>[Idx1, Idx2] : std::vector<T>[Idx2]
744  *
745  * @tparam T Type of list elements.
746  * @tparam Idx1 Index list type for first index.
747  * @tparam Idx2 Index list type for second index index.
748  * @param[in] v Container of list elements.
749  * @param[in] name String form of expression being evaluated.
750  * @param[in] idx1 first index
751  * @param[in] idxs remaining indices
752  * @return Result of indexing array.
753  */
754 template <typename StdVec, typename Idx1, typename... Idxs,
755           require_std_vector_t<StdVec>* = nullptr,
756           require_not_same_t<Idx1, index_uni>* = nullptr>
rvalue(StdVec && v,const char * name,Idx1 idx1,const Idxs &...idxs)757 inline auto rvalue(StdVec&& v, const char* name, Idx1 idx1,
758                    const Idxs&... idxs) {
759   using inner_type = plain_type_t<decltype(
760       rvalue(v[rvalue_at(0, idx1) - 1], name, idxs...))>;
761   std::vector<inner_type> result;
762   const int index_size = rvalue_index_size(idx1, v.size());
763   if (index_size > 0) {
764     result.reserve(index_size);
765   }
766   for (int i = 0; i < index_size; ++i) {
767     const int n = rvalue_at(i, idx1);
768     math::check_range("array[..., ...] index", name, v.size(), n);
769     if (std::is_rvalue_reference<StdVec>::value) {
770       result.emplace_back(rvalue(std::move(v[n - 1]), name, idxs...));
771     } else {
772       result.emplace_back(rvalue(v[n - 1], name, idxs...));
773     }
774   }
775   return result;
776 }
777 
778 }  // namespace model
779 }  // namespace stan
780 #endif
781