1 #ifndef STAN_MATH_REV_MAT_FUN_MDIVIDE_LEFT_TRI_HPP
2 #define STAN_MATH_REV_MAT_FUN_MDIVIDE_LEFT_TRI_HPP
16 template <
int TriView,
int R1,
int C1,
int R2,
int C2>
17 class mdivide_left_tri_vv_vari :
public vari {
27 mdivide_left_tri_vv_vari(
const Eigen::Matrix<var, R1, C1> &A,
28 const Eigen::Matrix<var, R2, C2> &B)
32 A_(reinterpret_cast<double*>
34 .alloc(sizeof(double) * A.
rows() * A.
cols()))),
35 C_(reinterpret_cast<double*>
37 .alloc(sizeof(double) * B.
rows() * B.
cols()))),
38 variRefA_(reinterpret_cast<vari**>
40 .alloc(sizeof(vari*) * A.
rows() * (A.
rows() + 1) / 2))),
41 variRefB_(reinterpret_cast<vari**>
43 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))),
44 variRefC_(reinterpret_cast<vari**>
46 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))) {
51 if (TriView == Eigen::Lower) {
54 variRefA_[pos++] = A(i, j).vi_;
55 }
else if (TriView == Eigen::Upper) {
58 variRefA_[pos++] = A(i, j).vi_;
64 A_[pos++] = A(i, j).val();
71 variRefB_[pos] = B(i, j).vi_;
72 C_[pos++] = B(i, j).val();
76 Matrix<double, R1, C2> C(M_, N_);
77 C = Map<Matrix<double, R1, C2> >(
C_,
M_,
N_);
79 C = Map<Matrix<double, R1, C1> >(
A_,
M_,
M_)
80 .
template triangularView<TriView>().solve(C);
86 variRefC_[pos] =
new vari(C_[pos],
false);
92 virtual void chain() {
95 Matrix<double, R1, C1> adjA(M_, M_);
96 Matrix<double, R2, C2> adjB(M_, N_);
97 Matrix<double, R1, C2> adjC(M_, N_);
100 for (
size_type j = 0; j < adjC.cols(); j++)
101 for (
size_type i = 0; i < adjC.rows(); i++)
102 adjC(i, j) = variRefC_[pos++]->adj_;
104 adjB = Map<Matrix<double, R1, C1> >(
A_,
M_,
M_)
105 .
template triangularView<TriView>().transpose().solve(adjC);
106 adjA.noalias() = -adjB
110 if (TriView == Eigen::Lower) {
111 for (
size_type j = 0; j < adjA.cols(); j++)
112 for (
size_type i = j; i < adjA.rows(); i++)
113 variRefA_[pos++]->adj_ += adjA(i, j);
114 }
else if (TriView == Eigen::Upper) {
115 for (
size_type j = 0; j < adjA.cols(); j++)
117 variRefA_[pos++]->adj_ += adjA(i, j);
121 for (
size_type j = 0; j < adjB.cols(); j++)
122 for (
size_type i = 0; i < adjB.rows(); i++)
123 variRefB_[pos++]->adj_ += adjB(i, j);
127 template <
int TriView,
int R1,
int C1,
int R2,
int C2>
128 class mdivide_left_tri_dv_vari :
public vari {
137 mdivide_left_tri_dv_vari(
const Eigen::Matrix<double, R1, C1> &A,
138 const Eigen::Matrix<var, R2, C2> &B)
142 A_(reinterpret_cast<double*>
144 .alloc(sizeof(double) * A.
rows() * A.
cols()))),
145 C_(reinterpret_cast<double*>
147 .alloc(sizeof(double) * B.
rows() * B.
cols()))),
148 variRefB_(reinterpret_cast<vari**>
150 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))),
151 variRefC_(reinterpret_cast<vari**>
153 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))) {
167 variRefB_[pos] = B(i, j).vi_;
168 C_[pos++] = B(i, j).val();
172 Matrix<double, R1, C2> C(M_, N_);
173 C = Map<Matrix<double, R1, C2> >(
C_,
M_,
N_);
175 C = Map<Matrix<double, R1, C1> >(
A_,
M_,
M_)
176 .
template triangularView<TriView>().solve(C);
182 variRefC_[pos] =
new vari(C_[pos],
false);
188 virtual void chain() {
191 Matrix<double, R2, C2> adjB(M_, N_);
192 Matrix<double, R1, C2> adjC(M_, N_);
195 for (
size_type j = 0; j < adjC.cols(); j++)
196 for (
size_type i = 0; i < adjC.rows(); i++)
197 adjC(i, j) = variRefC_[pos++]->adj_;
199 adjB = Map<Matrix<double, R1, C1> >(
A_,
M_,
M_)
200 .
template triangularView<TriView>().transpose().solve(adjC);
203 for (
size_type j = 0; j < adjB.cols(); j++)
204 for (
size_type i = 0; i < adjB.rows(); i++)
205 variRefB_[pos++]->adj_ += adjB(i, j);
209 template <
int TriView,
int R1,
int C1,
int R2,
int C2>
210 class mdivide_left_tri_vd_vari :
public vari {
219 mdivide_left_tri_vd_vari(
const Eigen::Matrix<var, R1, C1> &A,
220 const Eigen::Matrix<double, R2, C2> &B)
224 A_(reinterpret_cast<double*>
226 .alloc(sizeof(double) * A.
rows() * A.
cols()))),
227 C_(reinterpret_cast<double*>
229 .alloc(sizeof(double) * B.
rows() * B.
cols()))),
230 variRefA_(reinterpret_cast<vari**>
232 .alloc(sizeof(vari*) * A.
rows() * (A.
rows() + 1) / 2))),
233 variRefC_(reinterpret_cast<vari**>
235 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))) {
240 if (TriView == Eigen::Lower) {
243 variRefA_[pos++] = A(i, j).vi_;
244 }
else if (TriView == Eigen::Upper) {
247 variRefA_[pos++] = A(i, j).vi_;
253 A_[pos++] = A(i, j).val();
257 Matrix<double, R1, C2> C(M_, N_);
258 C = Map<Matrix<double, R1, C1> >(
A_,
M_,
M_)
259 .
template triangularView<TriView>().solve(B);
265 variRefC_[pos] =
new vari(C_[pos],
false);
271 virtual void chain() {
274 Matrix<double, R1, C1> adjA(M_, M_);
275 Matrix<double, R1, C2> adjC(M_, N_);
278 for (
size_type j = 0; j < adjC.cols(); j++)
279 for (
size_type i = 0; i < adjC.rows(); i++)
280 adjC(i, j) = variRefC_[pos++]->adj_;
282 adjA.noalias() = -Map<Matrix<double, R1, C1> >(
A_,
M_,
M_)
283 .
template triangularView<TriView>()
284 .transpose().solve(adjC * Map<Matrix<double, R1, C2> >(C_, M_, N_)
288 if (TriView == Eigen::Lower) {
289 for (
size_type j = 0; j < adjA.cols(); j++)
290 for (
size_type i = j; i < adjA.rows(); i++)
291 variRefA_[pos++]->adj_ += adjA(i, j);
292 }
else if (TriView == Eigen::Upper) {
293 for (
size_type j = 0; j < adjA.cols(); j++)
295 variRefA_[pos++]->adj_ += adjA(i, j);
301 template <
int TriView,
int R1,
int C1,
int R2,
int C2>
303 Eigen::Matrix<var, R1, C2>
305 const Eigen::Matrix<var, R2, C2> &b) {
306 Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
317 mdivide_left_tri_vv_vari<TriView, R1, C1, R2, C2> *baseVari
318 =
new mdivide_left_tri_vv_vari<TriView, R1, C1, R2, C2>(A, b);
321 for (
size_type j = 0; j < res.cols(); j++)
322 for (
size_type i = 0; i < res.rows(); i++)
323 res(i, j).vi_ = baseVari->variRefC_[pos++];
327 template <
int TriView,
int R1,
int C1,
int R2,
int C2>
329 Eigen::Matrix<var, R1, C2>
331 const Eigen::Matrix<var, R2, C2> &b) {
332 Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
343 mdivide_left_tri_dv_vari<TriView, R1, C1, R2, C2> *baseVari
344 =
new mdivide_left_tri_dv_vari<TriView, R1, C1, R2, C2>(A, b);
347 for (
size_type j = 0; j < res.cols(); j++)
348 for (
size_type i = 0; i < res.rows(); i++)
349 res(i, j).vi_ = baseVari->variRefC_[pos++];
353 template <
int TriView,
int R1,
int C1,
int R2,
int C2>
355 Eigen::Matrix<var, R1, C2>
357 const Eigen::Matrix<double, R2, C2> &b) {
358 Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
369 mdivide_left_tri_vd_vari<TriView, R1, C1, R2, C2> *baseVari
370 =
new mdivide_left_tri_vd_vari<TriView, R1, C1, R2, C2>(A, b);
373 for (
size_type j = 0; j < res.cols(); j++)
374 for (
size_type i = 0; i < res.rows(); i++)
375 res(i, j).vi_ = baseVari->variRefC_[pos++];
int rows(const Eigen::Matrix< T, R, C > &m)
Return the number of rows in the specified matrix, vector, or row vector.
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
Type for sizes and indexes in an Eigen matrix with double e.
Eigen::Matrix< typename boost::math::tools::promote_args< T1, T2 >::type, R1, C2 > mdivide_left_tri(const Eigen::Matrix< T1, R1, C1 > &A, const Eigen::Matrix< T2, R2, C2 > &b)
Returns the solution of the system Ax=b when A is triangular.
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.
int cols(const Eigen::Matrix< T, R, C > &m)
Return the number of columns in the specified matrix, vector, or row vector.
Eigen::Matrix< T, C, R > transpose(const Eigen::Matrix< T, R, C > &m)
bool check_square(const char *function, const char *name, const Eigen::Matrix< T_y, Eigen::Dynamic, Eigen::Dynamic > &y)
Return true if the specified matrix is square.
AutodiffStackStorage< vari, chainable_alloc > ChainableStack