simplifications in the ei_solve_impl system, factor out some boilerplate code

This commit is contained in:
Benoit Jacob
2009-11-08 16:51:41 -05:00
parent ba7bfe110c
commit e4e58e8337
16 changed files with 189 additions and 175 deletions

View File

@@ -324,54 +324,52 @@ ColPivHouseholderQR<MatrixType>& ColPivHouseholderQR<MatrixType>::compute(const
return *this;
}
template<typename MatrixType, typename Rhs, typename Dest>
struct ei_solve_impl<ColPivHouseholderQR<MatrixType>, Rhs, Dest>
: ei_solve_return_value<ColPivHouseholderQR<MatrixType>, Rhs>
template<typename _MatrixType, typename Rhs>
struct ei_solve_impl<ColPivHouseholderQR<_MatrixType>, Rhs>
: ei_solve_return_value<ColPivHouseholderQR<_MatrixType>, Rhs>
{
void evalTo(Dest& dst) const
EIGEN_MAKE_SOLVE_HELPERS(ColPivHouseholderQR<_MatrixType>,Rhs)
template<typename Dest> void evalTo(Dest& dst) const
{
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
const ColPivHouseholderQR<MatrixType>& dec = this->m_dec;
const Rhs& rhs = this->m_rhs;
const int rows = dec.rows(), cols = dec.cols();
dst.resize(cols, rhs.cols());
ei_assert(rhs.rows() == rows);
const int rows = dec().rows(), cols = dec().cols();
dst.resize(cols, rhs().cols());
ei_assert(rhs().rows() == rows);
// FIXME introduce nonzeroPivots() and use it here. and more generally,
// make the same improvements in this dec as in FullPivLU.
if(dec.rank()==0)
if(dec().rank()==0)
{
dst.setZero();
return;
}
typename Rhs::PlainMatrixType c(rhs);
typename Rhs::PlainMatrixType c(rhs());
// Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
c.applyOnTheLeft(makeHouseholderSequence(
dec.matrixQR().corner(TopLeft,rows,dec.rank()),
dec.hCoeffs().start(dec.rank())).transpose()
dec().matrixQR().corner(TopLeft,rows,dec().rank()),
dec().hCoeffs().start(dec().rank())).transpose()
);
if(!dec.isSurjective())
if(!dec().isSurjective())
{
// is c is in the image of R ?
RealScalar biggest_in_upper_part_of_c = c.corner(TopLeft, dec.rank(), c.cols()).cwise().abs().maxCoeff();
RealScalar biggest_in_lower_part_of_c = c.corner(BottomLeft, rows-dec.rank(), c.cols()).cwise().abs().maxCoeff();
RealScalar biggest_in_upper_part_of_c = c.corner(TopLeft, dec().rank(), c.cols()).cwise().abs().maxCoeff();
RealScalar biggest_in_lower_part_of_c = c.corner(BottomLeft, rows-dec().rank(), c.cols()).cwise().abs().maxCoeff();
// FIXME brain dead
const RealScalar m_precision = epsilon<Scalar>() * std::min(rows,cols);
if(!ei_isMuchSmallerThan(biggest_in_lower_part_of_c, biggest_in_upper_part_of_c, m_precision*4))
return;
}
dec.matrixQR()
.corner(TopLeft, dec.rank(), dec.rank())
dec().matrixQR()
.corner(TopLeft, dec().rank(), dec().rank())
.template triangularView<UpperTriangular>()
.solveInPlace(c.corner(TopLeft, dec.rank(), c.cols()));
.solveInPlace(c.corner(TopLeft, dec().rank(), c.cols()));
for(int i = 0; i < dec.rank(); ++i) dst.row(dec.colsPermutation().coeff(i)) = c.row(i);
for(int i = dec.rank(); i < cols; ++i) dst.row(dec.colsPermutation().coeff(i)).setZero();
for(int i = 0; i < dec().rank(); ++i) dst.row(dec().colsPermutation().coeff(i)) = c.row(i);
for(int i = dec().rank(); i < cols; ++i) dst.row(dec().colsPermutation().coeff(i)).setZero();
}
};

View File

