From 8710bd23e7a3727af31e539bfbe039ab3d07fedd Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 2 Jun 2010 13:32:13 +0200 Subject: [PATCH] clean the ambiguity with insertBack and add a insertBackByOuterInner function --- Eigen/src/Sparse/CholmodSupport.h | 1 + Eigen/src/Sparse/DynamicSparseMatrix.h | 94 +++++++++------- Eigen/src/Sparse/RandomSetter.h | 2 +- Eigen/src/Sparse/SparseMatrix.h | 150 +++++++++++++++---------- Eigen/src/Sparse/SparseMatrixBase.h | 4 +- Eigen/src/Sparse/SparseProduct.h | 2 +- Eigen/src/Sparse/SparseVector.h | 80 +++++++------ doc/C07_TutorialSparse.dox | 2 +- test/sparse.h | 12 +- test/sparse_basic.cpp | 4 +- 10 files changed, 205 insertions(+), 146 deletions(-) diff --git a/Eigen/src/Sparse/CholmodSupport.h b/Eigen/src/Sparse/CholmodSupport.h index 82a09f35c..1b34492aa 100644 --- a/Eigen/src/Sparse/CholmodSupport.h +++ b/Eigen/src/Sparse/CholmodSupport.h @@ -128,6 +128,7 @@ class SparseLLT : public SparseLLT typedef typename Base::Scalar Scalar; typedef typename Base::RealScalar RealScalar; typedef typename Base::CholMatrixType CholMatrixType; + typedef typename MatrixType::Index Index; using Base::MatrixLIsDirty; using Base::SupernodalFactorIsDirty; using Base::m_flags; diff --git a/Eigen/src/Sparse/DynamicSparseMatrix.h b/Eigen/src/Sparse/DynamicSparseMatrix.h index fea707f15..dea71bdba 100644 --- a/Eigen/src/Sparse/DynamicSparseMatrix.h +++ b/Eigen/src/Sparse/DynamicSparseMatrix.h @@ -127,13 +127,7 @@ class DynamicSparseMatrix return res; } - /** \deprecated - * Set the matrix to zero and reserve the memory for \a reserveSize nonzero coefficients. */ - EIGEN_DEPRECATED void startFill(Index reserveSize = 1000) - { - setZero(); - reserve(reserveSize); - } + void reserve(Index reserveSize = 1000) { @@ -147,9 +141,21 @@ class DynamicSparseMatrix } } + /** Does nothing: provided for compatibility with SparseMatrix */ inline void startVec(Index /*outer*/) {} - inline Scalar& insertBack(Index outer, Index inner) + /** \returns a reference to the non zero coefficient at position \a row, \a col assuming that: + * - the nonzero does not already exist + * - the new coefficient is the last one of the given inner vector. + * + * \sa insert, insertBackByInnerOuter */ + inline Scalar& insertBack(Index row, Index col) + { + return insertBackByInnerOuter(IsRowMajor?row:col, IsRowMajor?col:row); + } + + /** \sa insertBack */ + inline Scalar& insertBackByOuterInner(Index outer, Index inner) { ei_assert(outer= \a row. Otherwise the matrix is invalid. - * - * \see fillrand(), coeffRef() - */ - EIGEN_DEPRECATED Scalar& fill(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - return insertBack(outer,inner); - } - - /** \deprecated use insert() - * Like fill() but with random inner coordinates. - * Compared to the generic coeffRef(), the unique limitation is that we assume - * the coefficient does not exist yet. - */ - EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col) - { - return insert(row,col); - } - inline Scalar& insert(Index row, Index col) { const Index outer = IsRowMajor ? row : col; @@ -204,12 +184,10 @@ class DynamicSparseMatrix return m_data[outer].value(id+1); } - /** \deprecated use finalize() - * Does nothing. Provided for compatibility with SparseMatrix. */ - EIGEN_DEPRECATED void endFill() {} - + /** Does nothing: provided for compatibility with SparseMatrix */ inline void finalize() {} + /** Suppress all nonzeros which are smaller than \a reference under the tolerence \a epsilon */ void prune(Scalar reference, RealScalar epsilon = NumTraits::dummy_precision()) { for (Index j=0; j= \a row. Otherwise the matrix is invalid. + * + * \see fillrand(), coeffRef() + */ + EIGEN_DEPRECATED Scalar& fill(Index row, Index col) + { + const Index outer = IsRowMajor ? row : col; + const Index inner = IsRowMajor ? col : row; + return insertBack(outer,inner); + } + + /** \deprecated use insert() + * Like fill() but with random inner coordinates. + * Compared to the generic coeffRef(), the unique limitation is that we assume + * the coefficient does not exist yet. + */ + EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col) + { + return insert(row,col); + } + + /** \deprecated use finalize() + * Does nothing. Provided for compatibility with SparseMatrix. */ + EIGEN_DEPRECATED void endFill() {} }; template diff --git a/Eigen/src/Sparse/RandomSetter.h b/Eigen/src/Sparse/RandomSetter.h index abe98815f..18777e23d 100644 --- a/Eigen/src/Sparse/RandomSetter.h +++ b/Eigen/src/Sparse/RandomSetter.h @@ -243,7 +243,7 @@ class RandomSetter mp_target->startVec(j); prevOuter = outer; } - mp_target->insertBack(outer, inner) = it->second.value; + mp_target->insertBackByOuterInner(outer, inner) = it->second.value; } } mp_target->finalize(); diff --git a/Eigen/src/Sparse/SparseMatrix.h b/Eigen/src/Sparse/SparseMatrix.h index fd41d7302..b60aba853 100644 --- a/Eigen/src/Sparse/SparseMatrix.h +++ b/Eigen/src/Sparse/SparseMatrix.h @@ -1,7 +1,7 @@ // This file is part of Eigen, a lightweight C++ template library // for linear algebra. // -// Copyright (C) 2008-2009 Gael Guennebaud +// Copyright (C) 2008-2010 Gael Guennebaud // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -135,67 +135,41 @@ class SparseMatrix /** \returns the number of non zero coefficients */ inline Index nonZeros() const { return static_cast(m_data.size()); } - /** \deprecated use setZero() and reserve() - * Initializes the filling process of \c *this. - * \param reserveSize approximate number of nonzeros - * Note that the matrix \c *this is zero-ed. - */ - EIGEN_DEPRECATED void startFill(Index reserveSize = 1000) - { - setZero(); - m_data.reserve(reserveSize); - } - /** Preallocates \a reserveSize non zeros */ inline void reserve(Index reserveSize) { m_data.reserve(reserveSize); } - /** \deprecated use insert() - */ - EIGEN_DEPRECATED Scalar& fill(Index row, Index col) - { - const Index outer = IsRowMajor ? row : col; - const Index inner = IsRowMajor ? col : row; - - if (m_outerIndex[outer+1]==0) - { - // we start a new inner vector - Index i = outer; - while (i>=0 && m_outerIndex[i]==0) - { - m_outerIndex[i] = m_data.size(); - --i; - } - m_outerIndex[outer+1] = m_outerIndex[outer]; - } - else - { - ei_assert(m_data.index(m_data.size()-1)::dummy_precision()) { Index k = 0; @@ -389,23 +358,29 @@ class SparseMatrix } memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(Index)); } + + /** Low level API + * Resize the nonzero vector to \a size */ void resizeNonZeros(Index size) { m_data.resize(size); } + /** Default constructor yielding an empty \c 0 \c x \c 0 matrix */ inline SparseMatrix() : m_outerSize(-1), m_innerSize(0), m_outerIndex(0) { resize(0, 0); } + /** Constructs a \a rows \c x \a cols empty matrix */ inline SparseMatrix(Index rows, Index cols) : m_outerSize(0), m_innerSize(0), m_outerIndex(0) { resize(rows, cols); } + /** Constructs a sparse matrix from the sparse expression \a other */ template inline SparseMatrix(const SparseMatrixBase& other) : m_outerSize(0), m_innerSize(0), m_outerIndex(0) @@ -413,12 +388,14 @@ class SparseMatrix *this = other.derived(); } + /** Copy constructor */ inline SparseMatrix(const SparseMatrix& other) : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0) { *this = other.derived(); } + /** Swap the content of two sparse matrices of same type (optimization) */ inline void swap(SparseMatrix& other) { //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n"); @@ -444,11 +421,13 @@ class SparseMatrix return *this; } + #ifndef EIGEN_PARSED_BY_DOXYGEN template inline SparseMatrix& operator=(const SparseProduct& product) { return Base::operator=(product); } + #endif template EIGEN_DONT_INLINE SparseMatrix& operator=(const SparseMatrixBase& other) @@ -534,6 +513,61 @@ class SparseMatrix /** Overloaded for performance */ Scalar sum() const; + + public: + + /** \deprecated use setZero() and reserve() + * Initializes the filling process of \c *this. + * \param reserveSize approximate number of nonzeros + * Note that the matrix \c *this is zero-ed. + */ + EIGEN_DEPRECATED void startFill(Index reserveSize = 1000) + { + setZero(); + m_data.reserve(reserveSize); + } + + /** \deprecated use insert() + * Like fill() but with random inner coordinates. + */ + EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col) + { + return insert(row,col); + } + + /** \deprecated use insert() + */ + EIGEN_DEPRECATED Scalar& fill(Index row, Index col) + { + const Index outer = IsRowMajor ? row : col; + const Index inner = IsRowMajor ? col : row; + + if (m_outerIndex[outer+1]==0) + { + // we start a new inner vector + Index i = outer; + while (i>=0 && m_outerIndex[i]==0) + { + m_outerIndex[i] = m_data.size(); + --i; + } + m_outerIndex[outer+1] = m_outerIndex[outer]; + } + else + { + ei_assert(m_data.index(m_data.size()-1) diff --git a/Eigen/src/Sparse/SparseMatrixBase.h b/Eigen/src/Sparse/SparseMatrixBase.h index a4326821d..6f34b5c4e 100644 --- a/Eigen/src/Sparse/SparseMatrixBase.h +++ b/Eigen/src/Sparse/SparseMatrixBase.h @@ -209,7 +209,7 @@ template class SparseMatrixBase : public EigenBase { Scalar v = it.value(); if (v!=Scalar(0)) - temp.insertBack(Flip?it.index():j,Flip?j:it.index()) = v; + temp.insertBackByOuterInner(Flip?it.index():j,Flip?j:it.index()) = v; } } temp.finalize(); @@ -239,7 +239,7 @@ template class SparseMatrixBase : public EigenBase { Scalar v = it.value(); if (v!=Scalar(0)) - derived().insertBack(j,it.index()) = v; + derived().insertBackByOuterInner(j,it.index()) = v; } } derived().finalize(); diff --git a/Eigen/src/Sparse/SparseProduct.h b/Eigen/src/Sparse/SparseProduct.h index fb53902f4..1cb676132 100644 --- a/Eigen/src/Sparse/SparseProduct.h +++ b/Eigen/src/Sparse/SparseProduct.h @@ -265,7 +265,7 @@ static void ei_sparse_product_impl(const Lhs& lhs, const Rhs& rhs, ResultType& r } res.startVec(j); for (typename AmbiVector::Iterator it(tempVector); it; ++it) - res.insertBack(j,it.index()) = it.value(); + res.insertBackByOuterInner(j,it.index()) = it.value(); } res.finalize(); } diff --git a/Eigen/src/Sparse/SparseVector.h b/Eigen/src/Sparse/SparseVector.h index 4013b4de5..b15ab8220 100644 --- a/Eigen/src/Sparse/SparseVector.h +++ b/Eigen/src/Sparse/SparseVector.h @@ -127,7 +127,7 @@ class SparseVector ei_assert(outer==0); } - inline Scalar& insertBack(Index outer, Index inner) + inline Scalar& insertBackByOuterInner(Index outer, Index inner) { ei_assert(outer==0); return insertBack(inner); @@ -138,8 +138,10 @@ class SparseVector return m_data.value(m_data.size()-1); } - inline Scalar& insert(Index outer, Index inner) + inline Scalar& insert(Index row, Index col) { + Index inner = IsColVector ? row : col; + Index outer = IsColVector ? col : row; ei_assert(outer==0); return insert(inner); } @@ -165,42 +167,7 @@ class SparseVector */ inline void reserve(Index reserveSize) { m_data.reserve(reserveSize); } - /** \deprecated use setZero() and reserve() */ - EIGEN_DEPRECATED void startFill(Index reserve) - { - setZero(); - m_data.reserve(reserve); - } - /** \deprecated use insertBack(Index,Index) */ - EIGEN_DEPRECATED Scalar& fill(Index r, Index c) - { - ei_assert(r==0 || c==0); - return fill(IsColVector ? r : c); - } - - /** \deprecated use insertBack(Index) */ - EIGEN_DEPRECATED Scalar& fill(Index i) - { - m_data.append(0, i); - return m_data.value(m_data.size()-1); - } - - /** \deprecated use insert(Index,Index) */ - EIGEN_DEPRECATED Scalar& fillrand(Index r, Index c) - { - ei_assert(r==0 || c==0); - return fillrand(IsColVector ? r : c); - } - - /** \deprecated use insert(Index) */ - EIGEN_DEPRECATED Scalar& fillrand(Index i) - { - return insert(i); - } - - /** \deprecated use finalize() */ - EIGEN_DEPRECATED void endFill() {} inline void finalize() {} void prune(Scalar reference, RealScalar epsilon = NumTraits::dummy_precision()) @@ -362,6 +329,45 @@ class SparseVector /** Overloaded for performance */ Scalar sum() const; + + public: + + /** \deprecated use setZero() and reserve() */ + EIGEN_DEPRECATED void startFill(Index reserve) + { + setZero(); + m_data.reserve(reserve); + } + + /** \deprecated use insertBack(Index,Index) */ + EIGEN_DEPRECATED Scalar& fill(Index r, Index c) + { + ei_assert(r==0 || c==0); + return fill(IsColVector ? r : c); + } + + /** \deprecated use insertBack(Index) */ + EIGEN_DEPRECATED Scalar& fill(Index i) + { + m_data.append(0, i); + return m_data.value(m_data.size()-1); + } + + /** \deprecated use insert(Index,Index) */ + EIGEN_DEPRECATED Scalar& fillrand(Index r, Index c) + { + ei_assert(r==0 || c==0); + return fillrand(IsColVector ? r : c); + } + + /** \deprecated use insert(Index) */ + EIGEN_DEPRECATED Scalar& fillrand(Index i) + { + return insert(i); + } + + /** \deprecated use finalize() */ + EIGEN_DEPRECATED void endFill() {} }; template diff --git a/doc/C07_TutorialSparse.dox b/doc/C07_TutorialSparse.dox index ae96d77c4..ee8a1a100 100644 --- a/doc/C07_TutorialSparse.dox +++ b/doc/C07_TutorialSparse.dox @@ -183,7 +183,7 @@ for(int j=0; j<1000; ++j) } mat.finalize(); // optional for a DynamicSparseMatrix \endcode - +Note that there also exist the insertBackByOuterInner(Index outer, Index, inner) function which allows to write code agnostic to the storage order. \section TutorialSparseFeatureSet Supported operators and functions diff --git a/test/sparse.h b/test/sparse.h index f0d230153..4733e4d10 100644 --- a/test/sparse.h +++ b/test/sparse.h @@ -81,13 +81,13 @@ initSparse(double density, v = Scalar(0); else if ((flags & MakeUpperTriangular) && jpush_back(Vector2i(i,j)); } @@ -126,13 +126,13 @@ initSparse(double density, v = Scalar(0); else if ((flags & MakeUpperTriangular) && jpush_back(Vector2i(i,j)); } diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 9de156d38..43d9c6254 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -323,12 +323,12 @@ template void sparse_basic(const SparseMatrixType& re else if (x<0.5) { countFalseNonZero++; - m2.insertBack(j,i) = Scalar(0); + m2.insertBackByOuterInner(j,i) = Scalar(0); } else { countTrueNonZero++; - m2.insertBack(j,i) = refM2(i,j) = Scalar(1); + m2.insertBackByOuterInner(j,i) = refM2(i,j) = Scalar(1); } } }