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)
57 *alloc =
new log_determinant_spd_alloc<R,C>();
60 (*alloc)->_invA.resize(A.rows(),A.cols());
63 (*alloc)->_invA(i,j) = A(i,j).val();
64 Eigen::LDLT< Eigen::Matrix<double,R,C> > ldlt((*alloc)->_invA);
65 if (ldlt.info() != Eigen::Success) {
67 (*alloc)->_invA.setZero(A.rows(),A.cols());
69 double result = -std::numeric_limits<double>::infinity();
70 return dom_err(
"log_determinant_spd(%1%)",
73 "failed LDLT factorization",
"",
78 (*alloc)->_invA.setIdentity(A.rows(),A.cols());
79 ldlt.solveInPlace((*alloc)->_invA);
81 if (ldlt.isNegative() || (ldlt.vectorD().array() <= 1
e-16).any()) {
83 double result = -std::numeric_limits<double>::infinity();
84 return dom_err(
"log_determinant_spd(%1%)",
87 "matrix is negative definite",
"",
91 double ret = ldlt.vectorD().array().log().sum();
94 double result = -std::numeric_limits<double>::infinity();
95 return dom_err(
"log_determinant_spd(%1%)",
98 "log determininant is infinite",
"",
104 virtual void chain() {
115 template <
int R,
int C>
118 return var(
new log_determinant_spd_vari<R,C>(m));
log_determinant_spd_alloc< R, C > * _alloc
bool dom_err(const char *function, const T &y, const char *name, const char *error_msg, const T_msg error_msg2, T_result *result)
bool isfinite(const stan::agrad::var &v)
Checks if the given number has finite value.
memory::stack_alloc memalloc_
var log_determinant_spd(const Eigen::Matrix< var, R, C > &m)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
size_t rows(const Eigen::Matrix< T, R, C > &m)
size_t cols(const Eigen::Matrix< T, R, C > &m)
Eigen::Matrix< double, R, C > _invA
Independent (input) and dependent (output) variables for gradients.
double e()
Return the base of the natural logarithm.
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.