@@ -332,57 +332,55 @@ FullPivHouseholderQR<MatrixType>& FullPivHouseholderQR<MatrixType>::compute(cons
return *this;
}
template<typename MatrixType, typename Rhs, typename Dest>
struct ei_solve_impl<FullPivHouseholderQR<MatrixType>, Rhs, Dest>
: ei_solve_return_value<FullPivHouseholderQR<MatrixType>, Rhs>
template<typename _MatrixType, typename Rhs>
struct ei_solve_impl<FullPivHouseholderQR<_MatrixType>, Rhs>
: ei_solve_return_value<FullPivHouseholderQR<_MatrixType>, Rhs>
{
void evalTo(Dest& dst) const
EIGEN_MAKE_SOLVE_HELPERS(FullPivHouseholderQR<_MatrixType>,Rhs)
template<typename Dest> void evalTo(Dest& dst) const
{
typedef typename MatrixType::Scalar Scalar;
typedef typename MatrixType::RealScalar RealScalar;
const FullPivHouseholderQR<MatrixType>& dec = this->m_dec;
const Rhs& rhs = this->m_rhs;
const int rows = dec.rows(), cols = dec.cols();
dst.resize(cols, rhs.cols());
ei_assert(rhs.rows() == rows);
const int rows = dec().rows(), cols = dec().cols();
dst.resize(cols, rhs().cols());
ei_assert(rhs().rows() == rows);
// FIXME introduce nonzeroPivots() and use it here. and more generally,
// make the same improvements in this dec as in FullPivLU.
if(dec.rank()==0)
if(dec().rank()==0)
{
dst.setZero();
return;
}
typename Rhs::PlainMatrixType c(rhs);
typename Rhs::PlainMatrixType c(rhs());
Matrix<Scalar,1,Rhs::ColsAtCompileTime> temp(rhs.cols());
for (int k = 0; k < dec.rank(); ++k)
Matrix<Scalar,1,Rhs::ColsAtCompileTime> temp(rhs().cols());
for (int k = 0; k < dec().rank(); ++k)
{
int remainingSize = rows-k;
c.row(k).swap(c.row(dec.rowsTranspositions().coeff(k)));
c.corner(BottomRight, remainingSize, rhs.cols())
.applyHouseholderOnTheLeft(dec.matrixQR().col(k).end(remainingSize-1),
dec.hCoeffs().coeff(k), &temp.coeffRef(0));
c.row(k).swap(c.row(dec().rowsTranspositions().coeff(k)));
c.corner(BottomRight, remainingSize, rhs().cols())
.applyHouseholderOnTheLeft(dec().matrixQR().col(k).end(remainingSize-1),
dec().hCoeffs().coeff(k), &temp.coeffRef(0));
}
if(!dec.isSurjective())
if(!dec().isSurjective())
{
// is c is in the image of R ?
RealScalar biggest_in_upper_part_of_c = c.corner(TopLeft, dec.rank(), c.cols()).cwise().abs().maxCoeff();
RealScalar biggest_in_lower_part_of_c = c.corner(BottomLeft, rows-dec.rank(), c.cols()).cwise().abs().maxCoeff();
RealScalar biggest_in_upper_part_of_c = c.corner(TopLeft, dec().rank(), c.cols()).cwise().abs().maxCoeff();
RealScalar biggest_in_lower_part_of_c = c.corner(BottomLeft, rows-dec().rank(), c.cols()).cwise().abs().maxCoeff();
// FIXME brain dead
const RealScalar m_precision = epsilon<Scalar>() * std::min(rows,cols);
if(!ei_isMuchSmallerThan(biggest_in_lower_part_of_c, biggest_in_upper_part_of_c, m_precision))
return;
}
dec.matrixQR()
.corner(TopLeft, dec.rank(), dec.rank())
dec().matrixQR()
.corner(TopLeft, dec().rank(), dec().rank())
.template triangularView<UpperTriangular>()
.solveInPlace(c.corner(TopLeft, dec.rank(), c.cols()));
.solveInPlace(c.corner(TopLeft, dec().rank(), c.cols()));
for(int i = 0; i < dec.rank(); ++i) dst.row(dec.colsPermutation().coeff(i)) = c.row(i);
for(int i = dec.rank(); i < cols; ++i) dst.row(dec.colsPermutation().coeff(i)).setZero();
for(int i = 0; i < dec().rank(); ++i) dst.row(dec().colsPermutation().coeff(i)) = c.row(i);
for(int i = dec().rank(); i < cols; ++i) dst.row(dec().colsPermutation().coeff(i)).setZero();
}
};

View File

@@ -209,28 +209,28 @@ HouseholderQR<MatrixType>& HouseholderQR<MatrixType>::compute(const MatrixType&
return *this;
}
template<typename MatrixType, typename Rhs, typename Dest>
struct ei_solve_impl<HouseholderQR<MatrixType>, Rhs, Dest>
: ei_solve_return_value<HouseholderQR<MatrixType>, Rhs>
template<typename _MatrixType, typename Rhs>
struct ei_solve_impl<HouseholderQR<_MatrixType>, Rhs>
: ei_solve_return_value<HouseholderQR<_MatrixType>, Rhs>
{
void evalTo(Dest& dst) const
{
const HouseholderQR<MatrixType>& dec = this->m_dec;
const Rhs& rhs = this->m_rhs;
const int rows = dec.rows(), cols = dec.cols();
dst.resize(cols, rhs.cols());
const int rank = std::min(rows, cols);
ei_assert(rhs.rows() == rows);
EIGEN_MAKE_SOLVE_HELPERS(HouseholderQR<_MatrixType>,Rhs)
typename Rhs::PlainMatrixType c(rhs);
template<typename Dest> void evalTo(Dest& dst) const
{
const int rows = dec().rows(), cols = dec().cols();
dst.resize(cols, rhs().cols());
const int rank = std::min(rows, cols);
ei_assert(rhs().rows() == rows);
typename Rhs::PlainMatrixType c(rhs());
// Note that the matrix Q = H_0^* H_1^*... so its inverse is Q^* = (H_0 H_1 ...)^T
c.applyOnTheLeft(makeHouseholderSequence(
dec.matrixQR().corner(TopLeft,rows,rank),
dec.hCoeffs().start(rank)).transpose()
dec().matrixQR().corner(TopLeft,rows,rank),
dec().hCoeffs().start(rank)).transpose()
);
dec.matrixQR()
dec().matrixQR()
.corner(TopLeft, rank, rank)
.template triangularView<UpperTriangular>()
.solveInPlace(c.corner(TopLeft, rank, c.cols()));