From 6dffdca123418a1e504c0b9ef5b313c122af246e Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Thu, 7 May 2009 13:13:42 +0000 Subject: [PATCH] fix realloc when initial size was 0 (bug reported by Jens Mueller) --- Eigen/src/Sparse/SparseMatrix.h | 54 +++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/Eigen/src/Sparse/SparseMatrix.h b/Eigen/src/Sparse/SparseMatrix.h index c4e2bfc37..8bcf3c8b9 100644 --- a/Eigen/src/Sparse/SparseMatrix.h +++ b/Eigen/src/Sparse/SparseMatrix.h @@ -138,7 +138,7 @@ class SparseMatrix setZero(); m_data.reserve(reserveSize); } - + /** Preallocates \a reserveSize non zeros */ inline void reserve(int reserveSize) { @@ -175,9 +175,9 @@ class SparseMatrix m_data.append(0, inner); return m_data.value(id); } - + //--- low level purely coherent filling --- - + inline Scalar& insertBack(int outer, int inner) { ei_assert(size_t(m_outerIndex[outer+1]) == m_data.size() && "wrong sorted insertion"); @@ -187,14 +187,14 @@ class SparseMatrix m_data.append(0, inner); return m_data.value(id); } - + inline void startVec(int outer) { ei_assert(m_outerIndex[outer]==int(m_data.size()) && "you must call startVec on each inner vec"); ei_assert(m_outerIndex[outer+1]==0 && "you must call startVec on each inner vec"); m_outerIndex[outer+1] = m_outerIndex[outer]; } - + //--- /** \deprecated use insert() @@ -204,20 +204,20 @@ class SparseMatrix { return insert(row,col); } - + /** \returns a reference to a novel non zero coefficient with coordinates \a row x \a col. * The non zero coefficient must \b not already exist. - * + * * \warning This function can be extremely slow if the non zero coefficients * are not inserted in a coherent order. - * + * * After an insertion session, you should call the finalize() function. */ EIGEN_DONT_INLINE Scalar& insert(int row, int col) { const int outer = IsRowMajor ? row : col; const int inner = IsRowMajor ? col : row; - + int previousOuter = outer; if (m_outerIndex[outer+1]==0) { @@ -229,13 +229,13 @@ class SparseMatrix } m_outerIndex[outer+1] = m_outerIndex[outer]; } - - // here we have to handle the tricky case where the outerIndex array + + // 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., // the 2nd inner vector... bool isLastVec = (!(previousOuter==-1 && m_data.size()!=0)) && (size_t(m_outerIndex[outer+1]) == m_data.size()); - + size_t startId = m_outerIndex[outer]; // FIXME let's make sure sizeof(long int) == sizeof(size_t) size_t id = m_outerIndex[outer+1]; @@ -244,18 +244,26 @@ class SparseMatrix float reallocRatio = 1; if (m_data.allocatedSize()<=m_data.size()) { - // we need to reallocate the data, to reduce multiple reallocations - // we use a smart resize algorithm based on the current filling ratio - // in addition, we use float to avoid integers overflows - float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer+1); - reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size()); - // furthermore we bound the realloc ratio to: - // 1) reduce multiple minor realloc when the matrix is almost filled - // 2) avoid to allocate too much memory when the matrix is almost empty - reallocRatio = std::min(std::max(reallocRatio,1.5f),8.f); + // if there is no preallocated memory, let's reserve a minimum of 32 elements + if (m_data.size()==0) + { + m_data.reserve(32); + } + else + { + // we need to reallocate the data, to reduce multiple reallocations + // we use a smart resize algorithm based on the current filling ratio + // in addition, we use float to avoid integers overflows + float nnzEstimate = float(m_outerIndex[outer])*float(m_outerSize)/float(outer+1); + reallocRatio = (nnzEstimate-float(m_data.size()))/float(m_data.size()); + // furthermore we bound the realloc ratio to: + // 1) reduce multiple minor realloc when the matrix is almost filled + // 2) avoid to allocate too much memory when the matrix is almost empty + reallocRatio = std::min(std::max(reallocRatio,1.5f),8.f); + } } m_data.resize(m_data.size()+1,reallocRatio); - + if (!isLastVec) { if (previousOuter==-1) @@ -310,7 +318,7 @@ class SparseMatrix } EIGEN_DEPRECATED void endFill() { finalize(); } - + /** Must be called after inserting a set of non zero entries. */ inline void finalize()