1 #ifndef STAN_MODEL_INDEXING_LVALUE_HPP 2 #define STAN_MODEL_INDEXING_LVALUE_HPP 3 4 #include <boost/utility/enable_if.hpp> 5 #include <boost/type_traits/is_same.hpp> 6 #include <Eigen/Dense> 7 #include <stan/math/prim/mat.hpp> 8 #include <stan/model/indexing/index.hpp> 9 #include <stan/model/indexing/index_list.hpp> 10 #include <stan/model/indexing/rvalue_at.hpp> 11 #include <stan/model/indexing/rvalue_index_size.hpp> 12 #include <vector> 13 14 namespace stan { 15 16 namespace model { 17 18 /** 19 * Assign the specified scalar reference under the specified 20 * indexing to the specified scalar value. 21 * 22 * Types: x[] <- y 23 * 24 * @tparam T Assigned variable type. 25 * @tparam U Value type (must be assignable to T). 26 * @param[in] x Variable to be assigned. 27 * @param[in] y Value. 28 * @param[in] name Name of variable (default "ANON"). 29 * @param[in] depth Indexing depth (default 0). 30 */ 31 template <typename T, typename U> assign(T & x,const nil_index_list &,const U & y,const char * name="ANON",int depth=0)32 inline void assign(T& x, const nil_index_list& /* idxs */, const U& y, 33 const char* name = "ANON", int depth = 0) { 34 x = y; 35 } 36 37 template <typename T, typename U, int R, int C> assign(Eigen::Matrix<T,R,C> & x,const nil_index_list &,const Eigen::Matrix<U,R,C> & y,const char * name="ANON",int depth=0)38 inline void assign(Eigen::Matrix<T, R, C>& x, 39 const nil_index_list& /* idxs */, 40 const Eigen::Matrix<U, R, C>& y, 41 const char* name = "ANON", 42 int depth = 0) { 43 x.resize(y.rows(), y.cols()); 44 for (int i = 0; i < y.size(); ++i) 45 assign(x(i), nil_index_list(), y(i), name, depth + 1); 46 } 47 48 49 template <typename T, typename U> assign(std::vector<T> & x,const nil_index_list &,const std::vector<U> & y,const char * name="ANON",int depth=0)50 inline void assign(std::vector<T>& x, const nil_index_list& /* idxs */, 51 const std::vector<U>& y, const char* name = "ANON", 52 int depth = 0) { 53 x.resize(y.size()); 54 for (size_t i = 0; i < y.size(); ++i) 55 assign(x[i], nil_index_list(), y[i], name, depth + 1); 56 } 57 58 59 /** 60 * Assign the specified Eigen vector at the specified single index 61 * to the specified value. 62 * 63 * Types: vec[uni] <- scalar 64 * 65 * @tparam T Type of assigned vector scalar. 66 * @tparam U Type of value (must be assignable to T). 67 * @param[in] x Vector variable to be assigned. 68 * @param[in] idxs Sequence of one single index (from 1). 69 * @param[in] y Value scalar. 70 * @param[in] name Name of variable (default "ANON"). 71 * @param[in] depth Indexing depth (default 0). 72 * @throw std::out_of_range If the index is out of bounds. 73 */ 74 template <typename T, typename U> assign(Eigen::Matrix<T,Eigen::Dynamic,1> & x,const cons_index_list<index_uni,nil_index_list> & idxs,const U & y,const char * name="ANON",int depth=0)75 inline void assign(Eigen::Matrix<T, Eigen::Dynamic, 1>& x, 76 const cons_index_list<index_uni, nil_index_list>& idxs, 77 const U& y, 78 const char* name = "ANON", int depth = 0) { 79 int i = idxs.head_.n_; 80 math::check_range("vector[uni] assign range", name, x.size(), i); 81 x(i - 1) = y; 82 } 83 84 /** 85 * Assign the specified Eigen vector at the specified single index 86 * to the specified value. 87 * 88 * Types: row_vec[uni] <- scalar 89 * 90 * @tparam T Type of assigned row vector scalar. 91 * @tparam U Type of value (must be assignable to T). 92 * @param[in] x Row vector variable to be assigned. 93 * @param[in] idxs Sequence of one single index (from 1). 94 * @param[in] y Value scalar. 95 * @param[in] name Name of variable (default "ANON"). 96 * @param[in] depth Indexing depth (default 0). 97 * @throw std::out_of_range Index is out of bounds. 98 */ 99 template <typename T, typename U> assign(Eigen::Matrix<T,1,Eigen::Dynamic> & x,const cons_index_list<index_uni,nil_index_list> & idxs,const U & y,const char * name="ANON",int depth=0)100 inline void assign(Eigen::Matrix<T, 1, Eigen::Dynamic>& x, 101 const cons_index_list<index_uni, nil_index_list>& idxs, 102 const U& y, 103 const char* name = "ANON", int depth = 0) { 104 int i = idxs.head_.n_; 105 math::check_range("row_vector[uni] assign range", name, x.size(), i); 106 x(i - 1) = y; 107 } 108 109 /** 110 * Assign the specified Eigen vector at the specified multiple 111 * index to the specified value. 112 * 113 * Types: vec[multi] <- vec 114 * 115 * @tparam T Type of assigned vector scalar. 116 * @tparam I Type of multiple index. 117 * @tparam U Type of vector value scalar (must be assignable to T). 118 * @param[in] x Row vector variable to be assigned. 119 * @param[in] idxs Sequence of one single index (from 1). 120 * @param[in] y Value vector. 121 * @param[in] name Name of variable (default "ANON"). 122 * @param[in] depth Indexing depth (default 0). 123 * @throw std::out_of_range If any of the indices are out of bounds. 124 * @throw std::invalid_argument If the value size isn't the same as 125 * the indexed size. 126 */ 127 template <typename T, typename I, typename U> 128 inline typename boost::disable_if<boost::is_same<I, index_uni>, void>::type assign(Eigen::Matrix<T,Eigen::Dynamic,1> & x,const cons_index_list<I,nil_index_list> & idxs,const Eigen::Matrix<U,Eigen::Dynamic,1> & y,const char * name="ANON",int depth=0)129 assign(Eigen::Matrix<T, Eigen::Dynamic, 1>& x, 130 const cons_index_list<I, nil_index_list>& idxs, 131 const Eigen::Matrix<U, Eigen::Dynamic, 1>& y, 132 const char* name = "ANON", int depth = 0) { 133 math::check_size_match("vector[multi] assign sizes", 134 "lhs", rvalue_index_size(idxs.head_, x.size()), 135 name, y.size()); 136 for (int n = 0; n < y.size(); ++n) { 137 int i = rvalue_at(n, idxs.head_); 138 math::check_range("vector[multi] assign range", name, x.size(), i); 139 x(i - 1) = y(n); 140 } 141 } 142 143 /** 144 * Assign the specified Eigen row vector at the specified multiple 145 * index to the specified value. 146 * 147 * Types: row_vec[multi] <- row_vec 148 * 149 * @tparam T Scalar type for assigned row vector. 150 * @tparam I Type of multiple index. 151 * @tparam U Type of value row vector scalar (must be assignable 152 * to T). 153 * @param[in] x Row vector variable to be assigned. 154 * @param[in] idxs Sequence of one multiple index (from 1). 155 * @param[in] y Value vector. 156 * @param[in] name Name of variable (default "ANON"). 157 * @param[in] depth Indexing depth (default 0). 158 * @throw std::out_of_range If any of the indices are out of bounds. 159 * @throw std::invalid_argument If the value size isn't the same as 160 * the indexed size. 161 */ 162 template <typename T, typename I, typename U> 163 inline typename boost::disable_if<boost::is_same<I, index_uni>, void>::type assign(Eigen::Matrix<T,1,Eigen::Dynamic> & x,const cons_index_list<I,nil_index_list> & idxs,const Eigen::Matrix<U,1,Eigen::Dynamic> & y,const char * name="ANON",int depth=0)164 assign(Eigen::Matrix<T, 1, Eigen::Dynamic>& x, 165 const cons_index_list<I, nil_index_list>& idxs, 166 const Eigen::Matrix<U, 1, Eigen::Dynamic>& y, 167 const char* name = "ANON", int depth = 0) { 168 math::check_size_match("row_vector[multi] assign sizes", 169 "lhs", rvalue_index_size(idxs.head_, x.size()), 170 name, y.size()); 171 for (int n = 0; n < y.size(); ++n) { 172 int i = rvalue_at(n, idxs.head_); 173 math::check_range("row_vector[multi] assign range", name, x.size(), i); 174 x(i - 1) = y(n); 175 } 176 } 177 178 /** 179 * Assign the specified Eigen matrix at the specified single index 180 * to the specified row vector value. 181 * 182 * Types: mat[uni] = rowvec 183 * 184 * @tparam T Assigned matrix scalar type. 185 * @tparam U Type of value scalar for row vector (must be 186 * assignable to T). 187 * @param[in] x Matrix variable to be assigned. 188 * @param[in] idxs Sequence of one single index (from 1). 189 * @param[in] y Value row vector. 190 * @param[in] name Name of variable (default "ANON"). 191 * @param[in] depth Indexing depth (default 0). 192 * @throw std::out_of_range If any of the indices are out of bounds. 193 * @throw std::invalid_argument If the number of columns in the row 194 * vector and matrix do not match. 195 */ 196 template <typename T, typename U> assign(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & x,const cons_index_list<index_uni,nil_index_list> & idxs,const Eigen::Matrix<U,1,Eigen::Dynamic> & y,const char * name="ANON",int depth=0)197 void assign(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& x, 198 const cons_index_list<index_uni, nil_index_list>& idxs, 199 const Eigen::Matrix<U, 1, Eigen::Dynamic>& y, 200 const char* name = "ANON", int depth = 0) { 201 math::check_size_match("matrix[uni] assign sizes", 202 "lhs", x.cols(), 203 name, y.cols()); 204 int i = idxs.head_.n_; 205 math::check_range("matrix[uni] assign range", name, x.rows(), i); 206 for (int j = 0; j < x.cols(); ++j) // loop allows double to var assgn 207 x(i - 1, j) = y(j); 208 } 209 210 /** 211 * Assign the specified Eigen matrix at the specified multiple 212 * index to the specified matrix value. 213 * 214 * Types: mat[multi] = mat 215 * 216 * @tparam T Assigned matrix scalar type. 217 * @tparam I Multiple index type. 218 * @tparam U Value matrix scalar type (must be assignable to T). 219 * @param[in] x Matrix variable to be assigned. 220 * @param[in] idxs Sequence of one multiple index (from 1). 221 * @param[in] y Value matrix. 222 * @param[in] name Name of variable (default "ANON"). 223 * @param[in] depth Indexing depth (default 0). 224 * @throw std::out_of_range If any of the indices are out of bounds. 225 * @throw std::invalid_argument If the dimensions of the indexed 226 * matrix and right-hand side matrix do not match. 227 */ 228 template <typename T, typename I, typename U> 229 inline typename boost::disable_if<boost::is_same<I, index_uni>, void>::type assign(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & x,const cons_index_list<I,nil_index_list> & idxs,const Eigen::Matrix<U,Eigen::Dynamic,Eigen::Dynamic> & y,const char * name="ANON",int depth=0)230 assign(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& x, 231 const cons_index_list<I, nil_index_list>& idxs, 232 const Eigen::Matrix<U, Eigen::Dynamic, Eigen::Dynamic>& y, 233 const char* name = "ANON", int depth = 0) { 234 int x_idx_rows = rvalue_index_size(idxs.head_, x.rows()); 235 math::check_size_match("matrix[multi] assign row sizes", 236 "lhs", x_idx_rows, 237 name, y.rows()); 238 math::check_size_match("matrix[multi] assign col sizes", 239 "lhs", x.cols(), 240 name, y.cols()); 241 for (int i = 0; i < y.rows(); ++i) { 242 int m = rvalue_at(i, idxs.head_); 243 math::check_range("matrix[multi] assign range", name, x.rows(), m); 244 // recurse to allow double to var assign 245 for (int j = 0; j < x.cols(); ++j) 246 x(m - 1, j) = y(i, j); 247 } 248 } 249 250 /** 251 * Assign the specified Eigen matrix at the specified pair of 252 * single indexes to the specified scalar value. 253 * 254 * Types: mat[single, single] = scalar 255 * 256 * @tparam T Matrix scalar type. 257 * @tparam U Scalar type. 258 * @param[in] x Matrix variable to be assigned. 259 * @param[in] idxs Sequence of two single indexes (from 1). 260 * @param[in] y Value scalar. 261 * @param[in] name Name of variable (default "ANON"). 262 * @param[in] depth Indexing depth (default 0). 263 * @throw std::out_of_range If either of the indices are out of bounds. 264 */ 265 template <typename T, typename U> assign(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & x,const cons_index_list<index_uni,cons_index_list<index_uni,nil_index_list>> & idxs,const U & y,const char * name="ANON",int depth=0)266 void assign(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& x, 267 const cons_index_list<index_uni, 268 cons_index_list<index_uni, 269 nil_index_list> >& idxs, 270 const U& y, 271 const char* name = "ANON", int depth = 0) { 272 int m = idxs.head_.n_; 273 int n = idxs.tail_.head_.n_; 274 math::check_range("matrix[uni,uni] assign range", name, x.rows(), m); 275 math::check_range("matrix[uni,uni] assign range", name, x.cols(), n); 276 x(m - 1, n - 1) = y; 277 } 278 279 /** 280 * Assign the specified Eigen matrix at the specified single and 281 * multiple index to the specified row vector. 282 * 283 * Types: mat[uni, multi] = rowvec 284 * 285 * @tparam T Assigned matrix scalar type. 286 * @tparam I Multi-index type. 287 * @tparam U Value row vector scalar type (must be assignable to 288 * T). 289 * @param[in] x Matrix variable to be assigned. 290 * @param[in] idxs Sequence of single and multiple index (from 1). 291 * @param[in] y Value row vector. 292 * @param[in] name Name of variable (default "ANON"). 293 * @param[in] depth Indexing depth (default 0). 294 * @throw std::out_of_range If any of the indices are out of bounds. 295 * @throw std::invalid_argument If the dimensions of the indexed 296 * matrix and right-hand side row vector do not match. 297 */ 298 template <typename T, typename I, typename U> 299 inline typename boost::disable_if<boost::is_same<I, index_uni>, void>::type assign(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & x,const cons_index_list<index_uni,cons_index_list<I,nil_index_list>> & idxs,const Eigen::Matrix<U,1,Eigen::Dynamic> & y,const char * name="ANON",int depth=0)300 assign(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& x, 301 const cons_index_list<index_uni, 302 cons_index_list<I, nil_index_list> >& idxs, 303 const Eigen::Matrix<U, 1, Eigen::Dynamic>& y, 304 const char* name = "ANON", int depth = 0) { 305 int x_idxs_cols = rvalue_index_size(idxs.tail_.head_, x.cols()); 306 math::check_size_match("matrix[uni,multi] assign sizes", 307 "lhs", x_idxs_cols, 308 name, y.cols()); 309 int m = idxs.head_.n_; 310 math::check_range("matrix[uni,multi] assign range", name, x.rows(), m); 311 for (int i = 0; i < y.size(); ++i) { 312 int n = rvalue_at(i, idxs.tail_.head_); 313 math::check_range("matrix[uni,multi] assign range", name, x.cols(), n); 314 x(m - 1, n - 1) = y(i); 315 } 316 } 317 318 /** 319 * Assign the specified Eigen matrix at the specified multiple and 320 * single index to the specified vector. 321 * 322 * Types: mat[multi, uni] = vec 323 * 324 * @tparam T Assigned matrix scalar type. 325 * @tparam I Multi-index type. 326 * @tparam U Value vector scalar type (must be assignable to T). 327 * @param[in] x Matrix variable to be assigned. 328 * @param[in] idxs Sequence of multiple and single index (from 1). 329 * @param[in] y Value vector. 330 * @param[in] name Name of variable (default "ANON"). 331 * @param[in] depth Indexing depth (default 0). 332 * @throw std::out_of_range If any of the indices are out of bounds. 333 * @throw std::invalid_argument If the dimensions of the indexed 334 * matrix and right-hand side vector do not match. 335 */ 336 template <typename T, typename I, typename U> 337 inline typename boost::disable_if<boost::is_same<I, index_uni>, void>::type assign(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & x,const cons_index_list<I,cons_index_list<index_uni,nil_index_list>> & idxs,const Eigen::Matrix<U,Eigen::Dynamic,1> & y,const char * name="ANON",int depth=0)338 assign(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& x, 339 const cons_index_list<I, 340 cons_index_list<index_uni, 341 nil_index_list> >& idxs, 342 const Eigen::Matrix<U, Eigen::Dynamic, 1>& y, 343 const char* name = "ANON", int depth = 0) { 344 int x_idxs_rows = rvalue_index_size(idxs.head_, x.rows()); 345 math::check_size_match("matrix[multi,uni] assign sizes", 346 "lhs", x_idxs_rows, 347 name, y.rows()); 348 int n = idxs.tail_.head_.n_; 349 math::check_range("matrix[multi,uni] assign range", name, x.cols(), n); 350 for (int i = 0; i < y.size(); ++i) { 351 int m = rvalue_at(i, idxs.head_); 352 math::check_range("matrix[multi,uni] assign range", name, x.rows(), m); 353 x(m - 1, n - 1) = y(i); 354 } 355 } 356 357 /** 358 * Assign the specified Eigen matrix at the specified pair of 359 * multiple indexes to the specified matrix. 360 * 361 * Types: mat[multi, multi] = mat 362 * 363 * @tparam T Assigned matrix scalar type. 364 * @tparam I1 First multiple index type. 365 * @tparam I2 Second multiple index type. 366 * @tparam U Value matrix scalar type (must be assignable to T). 367 * @param[in] x Matrix variable to be assigned. 368 * @param[in] idxs Pair of multiple indexes (from 1). 369 * @param[in] y Value matrix. 370 * @param[in] name Name of variable (default "ANON"). 371 * @param[in] depth Indexing depth (default 0). 372 * @throw std::out_of_range If any of the indices are out of bounds. 373 * @throw std::invalid_argument If the dimensions of the indexed 374 * matrix and value matrix do not match. 375 */ 376 template <typename T, typename I1, typename I2, typename U> 377 inline typename 378 boost::disable_if_c<boost::is_same<I1, index_uni>::value 379 || boost::is_same<I2, index_uni>::value, void>::type assign(Eigen::Matrix<T,Eigen::Dynamic,Eigen::Dynamic> & x,const cons_index_list<I1,cons_index_list<I2,nil_index_list>> & idxs,const Eigen::Matrix<U,Eigen::Dynamic,Eigen::Dynamic> & y,const char * name="ANON",int depth=0)380 assign(Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& x, 381 const cons_index_list<I1, 382 cons_index_list<I2, nil_index_list> >& idxs, 383 const Eigen::Matrix<U, Eigen::Dynamic, Eigen::Dynamic>& y, 384 const char* name = "ANON", int depth = 0) { 385 int x_idxs_rows = rvalue_index_size(idxs.head_, x.rows()); 386 int x_idxs_cols = rvalue_index_size(idxs.tail_.head_, x.cols()); 387 math::check_size_match("matrix[multi,multi] assign sizes", 388 "lhs", x_idxs_rows, 389 name, y.rows()); 390 math::check_size_match("matrix[multi,multi] assign sizes", 391 "lhs", x_idxs_cols, 392 name, y.cols()); 393 for (int j = 0; j < y.cols(); ++j) { 394 int n = rvalue_at(j, idxs.tail_.head_); 395 math::check_range("matrix[multi,multi] assign range", name, 396 x.cols(), n); 397 for (int i = 0; i < y.rows(); ++i) { 398 int m = rvalue_at(i, idxs.head_); 399 math::check_range("matrix[multi,multi] assign range", name, 400 x.rows(), m); 401 x(m - 1, n - 1) = y(i, j); 402 } 403 } 404 } 405 406 /** 407 * Assign the specified array (standard vector) at the specified 408 * index list beginning with a single index to the specified value. 409 * 410 * This function operates recursively to carry out the tail 411 * indexing. 412 * 413 * Types: x[uni | L] = y 414 * 415 * @tparam T Assigned vector member type. 416 * @tparam L Type of tail of index list. 417 * @tparam U Value scalar type (must be assignable to indexed 418 * variable). 419 * @param[in] x Array variable to be assigned. 420 * @param[in] idxs List of indexes beginning with single index 421 * (from 1). 422 * @param[in] y Value. 423 * @param[in] name Name of variable (default "ANON"). 424 * @param[in] depth Indexing depth (default 0). 425 * @throw std::out_of_range If any of the indices are out of bounds. 426 * @throw std::invalid_argument If the dimensions do not match in the 427 * tail assignment. 428 */ 429 template <typename T, typename L, typename U> assign(std::vector<T> & x,const cons_index_list<index_uni,L> & idxs,const U & y,const char * name="ANON",int depth=0)430 inline void assign(std::vector<T>& x, 431 const cons_index_list<index_uni, L>& idxs, const U& y, 432 const char* name = "ANON", int depth = 0) { 433 int i = idxs.head_.n_; 434 math::check_range("vector[uni,...] assign range", name, x.size(), i); 435 assign(x[i - 1], idxs.tail_, y, name, depth + 1); 436 } 437 438 /** 439 * Assign the specified array (standard vector) at the specified 440 * index list beginning with a multiple index to the specified value. 441 * 442 * This function operates recursively to carry out the tail 443 * indexing. 444 * 445 * Types: x[multi | L] = y 446 * 447 * @tparam T Assigned vector member type. 448 * @tparam I Type of multiple index heading index list. 449 * @tparam L Type of tail of index list. 450 * @tparam U Value scalar type (must be assignable to indexed 451 * variable). 452 * @param[in] x Array variable to be assigned. 453 * @param[in] idxs List of indexes beginning with multiple index 454 * (from 1). 455 * @param[in] y Value. 456 * @param[in] name Name of variable (default "ANON"). 457 * @param[in] depth Indexing depth (default 0). 458 * @throw std::out_of_range If any of the indices are out of bounds. 459 * @throw std::invalid_argument If the size of the multiple indexing 460 * and size of first dimension of value do not match, or any of 461 * the recursive tail assignment dimensions do not match. 462 */ 463 template <typename T, typename I, typename L, typename U> 464 typename boost::disable_if<boost::is_same<I, index_uni>, void>::type assign(std::vector<T> & x,const cons_index_list<I,L> & idxs,const std::vector<U> & y,const char * name="ANON",int depth=0)465 inline assign(std::vector<T>& x, const cons_index_list<I, L>& idxs, 466 const std::vector<U>& y, 467 const char* name = "ANON", int depth = 0) { 468 int x_idx_size = rvalue_index_size(idxs.head_, x.size()); 469 math::check_size_match("vector[multi,...] assign sizes", 470 "lhs", x_idx_size, 471 name, y.size()); 472 for (size_t n = 0; n < y.size(); ++n) { 473 int i = rvalue_at(n, idxs.head_); 474 math::check_range("vector[multi,...] assign range", name, x.size(), i); 475 assign(x[i - 1], idxs.tail_, y[n], name, depth + 1); 476 } 477 } 478 479 } 480 } 481 #endif 482