Stan  2.5.0
probability, sampling & optimization
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mdivide_left_tri.hpp
Go to the documentation of this file.
1 #ifndef STAN__AGRAD__REV__MATRIX__MDIVIDE_LEFT_TRI_HPP
2 #define STAN__AGRAD__REV__MATRIX__MDIVIDE_LEFT_TRI_HPP
3 
4 #include <vector>
9 #include <stan/agrad/rev/var.hpp>
11 
12 namespace stan {
13  namespace agrad {
14 
15  namespace {
16  template <int TriView,int R1,int C1,int R2,int C2>
17  class mdivide_left_tri_vv_vari : public vari {
18  public:
19  int M_; // A.rows() = A.cols() = B.rows()
20  int N_; // B.cols()
21  double* A_;
22  double* C_;
23  vari** _variRefA;
24  vari** _variRefB;
25  vari** _variRefC;
26 
27  mdivide_left_tri_vv_vari(const Eigen::Matrix<var,R1,C1> &A,
28  const Eigen::Matrix<var,R2,C2> &B)
29  : vari(0.0),
30  M_(A.rows()),
31  N_(B.cols()),
32  A_((double*)stan::agrad::memalloc_.alloc(sizeof(double)
33  * A.rows() * A.cols())),
34  C_((double*)stan::agrad::memalloc_.alloc(sizeof(double)
35  * B.rows() * B.cols())),
36  _variRefA((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
37  * A.rows()
38  * (A.rows() + 1) / 2)),
39  _variRefB((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
40  * B.rows() * B.cols())),
41  _variRefC((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
42  * B.rows() * B.cols()))
43  {
44  using Eigen::Matrix;
45  using Eigen::Map;
46 
47  size_t pos = 0;
48  if (TriView == Eigen::Lower) {
49  for (size_type j = 0; j < M_; j++)
50  for (size_type i = j; i < M_; i++)
51  _variRefA[pos++] = A(i,j).vi_;
52  } else if (TriView == Eigen::Upper) {
53  for (size_type j = 0; j < M_; j++)
54  for (size_type i = 0; i < j+1; i++)
55  _variRefA[pos++] = A(i,j).vi_;
56  }
57 
58  pos = 0;
59  for (size_type j = 0; j < M_; j++) {
60  for (size_type i = 0; i < M_; i++) {
61  A_[pos++] = A(i,j).val();
62  }
63  }
64 
65  pos = 0;
66  for (size_type j = 0; j < N_; j++) {
67  for (size_type i = 0; i < M_; i++) {
68  _variRefB[pos] = B(i,j).vi_;
69  C_[pos++] = B(i,j).val();
70  }
71  }
72 
73  Matrix<double,R1,C2> C(M_,N_);
74  C = Map<Matrix<double,R1,C2> >(C_,M_,N_);
75 
76  C = Map<Matrix<double,R1,C1> >(A_,M_,M_)
77  .template triangularView<TriView>().solve(C);
78 
79  pos = 0;
80  for (size_type j = 0; j < N_; j++) {
81  for (size_type i = 0; i < M_; i++) {
82  C_[pos] = C(i,j);
83  _variRefC[pos] = new vari(C_[pos],false);
84  pos++;
85  }
86  }
87 
88  }
89 
90  virtual void chain() {
91  using Eigen::Matrix;
92  using Eigen::Map;
93  Matrix<double,R1,C1> adjA(M_,M_);
94  Matrix<double,R2,C2> adjB(M_,N_);
95  Matrix<double,R1,C2> adjC(M_,N_);
96 
97  size_t pos = 0;
98  for (size_type j = 0; j < adjC.cols(); j++)
99  for (size_type i = 0; i < adjC.rows(); i++)
100  adjC(i,j) = _variRefC[pos++]->adj_;
101 
102  adjB = Map<Matrix<double,R1,C1> >(A_,M_,M_)
103  .template triangularView<TriView>().transpose().solve(adjC);
104  adjA.noalias() = -adjB
105  * Map<Matrix<double,R1,C2> >(C_,M_,N_).transpose();
106 
107  pos = 0;
108  if (TriView == Eigen::Lower) {
109  for (size_type j = 0; j < adjA.cols(); j++)
110  for (size_type i = j; i < adjA.rows(); i++)
111  _variRefA[pos++]->adj_ += adjA(i,j);
112  } else if (TriView == Eigen::Upper) {
113  for (size_type j = 0; j < adjA.cols(); j++)
114  for (size_type i = 0; i < j+1; i++)
115  _variRefA[pos++]->adj_ += adjA(i,j);
116  }
117 
118  pos = 0;
119  for (size_type j = 0; j < adjB.cols(); j++)
120  for (size_type i = 0; i < adjB.rows(); i++)
121  _variRefB[pos++]->adj_ += adjB(i,j);
122  }
123  };
124 
125  template <int TriView,int R1,int C1,int R2,int C2>
126  class mdivide_left_tri_dv_vari : public vari {
127  public:
128  int M_; // A.rows() = A.cols() = B.rows()
129  int N_; // B.cols()
130  double* A_;
131  double* C_;
132  vari** _variRefB;
133  vari** _variRefC;
134 
135  mdivide_left_tri_dv_vari(const Eigen::Matrix<double,R1,C1> &A,
136  const Eigen::Matrix<var,R2,C2> &B)
137  : vari(0.0),
138  M_(A.rows()),
139  N_(B.cols()),
140  A_((double*)stan::agrad::memalloc_.alloc(sizeof(double)
141  * A.rows() * A.cols())),
142  C_((double*)stan::agrad::memalloc_.alloc(sizeof(double)
143  * B.rows() * B.cols())),
144  _variRefB((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
145  * B.rows() * B.cols())),
146  _variRefC((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
147  * B.rows() * B.cols()))
148  {
149  using Eigen::Matrix;
150  using Eigen::Map;
151 
152  size_t pos = 0;
153  for (size_type j = 0; j < M_; j++) {
154  for (size_type i = 0; i < M_; i++) {
155  A_[pos++] = A(i,j);
156  }
157  }
158 
159  pos = 0;
160  for (size_type j = 0; j < N_; j++) {
161  for (size_type i = 0; i < M_; i++) {
162  _variRefB[pos] = B(i,j).vi_;
163  C_[pos++] = B(i,j).val();
164  }
165  }
166 
167  Matrix<double,R1,C2> C(M_,N_);
168  C = Map<Matrix<double,R1,C2> >(C_,M_,N_);
169 
170  C = Map<Matrix<double,R1,C1> >(A_,M_,M_)
171  .template triangularView<TriView>().solve(C);
172 
173  pos = 0;
174  for (size_type j = 0; j < N_; j++) {
175  for (size_type i = 0; i < M_; i++) {
176  C_[pos] = C(i,j);
177  _variRefC[pos] = new vari(C_[pos],false);
178  pos++;
179  }
180  }
181  }
182 
183  virtual void chain() {
184  using Eigen::Matrix;
185  using Eigen::Map;
186  Matrix<double,R2,C2> adjB(M_,N_);
187  Matrix<double,R1,C2> adjC(M_,N_);
188 
189  size_t pos = 0;
190  for (size_type j = 0; j < adjC.cols(); j++)
191  for (size_type i = 0; i < adjC.rows(); i++)
192  adjC(i,j) = _variRefC[pos++]->adj_;
193 
194  adjB = Map<Matrix<double,R1,C1> >(A_,M_,M_)
195  .template triangularView<TriView>().transpose().solve(adjC);
196 
197  pos = 0;
198  for (size_type j = 0; j < adjB.cols(); j++)
199  for (size_type i = 0; i < adjB.rows(); i++)
200  _variRefB[pos++]->adj_ += adjB(i,j);
201  }
202  };
203 
204  template <int TriView,int R1,int C1,int R2,int C2>
205  class mdivide_left_tri_vd_vari : public vari {
206  public:
207  int M_; // A.rows() = A.cols() = B.rows()
208  int N_; // B.cols()
209  double* A_;
210  double* C_;
211  vari** _variRefA;
212  vari** _variRefC;
213 
214  mdivide_left_tri_vd_vari(const Eigen::Matrix<var,R1,C1> &A,
215  const Eigen::Matrix<double,R2,C2> &B)
216  : vari(0.0),
217  M_(A.rows()),
218  N_(B.cols()),
219  A_((double*)stan::agrad::memalloc_.alloc(sizeof(double)
220  * A.rows() * A.cols())),
221  C_((double*)stan::agrad::memalloc_.alloc(sizeof(double)
222  * B.rows() * B.cols())),
223  _variRefA((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
224  * A.rows()
225  * (A.rows() + 1) / 2)),
226  _variRefC((vari**)stan::agrad::memalloc_.alloc(sizeof(vari*)
227  * B.rows() * B.cols()))
228  {
229  using Eigen::Matrix;
230  using Eigen::Map;
231 
232  size_t pos = 0;
233  if (TriView == Eigen::Lower) {
234  for (size_type j = 0; j < M_; j++)
235  for (size_type i = j; i < M_; i++)
236  _variRefA[pos++] = A(i,j).vi_;
237  } else if (TriView == Eigen::Upper) {
238  for (size_type j = 0; j < M_; j++)
239  for (size_type i = 0; i < j+1; i++)
240  _variRefA[pos++] = A(i,j).vi_;
241  }
242 
243  pos = 0;
244  for (size_type j = 0; j < M_; j++) {
245  for (size_type i = 0; i < M_; i++) {
246  A_[pos++] = A(i,j).val();
247  }
248  }
249 
250  Matrix<double,R1,C2> C(M_,N_);
251  C = Map<Matrix<double,R1,C1> >(A_,M_,M_)
252  .template triangularView<TriView>().solve(B);
253 
254  pos = 0;
255  for (size_type j = 0; j < N_; j++) {
256  for (size_type i = 0; i < M_; i++) {
257  C_[pos] = C(i,j);
258  _variRefC[pos] = new vari(C_[pos],false);
259  pos++;
260  }
261  }
262  }
263 
264  virtual void chain() {
265  using Eigen::Matrix;
266  using Eigen::Map;
267  Matrix<double,R1,C1> adjA(M_,M_);
268  Matrix<double,R1,C2> adjC(M_,N_);
269 
270  size_t pos = 0;
271  for (size_type j = 0; j < adjC.cols(); j++)
272  for (size_type i = 0; i < adjC.rows(); i++)
273  adjC(i,j) = _variRefC[pos++]->adj_;
274 
275  adjA.noalias() = -Map<Matrix<double,R1,C1> >(A_,M_,M_)
276  .template triangularView<TriView>()
277  .transpose().solve(adjC*Map<Matrix<double,R1,C2> >(C_,M_,N_).transpose());
278 
279  pos = 0;
280  if (TriView == Eigen::Lower) {
281  for (size_type j = 0; j < adjA.cols(); j++)
282  for (size_type i = j; i < adjA.rows(); i++)
283  _variRefA[pos++]->adj_ += adjA(i,j);
284  } else if (TriView == Eigen::Upper) {
285  for (size_type j = 0; j < adjA.cols(); j++)
286  for (size_type i = 0; i < j+1; i++)
287  _variRefA[pos++]->adj_ += adjA(i,j);
288  }
289  }
290  };
291  }
292 
293  template <int TriView,int R1,int C1,int R2,int C2>
294  inline
295  Eigen::Matrix<var,R1,C2>
296  mdivide_left_tri(const Eigen::Matrix<var,R1,C1> &A,
297  const Eigen::Matrix<var,R2,C2> &b) {
298  Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
299 
300  stan::math::check_square("mdivide_left_tri(%1%)",A,"A",(double*)0);
301  stan::math::check_multiplicable("mdivide_left_tri(%1%)",A,"A",
302  b,"b",(double*)0);
303 
304  // NOTE: this is not a memory leak, this vari is used in the
305  // expression graph to evaluate the adjoint, but is not needed
306  // for the returned matrix. Memory will be cleaned up with the arena allocator.
307  mdivide_left_tri_vv_vari<TriView,R1,C1,R2,C2> *baseVari = new mdivide_left_tri_vv_vari<TriView,R1,C1,R2,C2>(A,b);
308 
309  size_t pos = 0;
310  for (size_type j = 0; j < res.cols(); j++)
311  for (size_type i = 0; i < res.rows(); i++)
312  res(i,j).vi_ = baseVari->_variRefC[pos++];
313 
314  return res;
315  }
316  template <int TriView,int R1,int C1,int R2,int C2>
317  inline
318  Eigen::Matrix<var,R1,C2>
319  mdivide_left_tri(const Eigen::Matrix<double,R1,C1> &A,
320  const Eigen::Matrix<var,R2,C2> &b) {
321  Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
322 
323  stan::math::check_square("mdivide_left_tri(%1%)",A,"A",(double*)0);
324  stan::math::check_multiplicable("mdivide_left_tri(%1%)",A,"A",
325  b,"b",(double*)0);
326 
327  // NOTE: this is not a memory leak, this vari is used in the
328  // expression graph to evaluate the adjoint, but is not needed
329  // for the returned matrix. Memory will be cleaned up with the arena allocator.
330  mdivide_left_tri_dv_vari<TriView,R1,C1,R2,C2> *baseVari = new mdivide_left_tri_dv_vari<TriView,R1,C1,R2,C2>(A,b);
331 
332  size_t pos = 0;
333  for (size_type j = 0; j < res.cols(); j++)
334  for (size_type i = 0; i < res.rows(); i++)
335  res(i,j).vi_ = baseVari->_variRefC[pos++];
336 
337  return res;
338  }
339  template <int TriView,int R1,int C1,int R2,int C2>
340  inline
341  Eigen::Matrix<var,R1,C2>
342  mdivide_left_tri(const Eigen::Matrix<var,R1,C1> &A,
343  const Eigen::Matrix<double,R2,C2> &b) {
344  Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
345 
346  stan::math::check_square("mdivide_left_tri(%1%)",A,"A",(double*)0);
347  stan::math::check_multiplicable("mdivide_left_tri(%1%)",A,"A",
348  b,"b",(double*)0);
349 
350  // NOTE: this is not a memory leak, this vari is used in the
351  // expression graph to evaluate the adjoint, but is not needed
352  // for the returned matrix. Memory will be cleaned up with the arena allocator.
353  mdivide_left_tri_vd_vari<TriView,R1,C1,R2,C2> *baseVari = new mdivide_left_tri_vd_vari<TriView,R1,C1,R2,C2>(A,b);
354 
355  size_t pos = 0;
356  for (size_type j = 0; j < res.cols(); j++)
357  for (size_type i = 0; i < res.rows(); i++)
358  res(i,j).vi_ = baseVari->_variRefC[pos++];
359 
360  return res;
361  }
362 
363  }
364 }
365 #endif
Eigen::Matrix< var, R1, C2 > mdivide_left_tri(const Eigen::Matrix< var, R1, C1 > &A, const Eigen::Matrix< var, R2, C2 > &b)
memory::stack_alloc memalloc_
Definition: var_stack.cpp:16
int N_
bool check_multiplicable(const char *function, const T1 &y1, const char *name1, const T2 &y2, const char *name2, T_result *result)
vari ** _variRefC
Eigen::Matrix< T, C, R > transpose(const Eigen::Matrix< T, R, C > &m)
Definition: transpose.hpp:12
int M_
vari ** _variRefA
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
double * C_
vari ** _variRefB
double * A_
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.