1 #ifndef STAN_MATH_PRIM_FUN_TCROSSPROD_HPP
2 #define STAN_MATH_PRIM_FUN_TCROSSPROD_HPP
3 
4 #include <stan/math/prim/meta.hpp>
5 #include <stan/math/prim/fun/Eigen.hpp>
6 #include <stan/math/prim/fun/to_ref.hpp>
7 #include <stan/math/prim/fun/typedefs.hpp>
8 
9 namespace stan {
10 namespace math {
11 
12 /**
13  * Returns the result of post-multiplying a matrix by its
14  * own transpose.
15  *
16  * @tparam T type of the matrix (must be derived from \c Eigen::MatrixBase)
17  * @param M Matrix to multiply.
18  * @return M times its transpose.
19  */
20 template <typename T, require_eigen_vt<std::is_arithmetic, T>* = nullptr>
21 inline Eigen::Matrix<value_type_t<T>, T::RowsAtCompileTime,
22                      T::RowsAtCompileTime>
tcrossprod(const T & M)23 tcrossprod(const T& M) {
24   if (M.rows() == 0) {
25     return {};
26   }
27   const auto& M_ref = to_ref(M);
28   if (M.rows() == 1) {
29     return M_ref * M_ref.transpose();
30   }
31   Eigen::Matrix<value_type_t<T>, T::RowsAtCompileTime, T::RowsAtCompileTime>
32       result(M.rows(), M.rows());
33   return result.setZero().template selfadjointView<Eigen::Upper>().rankUpdate(
34       M_ref);
35 }
36 
37 }  // namespace math
38 }  // namespace stan
39 
40 #endif
41