DynamicSparseMatrix.h
00001 // This file is part of Eigen, a lightweight C++ template library
00002 // for linear algebra.
00003 //
00004 // Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
00005 //
00006 // This Source Code Form is subject to the terms of the Mozilla
00007 // Public License v. 2.0. If a copy of the MPL was not distributed
00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00009 
00010 #ifndef EIGEN_DYNAMIC_SPARSEMATRIX_H
00011 #define EIGEN_DYNAMIC_SPARSEMATRIX_H
00012 
00013 namespace Eigen { 
00014 
00035 namespace internal {
00036 template<typename _Scalar, int _Options, typename _StorageIndex>
00037 struct traits<DynamicSparseMatrix<_Scalar, _Options, _StorageIndex> >
00038 {
00039   typedef _Scalar Scalar;
00040   typedef _StorageIndex StorageIndex;
00041   typedef Sparse StorageKind;
00042   typedef MatrixXpr XprKind;
00043   enum {
00044     RowsAtCompileTime = Dynamic,
00045     ColsAtCompileTime = Dynamic,
00046     MaxRowsAtCompileTime = Dynamic,
00047     MaxColsAtCompileTime = Dynamic,
00048     Flags = _Options | NestByRefBit | LvalueBit,
00049     CoeffReadCost = NumTraits<Scalar>::ReadCost,
00050     SupportedAccessPatterns = OuterRandomAccessPattern
00051   };
00052 };
00053 }
00054 
00055 template<typename _Scalar, int _Options, typename _StorageIndex>
00056  class  DynamicSparseMatrix
00057   : public SparseMatrixBase<DynamicSparseMatrix<_Scalar, _Options, _StorageIndex> >
00058 {
00059     typedef SparseMatrixBase<DynamicSparseMatrix> Base;
00060     using Base::convert_index;
00061   public:
00062     EIGEN_SPARSE_PUBLIC_INTERFACE(DynamicSparseMatrix)
00063     // FIXME: why are these operator already alvailable ???
00064     // EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, +=)
00065     // EIGEN_SPARSE_INHERIT_ASSIGNMENT_OPERATOR(DynamicSparseMatrix, -=)
00066     typedef MappedSparseMatrix<Scalar,Flags> Map;
00067     using Base::IsRowMajor;
00068     using Base::operator=;
00069     enum {
00070       Options = _Options
00071     };
00072 
00073   protected:
00074 
00075     typedef DynamicSparseMatrix<Scalar,(Flags&~RowMajorBit)|(IsRowMajor?RowMajorBit:0), StorageIndex> TransposedSparseMatrix;
00076 
00077     Index m_innerSize;
00078     std::vector<internal::CompressedStorage<Scalar,StorageIndex> > m_data;
00079 
00080   public:
00081 
00082     inline Index rows() const { return IsRowMajor ? outerSize() : m_innerSize; }
00083     inline Index cols() const { return IsRowMajor ? m_innerSize : outerSize(); }
00084     inline Index innerSize() const { return m_innerSize; }
00085     inline Index outerSize() const { return convert_index(m_data.size()); }
00086     inline Index innerNonZeros(Index j) const { return m_data[j].size(); }
00087 
00088     std::vector<internal::CompressedStorage<Scalar,StorageIndex> >& _data() { return m_data; }
00089     const std::vector<internal::CompressedStorage<Scalar,StorageIndex> >& _data() const { return m_data; }
00090 
00094     inline Scalar coeff(Index row, Index col) const
00095     {
00096       const Index outer = IsRowMajor ? row : col;
00097       const Index inner = IsRowMajor ? col : row;
00098       return m_data[outer].at(inner);
00099     }
00100 
00105     inline Scalar& coeffRef(Index row, Index col)
00106     {
00107       const Index outer = IsRowMajor ? row : col;
00108       const Index inner = IsRowMajor ? col : row;
00109       return m_data[outer].atWithInsertion(inner);
00110     }
00111 
00112     class InnerIterator;
00113     class ReverseInnerIterator;
00114 
00115     void setZero()
00116     {
00117       for (Index j=0; j<outerSize(); ++j)
00118         m_data[j].clear();
00119     }
00120 
00122     Index nonZeros() const
00123     {
00124       Index res = 0;
00125       for (Index j=0; j<outerSize(); ++j)
00126         res += m_data[j].size();
00127       return res;
00128     }
00129 
00130 
00131 
00132     void reserve(Index reserveSize = 1000)
00133     {
00134       if (outerSize()>0)
00135       {
00136         Index reserveSizePerVector = (std::max)(reserveSize/outerSize(),Index(4));
00137         for (Index j=0; j<outerSize(); ++j)
00138         {
00139           m_data[j].reserve(reserveSizePerVector);
00140         }
00141       }
00142     }
00143 
00145     inline void startVec(Index /*outer*/) {}
00146 
00152     inline Scalar& insertBack(Index row, Index col)
00153     {
00154       return insertBackByOuterInner(IsRowMajor?row:col, IsRowMajor?col:row);
00155     }
00156 
00158     inline Scalar& insertBackByOuterInner(Index outer, Index inner)
00159     {
00160       eigen_assert(outer<Index(m_data.size()) && inner<m_innerSize && "out of range");
00161       eigen_assert(((m_data[outer].size()==0) || (m_data[outer].index(m_data[outer].size()-1)<inner))
00162                 && "wrong sorted insertion");
00163       m_data[outer].append(0, inner);
00164       return m_data[outer].value(m_data[outer].size()-1);
00165     }
00166 
00167     inline Scalar& insert(Index row, Index col)
00168     {
00169       const Index outer = IsRowMajor ? row : col;
00170       const Index inner = IsRowMajor ? col : row;
00171 
00172       Index startId = 0;
00173       Index id = static_cast<Index>(m_data[outer].size()) - 1;
00174       m_data[outer].resize(id+2,1);
00175 
00176       while ( (id >= startId) && (m_data[outer].index(id) > inner) )
00177       {
00178         m_data[outer].index(id+1) = m_data[outer].index(id);
00179         m_data[outer].value(id+1) = m_data[outer].value(id);
00180         --id;
00181       }
00182       m_data[outer].index(id+1) = inner;
00183       m_data[outer].value(id+1) = 0;
00184       return m_data[outer].value(id+1);
00185     }
00186 
00188     inline void finalize() {}
00189 
00191     void prune(Scalar reference, RealScalar epsilon = NumTraits<RealScalar>::dummy_precision())
00192     {
00193       for (Index j=0; j<outerSize(); ++j)
00194         m_data[j].prune(reference,epsilon);
00195     }
00196 
00199     void resize(Index rows, Index cols)
00200     {
00201       const Index outerSize = IsRowMajor ? rows : cols;
00202       m_innerSize = convert_index(IsRowMajor ? cols : rows);
00203       setZero();
00204       if (Index(m_data.size()) != outerSize)
00205       {
00206         m_data.resize(outerSize);
00207       }
00208     }
00209 
00210     void resizeAndKeepData(Index rows, Index cols)
00211     {
00212       const Index outerSize = IsRowMajor ? rows : cols;
00213       const Index innerSize = IsRowMajor ? cols : rows;
00214       if (m_innerSize>innerSize)
00215       {
00216         // remove all coefficients with innerCoord>=innerSize
00217         // TODO
00218         //std::cerr << "not implemented yet\n";
00219         exit(2);
00220       }
00221       if (m_data.size() != outerSize)
00222       {
00223         m_data.resize(outerSize);
00224       }
00225     }
00226 
00228     EIGEN_DEPRECATED inline DynamicSparseMatrix()
00229       : m_innerSize(0), m_data(0)
00230     {
00231       eigen_assert(innerSize()==0 && outerSize()==0);
00232     }
00233 
00235     EIGEN_DEPRECATED inline DynamicSparseMatrix(Index rows, Index cols)
00236       : m_innerSize(0)
00237     {
00238       resize(rows, cols);
00239     }
00240 
00242     template<typename OtherDerived>
00243     EIGEN_DEPRECATED explicit inline DynamicSparseMatrix(const SparseMatrixBase<OtherDerived>& other)
00244       : m_innerSize(0)
00245     {
00246     Base::operator=(other.derived());
00247     }
00248 
00249     inline DynamicSparseMatrix(const DynamicSparseMatrix& other)
00250       : Base(), m_innerSize(0)
00251     {
00252       *this = other.derived();
00253     }
00254 
00255     inline void swap(DynamicSparseMatrix& other)
00256     {
00257       //EIGEN_DBG_SPARSE(std::cout << "SparseMatrix:: swap\n");
00258       std::swap(m_innerSize, other.m_innerSize);
00259       //std::swap(m_outerSize, other.m_outerSize);
00260       m_data.swap(other.m_data);
00261     }
00262 
00263     inline DynamicSparseMatrix& operator=(const DynamicSparseMatrix& other)
00264     {
00265       if (other.isRValue())
00266       {
00267         swap(other.const_cast_derived());
00268       }
00269       else
00270       {
00271         resize(other.rows(), other.cols());
00272         m_data = other.m_data;
00273       }
00274       return *this;
00275     }
00276 
00278     inline ~DynamicSparseMatrix() {}
00279 
00280   public:
00281 
00284     EIGEN_DEPRECATED void startFill(Index reserveSize = 1000)
00285     {
00286       setZero();
00287       reserve(reserveSize);
00288     }
00289 
00299     EIGEN_DEPRECATED Scalar& fill(Index row, Index col)
00300     {
00301       const Index outer = IsRowMajor ? row : col;
00302       const Index inner = IsRowMajor ? col : row;
00303       return insertBack(outer,inner);
00304     }
00305 
00311     EIGEN_DEPRECATED Scalar& fillrand(Index row, Index col)
00312     {
00313       return insert(row,col);
00314     }
00315 
00318     EIGEN_DEPRECATED void endFill() {}
00319     
00320 #   ifdef EIGEN_DYNAMICSPARSEMATRIX_PLUGIN
00321 #     include EIGEN_DYNAMICSPARSEMATRIX_PLUGIN
00322 #   endif
00323  };
00324 
00325 template<typename Scalar, int _Options, typename _StorageIndex>
00326 class DynamicSparseMatrix<Scalar,_Options,_StorageIndex>::InnerIterator : public SparseVector<Scalar,_Options,_StorageIndex>::InnerIterator
00327 {
00328     typedef typename SparseVector<Scalar,_Options,_StorageIndex>::InnerIterator Base;
00329   public:
00330     InnerIterator(const DynamicSparseMatrix& mat, Index outer)
00331       : Base(mat.m_data[outer]), m_outer(outer)
00332     {}
00333 
00334     inline Index row() const { return IsRowMajor ? m_outer : Base::index(); }
00335     inline Index col() const { return IsRowMajor ? Base::index() : m_outer; }
00336     inline Index outer() const { return m_outer; }
00337 
00338   protected:
00339     const Index m_outer;
00340 };
00341 
00342 template<typename Scalar, int _Options, typename _StorageIndex>
00343 class DynamicSparseMatrix<Scalar,_Options,_StorageIndex>::ReverseInnerIterator : public SparseVector<Scalar,_Options,_StorageIndex>::ReverseInnerIterator
00344 {
00345     typedef typename SparseVector<Scalar,_Options,_StorageIndex>::ReverseInnerIterator Base;
00346   public:
00347     ReverseInnerIterator(const DynamicSparseMatrix& mat, Index outer)
00348       : Base(mat.m_data[outer]), m_outer(outer)
00349     {}
00350 
00351     inline Index row() const { return IsRowMajor ? m_outer : Base::index(); }
00352     inline Index col() const { return IsRowMajor ? Base::index() : m_outer; }
00353     inline Index outer() const { return m_outer; }
00354 
00355   protected:
00356     const Index m_outer;
00357 };
00358 
00359 namespace internal {
00360 
00361 template<typename _Scalar, int _Options, typename _StorageIndex>
00362 struct evaluator<DynamicSparseMatrix<_Scalar,_Options,_StorageIndex> >
00363   : evaluator_base<DynamicSparseMatrix<_Scalar,_Options,_StorageIndex> >
00364 {
00365   typedef _Scalar Scalar;
00366   typedef DynamicSparseMatrix<_Scalar,_Options,_StorageIndex> SparseMatrixType;
00367   typedef typename SparseMatrixType::InnerIterator InnerIterator;
00368   typedef typename SparseMatrixType::ReverseInnerIterator ReverseInnerIterator;
00369   
00370   enum {
00371     CoeffReadCost = NumTraits<_Scalar>::ReadCost,
00372     Flags = SparseMatrixType::Flags
00373   };
00374   
00375   evaluator() : m_matrix(0) {}
00376   evaluator(const SparseMatrixType &mat) : m_matrix(&mat) {}
00377   
00378   operator SparseMatrixType&() { return m_matrix->const_cast_derived(); }
00379   operator const SparseMatrixType&() const { return *m_matrix; }
00380   
00381   Scalar coeff(Index row, Index col) const { return m_matrix->coeff(row,col); }
00382   
00383   Index nonZerosEstimate() const { return m_matrix->nonZeros(); }
00384 
00385   const SparseMatrixType *m_matrix;
00386 };
00387 
00388 }
00389 
00390 } // end namespace Eigen
00391 
00392 #endif // EIGEN_DYNAMIC_SPARSEMATRIX_H
 All Classes Functions Variables Typedefs Enumerator