1 #ifndef STAN__AGRAD__REV__MATRIX__COLUMNS_MDIVIDE_LEFT_HPP
2 #define STAN__AGRAD__REV__MATRIX__COLUMNS_MDIVIDE_LEFT_HPP
16 template <
int R1,
int C1,
int R2,
int C2>
17 class mdivide_left_vv_vari :
public vari {
27 mdivide_left_vv_vari(
const Eigen::Matrix<var,R1,C1> &A,
28 const Eigen::Matrix<var,R2,C2> &B)
32 A_((double*)stan::agrad::
memalloc_.alloc(sizeof(double)
34 C_((double*)stan::agrad::
memalloc_.alloc(sizeof(double)
50 A_[pos++] = A(i,j).val();
58 C_[pos++] = B(i,j).val();
62 Matrix<double,R1,C2> C(M_,N_);
63 C = Map<Matrix<double,R1,C2> >(
C_,
M_,
N_);
65 C = Map<Matrix<double,R1,C1> >(
A_,
M_,
M_)
66 .colPivHouseholderQr().solve(C);
78 virtual void chain() {
81 Eigen::Matrix<double,R1,C1> adjA(
M_,
M_);
82 Eigen::Matrix<double,R2,C2> adjB(
M_,
N_);
83 Eigen::Matrix<double,R1,C2> adjC(
M_,
N_);
86 for (
size_type j = 0; j < adjC.cols(); j++)
87 for (
size_type i = 0; i < adjC.rows(); i++)
91 adjB = Map<Matrix<double,R1,C1> >(
A_,
M_,
M_)
92 .
transpose().colPivHouseholderQr().solve(adjC);
93 adjA.noalias() = -adjB
97 for (
size_type j = 0; j < adjA.cols(); j++)
98 for (
size_type i = 0; i < adjA.rows(); i++)
102 for (
size_type j = 0; j < adjB.cols(); j++)
103 for (
size_type i = 0; i < adjB.rows(); i++)
108 template <
int R1,
int C1,
int R2,
int C2>
109 class mdivide_left_dv_vari :
public vari {
118 mdivide_left_dv_vari(
const Eigen::Matrix<double,R1,C1> &A,
119 const Eigen::Matrix<var,R2,C2> &B)
123 A_((double*)stan::agrad::
memalloc_.alloc(sizeof(double)
125 C_((double*)stan::agrad::
memalloc_.alloc(sizeof(double)
146 C_[pos++] = B(i,j).val();
150 Matrix<double,R1,C2> C(M_,N_);
151 C = Map<Matrix<double,R1,C2> >(
C_,
M_,
N_);
153 C = Map<Matrix<double,R1,C1> >(
A_,
M_,
M_)
154 .colPivHouseholderQr().solve(C);
160 _variRefC[pos] =
new vari(C_[pos],
false);
166 virtual void chain() {
169 Eigen::Matrix<double,R2,C2> adjB(M_,N_);
170 Eigen::Matrix<double,R1,C2> adjC(M_,N_);
173 for (
size_type j = 0; j < adjC.cols(); j++)
174 for (
size_type i = 0; i < adjC.rows(); i++)
177 adjB = Map<Matrix<double,R1,C1> >(
A_,
M_,
M_)
178 .
transpose().colPivHouseholderQr().solve(adjC);
181 for (
size_type j = 0; j < adjB.cols(); j++)
182 for (
size_type i = 0; i < adjB.rows(); i++)
187 template <
int R1,
int C1,
int R2,
int C2>
188 class mdivide_left_vd_vari :
public vari {
197 mdivide_left_vd_vari(
const Eigen::Matrix<var,R1,C1> &A,
198 const Eigen::Matrix<double,R2,C2> &B)
202 A_((double*)stan::agrad::
memalloc_.alloc(sizeof(double)
204 C_((double*)stan::agrad::
memalloc_.alloc(sizeof(double)
218 A_[pos++] = A(i,j).val();
222 Matrix<double,R1,C2> C(M_,N_);
223 C = Map<Matrix<double,R1,C1> >(
A_,
M_,
M_)
224 .colPivHouseholderQr().solve(B);
230 _variRefC[pos] =
new vari(C_[pos],
false);
236 virtual void chain() {
239 Eigen::Matrix<double,R1,C1> adjA(M_,M_);
240 Eigen::Matrix<double,R1,C2> adjC(M_,N_);
243 for (
size_type j = 0; j < adjC.cols(); j++)
244 for (
size_type i = 0; i < adjC.rows(); i++)
248 adjA = -Map<Matrix<double,R1,C1> >(
A_,
M_,
M_)
250 .colPivHouseholderQr()
251 .solve(adjC*Map<Matrix<double,R1,C2> >(C_,M_,N_).
transpose());
254 for (
size_type j = 0; j < adjA.cols(); j++)
255 for (
size_type i = 0; i < adjA.rows(); i++)
261 template <
int R1,
int C1,
int R2,
int C2>
263 Eigen::Matrix<var,R1,C2>
265 const Eigen::Matrix<var,R2,C2> &b) {
266 Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
275 mdivide_left_vv_vari<R1,C1,R2,C2> *baseVari =
new mdivide_left_vv_vari<R1,C1,R2,C2>(A,b);
278 for (
size_type j = 0; j < res.cols(); j++)
279 for (
size_type i = 0; i < res.rows(); i++)
280 res(i,j).vi_ = baseVari->_variRefC[pos++];
285 template <
int R1,
int C1,
int R2,
int C2>
287 Eigen::Matrix<var,R1,C2>
289 const Eigen::Matrix<double,R2,C2> &b) {
290 Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
299 mdivide_left_vd_vari<R1,C1,R2,C2> *baseVari =
new mdivide_left_vd_vari<R1,C1,R2,C2>(A,b);
302 for (
size_type j = 0; j < res.cols(); j++)
303 for (
size_type i = 0; i < res.rows(); i++)
304 res(i,j).vi_ = baseVari->_variRefC[pos++];
309 template <
int R1,
int C1,
int R2,
int C2>
311 Eigen::Matrix<var,R1,C2>
313 const Eigen::Matrix<var,R2,C2> &b) {
314 Eigen::Matrix<var,R1,C2> res(b.rows(),b.cols());
323 mdivide_left_dv_vari<R1,C1,R2,C2> *baseVari =
new mdivide_left_dv_vari<R1,C1,R2,C2>(A,b);
326 for (
size_type j = 0; j < res.cols(); j++)
327 for (
size_type i = 0; i < res.rows(); i++)
328 res(i,j).vi_ = baseVari->_variRefC[pos++];
Eigen::Matrix< fvar< T >, R1, C2 > mdivide_left(const Eigen::Matrix< fvar< T >, R1, C1 > &A, const Eigen::Matrix< fvar< T >, R2, C2 > &b)
memory::stack_alloc memalloc_
bool check_multiplicable(const char *function, const T1 &y1, const char *name1, const T2 &y2, const char *name2, T_result *result)
Eigen::Matrix< T, C, R > transpose(const Eigen::Matrix< T, R, C > &m)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
size_t rows(const Eigen::Matrix< T, R, C > &m)
size_t cols(const Eigen::Matrix< T, R, C > &m)
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.