1 #ifndef STAN_MATH_PRIM_FUN_APPEND_COL_HPP
2 #define STAN_MATH_PRIM_FUN_APPEND_COL_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  * Return the result of appending the second argument matrix after the
14  * first argument matrix, that is, putting them side by side, with
15  * the first matrix followed by the second matrix.
16  *
17  * Given input types result in following outputs:
18  * (matrix, matrix) -> matrix,
19  * (matrix, vector) -> matrix,
20  * (vector, matrix) -> matrix,
21  * (vector, vector) -> matrix,
22  * (row vector, row vector) -> row_vector.
23  *
24  * @tparam T1 type of the first matrix
25  * @tparam T2 type of the second matrix
26  *
27  * @param A First matrix.
28  * @param B Second matrix.
29  * @return Result of appending the first matrix followed by the
30  * second matrix side by side.
31  */
32 template <typename T1, typename T2, typename = require_all_eigen_t<T1, T2>>
append_col(const T1 & A,const T2 & B)33 inline auto append_col(const T1& A, const T2& B) {
34   using Eigen::Dynamic;
35   using Eigen::Matrix;
36   using T_return = return_type_t<T1, T2>;
37   constexpr int row_type
38       = (T1::RowsAtCompileTime == 1 && T2::RowsAtCompileTime == 1)
39             ? 1
40             : Eigen::Dynamic;
41 
42   int Arows = A.rows();
43   int Brows = B.rows();
44   int Acols = A.cols();
45   int Bcols = B.cols();
46   check_size_match("append_col", "rows of A", Arows, "rows of B", Brows);
47 
48   Matrix<T_return, row_type, Dynamic> result(Arows, Acols + Bcols);
49   result.leftCols(Acols) = A.template cast<T_return>();
50   result.rightCols(Bcols) = B.template cast<T_return>();
51   return result;
52 }
53 
54 /**
55  * Return the result of stacking an scalar on top of the
56  * a row vector, with the result being a row vector.
57  *
58  * This function applies to (scalar, row vector) and returns a
59  * row vector.
60  *
61  * @tparam Scal type of the scalar
62  * @tparam RowVec type of the row vector
63  *
64  * @param A scalar.
65  * @param B row vector.
66  * @return Result of stacking the scalar on top of the row vector.
67  */
68 template <typename Scal, typename RowVec,
69           require_stan_scalar_t<Scal>* = nullptr,
70           require_t<is_eigen_row_vector<RowVec>>* = nullptr>
append_col(const Scal & A,const RowVec & B)71 inline Eigen::Matrix<return_type_t<Scal, RowVec>, 1, Eigen::Dynamic> append_col(
72     const Scal& A, const RowVec& B) {
73   using Eigen::Dynamic;
74   using Eigen::Matrix;
75   using T_return = return_type_t<Scal, RowVec>;
76 
77   Matrix<T_return, 1, Dynamic> result(B.size() + 1);
78   result << A, B.template cast<T_return>();
79   return result;
80 }
81 
82 /**
83  * Return the result of stacking a row vector on top of the
84  * an scalar, with the result being a row vector.
85  *
86  * This function applies to (row vector, scalar) and returns a
87  * row vector.
88  *
89  * @tparam RowVec type of the row vector
90  * @tparam Scal type of the scalar
91  *
92  * @param A row vector.
93  * @param B scalar.
94  * @return Result of stacking the row vector on top of the scalar.
95  */
96 template <typename RowVec, typename Scal,
97           require_t<is_eigen_row_vector<RowVec>>* = nullptr,
98           require_stan_scalar_t<Scal>* = nullptr>
append_col(const RowVec & A,const Scal & B)99 inline Eigen::Matrix<return_type_t<RowVec, Scal>, 1, Eigen::Dynamic> append_col(
100     const RowVec& A, const Scal& B) {
101   using Eigen::Dynamic;
102   using Eigen::Matrix;
103   using T_return = return_type_t<RowVec, Scal>;
104 
105   Matrix<T_return, 1, Dynamic> result(A.size() + 1);
106   result << A.template cast<T_return>(), B;
107   return result;
108 }
109 
110 }  // namespace math
111 }  // namespace stan
112 
113 #endif
114