44#include < stan/math/prim/meta.hpp>
55#include < stan/math/prim/fun/Eigen.hpp>
66#include < stan/math/prim/fun/ceil.hpp>
7+ #include < stan/math/prim/fun/to_ref.hpp>
78#include < unsupported/Eigen/MatrixFunctions>
89#include < vector>
910#include < cmath>
@@ -23,10 +24,10 @@ namespace math {
2324 * and t is double.
2425 */
2526class matrix_exp_action_handler {
26- const int _p_max = 8 ;
27- const int _m_max = 55 ;
28- const double _tol = 1.1e-16 ; // from the paper, double precision: 2^-53
29- const std::vector <double > _theta_m{
27+ static constexpr int _p_max = 8 ;
28+ static constexpr int _m_max = 55 ;
29+ static constexpr double _tol = 1.1e-16 ; // from the paper, double precision: 2^-53
30+ static constexpr std::array <double , 100 > _theta_m{
3031 2.22044605e-16 , 2.58095680e-08 , 1.38634787e-05 , 3.39716884e-04 ,
3132 2.40087636e-03 , 9.06565641e-03 , 2.38445553e-02 , 4.99122887e-02 ,
3233 8.95776020e-02 , 1.44182976e-01 , 2.14235807e-01 , 2.99615891e-01 ,
@@ -64,18 +65,18 @@ class matrix_exp_action_handler {
6465 template <typename EigMat1, typename EigMat2,
6566 require_all_eigen_t <EigMat1, EigMat2>* = nullptr ,
6667 require_all_st_same<double , EigMat1, EigMat2>* = nullptr >
67- inline Eigen::MatrixXd action (const EigMat1& mat, const EigMat2& b,
68- const double & t = 1.0 ) {
69- Eigen::MatrixXd A = mat;
68+ inline Eigen::MatrixXd action (EigMat1&& mat, EigMat2& & b,
69+ const double t = 1.0 ) {
70+ decltype ( auto ) A = to_ref (std::forward<EigMat1>( mat)) ;
7071 double mu = A.trace () / A.rows ();
7172 A.diagonal ().array () -= mu;
7273
7374 int m, s;
74- set_approx_order (A, b, t, m, s);
75+ decltype (auto ) b_eval = to_ref (std::forward<EigMat2>(b));
76+ set_approx_order (A, b_eval, t, m, s);
7577
7678 double eta = exp (t * mu / s);
7779
78- const auto & b_eval = b.eval ();
7980 Eigen::MatrixXd f = b_eval;
8081 Eigen::MatrixXd bi = b_eval;
8182
@@ -102,8 +103,11 @@ class matrix_exp_action_handler {
102103 *
103104 * @param x matrix
104105 */
105- double matrix_operator_inf_norm (Eigen::MatrixXd const & x) {
106- return x.cwiseAbs ().rowwise ().sum ().maxCoeff ();
106+ template <typename EigenMat>
107+ double matrix_operator_inf_norm (EigenMat&& x) {
108+ return make_holder ([](auto && x_) {
109+ return x_.cwiseAbs ().rowwise ().sum ().maxCoeff ();
110+ }, std::forward<EigenMat>(x));
107111 }
108112
109113 /* *
@@ -125,15 +129,16 @@ class matrix_exp_action_handler {
125129 */
126130 template <typename EigMat1, require_all_eigen_t <EigMat1>* = nullptr ,
127131 require_all_st_same<double , EigMat1>* = nullptr >
128- double mat_power_1_norm (const EigMat1& mat, int m) {
129- if ((mat.array () > 0.0 ).all ()) {
130- Eigen::VectorXd e = Eigen::VectorXd::Constant (mat.rows (), 1.0 );
132+ double mat_power_1_norm (EigMat1&& mat, const int m) {
133+ auto && mat_ref = to_ref (std::forward<EigMat1>(mat));
134+ if ((mat_ref.array () > 0.0 ).all ()) {
135+ Eigen::VectorXd e = Eigen::VectorXd::Constant (mat_ref.rows (), 1.0 );
131136 for (int j = 0 ; j < m; ++j) {
132- e = mat .transpose () * e;
137+ e = mat_ref .transpose () * e;
133138 }
134139 return e.lpNorm <Eigen::Infinity>();
135140 } else {
136- return mat .pow (m).cwiseAbs ().colwise ().sum ().maxCoeff ();
141+ return mat_ref .pow (m).cwiseAbs ().colwise ().sum ().maxCoeff ();
137142 }
138143 }
139144
@@ -156,8 +161,8 @@ class matrix_exp_action_handler {
156161 template <typename EigMat1, typename EigMat2,
157162 require_all_eigen_t <EigMat1, EigMat2>* = nullptr ,
158163 require_all_st_same<double , EigMat1, EigMat2>* = nullptr >
159- inline void set_approx_order (const EigMat1& mat, const EigMat2& b,
160- const double & t, int & m, int & s) {
164+ inline void set_approx_order (EigMat1&& mat, EigMat2& & b,
165+ const double t, int & m, int & s) {
161166 if (t < _tol) {
162167 m = 0 ;
163168 s = 1 ;
0 commit comments