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