1 #ifndef STAN__AGRAD__REV__MATRIX__TRACE_GEN_QUAD_FORM_HPP
2 #define STAN__AGRAD__REV__MATRIX__TRACE_GEN_QUAD_FORM_HPP
4 #include <boost/utility/enable_if.hpp>
5 #include <boost/type_traits.hpp>
19 template<
typename TD,
int RD,
int CD,
20 typename TA,
int RA,
int CA,
21 typename TB,
int RB,
int CB>
22 class trace_gen_quad_form_vari_alloc :
public chainable_alloc {
24 trace_gen_quad_form_vari_alloc(
const Eigen::Matrix<TD,RD,CD> &D,
25 const Eigen::Matrix<TA,RA,CA> &A,
26 const Eigen::Matrix<TB,RB,CB> &B)
36 Eigen::Matrix<TD,RD,CD>
D_;
37 Eigen::Matrix<TA,RA,CA>
A_;
38 Eigen::Matrix<TB,RB,CB>
B_;
41 template<
typename TD,
int RD,
int CD,
42 typename TA,
int RA,
int CA,
43 typename TB,
int RB,
int CB>
44 class trace_gen_quad_form_vari :
public vari {
46 static inline void computeAdjoints(
const double &adj,
47 const Eigen::Matrix<double,RD,CD> &D,
48 const Eigen::Matrix<double,RA,CA> &A,
49 const Eigen::Matrix<double,RB,CB> &B,
50 Eigen::Matrix<var,RD,CD> *varD,
51 Eigen::Matrix<var,RA,CA> *varA,
52 Eigen::Matrix<var,RB,CB> *varB)
54 Eigen::Matrix<double,CA,CB> AtB;
55 Eigen::Matrix<double,RA,CB> BD;
59 AtB.noalias() = A.transpose()*B;
62 Eigen::Matrix<double,RB,CB> adjB(adj*(A*BD + AtB*D.transpose()));
64 for (j = 0; j < B.cols(); j++)
65 for (i = 0; i < B.rows(); i++)
66 (*varB)(i,j).vi_->adj_ += adjB(i,j);
69 Eigen::Matrix<double,RA,CA> adjA(adj*(B*BD.transpose()));
71 for (j = 0; j < A.cols(); j++)
72 for (i = 0; i < A.rows(); i++)
73 (*varA)(i,j).vi_->adj_ += adjA(i,j);
76 Eigen::Matrix<double,RD,CD> adjD(adj*(B.transpose()*AtB));
78 for (j = 0; j < D.cols(); j++)
79 for (i = 0; i < D.rows(); i++)
80 (*varD)(i,j).vi_->adj_ += adjD(i,j);
86 trace_gen_quad_form_vari(trace_gen_quad_form_vari_alloc<TD,RD,CD,TA,RA,CA,TB,RB,CB> *impl)
87 : vari(impl->compute()),
_impl(impl) { }
89 virtual void chain() {
94 (Eigen::Matrix<var,RD,CD>*)(boost::is_same<TD,var>::value?(&
_impl->D_):NULL),
95 (Eigen::Matrix<var,RA,CA>*)(boost::is_same<TA,var>::value?(&
_impl->A_):NULL),
96 (Eigen::Matrix<var,RB,CB>*)(boost::is_same<TB,var>::value?(&
_impl->B_):NULL));
99 trace_gen_quad_form_vari_alloc<TD,RD,CD,TA,RA,CA,TB,RB,CB> *
_impl;
103 template<
typename TD,
int RD,
int CD,
104 typename TA,
int RA,
int CA,
105 typename TB,
int RB,
int CB>
107 boost::enable_if_c< boost::is_same<TD,var>::value ||
108 boost::is_same<TA,var>::value ||
109 boost::is_same<TB,var>::value,
112 const Eigen::Matrix<TA,RA,CA> &A,
113 const Eigen::Matrix<TB,RB,CB> &B)
122 trace_gen_quad_form_vari_alloc<TD,RD,CD,TA,RA,CA,TB,RB,CB> *baseVari =
new trace_gen_quad_form_vari_alloc<TD,RD,CD,TA,RA,CA,TB,RB,CB>(D,A,B);
124 return var(
new trace_gen_quad_form_vari<TD,RD,CD,TA,RA,CA,TB,RB,CB>(baseVari));
fvar< T > trace_gen_quad_form(const Eigen::Matrix< fvar< T >, RD, CD > &D, const Eigen::Matrix< fvar< T >, RA, CA > &A, const Eigen::Matrix< fvar< T >, RB, CB > &B)
T value_of(const fvar< T > &v)
Return the value of the specified variable.
bool check_multiplicable(const char *function, const T1 &y1, const char *name1, const T2 &y2, const char *name2, T_result *result)
Independent (input) and dependent (output) variables for gradients.
double trace_gen_quad_form(const Eigen::Matrix< double, RD, CD > &D, const Eigen::Matrix< double, RA, CA > &A, const Eigen::Matrix< double, RB, CB > &B)
Compute trace(D B^T A B).
bool check_square(const char *function, const Eigen::Matrix< T_y, Eigen::Dynamic, Eigen::Dynamic > &y, const char *name, T_result *result)
Return true if the specified matrix is square.