1 #ifndef STAN_MATH_PRIM_FUN_TO_MATRIX_HPP
2 #define STAN_MATH_PRIM_FUN_TO_MATRIX_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/err.hpp>
6 #include <stan/math/prim/fun/Eigen.hpp>
7 #include <vector>
8 
9 namespace stan {
10 namespace math {
11 
12 /**
13  * Returns a matrix with dynamic dimensions constructed from an
14  * Eigen matrix which is either a row vector, column vector,
15  * or matrix.
16  * The runtime dimensions will be the same as the input.
17  *
18  * @tparam EigMat type of the matrix
19  *
20  * @param x matrix
21  * @return the matrix representation of the input
22  */
23 template <typename EigMat, require_eigen_t<EigMat>* = nullptr>
to_matrix(EigMat && x)24 inline EigMat to_matrix(EigMat&& x) {
25   return std::forward<EigMat>(x);
26 }
27 
28 /**
29  * Returns a matrix representation of a standard vector of Eigen
30  * row vectors with the same dimensions and indexing order.
31  *
32  * @tparam T type of the elements in the vector
33  * @param x Eigen vector of vectors of scalar values
34  * @return the matrix representation of the input
35  */
36 template <typename T>
to_matrix(const std::vector<Eigen::Matrix<T,1,Eigen::Dynamic>> & x)37 inline Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> to_matrix(
38     const std::vector<Eigen::Matrix<T, 1, Eigen::Dynamic>>& x) {
39   int rows = x.size();
40   if (rows == 0) {
41     return {};
42   }
43   int cols = x[0].size();
44   Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> result(rows, cols);
45   for (int i = 0, ij = 0; i < cols; i++) {
46     for (int j = 0; j < rows; j++, ij++) {
47       result.coeffRef(ij) = x[j][i];
48     }
49   }
50   return result;
51 }
52 
53 /**
54  * Returns a matrix representation of the standard vector of
55  * standard vectors with the same dimensions and indexing order.
56  *
57  * @tparam T type of elements in the vector
58  * @param x vector of vectors of scalar values
59  * @return the matrix representation of the input
60  */
61 template <typename T>
62 inline Eigen::Matrix<return_type_t<T, double>, Eigen::Dynamic, Eigen::Dynamic>
to_matrix(const std::vector<std::vector<T>> & x)63 to_matrix(const std::vector<std::vector<T>>& x) {
64   size_t rows = x.size();
65   if (rows == 0) {
66     return {};
67   }
68   size_t cols = x[0].size();
69   Eigen::Matrix<return_type_t<T, double>, Eigen::Dynamic, Eigen::Dynamic>
70       result(rows, cols);
71   for (size_t i = 0, ij = 0; i < cols; i++) {
72     for (size_t j = 0; j < rows; j++, ij++) {
73       result.coeffRef(ij) = x[j][i];
74     }
75   }
76   return result;
77 }
78 
79 /**
80  * Returns a matrix representation of the vector in column-major
81  * order with the specified number of rows and columns.
82  *
83  * @tparam EigMat type of the matrix
84  *
85  * @param x matrix
86  * @param m rows
87  * @param n columns
88  * @return Reshaped inputted matrix
89  * @throw <code>std::invalid_argument</code> if the sizes
90  * do not match
91  */
92 template <typename EigMat, require_eigen_t<EigMat>* = nullptr>
93 inline Eigen::Matrix<value_type_t<EigMat>, Eigen::Dynamic, Eigen::Dynamic>
to_matrix(EigMat && x,int m,int n)94 to_matrix(EigMat&& x, int m, int n) {
95   static const char* function = "to_matrix(matrix)";
96   check_size_match(function, "rows * columns", m * n, "vector size", x.size());
97   Eigen::Matrix<value_type_t<EigMat>, Eigen::Dynamic, Eigen::Dynamic> y
98       = std::forward<EigMat>(x);
99   y.resize(m, n);
100   return y;
101 }
102 
103 /**
104  * Returns a matrix representation of the vector in column-major
105  * order with the specified number of rows and columns.
106  *
107  * @tparam T type of elements in the vector
108  * @param x vector of values
109  * @param m rows
110  * @param n columns
111  * @return the matrix representation of the input
112  * @throw <code>std::invalid_argument</code>
113  * if the sizes do not match
114  */
115 template <typename T>
to_matrix(const std::vector<T> & x,int m,int n)116 inline auto to_matrix(const std::vector<T>& x, int m, int n) {
117   static const char* function = "to_matrix(array)";
118   check_size_match(function, "rows * columns", m * n, "vector size", x.size());
119   return Eigen::Map<const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>>(
120       &x[0], m, n);
121 }
122 
123 /**
124  * Returns a matrix representation of the vector in column-major
125  * order with the specified number of rows and columns.
126  *
127  * @param x vector of values
128  * @param m rows
129  * @param n columns
130  * @return the matrix representation of the input
131  * @throw <code>std::invalid_argument</code>
132  * if the sizes do not match
133  */
to_matrix(const std::vector<int> & x,int m,int n)134 inline Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> to_matrix(
135     const std::vector<int>& x, int m, int n) {
136   static const char* function = "to_matrix(array)";
137   int x_size = x.size();
138   check_size_match(function, "rows * columns", m * n, "vector size", x_size);
139   Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> result(m, n);
140   for (int i = 0; i < x_size; i++) {
141     result.coeffRef(i) = x[i];
142   }
143   return result;
144 }
145 
146 /**
147  * Returns a matrix representation of the vector in column-major
148  * order with the specified number of rows and columns.
149  *
150  * @tparam EigMat type of the matrix
151  *
152  * @param x matrix
153  * @param m rows
154  * @param n columns
155  * @param col_major column-major indicator:
156  * if 1, output matrix is transversed in column-major order,
157  * if 0, output matrix is transversed in row-major order,
158  * otherwise function throws std::invalid_argument
159  * @return Reshaped inputted matrix
160  * @throw <code>std::invalid_argument</code>
161  * if the sizes do not match
162  */
163 template <typename EigMat, require_eigen_t<EigMat>* = nullptr>
164 inline Eigen::Matrix<value_type_t<EigMat>, Eigen::Dynamic, Eigen::Dynamic>
to_matrix(EigMat && x,int m,int n,bool col_major)165 to_matrix(EigMat&& x, int m, int n, bool col_major) {
166   if (col_major) {
167     return to_matrix(std::forward<EigMat>(x), m, n);
168   } else {
169     Eigen::Matrix<value_type_t<EigMat>, Eigen::Dynamic, Eigen::Dynamic> res
170         = to_matrix(std::forward<EigMat>(x), n, m);
171     res.transposeInPlace();
172     return res;
173   }
174 }
175 
176 /**
177  * Returns a matrix representation of the vector in column-major
178  * order with the specified number of rows and columns.
179  *
180  * @tparam T type of elements in the vector
181  * @param x vector of values
182  * @param m rows
183  * @param n columns
184  * @param col_major column-major indicator:
185  * if 1, output matrix is transversed in column-major order,
186  * if 0, output matrix is transversed in row-major order,
187  * otherwise function throws std::invalid_argument
188  * @return the matrix representation of the input
189  * @throw <code>std::invalid_argument</code>
190  * if the sizes do not match
191  */
192 template <typename T>
193 inline Eigen::Matrix<return_type_t<T, double>, Eigen::Dynamic, Eigen::Dynamic>
to_matrix(const std::vector<T> & x,int m,int n,bool col_major)194 to_matrix(const std::vector<T>& x, int m, int n, bool col_major) {
195   if (col_major) {
196     return to_matrix(x, m, n);
197   }
198   check_size_match("to_matrix", "rows * columns", m * n, "matrix size",
199                    x.size());
200   Eigen::Matrix<return_type_t<T, double>, Eigen::Dynamic, Eigen::Dynamic>
201       result(m, n);
202   for (int i = 0, ij = 0; i < m; i++) {
203     for (int j = 0; j < n; j++, ij++) {
204       result.coeffRef(i, j) = x[ij];
205     }
206   }
207   return result;
208 }
209 
210 }  // namespace math
211 }  // namespace stan
212 
213 #endif
214