All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Groups
mdivide_left_tri.hpp
Go to the documentation of this file.
#ifndef STAN_MATH_REV_MAT_FUN_MDIVIDE_LEFT_TRI_HPP
#define STAN_MATH_REV_MAT_FUN_MDIVIDE_LEFT_TRI_HPP
#include <stan/math/prim/mat/fun/Eigen.hpp>
#include <stan/math/prim/mat/fun/typedefs.hpp>
#include <stan/math/prim/mat/err/check_multiplicable.hpp>
#include <stan/math/prim/mat/err/check_square.hpp>
#include <stan/math/rev/core.hpp>
#include <stan/math/rev/mat/fun/typedefs.hpp>
#include <vector>
namespace stan {
namespace math {
namespace {
template <int TriView, int R1, int C1, int R2, int C2>
class mdivide_left_tri_vv_vari : public vari {
public:
int M_; // A.rows() = A.cols() = B.rows()
int N_; // B.cols()
double* A_;
double* C_;
vari** _variRefA;
vari** _variRefB;
vari** _variRefC;
mdivide_left_tri_vv_vari(const Eigen::Matrix<var, R1, C1> &A,
const Eigen::Matrix<var, R2, C2> &B)
: vari(0.0),
M_(A.rows()),
N_(B.cols()),
A_(reinterpret_cast<double*>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(double) * A.rows() * A.cols()))),
C_(reinterpret_cast<double*>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(double) * B.rows() * B.cols()))),
_variRefA(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * A.rows() * (A.rows() + 1) / 2))),
_variRefB(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))),
_variRefC(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))) {
using Eigen::Matrix;
using Eigen::Map;
size_t pos = 0;
if (TriView == Eigen::Lower) {
for (size_type j = 0; j < M_; j++)
for (size_type i = j; i < M_; i++)
_variRefA[pos++] = A(i, j).vi_;
} else if (TriView == Eigen::Upper) {
for (size_type j = 0; j < M_; j++)
for (size_type i = 0; i < j+1; i++)
_variRefA[pos++] = A(i, j).vi_;
}
pos = 0;
for (size_type j = 0; j < M_; j++) {
for (size_type i = 0; i < M_; i++) {
A_[pos++] = A(i, j).val();
}
}
pos = 0;
for (size_type j = 0; j < N_; j++) {
for (size_type i = 0; i < M_; i++) {
_variRefB[pos] = B(i, j).vi_;
C_[pos++] = B(i, j).val();
}
}
Matrix<double, R1, C2> C(M_, N_);
C = Map<Matrix<double, R1, C2> >(C_, M_, N_);
C = Map<Matrix<double, R1, C1> >(A_, M_, M_)
.template triangularView<TriView>().solve(C);
pos = 0;
for (size_type j = 0; j < N_; j++) {
for (size_type i = 0; i < M_; i++) {
C_[pos] = C(i, j);
_variRefC[pos] = new vari(C_[pos], false);
pos++;
}
}
}
virtual void chain() {
using Eigen::Matrix;
using Eigen::Map;
Matrix<double, R1, C1> adjA(M_, M_);
Matrix<double, R2, C2> adjB(M_, N_);
Matrix<double, R1, C2> adjC(M_, N_);
size_t pos = 0;
for (size_type j = 0; j < adjC.cols(); j++)
for (size_type i = 0; i < adjC.rows(); i++)
adjC(i, j) = _variRefC[pos++]->adj_;
adjB = Map<Matrix<double, R1, C1> >(A_, M_, M_)
.template triangularView<TriView>().transpose().solve(adjC);
adjA.noalias() = -adjB
* Map<Matrix<double, R1, C2> >(C_, M_, N_).transpose();
pos = 0;
if (TriView == Eigen::Lower) {
for (size_type j = 0; j < adjA.cols(); j++)
for (size_type i = j; i < adjA.rows(); i++)
_variRefA[pos++]->adj_ += adjA(i, j);
} else if (TriView == Eigen::Upper) {
for (size_type j = 0; j < adjA.cols(); j++)
for (size_type i = 0; i < j+1; i++)
_variRefA[pos++]->adj_ += adjA(i, j);
}
pos = 0;
for (size_type j = 0; j < adjB.cols(); j++)
for (size_type i = 0; i < adjB.rows(); i++)
_variRefB[pos++]->adj_ += adjB(i, j);
}
};
template <int TriView, int R1, int C1, int R2, int C2>
class mdivide_left_tri_dv_vari : public vari {
public:
int M_; // A.rows() = A.cols() = B.rows()
int N_; // B.cols()
double* A_;
double* C_;
vari** _variRefB;
vari** _variRefC;
mdivide_left_tri_dv_vari(const Eigen::Matrix<double, R1, C1> &A,
const Eigen::Matrix<var, R2, C2> &B)
: vari(0.0),
M_(A.rows()),
N_(B.cols()),
A_(reinterpret_cast<double*>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(double) * A.rows() * A.cols()))),
C_(reinterpret_cast<double*>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(double) * B.rows() * B.cols()))),
_variRefB(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))),
_variRefC(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))) {
using Eigen::Matrix;
using Eigen::Map;
size_t pos = 0;
for (size_type j = 0; j < M_; j++) {
for (size_type i = 0; i < M_; i++) {
A_[pos++] = A(i, j);
}
}
pos = 0;
for (size_type j = 0; j < N_; j++) {
for (size_type i = 0; i < M_; i++) {
_variRefB[pos] = B(i, j).vi_;
C_[pos++] = B(i, j).val();
}
}
Matrix<double, R1, C2> C(M_, N_);
C = Map<Matrix<double, R1, C2> >(C_, M_, N_);
C = Map<Matrix<double, R1, C1> >(A_, M_, M_)
.template triangularView<TriView>().solve(C);
pos = 0;
for (size_type j = 0; j < N_; j++) {
for (size_type i = 0; i < M_; i++) {
C_[pos] = C(i, j);
_variRefC[pos] = new vari(C_[pos], false);
pos++;
}
}
}
virtual void chain() {
using Eigen::Matrix;
using Eigen::Map;
Matrix<double, R2, C2> adjB(M_, N_);
Matrix<double, R1, C2> adjC(M_, N_);
size_t pos = 0;
for (size_type j = 0; j < adjC.cols(); j++)
for (size_type i = 0; i < adjC.rows(); i++)
adjC(i, j) = _variRefC[pos++]->adj_;
adjB = Map<Matrix<double, R1, C1> >(A_, M_, M_)
.template triangularView<TriView>().transpose().solve(adjC);
pos = 0;
for (size_type j = 0; j < adjB.cols(); j++)
for (size_type i = 0; i < adjB.rows(); i++)
_variRefB[pos++]->adj_ += adjB(i, j);
}
};
template <int TriView, int R1, int C1, int R2, int C2>
class mdivide_left_tri_vd_vari : public vari {
public:
int M_; // A.rows() = A.cols() = B.rows()
int N_; // B.cols()
double* A_;
double* C_;
vari** _variRefA;
vari** _variRefC;
mdivide_left_tri_vd_vari(const Eigen::Matrix<var, R1, C1> &A,
const Eigen::Matrix<double, R2, C2> &B)
: vari(0.0),
M_(A.rows()),
N_(B.cols()),
A_(reinterpret_cast<double*>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(double) * A.rows() * A.cols()))),
C_(reinterpret_cast<double*>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(double) * B.rows() * B.cols()))),
_variRefA(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * A.rows() * (A.rows() + 1) / 2))),
_variRefC(reinterpret_cast<vari**>
(stan::math::ChainableStack::memalloc_
.alloc(sizeof(vari*) * B.rows() * B.cols()))) {
using Eigen::Matrix;
using Eigen::Map;
size_t pos = 0;
if (TriView == Eigen::Lower) {
for (size_type j = 0; j < M_; j++)
for (size_type i = j; i < M_; i++)
_variRefA[pos++] = A(i, j).vi_;
} else if (TriView == Eigen::Upper) {
for (size_type j = 0; j < M_; j++)
for (size_type i = 0; i < j+1; i++)
_variRefA[pos++] = A(i, j).vi_;
}
pos = 0;
for (size_type j = 0; j < M_; j++) {
for (size_type i = 0; i < M_; i++) {
A_[pos++] = A(i, j).val();
}
}
Matrix<double, R1, C2> C(M_, N_);
C = Map<Matrix<double, R1, C1> >(A_, M_, M_)
.template triangularView<TriView>().solve(B);
pos = 0;
for (size_type j = 0; j < N_; j++) {
for (size_type i = 0; i < M_; i++) {
C_[pos] = C(i, j);
_variRefC[pos] = new vari(C_[pos], false);
pos++;
}
}
}
virtual void chain() {
using Eigen::Matrix;
using Eigen::Map;
Matrix<double, R1, C1> adjA(M_, M_);
Matrix<double, R1, C2> adjC(M_, N_);
size_t pos = 0;
for (size_type j = 0; j < adjC.cols(); j++)
for (size_type i = 0; i < adjC.rows(); i++)
adjC(i, j) = _variRefC[pos++]->adj_;
adjA.noalias() = -Map<Matrix<double, R1, C1> >(A_, M_, M_)
.template triangularView<TriView>()
.transpose().solve(adjC * Map<Matrix<double, R1, C2> >(C_, M_, N_)
.transpose());
pos = 0;
if (TriView == Eigen::Lower) {
for (size_type j = 0; j < adjA.cols(); j++)
for (size_type i = j; i < adjA.rows(); i++)
_variRefA[pos++]->adj_ += adjA(i, j);
} else if (TriView == Eigen::Upper) {
for (size_type j = 0; j < adjA.cols(); j++)
for (size_type i = 0; i < j+1; i++)
_variRefA[pos++]->adj_ += adjA(i, j);
}
}
};
}
template <int TriView, int R1, int C1, int R2, int C2>
inline
Eigen::Matrix<var, R1, C2>
mdivide_left_tri(const Eigen::Matrix<var, R1, C1> &A,
const Eigen::Matrix<var, R2, C2> &b) {
Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
stan::math::check_square("mdivide_left_tri", "A", A);
stan::math::check_multiplicable("mdivide_left_tri",
"A", A,
"b", b);
// NOTE: this is not a memory leak, this vari is used in the
// expression graph to evaluate the adjoint, but is not needed
// for the returned matrix. Memory will be cleaned up with the
// arena allocator.
mdivide_left_tri_vv_vari<TriView, R1, C1, R2, C2> *baseVari
= new mdivide_left_tri_vv_vari<TriView, R1, C1, R2, C2>(A, b);
size_t pos = 0;
for (size_type j = 0; j < res.cols(); j++)
for (size_type i = 0; i < res.rows(); i++)
res(i, j).vi_ = baseVari->_variRefC[pos++];
return res;
}
template <int TriView, int R1, int C1, int R2, int C2>
inline
Eigen::Matrix<var, R1, C2>
mdivide_left_tri(const Eigen::Matrix<double, R1, C1> &A,
const Eigen::Matrix<var, R2, C2> &b) {
Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
stan::math::check_square("mdivide_left_tri", "A", A);
stan::math::check_multiplicable("mdivide_left_tri",
"A", A,
"b", b);
// NOTE: this is not a memory leak, this vari is used in the
// expression graph to evaluate the adjoint, but is not needed
// for the returned matrix. Memory will be cleaned up with the
// arena allocator.
mdivide_left_tri_dv_vari<TriView, R1, C1, R2, C2> *baseVari
= new mdivide_left_tri_dv_vari<TriView, R1, C1, R2, C2>(A, b);
size_t pos = 0;
for (size_type j = 0; j < res.cols(); j++)
for (size_type i = 0; i < res.rows(); i++)
res(i, j).vi_ = baseVari->_variRefC[pos++];
return res;
}
template <int TriView, int R1, int C1, int R2, int C2>
inline
Eigen::Matrix<var, R1, C2>
mdivide_left_tri(const Eigen::Matrix<var, R1, C1> &A,
const Eigen::Matrix<double, R2, C2> &b) {
Eigen::Matrix<var, R1, C2> res(b.rows(), b.cols());
stan::math::check_square("mdivide_left_tri", "A", A);
stan::math::check_multiplicable("mdivide_left_tri",
"A", A,
"b", b);
// NOTE: this is not a memory leak, this vari is used in the
// expression graph to evaluate the adjoint, but is not needed
// for the returned matrix. Memory will be cleaned up with the
// arena allocator.
mdivide_left_tri_vd_vari<TriView, R1, C1, R2, C2> *baseVari
= new mdivide_left_tri_vd_vari<TriView, R1, C1, R2, C2>(A, b);
size_t pos = 0;
for (size_type j = 0; j < res.cols(); j++)
for (size_type i = 0; i < res.rows(); i++)
res(i, j).vi_ = baseVari->_variRefC[pos++];
return res;
}
}
}
#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
check_multiplicable.hpp
N_
int N_
Definition: mdivide_left_tri.hpp:20
stan::math::size_type
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic >::Index size_type
Type for sizes and indexes in an Eigen matrix with double e.
Definition: typedefs.hpp:13
C_
double * C_
Definition: mdivide_left_tri.hpp:22
stan::math::mdivide_left_tri
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.
Definition: mdivide_left_tri.hpp:27
stan::math::ChainableStack
AutodiffStackStorage< chainable, chainable_alloc > ChainableStack
Definition: chainablestack.hpp:11
typedefs.hpp
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
_variRefC
vari ** _variRefC
Definition: mdivide_left_tri.hpp:25
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
A_
double * A_
Definition: mdivide_left_tri.hpp:21
_variRefA
vari ** _variRefA
Definition: mdivide_left_tri.hpp:23
stan::math::transpose
Eigen::Matrix< T, C, R > transpose(const Eigen::Matrix< T, R, C > &m)
Definition: transpose.hpp:12
stan::math::check_square
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.
Definition: check_square.hpp:28
M_
int M_
Definition: mdivide_left_tri.hpp:19
_variRefB
vari ** _variRefB
Definition: mdivide_left_tri.hpp:24
typedefs.hpp
check_square.hpp

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