diff --git a/Eigen/src/SparseCore/SparseMatrix.h b/Eigen/src/SparseCore/SparseMatrix.h index 8463269c3..e94e55cfb 100644 --- a/Eigen/src/SparseCore/SparseMatrix.h +++ b/Eigen/src/SparseCore/SparseMatrix.h @@ -286,7 +286,8 @@ class SparseMatrix { std::size_t totalReserveSize = 0; // turn the matrix into non-compressed mode - m_innerNonZeros = new Index[m_outerSize]; + m_innerNonZeros = static_cast(std::malloc(m_outerSize * sizeof(Index))); + if (!m_innerNonZeros) internal::throw_std_bad_alloc(); // temporarily use m_innerSizes to hold the new starting points. Index* newOuterIndex = m_innerNonZeros; @@ -318,7 +319,9 @@ class SparseMatrix } else { - Index* newOuterIndex = new Index[m_outerSize+1]; + Index* newOuterIndex = static_cast(std::malloc((m_outerSize+1)*sizeof(Index))); + if (!newOuterIndex) internal::throw_std_bad_alloc(); + Index count = 0; for(Index j=0; jrows() == rows && this->cols() == cols) return; + + Index innerChange = IsRowMajor ? cols - this->cols() : rows - this->rows(); + Index outerChange = IsRowMajor ? rows - this->rows() : cols - this->cols(); + Index newInnerSize = IsRowMajor ? cols : rows; + + // Deals with inner non zeros + if (m_innerNonZeros) + { + // Resize m_innerNonZeros + Index *newInnerNonZeros = static_cast(std::realloc(m_innerNonZeros, (m_outerSize + outerChange) * sizeof(Index))); + if (!newInnerNonZeros) internal::throw_std_bad_alloc(); + m_innerNonZeros = newInnerNonZeros; + + for(Index i=m_outerSize; i(std::malloc((m_outerSize+outerChange+1) * sizeof(Index))); + if (!m_innerNonZeros) internal::throw_std_bad_alloc(); + for(Index i = 0; i < m_outerSize; i++) + m_innerNonZeros[i] = m_outerIndex[i+1] - m_outerIndex[i]; + } + + // Change the m_innerNonZeros in case of a decrease of inner size + if (m_innerNonZeros && innerChange < 0) { + for(Index i = 0; i= 0 && m_data.index(start+n-1) >= newInnerSize) --n; + } + } + + m_innerSize = newInnerSize; + + // Re-allocate outer index structure if necessary + if (outerChange == 0) + return; + + Index *newOuterIndex = static_cast(std::realloc(m_outerIndex, (m_outerSize + outerChange + 1) * sizeof(Index))); + if (!newOuterIndex) internal::throw_std_bad_alloc(); + m_outerIndex = newOuterIndex; + Index last = m_outerSize == 0 ? 0 : m_outerIndex[m_outerSize]; + for(Index i=m_outerSize; i(std::malloc((outerSize + 1) * sizeof(Index))); + if (!m_outerIndex) internal::throw_std_bad_alloc(); + m_outerSize = outerSize; } if(m_innerNonZeros) { - delete[] m_innerNonZeros; + std::free(m_innerNonZeros); m_innerNonZeros = 0; } memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(Index)); @@ -714,8 +777,8 @@ class SparseMatrix /** Destructor */ inline ~SparseMatrix() { - delete[] m_outerIndex; - delete[] m_innerNonZeros; + std::free(m_outerIndex); + std::free(m_innerNonZeros); } #ifndef EIGEN_PARSED_BY_DOXYGEN @@ -735,7 +798,7 @@ protected: resize(other.rows(), other.cols()); if(m_innerNonZeros) { - delete[] m_innerNonZeros; + std::free(m_innerNonZeros); m_innerNonZeros = 0; } } @@ -1105,7 +1168,7 @@ void SparseMatrix::sumupDuplicates() m_outerIndex[m_outerSize] = count; // turn the matrix into compressed form - delete[] m_innerNonZeros; + std::free(m_innerNonZeros); m_innerNonZeros = 0; m_data.resize(m_outerIndex[m_outerSize]); } diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 8897a9dca..767451450 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -379,6 +379,41 @@ template void sparse_basic(const SparseMatrixType& re initSparse(density, refMat2, m2); VERIFY_IS_APPROX(m2.diagonal(), refMat2.diagonal().eval()); } + + // test conservative resize + { + std::vector< std::pair > inc; + inc.push_back(std::pair(-3,-2)); + inc.push_back(std::pair(0,0)); + inc.push_back(std::pair(3,2)); + inc.push_back(std::pair(3,0)); + inc.push_back(std::pair(0,3)); + + for(size_t i = 0; i< inc.size(); i++) { + int incRows = inc[i].first; + int incCols = inc[i].second; + SparseMatrixType m1(rows, cols); + DenseMatrix refMat1 = DenseMatrix::Zero(rows, cols); + initSparse(density, refMat1, m1); + + m1.conservativeResize(rows+incRows, cols+incCols); + refMat1.conservativeResize(rows+incRows, cols+incCols); + if (incRows > 0) refMat1.bottomRows(incRows).setZero(); + if (incCols > 0) refMat1.rightCols(incCols).setZero(); + + VERIFY_IS_APPROX(m1, refMat1); + + // Insert new values + if (incRows > 0) + m1.insert(refMat1.rows()-1, 0) = refMat1(refMat1.rows()-1, 0) = 1; + if (incCols > 0) + m1.insert(0, refMat1.cols()-1) = refMat1(0, refMat1.cols()-1) = 1; + + VERIFY_IS_APPROX(m1, refMat1); + + + } + } } void test_sparse_basic()