All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Groups
mdivide_left_ldlt.hpp
Go to the documentation of this file.
#ifndef STAN_MATH_REV_MAT_FUN_MDIVIDE_LEFT_LDLT_HPP
#define STAN_MATH_REV_MAT_FUN_MDIVIDE_LEFT_LDLT_HPP
#include <stan/math/rev/core.hpp>
#include <stan/math/prim/mat/fun/Eigen.hpp>
#include <stan/math/rev/mat/fun/LDLT_alloc.hpp>
#include <stan/math/rev/mat/fun/LDLT_factor.hpp>
#include <stan/math/prim/mat/err/check_multiplicable.hpp>
namespace stan {
namespace math {
namespace {
template <int R1, int C1, int R2, int C2>
class mdivide_left_ldlt_alloc : public chainable_alloc {
public:
virtual ~mdivide_left_ldlt_alloc() {}
boost::shared_ptr<Eigen::LDLT<Eigen::Matrix<double, R1, C1> > > _ldltP;
Eigen::Matrix<double, R2, C2> C_;
};
template <int R1, int C1, int R2, int C2>
class mdivide_left_ldlt_vv_vari : public vari {
public:
int M_; // A.rows() = A.cols() = B.rows()
int N_; // B.cols()
vari** _variRefB;
vari** _variRefC;
mdivide_left_ldlt_alloc<R1, C1, R2, C2> *_alloc;
const LDLT_alloc<R1, C1> *_alloc_ldlt;
mdivide_left_ldlt_vv_vari(const stan::math::LDLT_factor<var, R1, C1> &A,
const Eigen::Matrix<var, R2, C2> &B)
: vari(0.0),
M_(A.rows()),
N_(B.cols()),
_variRefB(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))),
_variRefC(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))),
_alloc(new mdivide_left_ldlt_alloc<R1, C1, R2, C2>()),
_alloc_ldlt(A._alloc) {
int pos = 0;
_alloc->C_.resize(M_, N_);
for (int j = 0; j < N_; j++) {
for (int i = 0; i < M_; i++) {
_variRefB[pos] = B(i, j).vi_;
_alloc->C_(i, j) = B(i, j).val();
pos++;
}
}
_alloc_ldlt->_ldlt.solveInPlace(_alloc->C_);
pos = 0;
for (int j = 0; j < N_; j++) {
for (int i = 0; i < M_; i++) {
_variRefC[pos] = new vari(_alloc->C_(i, j), false);
pos++;
}
}
}
virtual void chain() {
Eigen::Matrix<double, R1, C1> adjA(M_, M_);
Eigen::Matrix<double, R2, C2> adjB(M_, N_);
int pos = 0;
for (int j = 0; j < N_; j++)
for (int i = 0; i < M_; i++)
adjB(i, j) = _variRefC[pos++]->adj_;
_alloc_ldlt->_ldlt.solveInPlace(adjB);
adjA.noalias() = -adjB * _alloc->C_.transpose();
for (int j = 0; j < M_; j++)
for (int i = 0; i < M_; i++)
_alloc_ldlt->_variA(i, j)->adj_ += adjA(i, j);
pos = 0;
for (int j = 0; j < N_; j++)
for (int i = 0; i < M_; i++)
_variRefB[pos++]->adj_ += adjB(i, j);
}
};
template <int R1, int C1, int R2, int C2>
class mdivide_left_ldlt_dv_vari : public vari {
public:
int M_; // A.rows() = A.cols() = B.rows()
int N_; // B.cols()
vari** _variRefB;
vari** _variRefC;
mdivide_left_ldlt_alloc<R1, C1, R2, C2> *_alloc;
mdivide_left_ldlt_dv_vari(const stan::math::LDLT_factor<double, R1, C1>
&A,
const Eigen::Matrix<var, R2, C2> &B)
: vari(0.0),
M_(A.rows()),
N_(B.cols()),
_variRefB(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))),
_variRefC(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))),
_alloc(new mdivide_left_ldlt_alloc<R1, C1, R2, C2>()) {
using Eigen::Matrix;
using Eigen::Map;
int pos = 0;
_alloc->C_.resize(M_, N_);
for (int j = 0; j < N_; j++) {
for (int i = 0; i < M_; i++) {
_variRefB[pos] = B(i, j).vi_;
_alloc->C_(i, j) = B(i, j).val();
pos++;
}
}
_alloc->_ldltP = A._ldltP;
_alloc->_ldltP->solveInPlace(_alloc->C_);
pos = 0;
for (int j = 0; j < N_; j++) {
for (int i = 0; i < M_; i++) {
_variRefC[pos] = new vari(_alloc->C_(i, j), false);
pos++;
}
}
}
virtual void chain() {
Eigen::Matrix<double, R2, C2> adjB(M_, N_);
int pos = 0;
for (int j = 0; j < adjB.cols(); j++)
for (int i = 0; i < adjB.rows(); i++)
adjB(i, j) = _variRefC[pos++]->adj_;
_alloc->_ldltP->solveInPlace(adjB);
pos = 0;
for (int j = 0; j < adjB.cols(); j++)
for (int i = 0; i < adjB.rows(); i++)
_variRefB[pos++]->adj_ += adjB(i, j);
}
};
template <int R1, int C1, int R2, int C2>
class mdivide_left_ldlt_vd_vari : public vari {
public:
int M_; // A.rows() = A.cols() = B.rows()
int N_; // B.cols()
vari** _variRefC;
mdivide_left_ldlt_alloc<R1, C1, R2, C2> *_alloc;
const LDLT_alloc<R1, C1> *_alloc_ldlt;
mdivide_left_ldlt_vd_vari(const stan::math::LDLT_factor<var, R1, C1> &A,
const Eigen::Matrix<double, R2, C2> &B)
: vari(0.0),
M_(A.rows()),
N_(B.cols()),
_variRefC(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))),
_alloc(new mdivide_left_ldlt_alloc<R1, C1, R2, C2>()),
_alloc_ldlt(A._alloc) {
_alloc->C_ = B;
_alloc_ldlt->_ldlt.solveInPlace(_alloc->C_);
int pos = 0;
for (int j = 0; j < N_; j++) {
for (int i = 0; i < M_; i++) {
_variRefC[pos] = new vari(_alloc->C_(i, j), false);
pos++;
}
}
}
virtual void chain() {
Eigen::Matrix<double, R1, C1> adjA(M_, M_);
Eigen::Matrix<double, R1, C2> adjC(M_, N_);
int pos = 0;
for (int j = 0; j < adjC.cols(); j++)
for (int i = 0; i < adjC.rows(); i++)
adjC(i, j) = _variRefC[pos++]->adj_;
adjA = -_alloc_ldlt->_ldlt.solve(adjC*_alloc->C_.transpose());
for (int j = 0; j < adjA.cols(); j++)
for (int i = 0; i < adjA.rows(); i++)
_alloc_ldlt->_variA(i, j)->adj_ += adjA(i, j);
}
};
}
template <int R1, int C1, int R2, int C2>
inline Eigen::Matrix<var, R1, C2>
mdivide_left_ldlt(const stan::math::LDLT_factor<var, R1, C1> &A,
const Eigen::Matrix<var, R2, C2> &b) {
Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
stan::math::check_multiplicable("mdivide_left_ldlt",
"A", A,
"b", b);
mdivide_left_ldlt_vv_vari<R1, C1, R2, C2> *baseVari
= new mdivide_left_ldlt_vv_vari<R1, C1, R2, C2>(A, b);
int pos = 0;
for (int j = 0; j < res.cols(); j++)
for (int i = 0; i < res.rows(); i++)
res(i, j).vi_ = baseVari->_variRefC[pos++];
return res;
}
template <int R1, int C1, int R2, int C2>
inline Eigen::Matrix<var, R1, C2>
mdivide_left_ldlt(const stan::math::LDLT_factor<var, R1, C1> &A,
const Eigen::Matrix<double, R2, C2> &b) {
Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
stan::math::check_multiplicable("mdivide_left_ldlt",
"A", A,
"b", b);
mdivide_left_ldlt_vd_vari<R1, C1, R2, C2> *baseVari
= new mdivide_left_ldlt_vd_vari<R1, C1, R2, C2>(A, b);
int pos = 0;
for (int j = 0; j < res.cols(); j++)
for (int i = 0; i < res.rows(); i++)
res(i, j).vi_ = baseVari->_variRefC[pos++];
return res;
}
template <int R1, int C1, int R2, int C2>
inline Eigen::Matrix<var, R1, C2>
mdivide_left_ldlt(const stan::math::LDLT_factor<double, R1, C1> &A,
const Eigen::Matrix<var, R2, C2> &b) {
Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
stan::math::check_multiplicable("mdivide_left_ldlt",
"A", A,
"b", b);
mdivide_left_ldlt_dv_vari<R1, C1, R2, C2> *baseVari
= new mdivide_left_ldlt_dv_vari<R1, C1, R2, C2>(A, b);
int pos = 0;
for (int j = 0; j < res.cols(); j++)
for (int i = 0; i < res.rows(); i++)
res(i, j).vi_ = baseVari->_variRefC[pos++];
return res;
}
}
}
#endif
stan::math::rows
int rows(const Eigen::Matrix< T, R, C > &m)
Return the number of rows in the specified matrix, vector, or row vector.
Definition: rows.hpp:20
core.hpp
LDLT_alloc.hpp
check_multiplicable.hpp
N_
int N_
Definition: mdivide_left_ldlt.hpp:41
_alloc
mdivide_left_ldlt_alloc< R1, C1, R2, C2 > * _alloc
Definition: mdivide_left_ldlt.hpp:44
M_
int M_
Definition: mdivide_left_ldlt.hpp:40
stan::math::LDLT_factor
Definition: LDLT_factor.hpp:18
stan::math::ChainableStack
AutodiffStackStorage< chainable, chainable_alloc > ChainableStack
Definition: chainablestack.hpp:11
_variRefC
vari ** _variRefC
Definition: mdivide_left_ldlt.hpp:43
stan::math::mdivide_left_ldlt
Eigen::Matrix< fvar< T2 >, R1, C2 > mdivide_left_ldlt(const stan::math::LDLT_factor< double, R1, C1 > &A, const Eigen::Matrix< fvar< T2 >, R2, C2 > &b)
Returns the solution of the system Ax=b given an LDLT_factor of A.
Definition: mdivide_left_ldlt.hpp:25
stan::math::check_multiplicable
bool check_multiplicable(const char *function, const char *name1, const T1 &y1, const char *name2, const T2 &y2)
Return true if the matrices can be multiplied.
Definition: check_multiplicable.hpp:33
_ldltP
boost::shared_ptr< Eigen::LDLT< Eigen::Matrix< double, R1, C1 > > > _ldltP
This share_ptr is used to prevent copying the LDLT factorizations for mdivide_left_ldlt(ldltA, b) when ldltA is a LDLT_factor<double>.
Definition: mdivide_left_ldlt.hpp:23
LDLT_factor.hpp
stan::math::cols
int cols(const Eigen::Matrix< T, R, C > &m)
Return the number of columns in the specified matrix, vector, or row vector.
Definition: cols.hpp:20
Eigen.hpp
_alloc_ldlt
const LDLT_alloc< R1, C1 > * _alloc_ldlt
Definition: mdivide_left_ldlt.hpp:45
C_
Eigen::Matrix< double, R2, C2 > C_
Definition: mdivide_left_ldlt.hpp:24
_variRefB
vari ** _variRefB
Definition: mdivide_left_ldlt.hpp:42

[ Stan Home Page ] © 2011–2015, Stan Development Team.