1 #ifndef STAN__AGRAD__REV__MATRIX__TRACE_INV_QUAD_FORM_LDLT_HPP
2 #define STAN__AGRAD__REV__MATRIX__TRACE_INV_QUAD_FORM_LDLT_HPP
8 #include <boost/type_traits/is_same.hpp>
9 #include <boost/utility/enable_if.hpp>
15 template <
typename T2,
int R2,
int C2,
typename T3,
int R3,
int C3>
16 class trace_inv_quad_form_ldlt_impl :
public chainable_alloc {
18 inline void initializeB(
const Eigen::Matrix<var,R3,C3> &B,
bool haveD) {
19 Eigen::Matrix<double,R3,C3> Bd(B.rows(),B.cols());
20 _variB.resize(B.rows(),B.cols());
21 for (
int j = 0; j < B.cols(); j++) {
22 for (
int i = 0; i < B.rows(); i++) {
24 Bd(i,j) = B(i,j).val();
29 C_.noalias() = Bd.transpose()*
AinvB_;
33 inline void initializeB(
const Eigen::Matrix<double,R3,C3> &B,
bool haveD) {
41 template<
int R1,
int C1>
42 inline void initializeD(
const Eigen::Matrix<var,R1,C1> &D) {
43 D_.resize(D.rows(),D.cols());
44 _variD.resize(D.rows(),D.cols());
45 for (
int j = 0; j < D.cols(); j++) {
46 for (
int i = 0; i < D.rows(); i++) {
48 D_(i,j) = D(i,j).val();
52 template<
int R1,
int C1>
53 inline void initializeD(
const Eigen::Matrix<double,R1,C1> &D) {
58 template<
typename T1,
int R1,
int C1>
59 trace_inv_quad_form_ldlt_impl(
const Eigen::Matrix<T1,R1,C1> &D,
61 const Eigen::Matrix<T3,R3,C3> &B)
62 :
Dtype_(boost::is_same<T1,var>::value?1:0),
72 const Eigen::Matrix<T3,R3,C3> &B)
81 Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>
D_;
82 Eigen::Matrix<vari*,Eigen::Dynamic,Eigen::Dynamic>
_variD;
85 Eigen::Matrix<double,C3,C3>
C_;
89 template <
typename T2,
int R2,
int C2,
typename T3,
int R3,
int C3>
90 class trace_inv_quad_form_ldlt_vari :
public vari {
92 static inline void chainA(
const double &adj,
93 trace_inv_quad_form_ldlt_impl<double,R2,C2,T3,R3,C3> *impl) {
95 static inline void chainB(
const double &adj,
96 trace_inv_quad_form_ldlt_impl<T2,R2,C2,double,R3,C3> *impl) {
99 static inline void chainA(
const double &adj,
100 trace_inv_quad_form_ldlt_impl<var,R2,C2,T3,R3,C3> *impl) {
101 Eigen::Matrix<double,R2,C2> aA;
103 if (impl->Dtype_ != 2)
104 aA.noalias() = -adj*(impl->AinvB_ * impl->D_.transpose() * impl->AinvB_.transpose());
106 aA.noalias() = -adj*(impl->AinvB_ * impl->AinvB_.transpose());
108 for (
int j = 0; j < aA.cols(); j++)
109 for (
int i = 0; i < aA.rows(); i++)
110 impl->_ldlt._alloc->_variA(i,j)->adj_ += aA(i,j);
112 static inline void chainB(
const double &adj,
113 trace_inv_quad_form_ldlt_impl<T2,R2,C2,var,R3,C3> *impl) {
114 Eigen::Matrix<double,R3,C3> aB;
116 if (impl->Dtype_ != 2)
117 aB.noalias() = adj*impl->AinvB_*(impl->D_ + impl->D_.transpose());
119 aB.noalias() = 2*adj*impl->AinvB_;
121 for (
int j = 0; j < aB.cols(); j++)
122 for (
int i = 0; i < aB.rows(); i++)
123 impl->_variB(i,j)->adj_ += aB(i,j);
127 trace_inv_quad_form_ldlt_vari(trace_inv_quad_form_ldlt_impl<T2,R2,C2,T3,R3,C3> *impl)
131 virtual void chain() {
140 if (
_impl->Dtype_ == 1) {
141 for (
int j = 0; j <
_impl->_variD.cols(); j++)
142 for (
int i = 0; i <
_impl->_variD.rows(); i++)
143 _impl->_variD(i,j)->adj_ += adj_*
_impl->C_(i,j);
147 trace_inv_quad_form_ldlt_impl<T2,R2,C2,T3,R3,C3> *
_impl;
158 template <
typename T2,
int R2,
int C2,
typename T3,
int R3,
int C3>
160 boost::enable_if_c<boost::is_same<T2,var>::value ||
161 boost::is_same<T3,var>::value, var>::type
163 const Eigen::Matrix<T3,R3,C3> &B)
168 trace_inv_quad_form_ldlt_impl<T2,R2,C2,T3,R3,C3> *
_impl =
new trace_inv_quad_form_ldlt_impl<T2,R2,C2,T3,R3,C3>(A,B);
170 return var(
new trace_inv_quad_form_ldlt_vari<T2,R2,C2,T3,R3,C3>(_impl));
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.
T trace(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &m)
Returns the trace of the specified matrix.
boost::enable_if_c< boost::is_same< T2, var >::value||boost::is_same< T3, var >::value, var >::type trace_inv_quad_form_ldlt(const stan::math::LDLT_factor< T2, R2, C2 > &A, const Eigen::Matrix< T3, R3, C3 > &B)
Compute the trace of an inverse quadratic form.