Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mdivide_left_ldlt.hpp
Go to the documentation of this file.
1 #ifndef STAN__AGRAD__REV__MATRIX__MDIVIDE_LEFT_LDLT_HPP
2 #define STAN__AGRAD__REV__MATRIX__MDIVIDE_LEFT_LDLT_HPP
3 
5 #include <stan/agrad/rev/var.hpp>
9 
10 namespace stan {
11  namespace agrad {
12  namespace {
13  template <int R1,int C1,int R2,int C2>
14  class mdivide_left_ldlt_alloc : public chainable_alloc {
15  public:
16  virtual ~mdivide_left_ldlt_alloc() {}
17 
23  boost::shared_ptr< Eigen::LDLT< Eigen::Matrix<double,R1,C1> > > _ldltP;
24  Eigen::Matrix<double,R2,C2> C_;
25  };
26 
37  template <int R1,int C1,int R2,int C2>
38  class mdivide_left_ldlt_vv_vari : public vari {
39  public:
40  int M_; // A.rows() = A.cols() = B.rows()
41  int N_; // B.cols()
42  vari** _variRefB;
43  vari** _variRefC;
44  mdivide_left_ldlt_alloc<R1,C1,R2,C2> *_alloc;
45  const LDLT_alloc<R1,C1> *_alloc_ldlt;
46 
47  mdivide_left_ldlt_vv_vari(const stan::math::LDLT_factor<var,R1,C1> &A,
48  const Eigen::Matrix<var,R2,C2> &B)
49  : vari(0.0),
50  M_(A.rows()),
51  N_(B.cols()),
52  _variRefB((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
53  * B.rows() * B.cols())),
54  _variRefC((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
55  * B.rows() * B.cols())),
56  _alloc(new mdivide_left_ldlt_alloc<R1,C1,R2,C2>()),
58  {
59  int pos = 0;
60  _alloc->C_.resize(M_,N_);
61  for (int j = 0; j < N_; j++) {
62  for (int i = 0; i < M_; i++) {
63  _variRefB[pos] = B(i,j).vi_;
64  _alloc->C_(i,j) = B(i,j).val();
65  pos++;
66  }
67  }
68 
69  _alloc_ldlt->_ldlt.solveInPlace(_alloc->C_);
70 
71  pos = 0;
72  for (int j = 0; j < N_; j++) {
73  for (int i = 0; i < M_; i++) {
74  _variRefC[pos] = new vari(_alloc->C_(i,j),false);
75  pos++;
76  }
77  }
78  }
79 
80  virtual void chain() {
81  Eigen::Matrix<double,R1,C1> adjA(M_,M_);
82  Eigen::Matrix<double,R2,C2> adjB(M_,N_);
83 
84  int pos = 0;
85  for (int j = 0; j < N_; j++)
86  for (int i = 0; i < M_; i++)
87  adjB(i,j) = _variRefC[pos++]->adj_;
88 
89  _alloc_ldlt->_ldlt.solveInPlace(adjB);
90  adjA.noalias() = -adjB * _alloc->C_.transpose();
91 
92  for (int j = 0; j < M_; j++)
93  for (int i = 0; i < M_; i++)
94  _alloc_ldlt->_variA(i,j)->adj_ += adjA(i,j);
95 
96  pos = 0;
97  for (int j = 0; j < N_; j++)
98  for (int i = 0; i < M_; i++)
99  _variRefB[pos++]->adj_ += adjB(i,j);
100  }
101  };
102 
113  template <int R1,int C1,int R2,int C2>
114  class mdivide_left_ldlt_dv_vari : public vari {
115  public:
116  int M_; // A.rows() = A.cols() = B.rows()
117  int N_; // B.cols()
118  vari** _variRefB;
119  vari** _variRefC;
120  mdivide_left_ldlt_alloc<R1,C1,R2,C2> *_alloc;
121 
122  mdivide_left_ldlt_dv_vari(const stan::math::LDLT_factor<double,R1,C1> &A,
123  const Eigen::Matrix<var,R2,C2> &B)
124  : vari(0.0),
125  M_(A.rows()),
126  N_(B.cols()),
127  _variRefB((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
128  * B.rows() * B.cols())),
129  _variRefC((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
130  * B.rows() * B.cols())),
131  _alloc(new mdivide_left_ldlt_alloc<R1,C1,R2,C2>())
132  {
133  using Eigen::Matrix;
134  using Eigen::Map;
135 
136  int pos = 0;
137  _alloc->C_.resize(M_,N_);
138  for (int j = 0; j < N_; j++) {
139  for (int i = 0; i < M_; i++) {
140  _variRefB[pos] = B(i,j).vi_;
141  _alloc->C_(i,j) = B(i,j).val();
142  pos++;
143  }
144  }
145 
146  _alloc->_ldltP = A._ldltP;
147  _alloc->_ldltP->solveInPlace(_alloc->C_);
148 
149  pos = 0;
150  for (int j = 0; j < N_; j++) {
151  for (int i = 0; i < M_; i++) {
152  _variRefC[pos] = new vari(_alloc->C_(i,j),false);
153  pos++;
154  }
155  }
156  }
157 
158  virtual void chain() {
159  Eigen::Matrix<double,R2,C2> adjB(M_,N_);
160 
161  int pos = 0;
162  for (int j = 0; j < adjB.cols(); j++)
163  for (int i = 0; i < adjB.rows(); i++)
164  adjB(i,j) = _variRefC[pos++]->adj_;
165 
166  _alloc->_ldltP->solveInPlace(adjB);
167 
168  pos = 0;
169  for (int j = 0; j < adjB.cols(); j++)
170  for (int i = 0; i < adjB.rows(); i++)
171  _variRefB[pos++]->adj_ += adjB(i,j);
172  }
173  };
174 
185  template <int R1,int C1,int R2,int C2>
186  class mdivide_left_ldlt_vd_vari : public vari {
187  public:
188  int M_; // A.rows() = A.cols() = B.rows()
189  int N_; // B.cols()
190  vari** _variRefC;
191  mdivide_left_ldlt_alloc<R1,C1,R2,C2> *_alloc;
192  const LDLT_alloc<R1,C1> *_alloc_ldlt;
193 
194  mdivide_left_ldlt_vd_vari(const stan::math::LDLT_factor<var,R1,C1> &A,
195  const Eigen::Matrix<double,R2,C2> &B)
196  : vari(0.0),
197  M_(A.rows()),
198  N_(B.cols()),
199  _variRefC((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
200  * B.rows() * B.cols())),
201  _alloc(new mdivide_left_ldlt_alloc<R1,C1,R2,C2>()),
203  {
204  _alloc->C_ = B;
205  _alloc_ldlt->_ldlt.solveInPlace(_alloc->C_);
206 
207  int pos = 0;
208  for (int j = 0; j < N_; j++) {
209  for (int i = 0; i < M_; i++) {
210  _variRefC[pos] = new vari(_alloc->C_(i,j),false);
211  pos++;
212  }
213  }
214  }
215 
216  virtual void chain() {
217  Eigen::Matrix<double,R1,C1> adjA(M_,M_);
218  Eigen::Matrix<double,R1,C2> adjC(M_,N_);
219 
220  int pos = 0;
221  for (int j = 0; j < adjC.cols(); j++)
222  for (int i = 0; i < adjC.rows(); i++)
223  adjC(i,j) = _variRefC[pos++]->adj_;
224 
225  adjA = -_alloc_ldlt->_ldlt.solve(adjC*_alloc->C_.transpose());
226 
227  for (int j = 0; j < adjA.cols(); j++)
228  for (int i = 0; i < adjA.rows(); i++)
229  _alloc_ldlt->_variA(i,j)->adj_ += adjA(i,j);
230  }
231  };
232  }
233 
241  template <int R1,int C1,int R2,int C2>
242  inline Eigen::Matrix<var,R1,C2>
244  const Eigen::Matrix<var,R2,C2> &b) {
245  Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
246 
247  stan::math::check_multiplicable("mdivide_left_ldlt(%1%)",A,"A",
248  b,"b",(double*)0);
249 
250  mdivide_left_ldlt_vv_vari<R1,C1,R2,C2> *baseVari = new mdivide_left_ldlt_vv_vari<R1,C1,R2,C2>(A,b);
251 
252  int pos = 0;
253  for (int j = 0; j < res.cols(); j++)
254  for (int i = 0; i < res.rows(); i++)
255  res(i,j).vi_ = baseVari->_variRefC[pos++];
256 
257  return res;
258  }
259 
267  template <int R1,int C1,int R2,int C2>
268  inline Eigen::Matrix<var,R1,C2>
270  const Eigen::Matrix<double,R2,C2> &b) {
271  Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
272 
273  stan::math::check_multiplicable("mdivide_left_ldlt(%1%)",A,"A",
274  b,"b",(double*)0);
275 
276  mdivide_left_ldlt_vd_vari<R1,C1,R2,C2> *baseVari = new mdivide_left_ldlt_vd_vari<R1,C1,R2,C2>(A,b);
277 
278  int pos = 0;
279  for (int j = 0; j < res.cols(); j++)
280  for (int i = 0; i < res.rows(); i++)
281  res(i,j).vi_ = baseVari->_variRefC[pos++];
282 
283  return res;
284  }
285 
293  template <int R1,int C1,int R2,int C2>
294  inline Eigen::Matrix<var,R1,C2>
296  const Eigen::Matrix<var,R2,C2> &b) {
297  Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
298 
299  stan::math::check_multiplicable("mdivide_left_ldlt(%1%)",A,"A",
300  b,"b",(double*)0);
301 
302  mdivide_left_ldlt_dv_vari<R1,C1,R2,C2> *baseVari = new mdivide_left_ldlt_dv_vari<R1,C1,R2,C2>(A,b);
303 
304  int pos = 0;
305  for (int j = 0; j < res.cols(); j++)
306  for (int i = 0; i < res.rows(); i++)
307  res(i,j).vi_ = baseVari->_variRefC[pos++];
308 
309  return res;
310  }
311 
312  }
313 }
314 #endif
Eigen::Matrix< double, R2, C2 > C_
memory::stack_alloc memalloc_
Definition: var_stack.cpp:16
int N_
const LDLT_alloc< R1, C1 > * _alloc_ldlt
mdivide_left_ldlt_alloc< R1, C1, R2, C2 > * _alloc
bool check_multiplicable(const char *function, const T1 &y1, const char *name1, const T2 &y2, const char *name2, T_result *result)
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.
vari ** _variRefC
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
int M_
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>.
vari ** _variRefB

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