mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-07-28 07:42:02 +08:00
add a generic mechanism to copy a special matrix to a dense matrix so that
we don't need to add other specialization of MatrixBase::operator=, Matrix::=, and Matrix::Matrix(...)
This commit is contained in:
parent
1aea45335f
commit
544888e342
@ -225,47 +225,6 @@ template<typename MatrixType> struct LLT_Traits<MatrixType,UpperTriangular>
|
|||||||
template<typename MatrixType, int _UpLo>
|
template<typename MatrixType, int _UpLo>
|
||||||
void LLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
void LLT<MatrixType,_UpLo>::compute(const MatrixType& a)
|
||||||
{
|
{
|
||||||
// assert(a.rows()==a.cols());
|
|
||||||
// const int size = a.rows();
|
|
||||||
// m_matrix.resize(size, size);
|
|
||||||
// // The biggest overall is the point of reference to which further diagonals
|
|
||||||
// // are compared; if any diagonal is negligible compared
|
|
||||||
// // to the largest overall, the algorithm bails. This cutoff is suggested
|
|
||||||
// // in "Analysis of the Cholesky Decomposition of a Semi-definite Matrix" by
|
|
||||||
// // Nicholas J. Higham. Also see "Accuracy and Stability of Numerical
|
|
||||||
// // Algorithms" page 217, also by Higham.
|
|
||||||
// const RealScalar cutoff = machine_epsilon<Scalar>() * size * a.diagonal().cwise().abs().maxCoeff();
|
|
||||||
// RealScalar x;
|
|
||||||
// x = ei_real(a.coeff(0,0));
|
|
||||||
// m_matrix.coeffRef(0,0) = ei_sqrt(x);
|
|
||||||
// if(size==1)
|
|
||||||
// {
|
|
||||||
// m_isInitialized = true;
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// m_matrix.col(0).end(size-1) = a.row(0).end(size-1).adjoint() / ei_real(m_matrix.coeff(0,0));
|
|
||||||
// for (int j = 1; j < size; ++j)
|
|
||||||
// {
|
|
||||||
// x = ei_real(a.coeff(j,j)) - m_matrix.row(j).start(j).squaredNorm();
|
|
||||||
// if (ei_abs(x) < cutoff) continue;
|
|
||||||
//
|
|
||||||
// m_matrix.coeffRef(j,j) = x = ei_sqrt(x);
|
|
||||||
//
|
|
||||||
// int endSize = size-j-1;
|
|
||||||
// if (endSize>0) {
|
|
||||||
// // Note that when all matrix columns have good alignment, then the following
|
|
||||||
// // product is guaranteed to be optimal with respect to alignment.
|
|
||||||
// m_matrix.col(j).end(endSize) =
|
|
||||||
// (m_matrix.block(j+1, 0, endSize, j) * m_matrix.row(j).start(j).adjoint()).lazy();
|
|
||||||
//
|
|
||||||
// // FIXME could use a.col instead of a.row
|
|
||||||
// m_matrix.col(j).end(endSize) = (a.row(j).end(endSize).adjoint()
|
|
||||||
// - m_matrix.col(j).end(endSize) ) / x;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// m_isInitialized = true;
|
|
||||||
|
|
||||||
assert(a.rows()==a.cols());
|
assert(a.rows()==a.cols());
|
||||||
const int size = a.rows();
|
const int size = a.rows();
|
||||||
m_matrix.resize(size, size);
|
m_matrix.resize(size, size);
|
||||||
|
@ -50,6 +50,8 @@ class DiagonalBase : public MultiplierBase<Derived>
|
|||||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
|
||||||
DenseMatrixType toDenseMatrix() const { return derived(); }
|
DenseMatrixType toDenseMatrix() const { return derived(); }
|
||||||
|
template<typename DenseDerived>
|
||||||
|
void evalToDense(MatrixBase<DenseDerived> &other) const;
|
||||||
|
|
||||||
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
|
inline const DiagonalVectorType& diagonal() const { return derived().diagonal(); }
|
||||||
inline DiagonalVectorType& diagonal() { return derived().diagonal(); }
|
inline DiagonalVectorType& diagonal() { return derived().diagonal(); }
|
||||||
@ -63,12 +65,11 @@ class DiagonalBase : public MultiplierBase<Derived>
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename DiagonalDerived>
|
template<typename DenseDerived>
|
||||||
Derived& MatrixBase<Derived>::operator=(const DiagonalBase<DiagonalDerived> &other)
|
void DiagonalBase<Derived>::evalToDense(MatrixBase<DenseDerived> &other) const
|
||||||
{
|
{
|
||||||
setZero();
|
other.setZero();
|
||||||
diagonal() = other.diagonal();
|
other.diagonal() = diagonal();
|
||||||
return derived();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \class DiagonalMatrix
|
/** \class DiagonalMatrix
|
||||||
|
@ -440,33 +440,19 @@ class Matrix
|
|||||||
/** Destructor */
|
/** Destructor */
|
||||||
inline ~Matrix() {}
|
inline ~Matrix() {}
|
||||||
|
|
||||||
|
/** \sa MatrixBase::operator=(const AnyMatrixBase<OtherDerived>&) */
|
||||||
template<typename DiagonalDerived>
|
template<typename OtherDerived>
|
||||||
EIGEN_STRONG_INLINE Matrix& operator=(const DiagonalBase<DiagonalDerived> &other)
|
EIGEN_STRONG_INLINE Matrix& operator=(const AnyMatrixBase<OtherDerived> &other)
|
||||||
{
|
{
|
||||||
resize(other.diagonal().size(), other.diagonal().size());
|
resize(other.derived().rows(), other.derived().cols());
|
||||||
Base::operator=(other);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename DiagonalDerived>
|
|
||||||
EIGEN_STRONG_INLINE Matrix(const DiagonalBase<DiagonalDerived> &other)
|
|
||||||
: m_storage(other.diagonal().size() * other.diagonal().size(), other.diagonal().size(), other.diagonal().size())
|
|
||||||
{
|
|
||||||
*this = other;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TriangularDerived>
|
|
||||||
EIGEN_STRONG_INLINE Matrix& operator=(const TriangularBase<TriangularDerived> &other)
|
|
||||||
{
|
|
||||||
resize(other.rows(), other.cols());
|
|
||||||
Base::operator=(other.derived());
|
Base::operator=(other.derived());
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TriangularDerived>
|
/** \sa MatrixBase::operator=(const AnyMatrixBase<OtherDerived>&) */
|
||||||
EIGEN_STRONG_INLINE Matrix(const TriangularBase<TriangularDerived> &other)
|
template<typename OtherDerived>
|
||||||
: m_storage(other.rows() * other.cols(), other.rows(), other.cols())
|
EIGEN_STRONG_INLINE Matrix(const AnyMatrixBase<OtherDerived> &other)
|
||||||
|
: m_storage(other.derived().rows() * other.derived().cols(), other.derived().rows(), other.derived().cols())
|
||||||
{
|
{
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
@ -284,6 +284,17 @@ template<typename Derived> class MatrixBase
|
|||||||
*/
|
*/
|
||||||
Derived& operator=(const MatrixBase& other);
|
Derived& operator=(const MatrixBase& other);
|
||||||
|
|
||||||
|
/** Copies the generic expression \a other into *this. \returns a reference to *this.
|
||||||
|
* The expression must provide a (templated) evalToDense(Derived& dst) const function
|
||||||
|
* which does the actual job. In practice, this allows any user to write its own
|
||||||
|
* special matrix without having to modify MatrixBase */
|
||||||
|
template<typename OtherDerived>
|
||||||
|
Derived& operator=(const AnyMatrixBase<OtherDerived> &other)
|
||||||
|
{ other.derived().evalToDense(derived()); return derived(); }
|
||||||
|
|
||||||
|
template<typename OtherDerived,typename OtherEvalType>
|
||||||
|
Derived& operator=(const ReturnByValue<OtherDerived,OtherEvalType>& func);
|
||||||
|
|
||||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||||
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
/** Copies \a other into *this without evaluating other. \returns a reference to *this. */
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
@ -297,10 +308,6 @@ template<typename Derived> class MatrixBase
|
|||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
|
Derived& lazyAssign(const Flagged<OtherDerived, 0, EvalBeforeNestingBit | EvalBeforeAssigningBit>& other)
|
||||||
{ return lazyAssign(other._expression()); }
|
{ return lazyAssign(other._expression()); }
|
||||||
|
|
||||||
/** Overloaded for fast triangular part to dense matrix evaluation */
|
|
||||||
template<typename TriangularDerived>
|
|
||||||
Derived& lazyAssign(const TriangularBase<TriangularDerived> &other);
|
|
||||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
|
||||||
CommaInitializer<Derived> operator<< (const Scalar& s);
|
CommaInitializer<Derived> operator<< (const Scalar& s);
|
||||||
@ -403,12 +410,6 @@ template<typename Derived> class MatrixBase
|
|||||||
const DiagonalProduct<Derived, DiagonalDerived, DiagonalOnTheRight>
|
const DiagonalProduct<Derived, DiagonalDerived, DiagonalOnTheRight>
|
||||||
operator*(const DiagonalBase<DiagonalDerived> &diagonal) const;
|
operator*(const DiagonalBase<DiagonalDerived> &diagonal) const;
|
||||||
|
|
||||||
template<typename DiagonalDerived>
|
|
||||||
Derived& operator=(const DiagonalBase<DiagonalDerived> &other);
|
|
||||||
|
|
||||||
template<typename TriangularDerived>
|
|
||||||
Derived& operator=(const TriangularBase<TriangularDerived> &other);
|
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
typename ei_plain_matrix_type_column_major<OtherDerived>::type
|
typename ei_plain_matrix_type_column_major<OtherDerived>::type
|
||||||
solveTriangular(const MatrixBase<OtherDerived>& other) const;
|
solveTriangular(const MatrixBase<OtherDerived>& other) const;
|
||||||
@ -739,9 +740,6 @@ template<typename Derived> class MatrixBase
|
|||||||
template<typename Derived1, typename Derived2>
|
template<typename Derived1, typename Derived2>
|
||||||
Derived& lazyAssign(const SparseProduct<Derived1,Derived2,DenseTimeSparseProduct>& product);
|
Derived& lazyAssign(const SparseProduct<Derived1,Derived2,DenseTimeSparseProduct>& product);
|
||||||
|
|
||||||
template<typename OtherDerived,typename OtherEvalType>
|
|
||||||
Derived& operator=(const ReturnByValue<OtherDerived,OtherEvalType>& func);
|
|
||||||
|
|
||||||
#ifdef EIGEN_MATRIXBASE_PLUGIN
|
#ifdef EIGEN_MATRIXBASE_PLUGIN
|
||||||
#include EIGEN_MATRIXBASE_PLUGIN
|
#include EIGEN_MATRIXBASE_PLUGIN
|
||||||
#endif
|
#endif
|
||||||
|
@ -90,6 +90,11 @@ template<typename Derived> class TriangularBase : public MultiplierBase<Derived>
|
|||||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||||
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
#endif // not EIGEN_PARSED_BY_DOXYGEN
|
||||||
|
|
||||||
|
template<typename DenseDerived>
|
||||||
|
void evalToDense(MatrixBase<DenseDerived> &other) const;
|
||||||
|
template<typename DenseDerived>
|
||||||
|
void evalToDenseLazy(MatrixBase<DenseDerived> &other) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void check_coordinates(int row, int col)
|
void check_coordinates(int row, int col)
|
||||||
@ -516,36 +521,34 @@ void TriangularView<MatrixType, Mode>::lazyAssign(const TriangularBase<OtherDeri
|
|||||||
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
|
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
|
||||||
* If the matrix is triangular, the opposite part is set to zero. */
|
* If the matrix is triangular, the opposite part is set to zero. */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename TriangularDerived>
|
template<typename DenseDerived>
|
||||||
Derived& MatrixBase<Derived>::operator=(const TriangularBase<TriangularDerived> &other)
|
void TriangularBase<Derived>::evalToDense(MatrixBase<DenseDerived> &other) const
|
||||||
{
|
{
|
||||||
if(ei_traits<TriangularDerived>::Flags & EvalBeforeAssigningBit)
|
if(ei_traits<Derived>::Flags & EvalBeforeAssigningBit)
|
||||||
{
|
{
|
||||||
typename TriangularDerived::PlainMatrixType other_evaluated(other.rows(), other.cols());
|
typename Derived::PlainMatrixType other_evaluated(rows(), cols());
|
||||||
other_evaluated.lazyAssign(other);
|
evalToDenseLazy(other_evaluated);
|
||||||
this->swap(other_evaluated);
|
other.derived().swap(other_evaluated);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lazyAssign(other.derived());
|
evalToDenseLazy(other.derived());
|
||||||
return derived();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
|
/** Assigns a triangular or selfadjoint matrix to a dense matrix.
|
||||||
* If the matrix is triangular, the opposite part is set to zero. */
|
* If the matrix is triangular, the opposite part is set to zero. */
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
template<typename TriangularDerived>
|
template<typename DenseDerived>
|
||||||
Derived& MatrixBase<Derived>::lazyAssign(const TriangularBase<TriangularDerived> &other)
|
void TriangularBase<Derived>::evalToDenseLazy(MatrixBase<DenseDerived> &other) const
|
||||||
{
|
{
|
||||||
const bool unroll = Derived::SizeAtCompileTime * TriangularDerived::CoeffReadCost / 2
|
const bool unroll = DenseDerived::SizeAtCompileTime * Derived::CoeffReadCost / 2
|
||||||
<= EIGEN_UNROLLING_LIMIT;
|
<= EIGEN_UNROLLING_LIMIT;
|
||||||
ei_assert(this->rows() == other.rows() && this->cols() == other.cols());
|
ei_assert(this->rows() == other.rows() && this->cols() == other.cols());
|
||||||
|
|
||||||
ei_part_assignment_impl
|
ei_part_assignment_impl
|
||||||
<Derived, typename ei_traits<TriangularDerived>::ExpressionType, TriangularDerived::Mode,
|
<DenseDerived, typename ei_traits<Derived>::ExpressionType, Derived::Mode,
|
||||||
unroll ? int(Derived::SizeAtCompileTime) : Dynamic,
|
unroll ? int(DenseDerived::SizeAtCompileTime) : Dynamic,
|
||||||
true // clear the opposite triangular part
|
true // clear the opposite triangular part
|
||||||
>::run(this->const_cast_derived(), other.derived()._expression());
|
>::run(other.derived(), derived()._expression());
|
||||||
return derived();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \deprecated use MatrixBase::triangularView() */
|
/** \deprecated use MatrixBase::triangularView() */
|
||||||
|
@ -451,25 +451,19 @@ template<typename Derived> class SparseMatrixBase
|
|||||||
// Derived& setRandom();
|
// Derived& setRandom();
|
||||||
// Derived& setIdentity();
|
// Derived& setIdentity();
|
||||||
|
|
||||||
|
template<typename DenseDerived>
|
||||||
|
void evalToDense(MatrixBase<DenseDerived>& dst)
|
||||||
|
{
|
||||||
|
dst.resize(rows(),cols());
|
||||||
|
dst.setZero();
|
||||||
|
for (int j=0; j<outerSize(); ++j)
|
||||||
|
for (typename Derived::InnerIterator i(derived(),j); i; ++i)
|
||||||
|
res.coeffRef(i.row(),i.col()) = i.value();
|
||||||
|
}
|
||||||
|
|
||||||
Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> toDense() const
|
Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> toDense() const
|
||||||
{
|
{
|
||||||
Matrix<Scalar,RowsAtCompileTime,ColsAtCompileTime> res(rows(),cols());
|
return derived();
|
||||||
res.setZero();
|
|
||||||
for (int j=0; j<outerSize(); ++j)
|
|
||||||
{
|
|
||||||
for (typename Derived::InnerIterator i(derived(),j); i; ++i)
|
|
||||||
{
|
|
||||||
if(IsRowMajor)
|
|
||||||
std::cerr << i.row() << "," << i.col() << " == " << j << "," << i.index() << "\n";
|
|
||||||
else
|
|
||||||
std::cerr << i.row() << "," << i.col() << " == " << i.index() << "," << j << "\n";
|
|
||||||
// if(IsRowMajor)
|
|
||||||
res.coeffRef(i.row(),i.col()) = i.value();
|
|
||||||
// else
|
|
||||||
// res.coeffRef(i.index(),j) = i.value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OtherDerived>
|
template<typename OtherDerived>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user