mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-06-04 18:54:00 +08:00
new feature: copy from a sparse selfadjoint view to a full sparse matrix
This commit is contained in:
parent
5a3a229550
commit
9a3ec637ff
@ -108,7 +108,7 @@ class DynamicSparseMatrix
|
|||||||
|
|
||||||
/** \returns a reference to the coefficient value at given position \a row, \a col
|
/** \returns a reference to the coefficient value at given position \a row, \a col
|
||||||
* This operation involes a log(rho*outer_size) binary search. If the coefficient does not
|
* This operation involes a log(rho*outer_size) binary search. If the coefficient does not
|
||||||
* exist yet, then a sorted insertion Indexo a sequential buffer is performed.
|
* exist yet, then a sorted insertion into a sequential buffer is performed.
|
||||||
*/
|
*/
|
||||||
inline Scalar& coeffRef(Index row, Index col)
|
inline Scalar& coeffRef(Index row, Index col)
|
||||||
{
|
{
|
||||||
|
@ -69,6 +69,7 @@ class SparseMatrix
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EIGEN_SPARSE_PUBLIC_INTERFACE(SparseMatrix)
|
EIGEN_SPARSE_PUBLIC_INTERFACE(SparseMatrix)
|
||||||
|
using Base::operator=;
|
||||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=)
|
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, +=)
|
||||||
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=)
|
EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(SparseMatrix, -=)
|
||||||
// FIXME: why are these operator already alvailable ???
|
// FIXME: why are these operator already alvailable ???
|
||||||
|
@ -46,6 +46,16 @@ template<typename Derived> class SparseMatrixBase : public EigenBase<Derived>
|
|||||||
typedef typename internal::traits<Derived>::Index Index;
|
typedef typename internal::traits<Derived>::Index Index;
|
||||||
|
|
||||||
typedef SparseMatrixBase StorageBaseType;
|
typedef SparseMatrixBase StorageBaseType;
|
||||||
|
typedef EigenBase<Derived> Base;
|
||||||
|
|
||||||
|
template<typename OtherDerived>
|
||||||
|
Derived& operator=(const EigenBase<OtherDerived> &other)
|
||||||
|
{
|
||||||
|
other.derived().evalTo(derived());
|
||||||
|
return derived();
|
||||||
|
}
|
||||||
|
|
||||||
|
// using Base::operator=;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
||||||
|
@ -45,12 +45,24 @@ class SparseSelfAdjointTimeDenseProduct;
|
|||||||
template<typename Lhs, typename Rhs, int UpLo>
|
template<typename Lhs, typename Rhs, int UpLo>
|
||||||
class DenseTimeSparseSelfAdjointProduct;
|
class DenseTimeSparseSelfAdjointProduct;
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
template<typename MatrixType, unsigned int UpLo>
|
||||||
|
struct traits<SparseSelfAdjointView<MatrixType,UpLo> > : traits<MatrixType> {
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
|
template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
|
||||||
|
: public EigenBase<SparseSelfAdjointView<MatrixType,UpLo> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef typename MatrixType::Scalar Scalar;
|
typedef typename MatrixType::Scalar Scalar;
|
||||||
typedef typename MatrixType::Index Index;
|
typedef typename MatrixType::Index Index;
|
||||||
|
typedef Matrix<Index,Dynamic,1> VectorI;
|
||||||
|
typedef typename MatrixType::Nested MatrixTypeNested;
|
||||||
|
typedef typename internal::remove_all<MatrixTypeNested>::type _MatrixTypeNested;
|
||||||
|
|
||||||
inline SparseSelfAdjointView(const MatrixType& matrix) : m_matrix(matrix)
|
inline SparseSelfAdjointView(const MatrixType& matrix) : m_matrix(matrix)
|
||||||
{
|
{
|
||||||
@ -77,7 +89,7 @@ template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
|
|||||||
DenseTimeSparseSelfAdjointProduct<OtherDerived,MatrixType,UpLo>
|
DenseTimeSparseSelfAdjointProduct<OtherDerived,MatrixType,UpLo>
|
||||||
operator*(const MatrixBase<OtherDerived>& lhs, const SparseSelfAdjointView& rhs)
|
operator*(const MatrixBase<OtherDerived>& lhs, const SparseSelfAdjointView& rhs)
|
||||||
{
|
{
|
||||||
return DenseTimeSparseSelfAdjointProduct<OtherDerived,MatrixType,UpLo>(lhs.derived(), rhs.m_matrix);
|
return DenseTimeSparseSelfAdjointProduct<OtherDerived,_MatrixTypeNested,UpLo>(lhs.derived(), rhs.m_matrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
|
/** Perform a symmetric rank K update of the selfadjoint matrix \c *this:
|
||||||
@ -94,12 +106,78 @@ template<typename MatrixType, unsigned int UpLo> class SparseSelfAdjointView
|
|||||||
template<typename DerivedU>
|
template<typename DerivedU>
|
||||||
SparseSelfAdjointView& rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
|
SparseSelfAdjointView& rankUpdate(const SparseMatrixBase<DerivedU>& u, Scalar alpha = Scalar(1));
|
||||||
|
|
||||||
|
/** \internal triggered by sparse_matrix = SparseSelfadjointView; */
|
||||||
|
template<typename DestScalar> void evalTo(SparseMatrix<DestScalar>& _dest) const
|
||||||
|
{
|
||||||
|
typedef SparseMatrix<DestScalar> Dest;
|
||||||
|
Dest& dest(_dest.derived());
|
||||||
|
enum {
|
||||||
|
StorageOrderMatch = Dest::IsRowMajor == _MatrixTypeNested::IsRowMajor
|
||||||
|
};
|
||||||
|
VectorI count = Dest::IsRowMajor ? m_countPerRow : m_countPerCol;
|
||||||
|
Index size = m_matrix.rows();
|
||||||
|
count.resize(size);
|
||||||
|
count.setZero();
|
||||||
|
dest.resize(size,size);
|
||||||
|
for(Index j = 0; j<size; ++j)
|
||||||
|
{
|
||||||
|
for(typename _MatrixTypeNested::InnerIterator it(m_matrix,j); it; ++it)
|
||||||
|
{
|
||||||
|
Index i = it.index();
|
||||||
|
if(i==j)
|
||||||
|
count[i]++;
|
||||||
|
else if((UpLo==Lower && i>j) || (UpLo==Upper && i<j))
|
||||||
|
{
|
||||||
|
count[i]++;
|
||||||
|
count[j]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Index nnz = count.sum();
|
||||||
|
|
||||||
|
// reserve space
|
||||||
|
dest.reserve(nnz);
|
||||||
|
dest._outerIndexPtr()[0] = 0;
|
||||||
|
for(Index j=0; j<size; ++j)
|
||||||
|
dest._outerIndexPtr()[j+1] = dest._outerIndexPtr()[j] + count[j];
|
||||||
|
for(Index j=0; j<size; ++j)
|
||||||
|
count[j] = dest._outerIndexPtr()[j];
|
||||||
|
|
||||||
|
// copy data
|
||||||
|
for(Index j = 0; j<size; ++j)
|
||||||
|
{
|
||||||
|
for(typename _MatrixTypeNested::InnerIterator it(m_matrix,j); it; ++it)
|
||||||
|
{
|
||||||
|
Index i = it.index();
|
||||||
|
if(i==j)
|
||||||
|
{
|
||||||
|
int k = count[i]++;
|
||||||
|
dest._innerIndexPtr()[k] = i;
|
||||||
|
dest._valuePtr()[k] = it.value();
|
||||||
|
}
|
||||||
|
else if((UpLo==Lower && i>j) || (UpLo==Upper && i<j))
|
||||||
|
{
|
||||||
|
int k = count[j]++;
|
||||||
|
dest._innerIndexPtr()[k] = i;
|
||||||
|
dest._valuePtr()[k] = it.value();
|
||||||
|
k = count[i]++;
|
||||||
|
dest._innerIndexPtr()[k] = j;
|
||||||
|
dest._valuePtr()[k] = internal::conj(it.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const SparseLLT<PlainObject, UpLo> llt() const;
|
// const SparseLLT<PlainObject, UpLo> llt() const;
|
||||||
// const SparseLDLT<PlainObject, UpLo> ldlt() const;
|
// const SparseLDLT<PlainObject, UpLo> ldlt() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
const typename MatrixType::Nested m_matrix;
|
const typename MatrixType::Nested m_matrix;
|
||||||
|
VectorI m_countPerRow;
|
||||||
|
VectorI m_countPerCol;
|
||||||
};
|
};
|
||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
@ -133,7 +211,7 @@ SparseSelfAdjointView<MatrixType,UpLo>::rankUpdate(const SparseMatrixBase<Derive
|
|||||||
if(alpha==Scalar(0))
|
if(alpha==Scalar(0))
|
||||||
m_matrix.const_cast_derived() = tmp.template triangularView<UpLo>();
|
m_matrix.const_cast_derived() = tmp.template triangularView<UpLo>();
|
||||||
else
|
else
|
||||||
m_matrix.const_cast_derived() /*+*/= alpha * tmp.template triangularView<UpLo>();
|
m_matrix.const_cast_derived() += alpha * tmp.template triangularView<UpLo>();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -251,10 +251,21 @@ template<typename SparseMatrixType> void sparse_basic(const SparseMatrixType& re
|
|||||||
VERIFY_IS_APPROX(m2, refM2);
|
VERIFY_IS_APPROX(m2, refM2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test selfadjointView
|
||||||
|
{
|
||||||
|
DenseMatrix refMat2(rows, rows), refMat3(rows, rows);
|
||||||
|
SparseMatrixType m2(rows, rows), m3(rows, rows);
|
||||||
|
initSparse<Scalar>(density, refMat2, m2);
|
||||||
|
refMat3 = refMat2.template selfadjointView<Lower>();
|
||||||
|
m3 = m2.template selfadjointView<Lower>();
|
||||||
|
VERIFY_IS_APPROX(m3, refMat3);
|
||||||
|
}
|
||||||
|
|
||||||
// test sparseView
|
// test sparseView
|
||||||
{
|
{
|
||||||
DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
|
DenseMatrix refMat2 = DenseMatrix::Zero(rows, rows);
|
||||||
SparseMatrixType m2(rows, rows);
|
SparseMatrixType m2(rows, rows);
|
||||||
|
initSparse<Scalar>(density, refMat2, m2);
|
||||||
VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval());
|
VERIFY_IS_APPROX(m2.eval(), refMat2.sparseView().eval());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user