1 #ifndef __STAN__AGRAD__REV__MATRIX__LOG_DETERMINANT_SPD_HPP__
2 #define __STAN__AGRAD__REV__MATRIX__LOG_DETERMINANT_SPD_HPP__
19 template <
int R,
int C>
20 class log_determinant_spd_alloc :
public chainable_alloc {
22 virtual ~log_determinant_spd_alloc() {}
24 Eigen::Matrix<double,R,C>
_invA;
29 class log_determinant_spd_vari :
public vari {
30 log_determinant_spd_alloc<R,C> *
_alloc;
35 log_determinant_spd_vari(
const Eigen::Matrix<var,R,C> &A)
36 : vari(log_determinant_spd_vari_calc(A,&
_alloc)),
51 double log_determinant_spd_vari_calc(
const Eigen::Matrix<var,R,C> &A,
52 log_determinant_spd_alloc<R,C> **alloc)
55 *alloc =
new log_determinant_spd_alloc<R,C>();
58 (*alloc)->_invA.resize(A.rows(),A.cols());
61 (*alloc)->_invA(i,j) = A(i,j).val();
62 Eigen::LDLT< Eigen::Matrix<double,R,C> > ldlt((*alloc)->_invA);
63 if (ldlt.info() != Eigen::Success) {
65 std::cerr <<
"Failed LDLT factorization" << std::endl;
66 (*alloc)->_invA.setZero(A.rows(),A.cols());
67 return -std::numeric_limits<double>::infinity();
71 (*alloc)->_invA.setIdentity(A.rows(),A.cols());
72 ldlt.solveInPlace((*alloc)->_invA);
74 if (ldlt.isNegative() || (ldlt.vectorD().array() <= 1
e-16).any()) {
75 std::cerr <<
"Matrix is negative definite" << std::endl;
76 return -std::numeric_limits<double>::infinity();
79 double ret = ldlt.vectorD().array().log().sum();
81 std::cerr << ldlt.vectorD() << std::endl;
86 virtual void chain() {
97 template <
int R,
int C>
100 return var(
new log_determinant_spd_vari<R,C>(m));