Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
log_determinant_spd.hpp
Go to the documentation of this file.
1 #ifndef STAN__AGRAD__REV__MATRIX__LOG_DETERMINANT_SPD_HPP
2 #define STAN__AGRAD__REV__MATRIX__LOG_DETERMINANT_SPD_HPP
3 
4 #include <vector>
8 #include <stan/agrad/rev/var.hpp>
11 
12 // FIXME: use explicit files
13 #include <stan/agrad/rev.hpp>
14 
15 namespace stan {
16  namespace agrad {
17 
18  namespace {
19  template <int R,int C>
20  class log_determinant_spd_alloc : public chainable_alloc {
21  public:
22  virtual ~log_determinant_spd_alloc() {}
23 
24  Eigen::Matrix<double,R,C> _invA;
25  };
26 
27 
28  template<int R,int C>
29  class log_determinant_spd_vari : public vari {
30  log_determinant_spd_alloc<R,C> *_alloc;
31  int _rows;
32  int _cols;
33  vari** _adjARef;
34  public:
35  log_determinant_spd_vari(const Eigen::Matrix<var,R,C> &A)
36  : vari(log_determinant_spd_vari_calc(A,&_alloc)),
37  _rows(A.rows()),
38  _cols(A.cols()),
39  _adjARef((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
40  * A.rows() * A.cols()))
41  {
42  size_t pos = 0;
43  for (size_type j = 0; j < _cols; j++) {
44  for (size_type i = 0; i < _rows; i++) {
45  _adjARef[pos++] = A(i,j).vi_;
46  }
47  }
48  }
49 
50  static
51  double log_determinant_spd_vari_calc(const Eigen::Matrix<var,R,C> &A,
52  log_determinant_spd_alloc<R,C> **alloc)
53  {
54  using stan::math::dom_err;
55 
56  // allocate space for information needed in chain
57  *alloc = new log_determinant_spd_alloc<R,C>();
58 
59  // compute cholesky decomposition of A
60  (*alloc)->_invA.resize(A.rows(),A.cols());
61  for (size_type j = 0; j < A.cols(); j++)
62  for (size_type i = 0; i < A.rows(); i++)
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) {
66  // Handle this better.
67  (*alloc)->_invA.setZero(A.rows(),A.cols());
68  double y = 0;
69  double result = -std::numeric_limits<double>::infinity();
70  return dom_err("log_determinant_spd(%1%)",
71  y,
72  "matrix argument",
73  "failed LDLT factorization","",
74  &result);
75  }
76 
77  // compute the inverse of A (needed for the derivative)
78  (*alloc)->_invA.setIdentity(A.rows(),A.cols());
79  ldlt.solveInPlace((*alloc)->_invA);
80 
81  if (ldlt.isNegative() || (ldlt.vectorD().array() <= 1e-16).any()) {
82  double y = 0;
83  double result = -std::numeric_limits<double>::infinity();
84  return dom_err("log_determinant_spd(%1%)",
85  y,
86  "matrix argument",
87  "matrix is negative definite","",
88  &result);
89  }
90 
91  double ret = ldlt.vectorD().array().log().sum();
92  if (!boost::math::isfinite(ret)) {
93  double y = 0;
94  double result = -std::numeric_limits<double>::infinity();
95  return dom_err("log_determinant_spd(%1%)",
96  y,
97  "matrix argument",
98  "log determininant is infinite","",
99  &result);
100  }
101  return ret;
102  }
103 
104  virtual void chain() {
105  size_t pos = 0;
106  for (size_type j = 0; j < _cols; j++) {
107  for (size_type i = 0; i < _rows; i++) {
108  _adjARef[pos++]->adj_ += adj_*_alloc->_invA(i,j);
109  }
110  }
111  }
112  };
113  }
114 
115  template <int R, int C>
116  inline var log_determinant_spd(const Eigen::Matrix<var,R,C>& m) {
117  stan::math::check_square("log_determinant_spd(%1%)",m,"m",(double*)0);
118  return var(new log_determinant_spd_vari<R,C>(m));
119  }
120 
121  }
122 }
123 #endif
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)
Definition: dom_err.hpp:36
bool isfinite(const stan::agrad::var &v)
Checks if the given number has finite value.
memory::stack_alloc memalloc_
Definition: var_stack.cpp:16
var log_determinant_spd(const Eigen::Matrix< var, R, C > &m)
int _cols
vari ** _adjARef
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
Definition: typedefs.hpp:14
size_t rows(const Eigen::Matrix< T, R, C > &m)
Definition: rows.hpp:12
size_t cols(const Eigen::Matrix< T, R, C > &m)
Definition: cols.hpp:12
Eigen::Matrix< double, R, C > _invA
int _rows
Independent (input) and dependent (output) variables for gradients.
Definition: var.hpp:27
double e()
Return the base of the natural logarithm.
Definition: constants.hpp:86
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.

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