diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h index 56811ce27..2d938a671 100644 --- a/Eigen/src/SparseCore/SparseMatrix.h +++ b/Eigen/src/SparseCore/SparseMatrix.h @@ -103,6 +103,7 @@ class SparseMatrix public: + /** \returns whether \c *this is in compressed form. */ inline bool compressed() const { return m_innerNonZeros==0; } /** \returns the number of rows of the matrix */ @@ -145,7 +146,9 @@ class SparseMatrix * \warning it returns 0 in compressed mode */ inline Index* _innerNonZeroPtr() { return m_innerNonZeros; } + /** \internal */ inline Storage& data() { return m_data; } + /** \internal */ inline const Storage& data() const { return m_data; } /** \returns the value of the matrix at position \a i, \a j @@ -159,7 +162,13 @@ class SparseMatrix } /** \returns a non-const reference to the value of the matrix at position \a i, \a j - * The element \b have to be a non-zero element. */ + * + * If the element does not exist then it is inserted via the insert(Index,Index) function + * which itself turns the matrix into a non compressed form if that was not the case. + * + * This is a O(log(nnz_j)) operation (binary search) plus the cost of insert(Index,Index) + * function if the element does not already exist. + */ inline Scalar& coeffRef(Index row, Index col) { const Index outer = IsRowMajor ? row : col; @@ -168,10 +177,34 @@ class SparseMatrix Index start = m_outerIndex[outer]; Index end = m_innerNonZeros ? m_outerIndex[outer] + m_innerNonZeros[outer] : m_outerIndex[outer+1]; eigen_assert(end>=start && "you probably called coeffRef on a non finalized matrix"); - eigen_assert(end>start && "coeffRef cannot be called on a zero coefficient"); + if(end<=start) + return insert(row,col); const Index p = m_data.searchLowerIndex(start,end-1,inner); - eigen_assert((p::dummy_precision()) { prune(default_prunning_func(reference,epsilon)); } - /** Suppress all nonzeros which do not satisfy the predicate \a keep. + /** Suppresses all nonzeros which do not satisfy the predicate \a keep. * The functor type \a KeepFunc must implement the following function: * \code * bool operator() (const Index& row, const Index& col, const Scalar& value) const; @@ -456,7 +477,7 @@ class SparseMatrix m_data.resize(k,0); } - /** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero + /** Resizes the matrix to a \a rows x \a cols matrix and initializes it to zero. * \sa resizeNonZeros(Index), reserve(), setZero() */ void resize(Index rows, Index cols) @@ -478,11 +499,8 @@ class SparseMatrix memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(Index)); } - /** \deprecated - * \internal - * Low level API - * Resize the nonzero vector to \a size - * */ + /** \internal + * Resize the nonzero vector to \a size */ void resizeNonZeros(Index size) { // TODO remove this function @@ -511,14 +529,15 @@ class SparseMatrix *this = other.derived(); } - /** Copy constructor */ + /** Copy constructor (it performs a deep copy) */ inline SparseMatrix(const SparseMatrix& other) : Base(), m_outerSize(0), m_innerSize(0), m_outerIndex(0), m_innerNonZeros(0) { *this = other.derived(); } - /** Swap the content of two sparse matrices of same type (optimization) */ + /** Swaps the content of two sparse matrices of the same type. + * This is a fast operation that simply swaps the underlying pointers and parameters. */ inline void swap(SparseMatrix& other) { //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n"); @@ -648,8 +667,10 @@ class SparseMatrix delete[] m_innerNonZeros; } +#ifndef EIGEN_PARSED_BY_DOXYGEN /** Overloaded for performance */ Scalar sum() const; +#endif # ifdef EIGEN_SPARSEMATRIX_PLUGIN # include EIGEN_SPARSEMATRIX_PLUGIN @@ -690,7 +711,7 @@ protected: } // here we have to handle the tricky case where the outerIndex array - // starts with: [ 0 0 0 0 0 1 ...] and we are inserting in, e.g., + // starts with: [ 0 0 0 0 0 1 ...] and we are inserted in, e.g., // the 2nd inner vector... bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0)) && (size_t(m_outerIndex[outer+1]) == m_data.size()); @@ -776,6 +797,8 @@ protected: return (m_data.value(p) = 0); } + /** \internal + * A vector object that is equal to 0 everywhere but v at the position i */ class SingletonVector { Index m_index; diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 487e3c1c3..c566bd957 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -110,7 +110,8 @@ template void sparse_basic(const SparseMatrixType& re DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); - m2.reserve(10); + if(internal::random()%2) + m2.reserve(VectorXi::Constant(m2.outerSize(), 2)); for (int j=0; j void sparse_basic(const SparseMatrixType& re DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); - m2.reserve(10); + if(internal::random()%2) + m2.reserve(VectorXi::Constant(m2.outerSize(), 2)); for (int k=0; k(0,rows-1); int j = internal::random(0,cols-1); - if (m1.coeff(i,j)==Scalar(0)) + if ((m1.coeff(i,j)==Scalar(0)) && (internal::random()%2)) m2.insert(i,j) = m1(i,j) = internal::random(); + else + { + Scalar v = internal::random(); + m2.coeffRef(i,j) += v; + m1(i,j) += v; + } } - m2.finalize(); VERIFY_IS_APPROX(m2,m1); } @@ -158,8 +165,8 @@ template void sparse_basic(const SparseMatrixType& re if(mode==3) m2.reserve(r); } - m2.finalize(); - m2.makeCompressed(); + if(internal::random()%2) + m2.makeCompressed(); VERIFY_IS_APPROX(m2,m1); }