1 #ifndef __STAN__AGRAD__REV__MATRIX__MDIVIDE_LEFT_SPD_HPP__
2 #define __STAN__AGRAD__REV__MATRIX__MDIVIDE_LEFT_SPD_HPP__
16 template <
int R1,
int C1,
int R2,
int C2>
17 class mdivide_left_spd_alloc :
public chainable_alloc {
19 virtual ~mdivide_left_spd_alloc() {}
21 Eigen::LLT< Eigen::Matrix<double,R1,C1> >
_llt;
22 Eigen::Matrix<double,R2,C2>
_C;
25 template <
int R1,
int C1,
int R2,
int C2>
26 class mdivide_left_spd_vv_vari :
public vari {
33 mdivide_left_spd_alloc<R1,C1,R2,C2> *
_alloc;
35 mdivide_left_spd_vv_vari(
const Eigen::Matrix<var,R1,C1> &A,
36 const Eigen::Matrix<var,R2,C2> &B)
46 _alloc(new mdivide_left_spd_alloc<R1,C1,R2,C2>())
51 Matrix<double,R1,C1> Ad(A.rows(),A.cols());
57 Ad(i,j) = A(i,j).val();
67 _alloc->_C(i,j) = B(i,j).val();
84 virtual void chain() {
87 Eigen::Matrix<double,R1,C1> adjA(
_M,
_M);
88 Eigen::Matrix<double,R2,C2> adjB(
_M,
_N);
95 _alloc->_llt.solveInPlace(adjB);
96 adjA.noalias() = -adjB *
_alloc->_C.transpose();
110 template <
int R1,
int C1,
int R2,
int C2>
111 class mdivide_left_spd_dv_vari :
public vari {
117 mdivide_left_spd_alloc<R1,C1,R2,C2> *
_alloc;
119 mdivide_left_spd_dv_vari(
const Eigen::Matrix<double,R1,C1> &A,
120 const Eigen::Matrix<var,R2,C2> &B)
128 _alloc(new mdivide_left_spd_alloc<R1,C1,R2,C2>())
138 _alloc->_C(i,j) = B(i,j).val();
155 virtual void chain() {
158 Eigen::Matrix<double,R2,C2> adjB(_M,_N);
161 for (
size_type j = 0; j < adjB.cols(); j++)
162 for (
size_type i = 0; i < adjB.rows(); i++)
165 _alloc->_llt.solveInPlace(adjB);
168 for (
size_type j = 0; j < adjB.cols(); j++)
169 for (
size_type i = 0; i < adjB.rows(); i++)
174 template <
int R1,
int C1,
int R2,
int C2>
175 class mdivide_left_spd_vd_vari :
public vari {
181 mdivide_left_spd_alloc<R1,C1,R2,C2> *
_alloc;
183 mdivide_left_spd_vd_vari(
const Eigen::Matrix<var,R1,C1> &A,
184 const Eigen::Matrix<double,R2,C2> &B)
192 _alloc(new mdivide_left_spd_alloc<R1,C1,R2,C2>())
197 Matrix<double,R1,C1> Ad(A.rows(),A.cols());
203 Ad(i,j) = A(i,j).val();
220 virtual void chain() {
223 Eigen::Matrix<double,R1,C1> adjA(_M,_M);
224 Eigen::Matrix<double,R1,C2> adjC(_M,_N);
227 for (
size_type j = 0; j < adjC.cols(); j++)
228 for (
size_type i = 0; i < adjC.rows(); i++)
231 adjA = -
_alloc->_llt.solve(adjC*
_alloc->_C.transpose());
234 for (
size_type j = 0; j < adjA.cols(); j++)
235 for (
size_type i = 0; i < adjA.rows(); i++)
241 template <
int R1,
int C1,
int R2,
int C2>
243 Eigen::Matrix<var,R1,C2>
245 const Eigen::Matrix<var,R2,C2> &b) {
246 Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
254 mdivide_left_spd_vv_vari<R1,C1,R2,C2> *baseVari =
new mdivide_left_spd_vv_vari<R1,C1,R2,C2>(A,b);
257 for (
size_type j = 0; j < res.cols(); j++)
258 for (
size_type i = 0; i < res.rows(); i++)
259 res(i,j).vi_ = baseVari->_variRefC[pos++];
264 template <
int R1,
int C1,
int R2,
int C2>
266 Eigen::Matrix<var,R1,C2>
268 const Eigen::Matrix<double,R2,C2> &b) {
269 Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
277 mdivide_left_spd_vd_vari<R1,C1,R2,C2> *baseVari =
new mdivide_left_spd_vd_vari<R1,C1,R2,C2>(A,b);
280 for (
size_type j = 0; j < res.cols(); j++)
281 for (
size_type i = 0; i < res.rows(); i++)
282 res(i,j).vi_ = baseVari->_variRefC[pos++];
287 template <
int R1,
int C1,
int R2,
int C2>
289 Eigen::Matrix<var,R1,C2>
291 const Eigen::Matrix<var,R2,C2> &b) {
292 Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
300 mdivide_left_spd_dv_vari<R1,C1,R2,C2> *baseVari =
new mdivide_left_spd_dv_vari<R1,C1,R2,C2>(A,b);
303 for (
size_type j = 0; j < res.cols(); j++)
304 for (
size_type i = 0; i < res.rows(); i++)
305 res(i,j).vi_ = baseVari->_variRefC[pos++];