diff --git a/Eigen/src/Sparse/CompressedStorage.h b/Eigen/src/Sparse/CompressedStorage.h index 4dbd32309..328c5f2e5 100644 --- a/Eigen/src/Sparse/CompressedStorage.h +++ b/Eigen/src/Sparse/CompressedStorage.h @@ -155,7 +155,7 @@ class CompressedStorage /** Like at(), but the search is performed in the range [start,end) */ inline Scalar atInRange(size_t start, size_t end, int key, Scalar defaultValue = Scalar(0)) const { - if (start==end) + if (start>=end) return Scalar(0); else if (end>start && key==m_indices[end-1]) return m_values[end-1]; diff --git a/Eigen/src/Sparse/DynamicSparseMatrix.h b/Eigen/src/Sparse/DynamicSparseMatrix.h index 7119a84bd..2927cd583 100644 --- a/Eigen/src/Sparse/DynamicSparseMatrix.h +++ b/Eigen/src/Sparse/DynamicSparseMatrix.h @@ -110,14 +110,14 @@ class DynamicSparseMatrix class InnerIterator; - inline void setZero() + void setZero() { for (int j=0; j0) { int reserveSizePerVector = std::max(reserveSize/outerSize(),4); for (int j=0; j()) { diff --git a/Eigen/src/Sparse/RandomSetter.h b/Eigen/src/Sparse/RandomSetter.h index d908e315f..839d18449 100644 --- a/Eigen/src/Sparse/RandomSetter.h +++ b/Eigen/src/Sparse/RandomSetter.h @@ -224,19 +224,28 @@ class RandomSetter KeyType keyBitsMask = (1<startFill(nonZeros()); + mp_target->setZero(); + mp_target->reserve(nonZeros()); + int prevOuter = -1; for (int k=0; kstartVec(k); const int outerOffset = (1<first >> m_keyBitsOffset) + outerOffset; const int inner = it->first & keyBitsMask; - mp_target->fill(TargetRowMajor ? outer : inner, TargetRowMajor ? inner : outer) = it->second.value; + if (prevOuter!=outer) + { + for (int j=prevOuter+1;j<=outer;++j) + mp_target->startVec(j); + prevOuter = outer; + } + mp_target->insertBack(outer, inner) = it->second.value; } } - mp_target->endFill(); + mp_target->finalize(); } else { diff --git a/Eigen/src/Sparse/SparseLLT.h b/Eigen/src/Sparse/SparseLLT.h index 40cefa189..5c2810472 100644 --- a/Eigen/src/Sparse/SparseLLT.h +++ b/Eigen/src/Sparse/SparseLLT.h @@ -135,7 +135,8 @@ void SparseLLT::compute(const MatrixType& a) RealScalar density = a.nonZeros()/RealScalar(size*size); // TODO estimate the number of non zeros - m_matrix.startFill(a.nonZeros()*2); + m_matrix.setZero(); + m_matrix.reserve(a.nonZeros()*2); for (int j = 0; j < size; ++j) { Scalar x = ei_real(a.coeff(j,j)); @@ -173,14 +174,15 @@ void SparseLLT::compute(const MatrixType& a) // copy the temporary vector to the respective m_matrix.col() // while scaling the result by 1/real(x) RealScalar rx = ei_sqrt(ei_real(x)); - m_matrix.fill(j,j) = rx; + m_matrix.insert(j,j) = rx; // FIXME use insertBack Scalar y = Scalar(1)/rx; for (typename AmbiVector::Iterator it(tempVector, m_precision*rx); it; ++it) { - m_matrix.fill(it.index(), j) = it.value() * y; + // FIXME use insertBack + m_matrix.insert(it.index(), j) = it.value() * y; } } - m_matrix.endFill(); + m_matrix.finalize(); } /** Computes b = L^-T L^-1 b */ diff --git a/Eigen/src/Sparse/SparseMatrix.h b/Eigen/src/Sparse/SparseMatrix.h index ad94e63ba..c4e2bfc37 100644 --- a/Eigen/src/Sparse/SparseMatrix.h +++ b/Eigen/src/Sparse/SparseMatrix.h @@ -118,33 +118,36 @@ class SparseMatrix class InnerIterator; + /** Removes all non zeros */ inline void setZero() { m_data.clear(); - //if (m_outerSize) memset(m_outerIndex, 0, (m_outerSize+1)*sizeof(int)); -// for (int i=0; i=0 && m_outerIndex[i]==0) + while (previousOuter>=0 && m_outerIndex[previousOuter]==0) { - m_outerIndex[i] = m_data.size(); - --i; + m_outerIndex[previousOuter] = m_data.size(); + --previousOuter; } m_outerIndex[outer+1] = m_outerIndex[outer]; } - assert(size_t(m_outerIndex[outer+1]) == m_data.size() && "invalid outer index"); + + // 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]; ++m_outerIndex[outer+1]; float reallocRatio = 1; - if (m_data.allocatedSize()0) + { + m_data.index(k) = m_data.index(k-1); + m_data.value(k) = m_data.value(k-1); + k--; + } + } + else + { + // we are not inserting into the last inner vec + // update outer indices: + int j = outer+2; + while (j<=m_outerSize && m_outerIndex[j]!=0) + m_outerIndex[j++]++; + --j; + // shift data of last vecs: + int k = m_outerIndex[j]-1; + while (k>=int(id)) + { + m_data.index(k) = m_data.index(k-1); + m_data.value(k) = m_data.value(k-1); + k--; + } + } + } while ( (id > startId) && (m_data.index(id-1) > inner) ) { @@ -223,7 +309,11 @@ class SparseMatrix return (m_data.value(id) = 0); } - inline void endFill() + EIGEN_DEPRECATED void endFill() { finalize(); } + + /** Must be called after inserting a set of non zero entries. + */ + inline void finalize() { int size = m_data.size(); int i = m_outerSize; diff --git a/Eigen/src/Sparse/SparseMatrixBase.h b/Eigen/src/Sparse/SparseMatrixBase.h index e611744d4..74a9a7feb 100644 --- a/Eigen/src/Sparse/SparseMatrixBase.h +++ b/Eigen/src/Sparse/SparseMatrixBase.h @@ -156,26 +156,26 @@ template class SparseMatrixBase ei_assert(( ((ei_traits::SupportedAccessPatterns&OuterRandomAccessPattern)==OuterRandomAccessPattern) || (!((Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit)))) && "the transpose operation is supposed to be handled in SparseMatrix::operator="); - + + enum { Flip = (Flags & RowMajorBit) != (OtherDerived::Flags & RowMajorBit) }; + const int outerSize = other.outerSize(); //typedef typename ei_meta_if, Derived>::ret TempType; // thanks to shallow copies, we always eval to a tempary Derived temp(other.rows(), other.cols()); - temp.startFill(std::max(this->rows(),this->cols())*2); + temp.reserve(std::max(this->rows(),this->cols())*2); for (int j=0; j class SparseMatrixBase { // eval without temporary derived().resize(other.rows(), other.cols()); - derived().startFill(std::max(this->rows(),this->cols())*2); + derived().setZero(); + derived().reserve(std::max(this->rows(),this->cols())*2); for (int j=0; j::Iterator it(tempVector); it; ++it) - if (ResultType::Flags&RowMajorBit) - res.fill(j,it.index()) = it.value(); - else - res.fill(it.index(), j) = it.value(); + res.insertBack(j,it.index()) = it.value(); } - res.endFill(); + res.finalize(); } template +// Copyright (C) 2008-2009w Gael Guennebaud // // Eigen is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -120,42 +120,32 @@ class SparseVector /** \returns the number of non zero coefficients */ inline int nonZeros() const { return m_data.size(); } - /** - */ - inline void reserve(int reserveSize) { m_data.reserve(reserveSize); } - - inline void startFill(int reserve) + inline void startVec(int outer) { - setZero(); - m_data.reserve(reserve); + ei_assert(outer==0); } - - /** - */ - inline Scalar& fill(int r, int c) + + inline Scalar& insertBack(int outer, int inner) { - ei_assert(r==0 || c==0); - return fill(IsColVector ? r : c); + ei_assert(outer==0); + return insertBack(inner); } - - inline Scalar& fill(int i) + inline Scalar& insertBack(int i) { m_data.append(0, i); return m_data.value(m_data.size()-1); } - inline Scalar& fillrand(int r, int c) + inline Scalar& insert(int outer, int inner) { - ei_assert(r==0 || c==0); - return fillrand(IsColVector ? r : c); + ei_assert(outer==0); + return insert(inner); } - - /** Like fill() but with random coordinates. - */ - inline Scalar& fillrand(int i) + Scalar& insert(int i) { int startId = 0; int id = m_data.size() - 1; + // TODO smart realloc m_data.resize(id+2,1); while ( (id >= startId) && (m_data.index(id) > i) ) @@ -169,8 +159,48 @@ class SparseVector return m_data.value(id+1); } - inline void endFill() {} + /** + */ + inline void reserve(int reserveSize) { m_data.reserve(reserveSize); } + /** \deprecated use setZero() and reserve() */ + EIGEN_DEPRECATED void startFill(int reserve) + { + setZero(); + m_data.reserve(reserve); + } + + /** \deprecated use insertBack(int,int) */ + EIGEN_DEPRECATED Scalar& fill(int r, int c) + { + ei_assert(r==0 || c==0); + return fill(IsColVector ? r : c); + } + + /** \deprecated use insertBack(int) */ + EIGEN_DEPRECATED Scalar& fill(int i) + { + m_data.append(0, i); + return m_data.value(m_data.size()-1); + } + + /** \deprecated use insert(int,int) */ + EIGEN_DEPRECATED Scalar& fillrand(int r, int c) + { + ei_assert(r==0 || c==0); + return fillrand(IsColVector ? r : c); + } + + /** \deprecated use insert(int) */ + EIGEN_DEPRECATED Scalar& fillrand(int i) + { + return insert(i); + } + + /** \deprecated use finalize() */ + EIGEN_DEPRECATED void endFill() {} + inline void finalize() {} + void prune(Scalar reference, RealScalar epsilon = precision()) { m_data.prune(reference,epsilon); diff --git a/Eigen/src/Sparse/TriangularSolver.h b/Eigen/src/Sparse/TriangularSolver.h index 30ddd1af2..284ce2b02 100644 --- a/Eigen/src/Sparse/TriangularSolver.h +++ b/Eigen/src/Sparse/TriangularSolver.h @@ -212,7 +212,7 @@ struct ei_sparse_solve_triangular_sparse_selector tempVector.setBounds(0,other.rows()); Rhs res(other.rows(), other.cols()); - res.startFill(other.nonZeros()); + res.reserve(other.nonZeros()); for(int col=0 ; col ++ count; // std::cerr << "fill " << it.index() << ", " << col << "\n"; // std::cout << it.value() << " "; - res.fill(it.index(), col) = it.value(); + // FIXME use insertBack + res.insert(it.index(), col) = it.value(); } // std::cout << "tempVector.nonZeros() == " << int(count) << " / " << (other.rows()) << "\n"; } - res.endFill(); + res.finalize(); other = res.markAsRValue(); } }; diff --git a/test/sparse.h b/test/sparse.h index 80d99dc5b..eb2f98f5f 100644 --- a/test/sparse.h +++ b/test/sparse.h @@ -64,9 +64,11 @@ initSparse(double density, std::vector* zeroCoords = 0, std::vector* nonzeroCoords = 0) { - sparseMat.startFill(int(refMat.rows()*refMat.cols()*density)); + sparseMat.setZero(); + sparseMat.reserve(int(refMat.rows()*refMat.cols()*density)); for(int j=0; j(0,1) < density) ? ei_random() : Scalar(0); @@ -85,7 +87,7 @@ initSparse(double density, if (v!=Scalar(0)) { - sparseMat.fill(i,j) = v; + sparseMat.insertBack(j,i) = v; if (nonzeroCoords) nonzeroCoords->push_back(Vector2i(i,j)); } @@ -96,7 +98,7 @@ initSparse(double density, refMat(i,j) = v; } } - sparseMat.endFill(); + sparseMat.finalize(); } template void @@ -107,9 +109,11 @@ initSparse(double density, std::vector* zeroCoords = 0, std::vector* nonzeroCoords = 0) { - sparseMat.startFill(int(refMat.rows()*refMat.cols()*density)); + sparseMat.setZero(); + sparseMat.reserve(int(refMat.rows()*refMat.cols()*density)); for(int j=0; j(0,1) < density) ? ei_random() : Scalar(0); @@ -128,7 +132,7 @@ initSparse(double density, if (v!=Scalar(0)) { - sparseMat.fill(i,j) = v; + sparseMat.insertBack(j,i) = v; if (nonzeroCoords) nonzeroCoords->push_back(Vector2i(i,j)); } @@ -139,7 +143,7 @@ initSparse(double density, refMat(i,j) = v; } } - sparseMat.endFill(); + sparseMat.finalize(); } template void @@ -156,7 +160,7 @@ initSparse(double density, Scalar v = (ei_random(0,1) < density) ? ei_random() : Scalar(0); if (v!=Scalar(0)) { - sparseVec.fill(i) = v; + sparseVec.insertBack(i) = v; if (nonzeroCoords) nonzeroCoords->push_back(i); } diff --git a/test/sparse_basic.cpp b/test/sparse_basic.cpp index 410ef96a6..cf58b30af 100644 --- a/test/sparse_basic.cpp +++ b/test/sparse_basic.cpp @@ -177,22 +177,39 @@ template void sparse_basic(const SparseMatrixType& re VERIFY(( test_random_setter >(m,refMat,nonzeroCoords) )); #endif - // test fillrand + // test insert (inner random) { DenseMatrix m1(rows,cols); m1.setZero(); SparseMatrixType m2(rows,cols); - m2.startFill(); + m2.reserve(10); for (int j=0; j(0,rows-1); if (m1.coeff(i,j)==Scalar(0)) - m2.fillrand(i,j) = m1(i,j) = ei_random(); + m2.insert(i,j) = m1(i,j) = ei_random(); } } - m2.endFill(); + m2.finalize(); + VERIFY_IS_APPROX(m2,m1); + } + + // test insert (fully random) + { + DenseMatrix m1(rows,cols); + m1.setZero(); + SparseMatrixType m2(rows,cols); + m2.reserve(10); + for (int k=0; k(0,rows-1); + int j = ei_random(0,cols-1); + if (m1.coeff(i,j)==Scalar(0)) + m2.insert(i,j) = m1(i,j) = ei_random(); + } + m2.finalize(); VERIFY_IS_APPROX(m2,m1); } @@ -291,8 +308,9 @@ template void sparse_basic(const SparseMatrixType& re refM2.setZero(); int countFalseNonZero = 0; int countTrueNonZero = 0; - m2.startFill(); for (int j=0; j(0,1); @@ -303,15 +321,16 @@ template void sparse_basic(const SparseMatrixType& re else if (x<0.5) { countFalseNonZero++; - m2.fill(i,j) = Scalar(0); + m2.insertBack(j,i) = Scalar(0); } else { countTrueNonZero++; - m2.fill(i,j) = refM2(i,j) = Scalar(1); + m2.insertBack(j,i) = refM2(i,j) = Scalar(1); } } - m2.endFill(); + } + m2.finalize(); VERIFY(countFalseNonZero+countTrueNonZero == m2.nonZeros()); VERIFY_IS_APPROX(m2, refM2); m2.prune(1); diff --git a/test/sparse_solvers.cpp b/test/sparse_solvers.cpp index e1ec1ef35..ce19153ff 100644 --- a/test/sparse_solvers.cpp +++ b/test/sparse_solvers.cpp @@ -37,12 +37,12 @@ initSPD(double density, initSparse(density,aux,sparseMat,ForceNonZeroDiag); refMat += aux * aux.adjoint(); } - sparseMat.startFill(); + sparseMat.setZero(); for (int j=0 ; j void sparse_solvers(int rows, int cols)