Stan Math Library: stan/math/rev/mat/fun/mdivide_left_ldlt.hpp Source File

| Stan Math Library 2.10.0 reverse mode automatic differentiation

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

mdivide_left_ldlt.hpp
Go to the documentation of this file.
1 #ifndef STAN_MATH_REV_MAT_FUN_MDIVIDE_LEFT_LDLT_HPP
2 #define STAN_MATH_REV_MAT_FUN_MDIVIDE_LEFT_LDLT_HPP
3
4 #include <stan/math/rev/core.hpp>
5 #include <stan/math/prim/mat/fun/Eigen.hpp>
6 #include <stan/math/rev/mat/fun/LDLT_alloc.hpp>
7 #include <stan/math/rev/mat/fun/LDLT_factor.hpp>
8 #include <stan/math/prim/mat/err/check_multiplicable.hpp>
9
10 namespace stan {
11 namespace math {
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(reinterpret_cast<vari**>
53 (stan::math::ChainableStack::memalloc_
54 .alloc(sizeof(vari*) * B.rows() * B.cols()))),
55 _variRefC(reinterpret_cast<vari**>
56 (stan::math::ChainableStack::memalloc_
57 .alloc(sizeof(vari*) * B.rows() * B.cols()))),
58 _alloc(new mdivide_left_ldlt_alloc<R1, C1, R2, C2>()),
59 _alloc_ldlt(A._alloc) {
60 int pos = 0;
61 _alloc->C_.resize(M_, N_);
62 for (int j = 0; j < N_; j++) {
63 for (int i = 0; i < M_; i++) {
64 _variRefB[pos] = B(i, j).vi_;
65 _alloc->C_(i, j) = B(i, j).val();
66 pos++;
67 }
68 }
69
70 _alloc_ldlt->_ldlt.solveInPlace(_alloc->C_);
71
72 pos = 0;
73 for (int j = 0; j < N_; j++) {
74 for (int i = 0; i < M_; i++) {
75 _variRefC[pos] = new vari(_alloc->C_(i, j), false);
76 pos++;
77 }
78 }
79 }
80
81 virtual void chain() {
82 Eigen::Matrix<double, R1, C1> adjA(M_, M_);
83 Eigen::Matrix<double, R2, C2> adjB(M_, N_);
84
85 int pos = 0;
86 for (int j = 0; j < N_; j++)
87 for (int i = 0; i < M_; i++)
88 adjB(i, j) = _variRefC[pos++]->adj_;
89
90 _alloc_ldlt->_ldlt.solveInPlace(adjB);
91 adjA.noalias() = -adjB * _alloc->C_.transpose();
92
93 for (int j = 0; j < M_; j++)
94 for (int i = 0; i < M_; i++)
95 _alloc_ldlt->_variA(i, j)->adj_ += adjA(i, j);
96
97 pos = 0;
98 for (int j = 0; j < N_; j++)
99 for (int i = 0; i < M_; i++)
100 _variRefB[pos++]->adj_ += adjB(i, j);
101 }
102 };
103
114 template <int R1, int C1, int R2, int C2>
115 class mdivide_left_ldlt_dv_vari : public vari {
116 public:
117 int M_; // A.rows() = A.cols() = B.rows()
118 int N_; // B.cols()
119 vari** _variRefB;
120 vari** _variRefC;
121 mdivide_left_ldlt_alloc<R1, C1, R2, C2> *_alloc;
122
123 mdivide_left_ldlt_dv_vari(const stan::math::LDLT_factor<double, R1, C1>
124 &A,
125 const Eigen::Matrix<var, R2, C2> &B)
126 : vari(0.0),
127 M_(A.rows()),
128 N_(B.cols()),
129 _variRefB(reinterpret_cast<vari**>
130 (stan::math::ChainableStack::memalloc_
131 .alloc(sizeof(vari*) * B.rows() * B.cols()))),
132 _variRefC(reinterpret_cast<vari**>
133 (stan::math::ChainableStack::memalloc_
134 .alloc(sizeof(vari*) * B.rows() * B.cols()))),
135 _alloc(new mdivide_left_ldlt_alloc<R1, C1, R2, C2>()) {
136 using Eigen::Matrix;
137 using Eigen::Map;
138
139 int pos = 0;
140 _alloc->C_.resize(M_, N_);
141 for (int j = 0; j < N_; j++) {
142 for (int i = 0; i < M_; i++) {
143 _variRefB[pos] = B(i, j).vi_;
144 _alloc->C_(i, j) = B(i, j).val();
145 pos++;
146 }
147 }
148
149 _alloc->_ldltP = A._ldltP;
150 _alloc->_ldltP->solveInPlace(_alloc->C_);
151
152 pos = 0;
153 for (int j = 0; j < N_; j++) {
154 for (int i = 0; i < M_; i++) {
155 _variRefC[pos] = new vari(_alloc->C_(i, j), false);
156 pos++;
157 }
158 }
159 }
160
161 virtual void chain() {
162 Eigen::Matrix<double, R2, C2> adjB(M_, N_);
163
164 int pos = 0;
165 for (int j = 0; j < adjB.cols(); j++)
166 for (int i = 0; i < adjB.rows(); i++)
167 adjB(i, j) = _variRefC[pos++]->adj_;
168
169 _alloc->_ldltP->solveInPlace(adjB);
170
171 pos = 0;
172 for (int j = 0; j < adjB.cols(); j++)
173 for (int i = 0; i < adjB.rows(); i++)
174 _variRefB[pos++]->adj_ += adjB(i, j);
175 }
176 };
177
188 template <int R1, int C1, int R2, int C2>
189 class mdivide_left_ldlt_vd_vari : public vari {
190 public:
191 int M_; // A.rows() = A.cols() = B.rows()
192 int N_; // B.cols()
193 vari** _variRefC;
194 mdivide_left_ldlt_alloc<R1, C1, R2, C2> *_alloc;
195 const LDLT_alloc<R1, C1> *_alloc_ldlt;
196
197 mdivide_left_ldlt_vd_vari(const stan::math::LDLT_factor<var, R1, C1> &A,
198 const Eigen::Matrix<double, R2, C2> &B)
199 : vari(0.0),
200 M_(A.rows()),
201 N_(B.cols()),
202 _variRefC(reinterpret_cast<vari**>
203 (stan::math::ChainableStack::memalloc_
204 .alloc(sizeof(vari*) * B.rows() * B.cols()))),
205 _alloc(new mdivide_left_ldlt_alloc<R1, C1, R2, C2>()),
206 _alloc_ldlt(A._alloc) {
207 _alloc->C_ = B;
208 _alloc_ldlt->_ldlt.solveInPlace(_alloc->C_);
209
210 int pos = 0;
211 for (int j = 0; j < N_; j++) {
212 for (int i = 0; i < M_; i++) {
213 _variRefC[pos] = new vari(_alloc->C_(i, j), false);
214 pos++;
215 }
216 }
217 }
218
219 virtual void chain() {
220 Eigen::Matrix<double, R1, C1> adjA(M_, M_);
221 Eigen::Matrix<double, R1, C2> adjC(M_, N_);
222
223 int pos = 0;
224 for (int j = 0; j < adjC.cols(); j++)
225 for (int i = 0; i < adjC.rows(); i++)
226 adjC(i, j) = _variRefC[pos++]->adj_;
227
228 adjA = -_alloc_ldlt->_ldlt.solve(adjC*_alloc->C_.transpose());
229
230 for (int j = 0; j < adjA.cols(); j++)
231 for (int i = 0; i < adjA.rows(); i++)
232 _alloc_ldlt->_variA(i, j)->adj_ += adjA(i, j);
233 }
234 };
235 }
236
244 template <int R1, int C1, int R2, int C2>
245 inline Eigen::Matrix<var, R1, C2>
246 mdivide_left_ldlt(const stan::math::LDLT_factor<var, R1, C1> &A,
247 const Eigen::Matrix<var, R2, C2> &b) {
248 Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
249
250 stan::math::check_multiplicable("mdivide_left_ldlt",
251 "A", A,
252 "b", b);
253
254 mdivide_left_ldlt_vv_vari<R1, C1, R2, C2> *baseVari
255 = new mdivide_left_ldlt_vv_vari<R1, C1, R2, C2>(A, b);
256
257 int pos = 0;
258 for (int j = 0; j < res.cols(); j++)
259 for (int i = 0; i < res.rows(); i++)
260 res(i, j).vi_ = baseVari->_variRefC[pos++];
261
262 return res;
263 }
264
272 template <int R1, int C1, int R2, int C2>
273 inline Eigen::Matrix<var, R1, C2>
274 mdivide_left_ldlt(const stan::math::LDLT_factor<var, R1, C1> &A,
275 const Eigen::Matrix<double, R2, C2> &b) {
276 Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
277
278 stan::math::check_multiplicable("mdivide_left_ldlt",
279 "A", A,
280 "b", b);
281
282 mdivide_left_ldlt_vd_vari<R1, C1, R2, C2> *baseVari
283 = new mdivide_left_ldlt_vd_vari<R1, C1, R2, C2>(A, b);
284
285 int pos = 0;
286 for (int j = 0; j < res.cols(); j++)
287 for (int i = 0; i < res.rows(); i++)
288 res(i, j).vi_ = baseVari->_variRefC[pos++];
289
290 return res;
291 }
292
300 template <int R1, int C1, int R2, int C2>
301 inline Eigen::Matrix<var, R1, C2>
302 mdivide_left_ldlt(const stan::math::LDLT_factor<double, R1, C1> &A,
303 const Eigen::Matrix<var, R2, C2> &b) {
304 Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
305
306 stan::math::check_multiplicable("mdivide_left_ldlt",
307 "A", A,
308 "b", b);
309
310 mdivide_left_ldlt_dv_vari<R1, C1, R2, C2> *baseVari
311 = new mdivide_left_ldlt_dv_vari<R1, C1, R2, C2>(A, b);
312
313 int pos = 0;
314 for (int j = 0; j < res.cols(); j++)
315 for (int i = 0; i < res.rows(); i++)
316 res(i, j).vi_ = baseVari->_variRefC[pos++];
317
318 return res;
319 }
320
321 }
322 }
323 #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
stan
Definition: log_sum_exp.hpp:8
_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
_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.
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::math::ChainableStack
AutodiffStackStorage< vari, chainable_alloc > ChainableStack
Definition: chainablestack.hpp:10

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