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()))),
40 .alloc(sizeof(vari*) * A.
rows() * (A.
rows() + 1) / 2))),
43 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))),
46 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))) {
51 if (TriView == Eigen::Lower) {
55 }
else if (TriView == Eigen::Upper) {
64 A_[pos++] = A(i, j).val();
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++)
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++)
114 }
else if (TriView == Eigen::Upper) {
115 for (
size_type j = 0; j < adjA.cols(); j++)
121 for (
size_type j = 0; j < adjB.cols(); j++)
122 for (
size_type i = 0; i < adjB.rows(); i++)
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()))),
150 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))),
153 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))) {
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++)
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++)
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()))),
232 .alloc(sizeof(vari*) * A.
rows() * (A.
rows() + 1) / 2))),
235 .alloc(sizeof(vari*) * B.
rows() * B.
cols()))) {
240 if (TriView == Eigen::Lower) {
244 }
else if (TriView == Eigen::Upper) {
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++)
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++)
292 }
else if (TriView == Eigen::Upper) {
293 for (
size_type j = 0; j < adjA.cols(); 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++];
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.
size_t rows(const Eigen::Matrix< T, R, C > &m)
AutodiffStackStorage< chainable, chainable_alloc > ChainableStack
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.
size_t cols(const Eigen::Matrix< T, R, C > &m)
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.